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
[] = {
1038 MockWrite("HEAD / HTTP/1.1\r\n"
1039 "Host: www.example.org\r\n"
1040 "Connection: keep-alive\r\n\r\n"),
1042 MockRead data_reads1
[] = {
1043 MockRead("HTTP/1.1 404 Not Found\r\n"),
1044 MockRead("Server: Blah\r\n"),
1045 MockRead("Content-Length: 1234\r\n\r\n"),
1047 // No response body because the test stops reading here.
1048 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1051 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1052 data_writes1
, arraysize(data_writes1
));
1053 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1055 TestCompletionCallback callback1
;
1057 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1058 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1060 rv
= callback1
.WaitForResult();
1063 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1064 ASSERT_TRUE(response
!= NULL
);
1066 // Check that the headers got parsed.
1067 EXPECT_TRUE(response
->headers
.get() != NULL
);
1068 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1069 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1070 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1071 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1073 std::string server_header
;
1075 bool has_server_header
= response
->headers
->EnumerateHeader(
1076 &iter
, "Server", &server_header
);
1077 EXPECT_TRUE(has_server_header
);
1078 EXPECT_EQ("Blah", server_header
);
1080 // Reading should give EOF right away, since there is no message body
1081 // (despite non-zero content-length).
1082 std::string response_data
;
1083 rv
= ReadTransaction(trans
.get(), &response_data
);
1085 EXPECT_EQ("", response_data
);
1088 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1089 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1091 MockRead data_reads
[] = {
1092 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1094 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1096 MockRead(SYNCHRONOUS
, OK
),
1098 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1099 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1101 const char* const kExpectedResponseData
[] = {
1105 for (int i
= 0; i
< 2; ++i
) {
1106 HttpRequestInfo request
;
1107 request
.method
= "GET";
1108 request
.url
= GURL("http://www.example.org/");
1109 request
.load_flags
= 0;
1111 scoped_ptr
<HttpTransaction
> trans(
1112 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1114 TestCompletionCallback callback
;
1116 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1117 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1119 rv
= callback
.WaitForResult();
1122 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1123 ASSERT_TRUE(response
!= NULL
);
1125 EXPECT_TRUE(response
->headers
.get() != NULL
);
1126 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1127 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1129 std::string response_data
;
1130 rv
= ReadTransaction(trans
.get(), &response_data
);
1132 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1136 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1137 ScopedVector
<UploadElementReader
> element_readers
;
1138 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1139 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1141 HttpRequestInfo request
;
1142 request
.method
= "POST";
1143 request
.url
= GURL("http://www.foo.com/");
1144 request
.upload_data_stream
= &upload_data_stream
;
1145 request
.load_flags
= 0;
1147 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1148 scoped_ptr
<HttpTransaction
> trans(
1149 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1151 MockRead data_reads
[] = {
1152 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1153 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1154 MockRead("hello world"),
1155 MockRead(SYNCHRONOUS
, OK
),
1157 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1158 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1160 TestCompletionCallback callback
;
1162 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1163 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1165 rv
= callback
.WaitForResult();
1168 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1169 ASSERT_TRUE(response
!= NULL
);
1171 EXPECT_TRUE(response
->headers
.get() != NULL
);
1172 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1174 std::string response_data
;
1175 rv
= ReadTransaction(trans
.get(), &response_data
);
1177 EXPECT_EQ("hello world", response_data
);
1180 // This test is almost the same as Ignores100 above, but the response contains
1181 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1182 // HTTP/1.1 and the two status headers are read in one read.
1183 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1184 HttpRequestInfo request
;
1185 request
.method
= "GET";
1186 request
.url
= GURL("http://www.foo.com/");
1187 request
.load_flags
= 0;
1189 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1190 scoped_ptr
<HttpTransaction
> trans(
1191 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1193 MockRead data_reads
[] = {
1194 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1195 "HTTP/1.1 200 OK\r\n\r\n"),
1196 MockRead("hello world"),
1197 MockRead(SYNCHRONOUS
, OK
),
1199 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1200 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1202 TestCompletionCallback callback
;
1204 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1205 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1207 rv
= callback
.WaitForResult();
1210 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1211 ASSERT_TRUE(response
!= NULL
);
1213 EXPECT_TRUE(response
->headers
.get() != NULL
);
1214 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1216 std::string response_data
;
1217 rv
= ReadTransaction(trans
.get(), &response_data
);
1219 EXPECT_EQ("hello world", response_data
);
1222 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1223 HttpRequestInfo request
;
1224 request
.method
= "POST";
1225 request
.url
= GURL("http://www.foo.com/");
1226 request
.load_flags
= 0;
1228 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1229 scoped_ptr
<HttpTransaction
> trans(
1230 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1232 MockRead data_reads
[] = {
1233 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1236 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1237 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1239 TestCompletionCallback callback
;
1241 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1242 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1244 rv
= callback
.WaitForResult();
1247 std::string response_data
;
1248 rv
= ReadTransaction(trans
.get(), &response_data
);
1250 EXPECT_EQ("", response_data
);
1253 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1254 HttpRequestInfo request
;
1255 request
.method
= "POST";
1256 request
.url
= GURL("http://www.foo.com/");
1257 request
.load_flags
= 0;
1259 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1260 scoped_ptr
<HttpTransaction
> trans(
1261 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1263 MockRead data_reads
[] = {
1266 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1267 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1269 TestCompletionCallback callback
;
1271 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1274 rv
= callback
.WaitForResult();
1275 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1278 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1279 const MockWrite
* write_failure
,
1280 const MockRead
* read_failure
) {
1281 HttpRequestInfo request
;
1282 request
.method
= "GET";
1283 request
.url
= GURL("http://www.foo.com/");
1284 request
.load_flags
= 0;
1287 session_deps_
.net_log
= &net_log
;
1288 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1290 // Written data for successfully sending both requests.
1291 MockWrite data1_writes
[] = {
1292 MockWrite("GET / HTTP/1.1\r\n"
1293 "Host: www.foo.com\r\n"
1294 "Connection: keep-alive\r\n\r\n"),
1295 MockWrite("GET / HTTP/1.1\r\n"
1296 "Host: www.foo.com\r\n"
1297 "Connection: keep-alive\r\n\r\n")
1300 // Read results for the first request.
1301 MockRead data1_reads
[] = {
1302 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1304 MockRead(ASYNC
, OK
),
1307 if (write_failure
) {
1308 ASSERT_FALSE(read_failure
);
1309 data1_writes
[1] = *write_failure
;
1311 ASSERT_TRUE(read_failure
);
1312 data1_reads
[2] = *read_failure
;
1315 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1316 data1_writes
, arraysize(data1_writes
));
1317 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1319 MockRead data2_reads
[] = {
1320 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1322 MockRead(ASYNC
, OK
),
1324 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1325 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1327 const char* const kExpectedResponseData
[] = {
1331 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1332 for (int i
= 0; i
< 2; ++i
) {
1333 TestCompletionCallback callback
;
1335 scoped_ptr
<HttpTransaction
> trans(
1336 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1338 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1339 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1341 rv
= callback
.WaitForResult();
1344 LoadTimingInfo load_timing_info
;
1345 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1346 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1348 first_socket_log_id
= load_timing_info
.socket_log_id
;
1350 // The second request should be using a new socket.
1351 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1354 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1355 ASSERT_TRUE(response
!= NULL
);
1357 EXPECT_TRUE(response
->headers
.get() != NULL
);
1358 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1360 std::string response_data
;
1361 rv
= ReadTransaction(trans
.get(), &response_data
);
1363 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1367 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1368 const MockWrite
* write_failure
,
1369 const MockRead
* read_failure
,
1371 HttpRequestInfo request
;
1372 request
.method
= "GET";
1373 request
.url
= GURL("https://www.foo.com/");
1374 request
.load_flags
= 0;
1377 session_deps_
.net_log
= &net_log
;
1378 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1380 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1381 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1383 ssl1
.SetNextProto(GetParam());
1384 ssl2
.SetNextProto(GetParam());
1386 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1387 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1389 // SPDY versions of the request and response.
1390 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1391 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1392 scoped_ptr
<SpdyFrame
> spdy_response(
1393 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1394 scoped_ptr
<SpdyFrame
> spdy_data(
1395 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1397 // HTTP/1.1 versions of the request and response.
1398 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1399 "Host: www.foo.com\r\n"
1400 "Connection: keep-alive\r\n\r\n";
1401 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1402 const char kHttpData
[] = "hello";
1404 std::vector
<MockRead
> data1_reads
;
1405 std::vector
<MockWrite
> data1_writes
;
1406 if (write_failure
) {
1407 ASSERT_FALSE(read_failure
);
1408 data1_writes
.push_back(*write_failure
);
1409 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1411 ASSERT_TRUE(read_failure
);
1413 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1415 data1_writes
.push_back(MockWrite(kHttpRequest
));
1417 data1_reads
.push_back(*read_failure
);
1420 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1421 &data1_writes
[0], data1_writes
.size());
1422 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1424 std::vector
<MockRead
> data2_reads
;
1425 std::vector
<MockWrite
> data2_writes
;
1428 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1430 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1431 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1432 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1434 data2_writes
.push_back(
1435 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1437 data2_reads
.push_back(
1438 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1439 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1440 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1442 SequencedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1443 &data2_writes
[0], data2_writes
.size());
1444 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1446 // Preconnect a socket.
1447 SSLConfig ssl_config
;
1448 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1449 session
->GetNextProtos(&ssl_config
.next_protos
);
1450 session
->http_stream_factory()->PreconnectStreams(1, request
, ssl_config
,
1452 // Wait for the preconnect to complete.
1453 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1454 base::RunLoop().RunUntilIdle();
1455 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1457 // Make the request.
1458 TestCompletionCallback callback
;
1460 scoped_ptr
<HttpTransaction
> trans(
1461 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1463 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1464 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1466 rv
= callback
.WaitForResult();
1469 LoadTimingInfo load_timing_info
;
1470 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1471 TestLoadTimingNotReused(
1473 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1475 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1476 ASSERT_TRUE(response
!= NULL
);
1478 EXPECT_TRUE(response
->headers
.get() != NULL
);
1479 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1481 std::string response_data
;
1482 rv
= ReadTransaction(trans
.get(), &response_data
);
1484 EXPECT_EQ(kHttpData
, response_data
);
1487 TEST_P(HttpNetworkTransactionTest
,
1488 KeepAliveConnectionNotConnectedOnWrite
) {
1489 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1490 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1493 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1494 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1495 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1498 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1499 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1500 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1503 // Make sure that on a 408 response (Request Timeout), the request is retried,
1504 // if the socket was a reused keep alive socket.
1505 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1506 MockRead
read_failure(SYNCHRONOUS
,
1507 "HTTP/1.1 408 Request Timeout\r\n"
1508 "Connection: Keep-Alive\r\n"
1509 "Content-Length: 6\r\n\r\n"
1511 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1514 TEST_P(HttpNetworkTransactionTest
,
1515 PreconnectErrorNotConnectedOnWrite
) {
1516 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1517 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1520 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1521 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1522 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1525 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1526 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1527 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1530 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1531 MockRead
read_failure(ASYNC
, OK
); // EOF
1532 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1535 // Make sure that on a 408 response (Request Timeout), the request is retried,
1536 // if the socket was a preconnected (UNUSED_IDLE) socket.
1537 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1538 MockRead
read_failure(SYNCHRONOUS
,
1539 "HTTP/1.1 408 Request Timeout\r\n"
1540 "Connection: Keep-Alive\r\n"
1541 "Content-Length: 6\r\n\r\n"
1543 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1544 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1547 TEST_P(HttpNetworkTransactionTest
,
1548 SpdyPreconnectErrorNotConnectedOnWrite
) {
1549 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1550 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1553 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1554 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1555 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1558 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1559 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1560 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1563 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1564 MockRead
read_failure(ASYNC
, OK
); // EOF
1565 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1568 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1569 HttpRequestInfo request
;
1570 request
.method
= "GET";
1571 request
.url
= GURL("http://www.example.org/");
1572 request
.load_flags
= 0;
1574 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1575 scoped_ptr
<HttpTransaction
> trans(
1576 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1578 MockRead data_reads
[] = {
1579 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1580 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1581 MockRead("hello world"),
1582 MockRead(SYNCHRONOUS
, OK
),
1584 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1585 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1587 TestCompletionCallback callback
;
1589 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1590 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1592 rv
= callback
.WaitForResult();
1593 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1596 // What do various browsers do when the server closes a non-keepalive
1597 // connection without sending any response header or body?
1600 // Safari 3.1.2 (Windows): error page
1601 // Firefox 3.0.1: blank page
1602 // Opera 9.52: after five attempts, blank page
1603 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1604 // Us: error page (EMPTY_RESPONSE)
1605 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1606 MockRead data_reads
[] = {
1607 MockRead(SYNCHRONOUS
, OK
), // EOF
1608 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1609 MockRead("hello world"),
1610 MockRead(SYNCHRONOUS
, OK
),
1612 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1613 arraysize(data_reads
));
1614 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1617 // Test that network access can be deferred and resumed.
1618 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1619 HttpRequestInfo request
;
1620 request
.method
= "GET";
1621 request
.url
= GURL("http://www.example.org/");
1622 request
.load_flags
= 0;
1624 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1625 scoped_ptr
<HttpTransaction
> trans(
1626 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1628 // Defer on OnBeforeNetworkStart.
1629 BeforeNetworkStartHandler
net_start_handler(true); // defer
1630 trans
->SetBeforeNetworkStartCallback(
1631 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1632 base::Unretained(&net_start_handler
)));
1634 MockRead data_reads
[] = {
1635 MockRead("HTTP/1.0 200 OK\r\n"),
1636 MockRead("Content-Length: 5\r\n\r\n"),
1638 MockRead(SYNCHRONOUS
, 0),
1640 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1641 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1643 TestCompletionCallback callback
;
1645 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1646 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1647 base::MessageLoop::current()->RunUntilIdle();
1649 // Should have deferred for network start.
1650 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1651 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1653 trans
->ResumeNetworkStart();
1654 rv
= callback
.WaitForResult();
1656 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1658 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1659 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1660 if (rv
== ERR_IO_PENDING
)
1661 rv
= callback
.WaitForResult();
1666 // Test that network use can be deferred and canceled.
1667 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1668 HttpRequestInfo request
;
1669 request
.method
= "GET";
1670 request
.url
= GURL("http://www.example.org/");
1671 request
.load_flags
= 0;
1673 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1674 scoped_ptr
<HttpTransaction
> trans(
1675 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1677 // Defer on OnBeforeNetworkStart.
1678 BeforeNetworkStartHandler
net_start_handler(true); // defer
1679 trans
->SetBeforeNetworkStartCallback(
1680 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1681 base::Unretained(&net_start_handler
)));
1683 TestCompletionCallback callback
;
1685 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1686 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1687 base::MessageLoop::current()->RunUntilIdle();
1689 // Should have deferred for network start.
1690 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1691 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1694 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1695 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1696 // destructor in such situations.
1697 // See http://crbug.com/154712 and http://crbug.com/156609.
1698 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1699 HttpRequestInfo request
;
1700 request
.method
= "GET";
1701 request
.url
= GURL("http://www.example.org/");
1702 request
.load_flags
= 0;
1704 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1705 scoped_ptr
<HttpTransaction
> trans(
1706 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1708 MockRead data_reads
[] = {
1709 MockRead("HTTP/1.0 200 OK\r\n"),
1710 MockRead("Connection: keep-alive\r\n"),
1711 MockRead("Content-Length: 100\r\n\r\n"),
1713 MockRead(SYNCHRONOUS
, 0),
1715 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1716 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1718 TestCompletionCallback callback
;
1720 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1721 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1723 rv
= callback
.WaitForResult();
1726 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1727 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1728 if (rv
== ERR_IO_PENDING
)
1729 rv
= callback
.WaitForResult();
1731 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1732 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1735 base::MessageLoop::current()->RunUntilIdle();
1736 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1739 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1740 HttpRequestInfo request
;
1741 request
.method
= "GET";
1742 request
.url
= GURL("http://www.example.org/");
1743 request
.load_flags
= 0;
1745 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1746 scoped_ptr
<HttpTransaction
> trans(
1747 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1749 MockRead data_reads
[] = {
1750 MockRead("HTTP/1.0 200 OK\r\n"),
1751 MockRead("Connection: keep-alive\r\n"),
1752 MockRead("Content-Length: 100\r\n\r\n"),
1753 MockRead(SYNCHRONOUS
, 0),
1755 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1756 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1758 TestCompletionCallback callback
;
1760 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1761 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1763 rv
= callback
.WaitForResult();
1766 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1767 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1768 if (rv
== ERR_IO_PENDING
)
1769 rv
= callback
.WaitForResult();
1770 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1773 base::MessageLoop::current()->RunUntilIdle();
1774 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1777 // Test that we correctly reuse a keep-alive connection after not explicitly
1778 // reading the body.
1779 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1780 HttpRequestInfo request
;
1781 request
.method
= "GET";
1782 request
.url
= GURL("http://www.foo.com/");
1783 request
.load_flags
= 0;
1786 session_deps_
.net_log
= &net_log
;
1787 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1789 // Note that because all these reads happen in the same
1790 // StaticSocketDataProvider, it shows that the same socket is being reused for
1791 // all transactions.
1792 MockRead data1_reads
[] = {
1793 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1794 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1795 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1796 MockRead("HTTP/1.1 302 Found\r\n"
1797 "Content-Length: 0\r\n\r\n"),
1798 MockRead("HTTP/1.1 302 Found\r\n"
1799 "Content-Length: 5\r\n\r\n"
1801 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1802 "Content-Length: 0\r\n\r\n"),
1803 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1804 "Content-Length: 5\r\n\r\n"
1806 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1809 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1810 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1812 MockRead data2_reads
[] = {
1813 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1815 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1816 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1818 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1819 std::string response_lines
[kNumUnreadBodies
];
1821 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1822 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1823 TestCompletionCallback callback
;
1825 scoped_ptr
<HttpTransaction
> trans(
1826 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1828 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1829 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1831 rv
= callback
.WaitForResult();
1834 LoadTimingInfo load_timing_info
;
1835 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1837 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1838 first_socket_log_id
= load_timing_info
.socket_log_id
;
1840 TestLoadTimingReused(load_timing_info
);
1841 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1844 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1845 ASSERT_TRUE(response
!= NULL
);
1847 ASSERT_TRUE(response
->headers
.get() != NULL
);
1848 response_lines
[i
] = response
->headers
->GetStatusLine();
1850 // We intentionally don't read the response bodies.
1853 const char* const kStatusLines
[] = {
1854 "HTTP/1.1 204 No Content",
1855 "HTTP/1.1 205 Reset Content",
1856 "HTTP/1.1 304 Not Modified",
1857 "HTTP/1.1 302 Found",
1858 "HTTP/1.1 302 Found",
1859 "HTTP/1.1 301 Moved Permanently",
1860 "HTTP/1.1 301 Moved Permanently",
1863 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1864 "forgot to update kStatusLines");
1866 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1867 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1869 TestCompletionCallback callback
;
1870 scoped_ptr
<HttpTransaction
> trans(
1871 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1872 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1873 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1874 rv
= callback
.WaitForResult();
1876 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1877 ASSERT_TRUE(response
!= NULL
);
1878 ASSERT_TRUE(response
->headers
.get() != NULL
);
1879 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1880 std::string response_data
;
1881 rv
= ReadTransaction(trans
.get(), &response_data
);
1883 EXPECT_EQ("hello", response_data
);
1886 // Test the request-challenge-retry sequence for basic auth.
1887 // (basic auth is the easiest to mock, because it has no randomness).
1888 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1889 HttpRequestInfo request
;
1890 request
.method
= "GET";
1891 request
.url
= GURL("http://www.example.org/");
1892 request
.load_flags
= 0;
1895 session_deps_
.net_log
= &log
;
1896 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1897 scoped_ptr
<HttpTransaction
> trans(
1898 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1900 MockWrite data_writes1
[] = {
1902 "GET / HTTP/1.1\r\n"
1903 "Host: www.example.org\r\n"
1904 "Connection: keep-alive\r\n\r\n"),
1907 MockRead data_reads1
[] = {
1908 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1909 // Give a couple authenticate options (only the middle one is actually
1911 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1912 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1913 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1914 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1915 // Large content-length -- won't matter, as connection will be reset.
1916 MockRead("Content-Length: 10000\r\n\r\n"),
1917 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1920 // After calling trans->RestartWithAuth(), this is the request we should
1921 // be issuing -- the final header line contains the credentials.
1922 MockWrite data_writes2
[] = {
1924 "GET / HTTP/1.1\r\n"
1925 "Host: www.example.org\r\n"
1926 "Connection: keep-alive\r\n"
1927 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1930 // Lastly, the server responds with the actual content.
1931 MockRead data_reads2
[] = {
1932 MockRead("HTTP/1.0 200 OK\r\n"),
1933 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1934 MockRead("Content-Length: 100\r\n\r\n"),
1935 MockRead(SYNCHRONOUS
, OK
),
1938 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1939 data_writes1
, arraysize(data_writes1
));
1940 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1941 data_writes2
, arraysize(data_writes2
));
1942 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1943 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1945 TestCompletionCallback callback1
;
1947 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1948 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1950 rv
= callback1
.WaitForResult();
1953 LoadTimingInfo load_timing_info1
;
1954 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1955 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1957 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1958 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1960 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1961 ASSERT_TRUE(response
!= NULL
);
1962 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1964 TestCompletionCallback callback2
;
1966 rv
= trans
->RestartWithAuth(
1967 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1968 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1970 rv
= callback2
.WaitForResult();
1973 LoadTimingInfo load_timing_info2
;
1974 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1975 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1976 // The load timing after restart should have a new socket ID, and times after
1977 // those of the first load timing.
1978 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1979 load_timing_info2
.connect_timing
.connect_start
);
1980 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1982 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1983 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1985 response
= trans
->GetResponseInfo();
1986 ASSERT_TRUE(response
!= NULL
);
1987 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1988 EXPECT_EQ(100, response
->headers
->GetContentLength());
1991 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1992 HttpRequestInfo request
;
1993 request
.method
= "GET";
1994 request
.url
= GURL("http://www.example.org/");
1995 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
1997 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1998 scoped_ptr
<HttpTransaction
> trans(
1999 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2001 MockWrite data_writes
[] = {
2003 "GET / HTTP/1.1\r\n"
2004 "Host: www.example.org\r\n"
2005 "Connection: keep-alive\r\n\r\n"),
2008 MockRead data_reads
[] = {
2009 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2010 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2011 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2012 // Large content-length -- won't matter, as connection will be reset.
2013 MockRead("Content-Length: 10000\r\n\r\n"),
2014 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2017 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2018 data_writes
, arraysize(data_writes
));
2019 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2020 TestCompletionCallback callback
;
2022 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2023 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2025 rv
= callback
.WaitForResult();
2028 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2029 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2031 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2032 ASSERT_TRUE(response
!= NULL
);
2033 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2036 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2038 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2039 HttpRequestInfo request
;
2040 request
.method
= "GET";
2041 request
.url
= GURL("http://www.example.org/");
2042 request
.load_flags
= 0;
2045 session_deps_
.net_log
= &log
;
2046 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2048 MockWrite data_writes1
[] = {
2050 "GET / HTTP/1.1\r\n"
2051 "Host: www.example.org\r\n"
2052 "Connection: keep-alive\r\n\r\n"),
2054 // After calling trans->RestartWithAuth(), this is the request we should
2055 // be issuing -- the final header line contains the credentials.
2057 "GET / HTTP/1.1\r\n"
2058 "Host: www.example.org\r\n"
2059 "Connection: keep-alive\r\n"
2060 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2063 MockRead data_reads1
[] = {
2064 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2065 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2066 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2067 MockRead("Content-Length: 14\r\n\r\n"),
2068 MockRead("Unauthorized\r\n"),
2070 // Lastly, the server responds with the actual content.
2071 MockRead("HTTP/1.1 200 OK\r\n"),
2072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2073 MockRead("Content-Length: 5\r\n\r\n"),
2077 // If there is a regression where we disconnect a Keep-Alive
2078 // connection during an auth roundtrip, we'll end up reading this.
2079 MockRead data_reads2
[] = {
2080 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2083 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2084 data_writes1
, arraysize(data_writes1
));
2085 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2087 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2088 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2090 TestCompletionCallback callback1
;
2092 scoped_ptr
<HttpTransaction
> trans(
2093 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2094 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2095 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2097 rv
= callback1
.WaitForResult();
2100 LoadTimingInfo load_timing_info1
;
2101 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2102 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2104 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2105 ASSERT_TRUE(response
!= NULL
);
2106 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2108 TestCompletionCallback callback2
;
2110 rv
= trans
->RestartWithAuth(
2111 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2112 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2114 rv
= callback2
.WaitForResult();
2117 LoadTimingInfo load_timing_info2
;
2118 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2119 TestLoadTimingReused(load_timing_info2
);
2120 // The load timing after restart should have the same socket ID, and times
2121 // those of the first load timing.
2122 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2123 load_timing_info2
.send_start
);
2124 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2126 response
= trans
->GetResponseInfo();
2127 ASSERT_TRUE(response
!= NULL
);
2128 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2129 EXPECT_EQ(5, response
->headers
->GetContentLength());
2131 std::string response_data
;
2132 rv
= ReadTransaction(trans
.get(), &response_data
);
2134 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2135 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2138 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2139 // connection and with no response body to drain.
2140 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2141 HttpRequestInfo request
;
2142 request
.method
= "GET";
2143 request
.url
= GURL("http://www.example.org/");
2144 request
.load_flags
= 0;
2146 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2148 MockWrite data_writes1
[] = {
2150 "GET / HTTP/1.1\r\n"
2151 "Host: www.example.org\r\n"
2152 "Connection: keep-alive\r\n\r\n"),
2154 // After calling trans->RestartWithAuth(), this is the request we should
2155 // be issuing -- the final header line contains the credentials.
2157 "GET / HTTP/1.1\r\n"
2158 "Host: www.example.org\r\n"
2159 "Connection: keep-alive\r\n"
2160 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2163 MockRead data_reads1
[] = {
2164 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2165 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2166 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2168 // Lastly, the server responds with the actual content.
2169 MockRead("HTTP/1.1 200 OK\r\n"),
2170 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2171 MockRead("Content-Length: 5\r\n\r\n"),
2175 // An incorrect reconnect would cause this to be read.
2176 MockRead data_reads2
[] = {
2177 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2180 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2181 data_writes1
, arraysize(data_writes1
));
2182 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2184 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2185 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2187 TestCompletionCallback callback1
;
2189 scoped_ptr
<HttpTransaction
> trans(
2190 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2191 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2192 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2194 rv
= callback1
.WaitForResult();
2197 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2198 ASSERT_TRUE(response
!= NULL
);
2199 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2201 TestCompletionCallback callback2
;
2203 rv
= trans
->RestartWithAuth(
2204 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2205 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2207 rv
= callback2
.WaitForResult();
2210 response
= trans
->GetResponseInfo();
2211 ASSERT_TRUE(response
!= NULL
);
2212 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2213 EXPECT_EQ(5, response
->headers
->GetContentLength());
2216 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2217 // connection and with a large response body to drain.
2218 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2219 HttpRequestInfo request
;
2220 request
.method
= "GET";
2221 request
.url
= GURL("http://www.example.org/");
2222 request
.load_flags
= 0;
2224 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2226 MockWrite data_writes1
[] = {
2228 "GET / HTTP/1.1\r\n"
2229 "Host: www.example.org\r\n"
2230 "Connection: keep-alive\r\n\r\n"),
2232 // After calling trans->RestartWithAuth(), this is the request we should
2233 // be issuing -- the final header line contains the credentials.
2235 "GET / HTTP/1.1\r\n"
2236 "Host: www.example.org\r\n"
2237 "Connection: keep-alive\r\n"
2238 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2241 // Respond with 5 kb of response body.
2242 std::string
large_body_string("Unauthorized");
2243 large_body_string
.append(5 * 1024, ' ');
2244 large_body_string
.append("\r\n");
2246 MockRead data_reads1
[] = {
2247 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2248 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2250 // 5134 = 12 + 5 * 1024 + 2
2251 MockRead("Content-Length: 5134\r\n\r\n"),
2252 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2254 // Lastly, the server responds with the actual content.
2255 MockRead("HTTP/1.1 200 OK\r\n"),
2256 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2257 MockRead("Content-Length: 5\r\n\r\n"),
2261 // An incorrect reconnect would cause this to be read.
2262 MockRead data_reads2
[] = {
2263 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2266 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2267 data_writes1
, arraysize(data_writes1
));
2268 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2270 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2271 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2273 TestCompletionCallback callback1
;
2275 scoped_ptr
<HttpTransaction
> trans(
2276 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2277 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2278 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2280 rv
= callback1
.WaitForResult();
2283 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2284 ASSERT_TRUE(response
!= NULL
);
2285 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2287 TestCompletionCallback callback2
;
2289 rv
= trans
->RestartWithAuth(
2290 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2291 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2293 rv
= callback2
.WaitForResult();
2296 response
= trans
->GetResponseInfo();
2297 ASSERT_TRUE(response
!= NULL
);
2298 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2299 EXPECT_EQ(5, response
->headers
->GetContentLength());
2302 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2303 // connection, but the server gets impatient and closes the connection.
2304 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2305 HttpRequestInfo request
;
2306 request
.method
= "GET";
2307 request
.url
= GURL("http://www.example.org/");
2308 request
.load_flags
= 0;
2310 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2312 MockWrite data_writes1
[] = {
2314 "GET / HTTP/1.1\r\n"
2315 "Host: www.example.org\r\n"
2316 "Connection: keep-alive\r\n\r\n"),
2317 // This simulates the seemingly successful write to a closed connection
2318 // if the bug is not fixed.
2320 "GET / HTTP/1.1\r\n"
2321 "Host: www.example.org\r\n"
2322 "Connection: keep-alive\r\n"
2323 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2326 MockRead data_reads1
[] = {
2327 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2328 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2329 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2330 MockRead("Content-Length: 14\r\n\r\n"),
2331 // Tell MockTCPClientSocket to simulate the server closing the connection.
2332 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2333 MockRead("Unauthorized\r\n"),
2334 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2337 // After calling trans->RestartWithAuth(), this is the request we should
2338 // be issuing -- the final header line contains the credentials.
2339 MockWrite data_writes2
[] = {
2341 "GET / HTTP/1.1\r\n"
2342 "Host: www.example.org\r\n"
2343 "Connection: keep-alive\r\n"
2344 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2347 // Lastly, the server responds with the actual content.
2348 MockRead data_reads2
[] = {
2349 MockRead("HTTP/1.1 200 OK\r\n"),
2350 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2351 MockRead("Content-Length: 5\r\n\r\n"),
2355 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2356 data_writes1
, arraysize(data_writes1
));
2357 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2358 data_writes2
, arraysize(data_writes2
));
2359 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2360 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2362 TestCompletionCallback callback1
;
2364 scoped_ptr
<HttpTransaction
> trans(
2365 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2366 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2367 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2369 rv
= callback1
.WaitForResult();
2372 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2373 ASSERT_TRUE(response
!= NULL
);
2374 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2376 TestCompletionCallback callback2
;
2378 rv
= trans
->RestartWithAuth(
2379 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2380 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2382 rv
= callback2
.WaitForResult();
2385 response
= trans
->GetResponseInfo();
2386 ASSERT_TRUE(response
!= NULL
);
2387 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2388 EXPECT_EQ(5, response
->headers
->GetContentLength());
2391 // Test the request-challenge-retry sequence for basic auth, over a connection
2392 // that requires a restart when setting up an SSL tunnel.
2393 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2394 HttpRequestInfo request
;
2395 request
.method
= "GET";
2396 request
.url
= GURL("https://www.example.org/");
2397 // when the no authentication data flag is set.
2398 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2400 // Configure against proxy server "myproxy:70".
2401 session_deps_
.proxy_service
.reset(
2402 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2403 BoundTestNetLog log
;
2404 session_deps_
.net_log
= log
.bound().net_log();
2405 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2407 // Since we have proxy, should try to establish tunnel.
2408 MockWrite data_writes1
[] = {
2410 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2411 "Host: www.example.org\r\n"
2412 "Proxy-Connection: keep-alive\r\n\r\n"),
2414 // After calling trans->RestartWithAuth(), this is the request we should
2415 // be issuing -- the final header line contains the credentials.
2417 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2418 "Host: www.example.org\r\n"
2419 "Proxy-Connection: keep-alive\r\n"
2420 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2423 "GET / HTTP/1.1\r\n"
2424 "Host: www.example.org\r\n"
2425 "Connection: keep-alive\r\n\r\n"),
2428 // The proxy responds to the connect with a 407, using a persistent
2430 MockRead data_reads1
[] = {
2432 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2433 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2435 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2437 MockRead("HTTP/1.1 200 OK\r\n"),
2438 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2439 MockRead("Content-Length: 5\r\n\r\n"),
2440 MockRead(SYNCHRONOUS
, "hello"),
2443 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2444 data_writes1
, arraysize(data_writes1
));
2445 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2446 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2447 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2449 TestCompletionCallback callback1
;
2451 scoped_ptr
<HttpTransaction
> trans(
2452 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2454 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2455 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2457 rv
= callback1
.WaitForResult();
2459 TestNetLogEntry::List entries
;
2460 log
.GetEntries(&entries
);
2461 size_t pos
= ExpectLogContainsSomewhere(
2462 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2463 NetLog::PHASE_NONE
);
2464 ExpectLogContainsSomewhere(
2465 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2466 NetLog::PHASE_NONE
);
2468 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2469 ASSERT_TRUE(response
!= NULL
);
2470 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2471 ASSERT_FALSE(response
->headers
.get() == NULL
);
2472 EXPECT_EQ(407, response
->headers
->response_code());
2473 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2474 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2476 LoadTimingInfo load_timing_info
;
2477 // CONNECT requests and responses are handled at the connect job level, so
2478 // the transaction does not yet have a connection.
2479 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2481 TestCompletionCallback callback2
;
2484 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2485 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2487 rv
= callback2
.WaitForResult();
2490 response
= trans
->GetResponseInfo();
2491 ASSERT_TRUE(response
!= NULL
);
2493 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2494 EXPECT_EQ(200, response
->headers
->response_code());
2495 EXPECT_EQ(5, response
->headers
->GetContentLength());
2496 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2498 // The password prompt info should not be set.
2499 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2501 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2502 TestLoadTimingNotReusedWithPac(load_timing_info
,
2503 CONNECT_TIMING_HAS_SSL_TIMES
);
2506 session
->CloseAllConnections();
2509 // Test the request-challenge-retry sequence for basic auth, over a connection
2510 // that requires a restart when setting up an SSL tunnel.
2511 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2512 HttpRequestInfo request
;
2513 request
.method
= "GET";
2514 request
.url
= GURL("https://www.example.org/");
2515 // when the no authentication data flag is set.
2516 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2518 // Configure against proxy server "myproxy:70".
2519 session_deps_
.proxy_service
.reset(
2520 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2521 BoundTestNetLog log
;
2522 session_deps_
.net_log
= log
.bound().net_log();
2523 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2525 // Since we have proxy, should try to establish tunnel.
2526 MockWrite data_writes1
[] = {
2528 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2529 "Host: www.example.org\r\n"
2530 "Proxy-Connection: keep-alive\r\n\r\n"),
2532 // After calling trans->RestartWithAuth(), this is the request we should
2533 // be issuing -- the final header line contains the credentials.
2535 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2536 "Host: www.example.org\r\n"
2537 "Proxy-Connection: keep-alive\r\n"
2538 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2541 "GET / HTTP/1.1\r\n"
2542 "Host: www.example.org\r\n"
2543 "Connection: keep-alive\r\n\r\n"),
2546 // The proxy responds to the connect with a 407, using a persistent
2548 MockRead data_reads1
[] = {
2550 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2551 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2552 MockRead("Proxy-Connection: close\r\n\r\n"),
2554 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2556 MockRead("HTTP/1.1 200 OK\r\n"),
2557 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2558 MockRead("Content-Length: 5\r\n\r\n"),
2559 MockRead(SYNCHRONOUS
, "hello"),
2562 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2563 data_writes1
, arraysize(data_writes1
));
2564 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2565 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2566 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2568 TestCompletionCallback callback1
;
2570 scoped_ptr
<HttpTransaction
> trans(
2571 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2573 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2574 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2576 rv
= callback1
.WaitForResult();
2578 TestNetLogEntry::List entries
;
2579 log
.GetEntries(&entries
);
2580 size_t pos
= ExpectLogContainsSomewhere(
2581 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2582 NetLog::PHASE_NONE
);
2583 ExpectLogContainsSomewhere(
2585 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2586 NetLog::PHASE_NONE
);
2588 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2589 ASSERT_TRUE(response
!= NULL
);
2590 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2591 ASSERT_FALSE(response
->headers
.get() == NULL
);
2592 EXPECT_EQ(407, response
->headers
->response_code());
2593 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2594 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2596 LoadTimingInfo load_timing_info
;
2597 // CONNECT requests and responses are handled at the connect job level, so
2598 // the transaction does not yet have a connection.
2599 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2601 TestCompletionCallback callback2
;
2603 rv
= trans
->RestartWithAuth(
2604 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2605 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2607 rv
= callback2
.WaitForResult();
2610 response
= trans
->GetResponseInfo();
2611 ASSERT_TRUE(response
!= NULL
);
2613 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2614 EXPECT_EQ(200, response
->headers
->response_code());
2615 EXPECT_EQ(5, response
->headers
->GetContentLength());
2616 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2618 // The password prompt info should not be set.
2619 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2621 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2622 TestLoadTimingNotReusedWithPac(load_timing_info
,
2623 CONNECT_TIMING_HAS_SSL_TIMES
);
2626 session
->CloseAllConnections();
2629 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2630 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2631 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2632 HttpRequestInfo request
;
2633 request
.method
= "GET";
2634 request
.url
= GURL("https://www.example.org/");
2635 // Ensure that proxy authentication is attempted even
2636 // when the no authentication data flag is set.
2637 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2639 // Configure against proxy server "myproxy:70".
2640 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2641 BoundTestNetLog log
;
2642 session_deps_
.net_log
= log
.bound().net_log();
2643 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2645 scoped_ptr
<HttpTransaction
> trans(
2646 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2648 // Since we have proxy, should try to establish tunnel.
2649 MockWrite data_writes1
[] = {
2651 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2652 "Host: www.example.org\r\n"
2653 "Proxy-Connection: keep-alive\r\n\r\n"),
2655 // After calling trans->RestartWithAuth(), this is the request we should
2656 // be issuing -- the final header line contains the credentials.
2658 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2659 "Host: www.example.org\r\n"
2660 "Proxy-Connection: keep-alive\r\n"
2661 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2664 // The proxy responds to the connect with a 407, using a persistent
2665 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2666 MockRead data_reads1
[] = {
2668 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2669 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2670 MockRead("Proxy-Connection: keep-alive\r\n"),
2671 MockRead("Content-Length: 10\r\n\r\n"),
2672 MockRead("0123456789"),
2674 // Wrong credentials (wrong password).
2675 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2676 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2677 MockRead("Proxy-Connection: keep-alive\r\n"),
2678 MockRead("Content-Length: 10\r\n\r\n"),
2679 // No response body because the test stops reading here.
2680 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2683 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2684 data_writes1
, arraysize(data_writes1
));
2685 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2687 TestCompletionCallback callback1
;
2689 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2690 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2692 rv
= callback1
.WaitForResult();
2694 TestNetLogEntry::List entries
;
2695 log
.GetEntries(&entries
);
2696 size_t pos
= ExpectLogContainsSomewhere(
2697 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2698 NetLog::PHASE_NONE
);
2699 ExpectLogContainsSomewhere(
2700 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2701 NetLog::PHASE_NONE
);
2703 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2704 ASSERT_TRUE(response
);
2705 ASSERT_TRUE(response
->headers
);
2706 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2707 EXPECT_EQ(407, response
->headers
->response_code());
2708 EXPECT_EQ(10, response
->headers
->GetContentLength());
2709 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2710 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2712 TestCompletionCallback callback2
;
2714 // Wrong password (should be "bar").
2716 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2717 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2719 rv
= callback2
.WaitForResult();
2722 response
= trans
->GetResponseInfo();
2723 ASSERT_TRUE(response
);
2724 ASSERT_TRUE(response
->headers
);
2725 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2726 EXPECT_EQ(407, response
->headers
->response_code());
2727 EXPECT_EQ(10, response
->headers
->GetContentLength());
2728 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2729 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2731 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2733 session
->CloseAllConnections();
2736 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2737 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2738 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2739 HttpRequestInfo request
;
2740 request
.method
= "GET";
2741 request
.url
= GURL("https://www.example.org/");
2742 // Ensure that proxy authentication is attempted even
2743 // when the no authentication data flag is set.
2744 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2746 // Configure against proxy server "myproxy:70".
2747 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2748 BoundTestNetLog log
;
2749 session_deps_
.net_log
= log
.bound().net_log();
2750 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2752 scoped_ptr
<HttpTransaction
> trans(
2753 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2755 // Since we have proxy, should try to establish tunnel.
2756 MockWrite data_writes1
[] = {
2758 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2759 "Host: www.example.org\r\n"
2760 "Proxy-Connection: keep-alive\r\n\r\n"),
2762 // After calling trans->RestartWithAuth(), this is the request we should
2763 // be issuing -- the final header line contains the credentials.
2765 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2766 "Host: www.example.org\r\n"
2767 "Proxy-Connection: keep-alive\r\n"
2768 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2771 // The proxy responds to the connect with a 407, using a persistent
2773 MockRead data_reads1
[] = {
2775 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2776 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2777 MockRead("Content-Length: 10\r\n\r\n"),
2778 MockRead("0123456789"),
2780 // Wrong credentials (wrong password).
2781 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2782 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2783 MockRead("Content-Length: 10\r\n\r\n"),
2784 // No response body because the test stops reading here.
2785 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2788 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2789 data_writes1
, arraysize(data_writes1
));
2790 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2792 TestCompletionCallback callback1
;
2794 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2795 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2797 rv
= callback1
.WaitForResult();
2799 TestNetLogEntry::List entries
;
2800 log
.GetEntries(&entries
);
2801 size_t pos
= ExpectLogContainsSomewhere(
2802 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2803 NetLog::PHASE_NONE
);
2804 ExpectLogContainsSomewhere(
2806 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2807 NetLog::PHASE_NONE
);
2809 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2810 ASSERT_TRUE(response
);
2811 ASSERT_TRUE(response
->headers
);
2812 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2813 EXPECT_EQ(407, response
->headers
->response_code());
2814 EXPECT_EQ(10, response
->headers
->GetContentLength());
2815 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2816 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2818 TestCompletionCallback callback2
;
2820 // Wrong password (should be "bar").
2821 rv
= trans
->RestartWithAuth(
2822 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2823 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2825 rv
= callback2
.WaitForResult();
2828 response
= trans
->GetResponseInfo();
2829 ASSERT_TRUE(response
);
2830 ASSERT_TRUE(response
->headers
);
2831 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2832 EXPECT_EQ(407, response
->headers
->response_code());
2833 EXPECT_EQ(10, response
->headers
->GetContentLength());
2834 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2835 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2837 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2839 session
->CloseAllConnections();
2842 // Test that we don't read the response body when we fail to establish a tunnel,
2843 // even if the user cancels the proxy's auth attempt.
2844 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2845 HttpRequestInfo request
;
2846 request
.method
= "GET";
2847 request
.url
= GURL("https://www.example.org/");
2848 request
.load_flags
= 0;
2850 // Configure against proxy server "myproxy:70".
2851 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2853 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2855 scoped_ptr
<HttpTransaction
> trans(
2856 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2858 // Since we have proxy, should try to establish tunnel.
2859 MockWrite data_writes
[] = {
2861 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2862 "Host: www.example.org\r\n"
2863 "Proxy-Connection: keep-alive\r\n\r\n"),
2866 // The proxy responds to the connect with a 407.
2867 MockRead data_reads
[] = {
2868 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2869 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2870 MockRead("Content-Length: 10\r\n\r\n"),
2871 MockRead("0123456789"), // Should not be reached.
2872 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2875 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2876 data_writes
, arraysize(data_writes
));
2877 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2879 TestCompletionCallback callback
;
2881 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2882 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2884 rv
= callback
.WaitForResult();
2887 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2888 ASSERT_TRUE(response
);
2889 ASSERT_TRUE(response
->headers
);
2890 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2891 EXPECT_EQ(407, response
->headers
->response_code());
2892 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2894 std::string response_data
;
2895 rv
= ReadTransaction(trans
.get(), &response_data
);
2896 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2898 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2899 session
->CloseAllConnections();
2902 // Test that we don't pass extraneous headers from the proxy's response to the
2903 // caller when the proxy responds to CONNECT with 407.
2904 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
2905 HttpRequestInfo request
;
2906 request
.method
= "GET";
2907 request
.url
= GURL("https://www.example.org/");
2908 request
.load_flags
= 0;
2910 // Configure against proxy server "myproxy:70".
2911 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2913 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2915 scoped_ptr
<HttpTransaction
> trans(
2916 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2918 // Since we have proxy, should try to establish tunnel.
2919 MockWrite data_writes
[] = {
2921 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2922 "Host: www.example.org\r\n"
2923 "Proxy-Connection: keep-alive\r\n\r\n"),
2926 // The proxy responds to the connect with a 407.
2927 MockRead data_reads
[] = {
2928 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2929 MockRead("X-Foo: bar\r\n"),
2930 MockRead("Set-Cookie: foo=bar\r\n"),
2931 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2932 MockRead("Content-Length: 10\r\n\r\n"),
2933 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2936 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
2937 arraysize(data_writes
));
2938 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2940 TestCompletionCallback callback
;
2942 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2943 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2945 rv
= callback
.WaitForResult();
2948 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2949 ASSERT_TRUE(response
);
2950 ASSERT_TRUE(response
->headers
);
2951 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2952 EXPECT_EQ(407, response
->headers
->response_code());
2953 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2954 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
2955 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
2957 std::string response_data
;
2958 rv
= ReadTransaction(trans
.get(), &response_data
);
2959 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2961 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2962 session
->CloseAllConnections();
2965 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2966 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2967 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2968 HttpRequestInfo request
;
2969 request
.method
= "GET";
2970 request
.url
= GURL("http://www.example.org/");
2971 request
.load_flags
= 0;
2973 // We are using a DIRECT connection (i.e. no proxy) for this session.
2974 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2975 scoped_ptr
<HttpTransaction
> trans(
2976 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2978 MockWrite data_writes1
[] = {
2980 "GET / HTTP/1.1\r\n"
2981 "Host: www.example.org\r\n"
2982 "Connection: keep-alive\r\n\r\n"),
2985 MockRead data_reads1
[] = {
2986 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2987 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2988 // Large content-length -- won't matter, as connection will be reset.
2989 MockRead("Content-Length: 10000\r\n\r\n"),
2990 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2993 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2994 data_writes1
, arraysize(data_writes1
));
2995 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2997 TestCompletionCallback callback
;
2999 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3000 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3002 rv
= callback
.WaitForResult();
3003 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3006 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3007 // through a non-authenticating proxy. The request should fail with
3008 // ERR_UNEXPECTED_PROXY_AUTH.
3009 // Note that it is impossible to detect if an HTTP server returns a 407 through
3010 // a non-authenticating proxy - there is nothing to indicate whether the
3011 // response came from the proxy or the server, so it is treated as if the proxy
3012 // issued the challenge.
3013 TEST_P(HttpNetworkTransactionTest
,
3014 HttpsServerRequestsProxyAuthThroughProxy
) {
3015 HttpRequestInfo request
;
3016 request
.method
= "GET";
3017 request
.url
= GURL("https://www.example.org/");
3019 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3020 BoundTestNetLog log
;
3021 session_deps_
.net_log
= log
.bound().net_log();
3022 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3024 // Since we have proxy, should try to establish tunnel.
3025 MockWrite data_writes1
[] = {
3027 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3028 "Host: www.example.org\r\n"
3029 "Proxy-Connection: keep-alive\r\n\r\n"),
3032 "GET / HTTP/1.1\r\n"
3033 "Host: www.example.org\r\n"
3034 "Connection: keep-alive\r\n\r\n"),
3037 MockRead data_reads1
[] = {
3038 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3040 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3041 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3043 MockRead(SYNCHRONOUS
, OK
),
3046 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3047 data_writes1
, arraysize(data_writes1
));
3048 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3049 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3050 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3052 TestCompletionCallback callback1
;
3054 scoped_ptr
<HttpTransaction
> trans(
3055 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3057 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3058 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3060 rv
= callback1
.WaitForResult();
3061 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3062 TestNetLogEntry::List entries
;
3063 log
.GetEntries(&entries
);
3064 size_t pos
= ExpectLogContainsSomewhere(
3065 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3066 NetLog::PHASE_NONE
);
3067 ExpectLogContainsSomewhere(
3069 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3070 NetLog::PHASE_NONE
);
3073 // Test the load timing for HTTPS requests with an HTTP proxy.
3074 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3075 HttpRequestInfo request1
;
3076 request1
.method
= "GET";
3077 request1
.url
= GURL("https://www.example.org/1");
3079 HttpRequestInfo request2
;
3080 request2
.method
= "GET";
3081 request2
.url
= GURL("https://www.example.org/2");
3083 // Configure against proxy server "myproxy:70".
3084 session_deps_
.proxy_service
.reset(
3085 ProxyService::CreateFixed("PROXY myproxy:70"));
3086 BoundTestNetLog log
;
3087 session_deps_
.net_log
= log
.bound().net_log();
3088 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3090 // Since we have proxy, should try to establish tunnel.
3091 MockWrite data_writes1
[] = {
3093 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3094 "Host: www.example.org\r\n"
3095 "Proxy-Connection: keep-alive\r\n\r\n"),
3098 "GET /1 HTTP/1.1\r\n"
3099 "Host: www.example.org\r\n"
3100 "Connection: keep-alive\r\n\r\n"),
3103 "GET /2 HTTP/1.1\r\n"
3104 "Host: www.example.org\r\n"
3105 "Connection: keep-alive\r\n\r\n"),
3108 // The proxy responds to the connect with a 407, using a persistent
3110 MockRead data_reads1
[] = {
3111 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3113 MockRead("HTTP/1.1 200 OK\r\n"),
3114 MockRead("Content-Length: 1\r\n\r\n"),
3115 MockRead(SYNCHRONOUS
, "1"),
3117 MockRead("HTTP/1.1 200 OK\r\n"),
3118 MockRead("Content-Length: 2\r\n\r\n"),
3119 MockRead(SYNCHRONOUS
, "22"),
3122 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3123 data_writes1
, arraysize(data_writes1
));
3124 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3125 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3126 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3128 TestCompletionCallback callback1
;
3129 scoped_ptr
<HttpTransaction
> trans1(
3130 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3132 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3133 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3135 rv
= callback1
.WaitForResult();
3138 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3139 ASSERT_TRUE(response1
!= NULL
);
3140 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3141 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3143 LoadTimingInfo load_timing_info1
;
3144 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3145 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3149 TestCompletionCallback callback2
;
3150 scoped_ptr
<HttpTransaction
> trans2(
3151 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3153 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3154 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3156 rv
= callback2
.WaitForResult();
3159 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3160 ASSERT_TRUE(response2
!= NULL
);
3161 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3162 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3164 LoadTimingInfo load_timing_info2
;
3165 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3166 TestLoadTimingReused(load_timing_info2
);
3168 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3171 session
->CloseAllConnections();
3174 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3175 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3176 HttpRequestInfo request1
;
3177 request1
.method
= "GET";
3178 request1
.url
= GURL("https://www.example.org/1");
3180 HttpRequestInfo request2
;
3181 request2
.method
= "GET";
3182 request2
.url
= GURL("https://www.example.org/2");
3184 // Configure against proxy server "myproxy:70".
3185 session_deps_
.proxy_service
.reset(
3186 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3187 BoundTestNetLog log
;
3188 session_deps_
.net_log
= log
.bound().net_log();
3189 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3191 // Since we have proxy, should try to establish tunnel.
3192 MockWrite data_writes1
[] = {
3194 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3195 "Host: www.example.org\r\n"
3196 "Proxy-Connection: keep-alive\r\n\r\n"),
3199 "GET /1 HTTP/1.1\r\n"
3200 "Host: www.example.org\r\n"
3201 "Connection: keep-alive\r\n\r\n"),
3204 "GET /2 HTTP/1.1\r\n"
3205 "Host: www.example.org\r\n"
3206 "Connection: keep-alive\r\n\r\n"),
3209 // The proxy responds to the connect with a 407, using a persistent
3211 MockRead data_reads1
[] = {
3212 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3214 MockRead("HTTP/1.1 200 OK\r\n"),
3215 MockRead("Content-Length: 1\r\n\r\n"),
3216 MockRead(SYNCHRONOUS
, "1"),
3218 MockRead("HTTP/1.1 200 OK\r\n"),
3219 MockRead("Content-Length: 2\r\n\r\n"),
3220 MockRead(SYNCHRONOUS
, "22"),
3223 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3224 data_writes1
, arraysize(data_writes1
));
3225 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3226 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3227 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3229 TestCompletionCallback callback1
;
3230 scoped_ptr
<HttpTransaction
> trans1(
3231 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3233 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3234 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3236 rv
= callback1
.WaitForResult();
3239 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3240 ASSERT_TRUE(response1
!= NULL
);
3241 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3242 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3244 LoadTimingInfo load_timing_info1
;
3245 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3246 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3247 CONNECT_TIMING_HAS_SSL_TIMES
);
3251 TestCompletionCallback callback2
;
3252 scoped_ptr
<HttpTransaction
> trans2(
3253 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3255 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3258 rv
= callback2
.WaitForResult();
3261 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3262 ASSERT_TRUE(response2
!= NULL
);
3263 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3264 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3266 LoadTimingInfo load_timing_info2
;
3267 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3268 TestLoadTimingReusedWithPac(load_timing_info2
);
3270 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3273 session
->CloseAllConnections();
3276 // Test a simple get through an HTTPS Proxy.
3277 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3278 HttpRequestInfo request
;
3279 request
.method
= "GET";
3280 request
.url
= GURL("http://www.example.org/");
3282 // Configure against https proxy server "proxy:70".
3283 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3284 "https://proxy:70"));
3285 BoundTestNetLog log
;
3286 session_deps_
.net_log
= log
.bound().net_log();
3287 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3289 // Since we have proxy, should use full url
3290 MockWrite data_writes1
[] = {
3292 "GET http://www.example.org/ HTTP/1.1\r\n"
3293 "Host: www.example.org\r\n"
3294 "Proxy-Connection: keep-alive\r\n\r\n"),
3297 MockRead data_reads1
[] = {
3298 MockRead("HTTP/1.1 200 OK\r\n"),
3299 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3300 MockRead("Content-Length: 100\r\n\r\n"),
3301 MockRead(SYNCHRONOUS
, OK
),
3304 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3305 data_writes1
, arraysize(data_writes1
));
3306 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3307 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3308 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3310 TestCompletionCallback callback1
;
3312 scoped_ptr
<HttpTransaction
> trans(
3313 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3315 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3316 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3318 rv
= callback1
.WaitForResult();
3321 LoadTimingInfo load_timing_info
;
3322 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3323 TestLoadTimingNotReused(load_timing_info
,
3324 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3326 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3327 ASSERT_TRUE(response
!= NULL
);
3329 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3330 EXPECT_EQ(200, response
->headers
->response_code());
3331 EXPECT_EQ(100, response
->headers
->GetContentLength());
3332 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3334 // The password prompt info should not be set.
3335 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3338 // Test a SPDY get through an HTTPS Proxy.
3339 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3340 HttpRequestInfo request
;
3341 request
.method
= "GET";
3342 request
.url
= GURL("http://www.example.org/");
3343 request
.load_flags
= 0;
3345 // Configure against https proxy server "proxy:70".
3346 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3347 "https://proxy:70"));
3348 BoundTestNetLog log
;
3349 session_deps_
.net_log
= log
.bound().net_log();
3350 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3352 // fetch http://www.example.org/ via SPDY
3353 scoped_ptr
<SpdyFrame
> req(
3354 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3355 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3357 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3358 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3359 MockRead spdy_reads
[] = {
3360 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3363 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3364 arraysize(spdy_writes
));
3365 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3367 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3368 ssl
.SetNextProto(GetParam());
3369 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3371 TestCompletionCallback callback1
;
3373 scoped_ptr
<HttpTransaction
> trans(
3374 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3376 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3377 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3379 rv
= callback1
.WaitForResult();
3382 LoadTimingInfo load_timing_info
;
3383 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3384 TestLoadTimingNotReused(load_timing_info
,
3385 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3387 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3388 ASSERT_TRUE(response
!= NULL
);
3389 ASSERT_TRUE(response
->headers
.get() != NULL
);
3390 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3392 std::string response_data
;
3393 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3394 EXPECT_EQ(kUploadData
, response_data
);
3397 // Verifies that a session which races and wins against the owning transaction
3398 // (completing prior to host resolution), doesn't fail the transaction.
3399 // Regression test for crbug.com/334413.
3400 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3401 HttpRequestInfo request
;
3402 request
.method
= "GET";
3403 request
.url
= GURL("http://www.example.org/");
3404 request
.load_flags
= 0;
3406 // Configure SPDY proxy server "proxy:70".
3407 session_deps_
.proxy_service
.reset(
3408 ProxyService::CreateFixed("https://proxy:70"));
3409 BoundTestNetLog log
;
3410 session_deps_
.net_log
= log
.bound().net_log();
3411 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3413 // Fetch http://www.example.org/ through the SPDY proxy.
3414 scoped_ptr
<SpdyFrame
> req(
3415 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3416 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3418 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3419 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3420 MockRead spdy_reads
[] = {
3421 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3424 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3425 arraysize(spdy_writes
));
3426 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3428 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3429 ssl
.SetNextProto(GetParam());
3430 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3432 TestCompletionCallback callback1
;
3434 scoped_ptr
<HttpTransaction
> trans(
3435 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3437 // Stall the hostname resolution begun by the transaction.
3438 session_deps_
.host_resolver
->set_synchronous_mode(false);
3439 session_deps_
.host_resolver
->set_ondemand_mode(true);
3441 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3442 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3444 // Race a session to the proxy, which completes first.
3445 session_deps_
.host_resolver
->set_ondemand_mode(false);
3447 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3448 base::WeakPtr
<SpdySession
> spdy_session
=
3449 CreateSecureSpdySession(session
, key
, log
.bound());
3451 // Unstall the resolution begun by the transaction.
3452 session_deps_
.host_resolver
->set_ondemand_mode(true);
3453 session_deps_
.host_resolver
->ResolveAllPending();
3455 EXPECT_FALSE(callback1
.have_result());
3456 rv
= callback1
.WaitForResult();
3459 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3460 ASSERT_TRUE(response
!= NULL
);
3461 ASSERT_TRUE(response
->headers
.get() != NULL
);
3462 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3464 std::string response_data
;
3465 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3466 EXPECT_EQ(kUploadData
, response_data
);
3469 // Test a SPDY get through an HTTPS Proxy.
3470 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3471 HttpRequestInfo request
;
3472 request
.method
= "GET";
3473 request
.url
= GURL("http://www.example.org/");
3474 request
.load_flags
= 0;
3476 // Configure against https proxy server "myproxy:70".
3477 session_deps_
.proxy_service
.reset(
3478 ProxyService::CreateFixed("https://myproxy:70"));
3479 BoundTestNetLog log
;
3480 session_deps_
.net_log
= log
.bound().net_log();
3481 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3483 // The first request will be a bare GET, the second request will be a
3484 // GET with a Proxy-Authorization header.
3485 scoped_ptr
<SpdyFrame
> req_get(
3486 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3487 const char* const kExtraAuthorizationHeaders
[] = {
3488 "proxy-authorization", "Basic Zm9vOmJhcg=="
3490 scoped_ptr
<SpdyFrame
> req_get_authorization(
3491 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3492 arraysize(kExtraAuthorizationHeaders
) / 2,
3497 MockWrite spdy_writes
[] = {
3498 CreateMockWrite(*req_get
, 0), CreateMockWrite(*req_get_authorization
, 3),
3501 // The first response is a 407 proxy authentication challenge, and the second
3502 // response will be a 200 response since the second request includes a valid
3503 // Authorization header.
3504 const char* const kExtraAuthenticationHeaders
[] = {
3505 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3507 scoped_ptr
<SpdyFrame
> resp_authentication(
3508 spdy_util_
.ConstructSpdySynReplyError(
3509 "407 Proxy Authentication Required",
3510 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3512 scoped_ptr
<SpdyFrame
> body_authentication(
3513 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3514 scoped_ptr
<SpdyFrame
> resp_data(
3515 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3516 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3517 MockRead spdy_reads
[] = {
3518 CreateMockRead(*resp_authentication
, 1),
3519 CreateMockRead(*body_authentication
, 2),
3520 CreateMockRead(*resp_data
, 4),
3521 CreateMockRead(*body_data
, 5),
3522 MockRead(ASYNC
, 0, 6),
3525 SequencedSocketData
data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3526 arraysize(spdy_writes
));
3527 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3529 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3530 ssl
.SetNextProto(GetParam());
3531 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3533 TestCompletionCallback callback1
;
3535 scoped_ptr
<HttpTransaction
> trans(
3536 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3538 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3539 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3541 rv
= callback1
.WaitForResult();
3544 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3546 ASSERT_TRUE(response
!= NULL
);
3547 ASSERT_TRUE(response
->headers
.get() != NULL
);
3548 EXPECT_EQ(407, response
->headers
->response_code());
3549 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3550 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3552 TestCompletionCallback callback2
;
3554 rv
= trans
->RestartWithAuth(
3555 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3556 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3558 rv
= callback2
.WaitForResult();
3561 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3563 ASSERT_TRUE(response_restart
!= NULL
);
3564 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3565 EXPECT_EQ(200, response_restart
->headers
->response_code());
3566 // The password prompt info should not be set.
3567 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3570 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3571 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3572 HttpRequestInfo request
;
3573 request
.method
= "GET";
3574 request
.url
= GURL("https://www.example.org/");
3575 request
.load_flags
= 0;
3577 // Configure against https proxy server "proxy:70".
3578 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3579 "https://proxy:70"));
3580 BoundTestNetLog log
;
3581 session_deps_
.net_log
= log
.bound().net_log();
3582 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3584 scoped_ptr
<HttpTransaction
> trans(
3585 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3587 // CONNECT to www.example.org:443 via SPDY
3588 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3589 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3590 // fetch https://www.example.org/ via HTTP
3593 "GET / HTTP/1.1\r\n"
3594 "Host: www.example.org\r\n"
3595 "Connection: keep-alive\r\n\r\n";
3596 scoped_ptr
<SpdyFrame
> wrapped_get(
3597 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3598 scoped_ptr
<SpdyFrame
> conn_resp(
3599 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3600 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3601 "Content-Length: 10\r\n\r\n";
3602 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3603 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3604 scoped_ptr
<SpdyFrame
> wrapped_body(
3605 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3606 scoped_ptr
<SpdyFrame
> window_update(
3607 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3609 MockWrite spdy_writes
[] = {
3610 CreateMockWrite(*connect
, 0),
3611 CreateMockWrite(*wrapped_get
, 2),
3612 CreateMockWrite(*window_update
, 6),
3615 MockRead spdy_reads
[] = {
3616 CreateMockRead(*conn_resp
, 1, ASYNC
),
3617 CreateMockRead(*wrapped_get_resp
, 3, ASYNC
),
3618 CreateMockRead(*wrapped_body
, 4, ASYNC
),
3619 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3620 MockRead(ASYNC
, 0, 7),
3623 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3624 arraysize(spdy_writes
));
3625 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3627 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3628 ssl
.SetNextProto(GetParam());
3629 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3630 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3631 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3633 TestCompletionCallback callback1
;
3635 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3636 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3638 rv
= callback1
.WaitForResult();
3641 LoadTimingInfo load_timing_info
;
3642 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3643 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3645 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3646 ASSERT_TRUE(response
!= NULL
);
3647 ASSERT_TRUE(response
->headers
.get() != NULL
);
3648 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3650 std::string response_data
;
3651 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3652 EXPECT_EQ("1234567890", response_data
);
3655 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3656 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3657 HttpRequestInfo request
;
3658 request
.method
= "GET";
3659 request
.url
= GURL("https://www.example.org/");
3660 request
.load_flags
= 0;
3662 // Configure against https proxy server "proxy:70".
3663 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3664 "https://proxy:70"));
3665 BoundTestNetLog log
;
3666 session_deps_
.net_log
= log
.bound().net_log();
3667 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3669 scoped_ptr
<HttpTransaction
> trans(
3670 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3672 // CONNECT to www.example.org:443 via SPDY
3673 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3674 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3675 // fetch https://www.example.org/ via SPDY
3676 const char kMyUrl
[] = "https://www.example.org/";
3677 scoped_ptr
<SpdyFrame
> get(
3678 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3679 scoped_ptr
<SpdyFrame
> wrapped_get(
3680 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3681 scoped_ptr
<SpdyFrame
> conn_resp(
3682 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3683 scoped_ptr
<SpdyFrame
> get_resp(
3684 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3685 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3686 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3687 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3688 scoped_ptr
<SpdyFrame
> wrapped_body(
3689 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3690 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3691 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3692 scoped_ptr
<SpdyFrame
> window_update_body(
3693 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3695 MockWrite spdy_writes
[] = {
3696 CreateMockWrite(*connect
, 0),
3697 CreateMockWrite(*wrapped_get
, 2),
3698 CreateMockWrite(*window_update_get_resp
, 6),
3699 CreateMockWrite(*window_update_body
, 7),
3702 MockRead spdy_reads
[] = {
3703 CreateMockRead(*conn_resp
, 1, ASYNC
),
3704 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3705 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3706 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3707 MockRead(ASYNC
, 0, 8),
3710 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3711 arraysize(spdy_writes
));
3712 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3714 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3715 ssl
.SetNextProto(GetParam());
3716 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3717 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3718 ssl2
.SetNextProto(GetParam());
3719 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3721 TestCompletionCallback callback1
;
3723 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3724 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3726 // Allow the SpdyProxyClientSocket's write callback to complete.
3727 base::MessageLoop::current()->RunUntilIdle();
3728 // Now allow the read of the response to complete.
3729 spdy_data
.CompleteRead();
3730 rv
= callback1
.WaitForResult();
3733 LoadTimingInfo load_timing_info
;
3734 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3735 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3737 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3738 ASSERT_TRUE(response
!= NULL
);
3739 ASSERT_TRUE(response
->headers
.get() != NULL
);
3740 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3742 std::string response_data
;
3743 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3744 EXPECT_EQ(kUploadData
, response_data
);
3747 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3748 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3749 HttpRequestInfo request
;
3750 request
.method
= "GET";
3751 request
.url
= GURL("https://www.example.org/");
3752 request
.load_flags
= 0;
3754 // Configure against https proxy server "proxy:70".
3755 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3756 "https://proxy:70"));
3757 BoundTestNetLog log
;
3758 session_deps_
.net_log
= log
.bound().net_log();
3759 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3761 scoped_ptr
<HttpTransaction
> trans(
3762 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3764 // CONNECT to www.example.org:443 via SPDY
3765 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3766 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3767 scoped_ptr
<SpdyFrame
> get(
3768 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3770 MockWrite spdy_writes
[] = {
3771 CreateMockWrite(*connect
, 0), CreateMockWrite(*get
, 2),
3774 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3775 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3776 MockRead spdy_reads
[] = {
3777 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3),
3780 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3781 arraysize(spdy_writes
));
3782 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3784 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3785 ssl
.SetNextProto(GetParam());
3786 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3787 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3788 ssl2
.SetNextProto(GetParam());
3789 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3791 TestCompletionCallback callback1
;
3793 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3794 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3796 rv
= callback1
.WaitForResult();
3797 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3799 // TODO(ttuttle): Anything else to check here?
3802 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3803 // HTTPS Proxy to different servers.
3804 TEST_P(HttpNetworkTransactionTest
,
3805 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3806 // Configure against https proxy server "proxy:70".
3807 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3808 "https://proxy:70"));
3809 BoundTestNetLog log
;
3810 session_deps_
.net_log
= log
.bound().net_log();
3811 scoped_refptr
<HttpNetworkSession
> session(
3812 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3814 HttpRequestInfo request1
;
3815 request1
.method
= "GET";
3816 request1
.url
= GURL("https://www.example.org/");
3817 request1
.load_flags
= 0;
3819 HttpRequestInfo request2
;
3820 request2
.method
= "GET";
3821 request2
.url
= GURL("https://mail.example.org/");
3822 request2
.load_flags
= 0;
3824 // CONNECT to www.example.org:443 via SPDY.
3825 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3826 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3827 scoped_ptr
<SpdyFrame
> conn_resp1(
3828 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3830 // Fetch https://www.example.org/ via HTTP.
3832 "GET / HTTP/1.1\r\n"
3833 "Host: www.example.org\r\n"
3834 "Connection: keep-alive\r\n\r\n";
3835 scoped_ptr
<SpdyFrame
> wrapped_get1(
3836 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3837 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3838 "Content-Length: 1\r\n\r\n";
3839 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3840 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3841 scoped_ptr
<SpdyFrame
> wrapped_body1(
3842 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3843 scoped_ptr
<SpdyFrame
> window_update(
3844 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3846 // CONNECT to mail.example.org:443 via SPDY.
3847 SpdyHeaderBlock connect2_block
;
3848 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3849 if (GetParam() >= kProtoHTTP2MinimumVersion
) {
3850 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org:443";
3852 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3853 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3855 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3856 scoped_ptr
<SpdyFrame
> connect2(
3857 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3859 scoped_ptr
<SpdyFrame
> conn_resp2(
3860 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3862 // Fetch https://mail.example.org/ via HTTP.
3864 "GET / HTTP/1.1\r\n"
3865 "Host: mail.example.org\r\n"
3866 "Connection: keep-alive\r\n\r\n";
3867 scoped_ptr
<SpdyFrame
> wrapped_get2(
3868 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3869 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3870 "Content-Length: 2\r\n\r\n";
3871 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3872 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3873 scoped_ptr
<SpdyFrame
> wrapped_body2(
3874 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3876 MockWrite spdy_writes
[] = {
3877 CreateMockWrite(*connect1
, 0),
3878 CreateMockWrite(*wrapped_get1
, 2),
3879 CreateMockWrite(*connect2
, 5),
3880 CreateMockWrite(*wrapped_get2
, 7),
3883 MockRead spdy_reads
[] = {
3884 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3885 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3886 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3887 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3888 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3889 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3890 MockRead(ASYNC
, 0, 10),
3893 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3894 arraysize(spdy_writes
));
3895 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3897 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3898 ssl
.SetNextProto(GetParam());
3899 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3900 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3901 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3902 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3903 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3905 TestCompletionCallback callback
;
3907 scoped_ptr
<HttpTransaction
> trans(
3908 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3909 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3910 EXPECT_EQ(OK
, callback
.GetResult(rv
));
3912 LoadTimingInfo load_timing_info
;
3913 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3914 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3916 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3917 ASSERT_TRUE(response
!= NULL
);
3918 ASSERT_TRUE(response
->headers
.get() != NULL
);
3919 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3921 std::string response_data
;
3922 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
3923 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
3924 EXPECT_EQ(1, callback
.GetResult(rv
));
3926 scoped_ptr
<HttpTransaction
> trans2(
3927 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3928 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3929 EXPECT_EQ(OK
, callback
.GetResult(rv
));
3931 LoadTimingInfo load_timing_info2
;
3932 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3933 // Even though the SPDY connection is reused, a new tunnelled connection has
3934 // to be created, so the socket's load timing looks like a fresh connection.
3935 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3937 // The requests should have different IDs, since they each are using their own
3939 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3941 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
3942 EXPECT_EQ(2, callback
.GetResult(rv
));
3945 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3946 // HTTPS Proxy to the same server.
3947 TEST_P(HttpNetworkTransactionTest
,
3948 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3949 // Configure against https proxy server "proxy:70".
3950 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3951 "https://proxy:70"));
3952 BoundTestNetLog log
;
3953 session_deps_
.net_log
= log
.bound().net_log();
3954 scoped_refptr
<HttpNetworkSession
> session(
3955 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3957 HttpRequestInfo request1
;
3958 request1
.method
= "GET";
3959 request1
.url
= GURL("https://www.example.org/");
3960 request1
.load_flags
= 0;
3962 HttpRequestInfo request2
;
3963 request2
.method
= "GET";
3964 request2
.url
= GURL("https://www.example.org/2");
3965 request2
.load_flags
= 0;
3967 // CONNECT to www.example.org:443 via SPDY.
3968 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3969 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3970 scoped_ptr
<SpdyFrame
> conn_resp1(
3971 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3973 // Fetch https://www.example.org/ via HTTP.
3975 "GET / HTTP/1.1\r\n"
3976 "Host: www.example.org\r\n"
3977 "Connection: keep-alive\r\n\r\n";
3978 scoped_ptr
<SpdyFrame
> wrapped_get1(
3979 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3980 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3981 "Content-Length: 1\r\n\r\n";
3982 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3983 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3984 scoped_ptr
<SpdyFrame
> wrapped_body1(
3985 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3986 scoped_ptr
<SpdyFrame
> window_update(
3987 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3989 // Fetch https://www.example.org/2 via HTTP.
3991 "GET /2 HTTP/1.1\r\n"
3992 "Host: www.example.org\r\n"
3993 "Connection: keep-alive\r\n\r\n";
3994 scoped_ptr
<SpdyFrame
> wrapped_get2(
3995 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3996 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3997 "Content-Length: 2\r\n\r\n";
3998 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3999 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
4000 scoped_ptr
<SpdyFrame
> wrapped_body2(
4001 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4003 MockWrite spdy_writes
[] = {
4004 CreateMockWrite(*connect1
, 0),
4005 CreateMockWrite(*wrapped_get1
, 2),
4006 CreateMockWrite(*wrapped_get2
, 5),
4009 MockRead spdy_reads
[] = {
4010 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4011 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4012 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4013 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4014 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4015 MockRead(ASYNC
, 0, 8),
4018 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4019 arraysize(spdy_writes
));
4020 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4022 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4023 ssl
.SetNextProto(GetParam());
4024 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4025 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4026 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4028 TestCompletionCallback callback
;
4030 scoped_ptr
<HttpTransaction
> trans(
4031 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4032 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4033 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4035 rv
= callback
.WaitForResult();
4038 LoadTimingInfo load_timing_info
;
4039 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4040 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4042 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4043 ASSERT_TRUE(response
!= NULL
);
4044 ASSERT_TRUE(response
->headers
.get() != NULL
);
4045 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4047 std::string response_data
;
4048 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4049 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4052 scoped_ptr
<HttpTransaction
> trans2(
4053 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4054 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4055 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4057 rv
= callback
.WaitForResult();
4060 LoadTimingInfo load_timing_info2
;
4061 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4062 TestLoadTimingReused(load_timing_info2
);
4064 // The requests should have the same ID.
4065 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4067 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4070 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4071 // Proxy to different servers.
4072 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4073 // Configure against https proxy server "proxy:70".
4074 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4075 "https://proxy:70"));
4076 BoundTestNetLog log
;
4077 session_deps_
.net_log
= log
.bound().net_log();
4078 scoped_refptr
<HttpNetworkSession
> session(
4079 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4081 HttpRequestInfo request1
;
4082 request1
.method
= "GET";
4083 request1
.url
= GURL("http://www.example.org/");
4084 request1
.load_flags
= 0;
4086 HttpRequestInfo request2
;
4087 request2
.method
= "GET";
4088 request2
.url
= GURL("http://mail.example.org/");
4089 request2
.load_flags
= 0;
4091 // http://www.example.org/
4092 scoped_ptr
<SpdyHeaderBlock
> headers(
4093 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4094 scoped_ptr
<SpdyFrame
> get1(
4095 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4096 scoped_ptr
<SpdyFrame
> get_resp1(
4097 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4098 scoped_ptr
<SpdyFrame
> body1(
4099 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4101 // http://mail.example.org/
4102 scoped_ptr
<SpdyHeaderBlock
> headers2(
4103 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4104 scoped_ptr
<SpdyFrame
> get2(
4105 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4106 scoped_ptr
<SpdyFrame
> get_resp2(
4107 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4108 scoped_ptr
<SpdyFrame
> body2(
4109 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4111 MockWrite spdy_writes
[] = {
4112 CreateMockWrite(*get1
, 0),
4113 CreateMockWrite(*get2
, 3),
4116 MockRead spdy_reads
[] = {
4117 CreateMockRead(*get_resp1
, 1, ASYNC
),
4118 CreateMockRead(*body1
, 2, ASYNC
),
4119 CreateMockRead(*get_resp2
, 4, ASYNC
),
4120 CreateMockRead(*body2
, 5, ASYNC
),
4121 MockRead(ASYNC
, 0, 6),
4124 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4125 arraysize(spdy_writes
));
4126 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4128 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4129 ssl
.SetNextProto(GetParam());
4130 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4132 TestCompletionCallback callback
;
4134 scoped_ptr
<HttpTransaction
> trans(
4135 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4136 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4137 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4139 LoadTimingInfo load_timing_info
;
4140 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4141 TestLoadTimingNotReused(load_timing_info
,
4142 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4144 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4145 ASSERT_TRUE(response
!= NULL
);
4146 ASSERT_TRUE(response
->headers
.get() != NULL
);
4147 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4149 std::string response_data
;
4150 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4151 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4152 EXPECT_EQ(1, callback
.GetResult(rv
));
4153 // Delete the first request, so the second one can reuse the socket.
4156 scoped_ptr
<HttpTransaction
> trans2(
4157 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4158 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4159 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4161 LoadTimingInfo load_timing_info2
;
4162 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4163 TestLoadTimingReused(load_timing_info2
);
4165 // The requests should have the same ID.
4166 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4168 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4169 EXPECT_EQ(2, callback
.GetResult(rv
));
4172 // Test the challenge-response-retry sequence through an HTTPS Proxy
4173 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4174 HttpRequestInfo request
;
4175 request
.method
= "GET";
4176 request
.url
= GURL("http://www.example.org/");
4177 // when the no authentication data flag is set.
4178 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4180 // Configure against https proxy server "myproxy:70".
4181 session_deps_
.proxy_service
.reset(
4182 ProxyService::CreateFixed("https://myproxy:70"));
4183 BoundTestNetLog log
;
4184 session_deps_
.net_log
= log
.bound().net_log();
4185 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4187 // Since we have proxy, should use full url
4188 MockWrite data_writes1
[] = {
4190 "GET http://www.example.org/ HTTP/1.1\r\n"
4191 "Host: www.example.org\r\n"
4192 "Proxy-Connection: keep-alive\r\n\r\n"),
4194 // After calling trans->RestartWithAuth(), this is the request we should
4195 // be issuing -- the final header line contains the credentials.
4197 "GET http://www.example.org/ HTTP/1.1\r\n"
4198 "Host: www.example.org\r\n"
4199 "Proxy-Connection: keep-alive\r\n"
4200 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4203 // The proxy responds to the GET with a 407, using a persistent
4205 MockRead data_reads1
[] = {
4207 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4208 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4209 MockRead("Proxy-Connection: keep-alive\r\n"),
4210 MockRead("Content-Length: 0\r\n\r\n"),
4212 MockRead("HTTP/1.1 200 OK\r\n"),
4213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4214 MockRead("Content-Length: 100\r\n\r\n"),
4215 MockRead(SYNCHRONOUS
, OK
),
4218 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4219 data_writes1
, arraysize(data_writes1
));
4220 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4221 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4222 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4224 TestCompletionCallback callback1
;
4226 scoped_ptr
<HttpTransaction
> trans(
4227 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4229 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4230 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4232 rv
= callback1
.WaitForResult();
4235 LoadTimingInfo load_timing_info
;
4236 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4237 TestLoadTimingNotReused(load_timing_info
,
4238 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4240 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4241 ASSERT_TRUE(response
!= NULL
);
4242 ASSERT_FALSE(response
->headers
.get() == NULL
);
4243 EXPECT_EQ(407, response
->headers
->response_code());
4244 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4245 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4247 TestCompletionCallback callback2
;
4249 rv
= trans
->RestartWithAuth(
4250 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4251 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4253 rv
= callback2
.WaitForResult();
4256 load_timing_info
= LoadTimingInfo();
4257 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4258 // Retrying with HTTP AUTH is considered to be reusing a socket.
4259 TestLoadTimingReused(load_timing_info
);
4261 response
= trans
->GetResponseInfo();
4262 ASSERT_TRUE(response
!= NULL
);
4264 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4265 EXPECT_EQ(200, response
->headers
->response_code());
4266 EXPECT_EQ(100, response
->headers
->GetContentLength());
4267 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4269 // The password prompt info should not be set.
4270 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4273 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4274 const MockRead
& status
, int expected_status
) {
4275 HttpRequestInfo request
;
4276 request
.method
= "GET";
4277 request
.url
= GURL("https://www.example.org/");
4278 request
.load_flags
= 0;
4280 // Configure against proxy server "myproxy:70".
4281 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4282 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4284 // Since we have proxy, should try to establish tunnel.
4285 MockWrite data_writes
[] = {
4287 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4288 "Host: www.example.org\r\n"
4289 "Proxy-Connection: keep-alive\r\n\r\n"),
4292 MockRead data_reads
[] = {
4294 MockRead("Content-Length: 10\r\n\r\n"),
4295 // No response body because the test stops reading here.
4296 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4299 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4300 data_writes
, arraysize(data_writes
));
4301 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4303 TestCompletionCallback callback
;
4305 scoped_ptr
<HttpTransaction
> trans(
4306 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4308 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4309 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4311 rv
= callback
.WaitForResult();
4312 EXPECT_EQ(expected_status
, rv
);
4315 void HttpNetworkTransactionTest::ConnectStatusHelper(
4316 const MockRead
& status
) {
4317 ConnectStatusHelperWithExpectedStatus(
4318 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4321 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4322 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4325 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4326 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4329 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4330 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4333 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4334 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4337 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4338 ConnectStatusHelper(
4339 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4342 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4343 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4346 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4347 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4350 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4351 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4354 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4355 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4358 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4359 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4362 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4363 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4366 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4367 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4370 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4371 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4374 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4375 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4378 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4379 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4382 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4383 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4386 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4387 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4390 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4391 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4394 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4395 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4398 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4399 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4402 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4403 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4406 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4407 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4410 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4411 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4414 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4415 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4418 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4419 ConnectStatusHelperWithExpectedStatus(
4420 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4421 ERR_PROXY_AUTH_UNSUPPORTED
);
4424 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4425 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4428 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4429 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4432 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4433 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4436 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4437 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4440 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4441 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4444 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4445 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4448 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4449 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4452 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4453 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4456 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4457 ConnectStatusHelper(
4458 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4461 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4462 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4465 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4466 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4469 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4470 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4473 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4474 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4477 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4478 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4481 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4482 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4485 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4486 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4489 // Test the flow when both the proxy server AND origin server require
4490 // authentication. Again, this uses basic auth for both since that is
4491 // the simplest to mock.
4492 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4493 HttpRequestInfo request
;
4494 request
.method
= "GET";
4495 request
.url
= GURL("http://www.example.org/");
4496 request
.load_flags
= 0;
4498 // Configure against proxy server "myproxy:70".
4499 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4500 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4502 scoped_ptr
<HttpTransaction
> trans(
4503 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4505 MockWrite data_writes1
[] = {
4507 "GET http://www.example.org/ HTTP/1.1\r\n"
4508 "Host: www.example.org\r\n"
4509 "Proxy-Connection: keep-alive\r\n\r\n"),
4512 MockRead data_reads1
[] = {
4513 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4514 // Give a couple authenticate options (only the middle one is actually
4516 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4517 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4518 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4519 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4520 // Large content-length -- won't matter, as connection will be reset.
4521 MockRead("Content-Length: 10000\r\n\r\n"),
4522 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4525 // After calling trans->RestartWithAuth() the first time, this is the
4526 // request we should be issuing -- the final header line contains the
4527 // proxy's credentials.
4528 MockWrite data_writes2
[] = {
4530 "GET http://www.example.org/ HTTP/1.1\r\n"
4531 "Host: www.example.org\r\n"
4532 "Proxy-Connection: keep-alive\r\n"
4533 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4536 // Now the proxy server lets the request pass through to origin server.
4537 // The origin server responds with a 401.
4538 MockRead data_reads2
[] = {
4539 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4540 // Note: We are using the same realm-name as the proxy server. This is
4541 // completely valid, as realms are unique across hosts.
4542 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4543 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4544 MockRead("Content-Length: 2000\r\n\r\n"),
4545 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4548 // After calling trans->RestartWithAuth() the second time, we should send
4549 // the credentials for both the proxy and origin server.
4550 MockWrite data_writes3
[] = {
4552 "GET http://www.example.org/ HTTP/1.1\r\n"
4553 "Host: www.example.org\r\n"
4554 "Proxy-Connection: keep-alive\r\n"
4555 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4556 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4559 // Lastly we get the desired content.
4560 MockRead data_reads3
[] = {
4561 MockRead("HTTP/1.0 200 OK\r\n"),
4562 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4563 MockRead("Content-Length: 100\r\n\r\n"),
4564 MockRead(SYNCHRONOUS
, OK
),
4567 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4568 data_writes1
, arraysize(data_writes1
));
4569 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4570 data_writes2
, arraysize(data_writes2
));
4571 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4572 data_writes3
, arraysize(data_writes3
));
4573 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4574 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4575 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4577 TestCompletionCallback callback1
;
4579 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4580 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4582 rv
= callback1
.WaitForResult();
4585 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4586 ASSERT_TRUE(response
!= NULL
);
4587 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4589 TestCompletionCallback callback2
;
4591 rv
= trans
->RestartWithAuth(
4592 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4593 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4595 rv
= callback2
.WaitForResult();
4598 response
= trans
->GetResponseInfo();
4599 ASSERT_TRUE(response
!= NULL
);
4600 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4602 TestCompletionCallback callback3
;
4604 rv
= trans
->RestartWithAuth(
4605 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4606 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4608 rv
= callback3
.WaitForResult();
4611 response
= trans
->GetResponseInfo();
4612 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4613 EXPECT_EQ(100, response
->headers
->GetContentLength());
4616 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4617 // can't hook into its internals to cause it to generate predictable NTLM
4618 // authorization headers.
4619 #if defined(NTLM_PORTABLE)
4620 // The NTLM authentication unit tests were generated by capturing the HTTP
4621 // requests and responses using Fiddler 2 and inspecting the generated random
4622 // bytes in the debugger.
4624 // Enter the correct password and authenticate successfully.
4625 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4626 HttpRequestInfo request
;
4627 request
.method
= "GET";
4628 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4630 // Ensure load is not disrupted by flags which suppress behaviour specific
4631 // to other auth schemes.
4632 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4634 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4636 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4638 MockWrite data_writes1
[] = {
4639 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4640 "Host: 172.22.68.17\r\n"
4641 "Connection: keep-alive\r\n\r\n"),
4644 MockRead data_reads1
[] = {
4645 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4646 // Negotiate and NTLM are often requested together. However, we only want
4647 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4648 // the header that requests Negotiate for this test.
4649 MockRead("WWW-Authenticate: NTLM\r\n"),
4650 MockRead("Connection: close\r\n"),
4651 MockRead("Content-Length: 42\r\n"),
4652 MockRead("Content-Type: text/html\r\n\r\n"),
4653 // Missing content -- won't matter, as connection will be reset.
4654 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4657 MockWrite data_writes2
[] = {
4658 // After restarting with a null identity, this is the
4659 // request we should be issuing -- the final header line contains a Type
4661 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4662 "Host: 172.22.68.17\r\n"
4663 "Connection: keep-alive\r\n"
4664 "Authorization: NTLM "
4665 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4667 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4668 // (the credentials for the origin server). The second request continues
4669 // on the same connection.
4670 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4671 "Host: 172.22.68.17\r\n"
4672 "Connection: keep-alive\r\n"
4673 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4674 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4675 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4676 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4677 "ahlhx5I=\r\n\r\n"),
4680 MockRead data_reads2
[] = {
4681 // The origin server responds with a Type 2 message.
4682 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4683 MockRead("WWW-Authenticate: NTLM "
4684 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4685 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4686 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4687 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4688 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4689 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4691 MockRead("Content-Length: 42\r\n"),
4692 MockRead("Content-Type: text/html\r\n\r\n"),
4693 MockRead("You are not authorized to view this page\r\n"),
4695 // Lastly we get the desired content.
4696 MockRead("HTTP/1.1 200 OK\r\n"),
4697 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4698 MockRead("Content-Length: 13\r\n\r\n"),
4699 MockRead("Please Login\r\n"),
4700 MockRead(SYNCHRONOUS
, OK
),
4703 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4704 data_writes1
, arraysize(data_writes1
));
4705 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4706 data_writes2
, arraysize(data_writes2
));
4707 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4708 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4710 TestCompletionCallback callback1
;
4712 scoped_ptr
<HttpTransaction
> trans(
4713 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4715 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4716 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4718 rv
= callback1
.WaitForResult();
4721 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4723 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4724 ASSERT_FALSE(response
== NULL
);
4725 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4727 TestCompletionCallback callback2
;
4729 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4730 callback2
.callback());
4731 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4733 rv
= callback2
.WaitForResult();
4736 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4738 response
= trans
->GetResponseInfo();
4739 ASSERT_TRUE(response
!= NULL
);
4740 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4742 TestCompletionCallback callback3
;
4744 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4745 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4747 rv
= callback3
.WaitForResult();
4750 response
= trans
->GetResponseInfo();
4751 ASSERT_TRUE(response
!= NULL
);
4752 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4753 EXPECT_EQ(13, response
->headers
->GetContentLength());
4756 // Enter a wrong password, and then the correct one.
4757 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4758 HttpRequestInfo request
;
4759 request
.method
= "GET";
4760 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4761 request
.load_flags
= 0;
4763 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4765 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4767 MockWrite data_writes1
[] = {
4768 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4769 "Host: 172.22.68.17\r\n"
4770 "Connection: keep-alive\r\n\r\n"),
4773 MockRead data_reads1
[] = {
4774 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4775 // Negotiate and NTLM are often requested together. However, we only want
4776 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4777 // the header that requests Negotiate for this test.
4778 MockRead("WWW-Authenticate: NTLM\r\n"),
4779 MockRead("Connection: close\r\n"),
4780 MockRead("Content-Length: 42\r\n"),
4781 MockRead("Content-Type: text/html\r\n\r\n"),
4782 // Missing content -- won't matter, as connection will be reset.
4783 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4786 MockWrite data_writes2
[] = {
4787 // After restarting with a null identity, this is the
4788 // request we should be issuing -- the final header line contains a Type
4790 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4791 "Host: 172.22.68.17\r\n"
4792 "Connection: keep-alive\r\n"
4793 "Authorization: NTLM "
4794 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4796 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4797 // (the credentials for the origin server). The second request continues
4798 // on the same connection.
4799 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4800 "Host: 172.22.68.17\r\n"
4801 "Connection: keep-alive\r\n"
4802 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4803 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4804 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4805 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4806 "4Ww7b7E=\r\n\r\n"),
4809 MockRead data_reads2
[] = {
4810 // The origin server responds with a Type 2 message.
4811 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4812 MockRead("WWW-Authenticate: NTLM "
4813 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4814 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4815 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4816 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4817 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4818 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4820 MockRead("Content-Length: 42\r\n"),
4821 MockRead("Content-Type: text/html\r\n\r\n"),
4822 MockRead("You are not authorized to view this page\r\n"),
4825 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4826 MockRead("WWW-Authenticate: NTLM\r\n"),
4827 MockRead("Connection: close\r\n"),
4828 MockRead("Content-Length: 42\r\n"),
4829 MockRead("Content-Type: text/html\r\n\r\n"),
4830 // Missing content -- won't matter, as connection will be reset.
4831 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4834 MockWrite data_writes3
[] = {
4835 // After restarting with a null identity, this is the
4836 // request we should be issuing -- the final header line contains a Type
4838 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4839 "Host: 172.22.68.17\r\n"
4840 "Connection: keep-alive\r\n"
4841 "Authorization: NTLM "
4842 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4844 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4845 // (the credentials for the origin server). The second request continues
4846 // on the same connection.
4847 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4848 "Host: 172.22.68.17\r\n"
4849 "Connection: keep-alive\r\n"
4850 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4851 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4852 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4853 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4854 "+4MUm7c=\r\n\r\n"),
4857 MockRead data_reads3
[] = {
4858 // The origin server responds with a Type 2 message.
4859 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4860 MockRead("WWW-Authenticate: NTLM "
4861 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4862 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4863 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4864 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4865 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4866 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4868 MockRead("Content-Length: 42\r\n"),
4869 MockRead("Content-Type: text/html\r\n\r\n"),
4870 MockRead("You are not authorized to view this page\r\n"),
4872 // Lastly we get the desired content.
4873 MockRead("HTTP/1.1 200 OK\r\n"),
4874 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4875 MockRead("Content-Length: 13\r\n\r\n"),
4876 MockRead("Please Login\r\n"),
4877 MockRead(SYNCHRONOUS
, OK
),
4880 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4881 data_writes1
, arraysize(data_writes1
));
4882 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4883 data_writes2
, arraysize(data_writes2
));
4884 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4885 data_writes3
, arraysize(data_writes3
));
4886 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4887 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4888 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4890 TestCompletionCallback callback1
;
4892 scoped_ptr
<HttpTransaction
> trans(
4893 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4895 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4896 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4898 rv
= callback1
.WaitForResult();
4901 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4903 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4904 ASSERT_TRUE(response
!= NULL
);
4905 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4907 TestCompletionCallback callback2
;
4909 // Enter the wrong password.
4910 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4911 callback2
.callback());
4912 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4914 rv
= callback2
.WaitForResult();
4917 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4918 TestCompletionCallback callback3
;
4919 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4920 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4921 rv
= callback3
.WaitForResult();
4923 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4925 response
= trans
->GetResponseInfo();
4926 ASSERT_FALSE(response
== NULL
);
4927 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4929 TestCompletionCallback callback4
;
4931 // Now enter the right password.
4932 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4933 callback4
.callback());
4934 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4936 rv
= callback4
.WaitForResult();
4939 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4941 TestCompletionCallback callback5
;
4943 // One more roundtrip
4944 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4947 rv
= callback5
.WaitForResult();
4950 response
= trans
->GetResponseInfo();
4951 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4952 EXPECT_EQ(13, response
->headers
->GetContentLength());
4954 #endif // NTLM_PORTABLE
4956 // Test reading a server response which has only headers, and no body.
4957 // After some maximum number of bytes is consumed, the transaction should
4958 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4959 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4960 HttpRequestInfo request
;
4961 request
.method
= "GET";
4962 request
.url
= GURL("http://www.example.org/");
4963 request
.load_flags
= 0;
4965 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4966 scoped_ptr
<HttpTransaction
> trans(
4967 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4969 // Respond with 300 kb of headers (we should fail after 256 kb).
4970 std::string large_headers_string
;
4971 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4973 MockRead data_reads
[] = {
4974 MockRead("HTTP/1.0 200 OK\r\n"),
4975 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4976 MockRead("\r\nBODY"),
4977 MockRead(SYNCHRONOUS
, OK
),
4979 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4980 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4982 TestCompletionCallback callback
;
4984 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4985 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4987 rv
= callback
.WaitForResult();
4988 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4991 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4992 // establish tunnel.
4993 // http://code.google.com/p/chromium/issues/detail?id=3772
4994 TEST_P(HttpNetworkTransactionTest
,
4995 DontRecycleTransportSocketForSSLTunnel
) {
4996 HttpRequestInfo request
;
4997 request
.method
= "GET";
4998 request
.url
= GURL("https://www.example.org/");
4999 request
.load_flags
= 0;
5001 // Configure against proxy server "myproxy:70".
5002 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5004 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5006 scoped_ptr
<HttpTransaction
> trans(
5007 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5009 // Since we have proxy, should try to establish tunnel.
5010 MockWrite data_writes1
[] = {
5012 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5013 "Host: www.example.org\r\n"
5014 "Proxy-Connection: keep-alive\r\n\r\n"),
5017 // The proxy responds to the connect with a 404, using a persistent
5018 // connection. Usually a proxy would return 501 (not implemented),
5019 // or 200 (tunnel established).
5020 MockRead data_reads1
[] = {
5021 MockRead("HTTP/1.1 404 Not Found\r\n"),
5022 MockRead("Content-Length: 10\r\n\r\n"),
5023 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5026 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5027 data_writes1
, arraysize(data_writes1
));
5028 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5030 TestCompletionCallback callback1
;
5032 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5033 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5035 rv
= callback1
.WaitForResult();
5036 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5038 // Empty the current queue. This is necessary because idle sockets are
5039 // added to the connection pool asynchronously with a PostTask.
5040 base::MessageLoop::current()->RunUntilIdle();
5042 // We now check to make sure the TCPClientSocket was not added back to
5044 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5046 base::MessageLoop::current()->RunUntilIdle();
5047 // Make sure that the socket didn't get recycled after calling the destructor.
5048 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5051 // Make sure that we recycle a socket after reading all of the response body.
5052 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5053 HttpRequestInfo request
;
5054 request
.method
= "GET";
5055 request
.url
= GURL("http://www.example.org/");
5056 request
.load_flags
= 0;
5058 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5060 scoped_ptr
<HttpTransaction
> trans(
5061 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5063 MockRead data_reads
[] = {
5064 // A part of the response body is received with the response headers.
5065 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5066 // The rest of the response body is received in two parts.
5069 MockRead("junk"), // Should not be read!!
5070 MockRead(SYNCHRONOUS
, OK
),
5073 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5074 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5076 TestCompletionCallback callback
;
5078 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5079 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5081 rv
= callback
.WaitForResult();
5084 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5085 ASSERT_TRUE(response
!= NULL
);
5087 EXPECT_TRUE(response
->headers
.get() != NULL
);
5088 std::string status_line
= response
->headers
->GetStatusLine();
5089 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5091 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5093 std::string response_data
;
5094 rv
= ReadTransaction(trans
.get(), &response_data
);
5096 EXPECT_EQ("hello world", response_data
);
5098 // Empty the current queue. This is necessary because idle sockets are
5099 // added to the connection pool asynchronously with a PostTask.
5100 base::MessageLoop::current()->RunUntilIdle();
5102 // We now check to make sure the socket was added back to the pool.
5103 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5106 // Make sure that we recycle a SSL socket after reading all of the response
5108 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5109 HttpRequestInfo request
;
5110 request
.method
= "GET";
5111 request
.url
= GURL("https://www.example.org/");
5112 request
.load_flags
= 0;
5114 MockWrite data_writes
[] = {
5116 "GET / HTTP/1.1\r\n"
5117 "Host: www.example.org\r\n"
5118 "Connection: keep-alive\r\n\r\n"),
5121 MockRead data_reads
[] = {
5122 MockRead("HTTP/1.1 200 OK\r\n"),
5123 MockRead("Content-Length: 11\r\n\r\n"),
5124 MockRead("hello world"),
5125 MockRead(SYNCHRONOUS
, OK
),
5128 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5129 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5131 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5132 data_writes
, arraysize(data_writes
));
5133 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5135 TestCompletionCallback callback
;
5137 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5138 scoped_ptr
<HttpTransaction
> trans(
5139 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5141 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5143 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5144 EXPECT_EQ(OK
, callback
.WaitForResult());
5146 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5147 ASSERT_TRUE(response
!= NULL
);
5148 ASSERT_TRUE(response
->headers
.get() != NULL
);
5149 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5151 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5153 std::string response_data
;
5154 rv
= ReadTransaction(trans
.get(), &response_data
);
5156 EXPECT_EQ("hello world", response_data
);
5158 // Empty the current queue. This is necessary because idle sockets are
5159 // added to the connection pool asynchronously with a PostTask.
5160 base::MessageLoop::current()->RunUntilIdle();
5162 // We now check to make sure the socket was added back to the pool.
5163 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5166 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5167 // from the pool and make sure that we recover okay.
5168 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5169 HttpRequestInfo request
;
5170 request
.method
= "GET";
5171 request
.url
= GURL("https://www.example.org/");
5172 request
.load_flags
= 0;
5174 MockWrite data_writes
[] = {
5176 "GET / HTTP/1.1\r\n"
5177 "Host: www.example.org\r\n"
5178 "Connection: keep-alive\r\n\r\n"),
5180 "GET / HTTP/1.1\r\n"
5181 "Host: www.example.org\r\n"
5182 "Connection: keep-alive\r\n\r\n"),
5185 MockRead data_reads
[] = {
5186 MockRead("HTTP/1.1 200 OK\r\n"),
5187 MockRead("Content-Length: 11\r\n\r\n"),
5188 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5189 MockRead("hello world"),
5190 MockRead(ASYNC
, 0, 0) // EOF
5193 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5194 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5195 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5196 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5198 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5199 data_writes
, arraysize(data_writes
));
5200 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5201 data_writes
, arraysize(data_writes
));
5202 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5203 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5205 TestCompletionCallback callback
;
5207 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5208 scoped_ptr
<HttpTransaction
> trans(
5209 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5211 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5213 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5214 EXPECT_EQ(OK
, callback
.WaitForResult());
5216 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5217 ASSERT_TRUE(response
!= NULL
);
5218 ASSERT_TRUE(response
->headers
.get() != NULL
);
5219 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5221 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5223 std::string response_data
;
5224 rv
= ReadTransaction(trans
.get(), &response_data
);
5226 EXPECT_EQ("hello world", response_data
);
5228 // Empty the current queue. This is necessary because idle sockets are
5229 // added to the connection pool asynchronously with a PostTask.
5230 base::MessageLoop::current()->RunUntilIdle();
5232 // We now check to make sure the socket was added back to the pool.
5233 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5235 // Now start the second transaction, which should reuse the previous socket.
5237 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5239 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5241 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5242 EXPECT_EQ(OK
, callback
.WaitForResult());
5244 response
= trans
->GetResponseInfo();
5245 ASSERT_TRUE(response
!= NULL
);
5246 ASSERT_TRUE(response
->headers
.get() != NULL
);
5247 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5249 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5251 rv
= ReadTransaction(trans
.get(), &response_data
);
5253 EXPECT_EQ("hello world", response_data
);
5255 // Empty the current queue. This is necessary because idle sockets are
5256 // added to the connection pool asynchronously with a PostTask.
5257 base::MessageLoop::current()->RunUntilIdle();
5259 // We now check to make sure the socket was added back to the pool.
5260 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5263 // Make sure that we recycle a socket after a zero-length response.
5264 // http://crbug.com/9880
5265 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5266 HttpRequestInfo request
;
5267 request
.method
= "GET";
5269 "http://www.example.org/csi?v=3&s=web&action=&"
5270 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5271 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5272 "rt=prt.2642,ol.2649,xjs.2951");
5273 request
.load_flags
= 0;
5275 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5277 scoped_ptr
<HttpTransaction
> trans(
5278 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5280 MockRead data_reads
[] = {
5281 MockRead("HTTP/1.1 204 No Content\r\n"
5282 "Content-Length: 0\r\n"
5283 "Content-Type: text/html\r\n\r\n"),
5284 MockRead("junk"), // Should not be read!!
5285 MockRead(SYNCHRONOUS
, OK
),
5288 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5289 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5291 TestCompletionCallback callback
;
5293 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5294 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5296 rv
= callback
.WaitForResult();
5299 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5300 ASSERT_TRUE(response
!= NULL
);
5302 EXPECT_TRUE(response
->headers
.get() != NULL
);
5303 std::string status_line
= response
->headers
->GetStatusLine();
5304 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5306 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5308 std::string response_data
;
5309 rv
= ReadTransaction(trans
.get(), &response_data
);
5311 EXPECT_EQ("", response_data
);
5313 // Empty the current queue. This is necessary because idle sockets are
5314 // added to the connection pool asynchronously with a PostTask.
5315 base::MessageLoop::current()->RunUntilIdle();
5317 // We now check to make sure the socket was added back to the pool.
5318 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5321 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5322 ScopedVector
<UploadElementReader
> element_readers
;
5323 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5324 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5326 HttpRequestInfo request
[2];
5327 // Transaction 1: a GET request that succeeds. The socket is recycled
5329 request
[0].method
= "GET";
5330 request
[0].url
= GURL("http://www.google.com/");
5331 request
[0].load_flags
= 0;
5332 // Transaction 2: a POST request. Reuses the socket kept alive from
5333 // transaction 1. The first attempts fails when writing the POST data.
5334 // This causes the transaction to retry with a new socket. The second
5335 // attempt succeeds.
5336 request
[1].method
= "POST";
5337 request
[1].url
= GURL("http://www.google.com/login.cgi");
5338 request
[1].upload_data_stream
= &upload_data_stream
;
5339 request
[1].load_flags
= 0;
5341 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5343 // The first socket is used for transaction 1 and the first attempt of
5346 // The response of transaction 1.
5347 MockRead data_reads1
[] = {
5348 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5349 MockRead("hello world"),
5350 MockRead(SYNCHRONOUS
, OK
),
5352 // The mock write results of transaction 1 and the first attempt of
5354 MockWrite data_writes1
[] = {
5355 MockWrite(SYNCHRONOUS
, 64), // GET
5356 MockWrite(SYNCHRONOUS
, 93), // POST
5357 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5359 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5360 data_writes1
, arraysize(data_writes1
));
5362 // The second socket is used for the second attempt of transaction 2.
5364 // The response of transaction 2.
5365 MockRead data_reads2
[] = {
5366 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5367 MockRead("welcome"),
5368 MockRead(SYNCHRONOUS
, OK
),
5370 // The mock write results of the second attempt of transaction 2.
5371 MockWrite data_writes2
[] = {
5372 MockWrite(SYNCHRONOUS
, 93), // POST
5373 MockWrite(SYNCHRONOUS
, 3), // POST data
5375 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5376 data_writes2
, arraysize(data_writes2
));
5378 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5379 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5381 const char* const kExpectedResponseData
[] = {
5382 "hello world", "welcome"
5385 for (int i
= 0; i
< 2; ++i
) {
5386 scoped_ptr
<HttpTransaction
> trans(
5387 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5389 TestCompletionCallback callback
;
5391 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5392 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5394 rv
= callback
.WaitForResult();
5397 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5398 ASSERT_TRUE(response
!= NULL
);
5400 EXPECT_TRUE(response
->headers
.get() != NULL
);
5401 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5403 std::string response_data
;
5404 rv
= ReadTransaction(trans
.get(), &response_data
);
5406 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5410 // Test the request-challenge-retry sequence for basic auth when there is
5411 // an identity in the URL. The request should be sent as normal, but when
5412 // it fails the identity from the URL is used to answer the challenge.
5413 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5414 HttpRequestInfo request
;
5415 request
.method
= "GET";
5416 request
.url
= GURL("http://foo:b@r@www.example.org/");
5417 request
.load_flags
= LOAD_NORMAL
;
5419 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5420 scoped_ptr
<HttpTransaction
> trans(
5421 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5423 // The password contains an escaped character -- for this test to pass it
5424 // will need to be unescaped by HttpNetworkTransaction.
5425 EXPECT_EQ("b%40r", request
.url
.password());
5427 MockWrite data_writes1
[] = {
5429 "GET / HTTP/1.1\r\n"
5430 "Host: www.example.org\r\n"
5431 "Connection: keep-alive\r\n\r\n"),
5434 MockRead data_reads1
[] = {
5435 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5436 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5437 MockRead("Content-Length: 10\r\n\r\n"),
5438 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5441 // After the challenge above, the transaction will be restarted using the
5442 // identity from the url (foo, b@r) to answer the challenge.
5443 MockWrite data_writes2
[] = {
5445 "GET / HTTP/1.1\r\n"
5446 "Host: www.example.org\r\n"
5447 "Connection: keep-alive\r\n"
5448 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5451 MockRead data_reads2
[] = {
5452 MockRead("HTTP/1.0 200 OK\r\n"),
5453 MockRead("Content-Length: 100\r\n\r\n"),
5454 MockRead(SYNCHRONOUS
, OK
),
5457 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5458 data_writes1
, arraysize(data_writes1
));
5459 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5460 data_writes2
, arraysize(data_writes2
));
5461 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5462 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5464 TestCompletionCallback callback1
;
5465 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5466 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5467 rv
= callback1
.WaitForResult();
5469 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5471 TestCompletionCallback callback2
;
5472 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5473 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5474 rv
= callback2
.WaitForResult();
5476 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5478 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5479 ASSERT_TRUE(response
!= NULL
);
5481 // There is no challenge info, since the identity in URL worked.
5482 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5484 EXPECT_EQ(100, response
->headers
->GetContentLength());
5486 // Empty the current queue.
5487 base::MessageLoop::current()->RunUntilIdle();
5490 // Test the request-challenge-retry sequence for basic auth when there is an
5491 // incorrect identity in the URL. The identity from the URL should be used only
5493 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5494 HttpRequestInfo request
;
5495 request
.method
= "GET";
5496 // Note: the URL has a username:password in it. The password "baz" is
5497 // wrong (should be "bar").
5498 request
.url
= GURL("http://foo:baz@www.example.org/");
5500 request
.load_flags
= LOAD_NORMAL
;
5502 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5503 scoped_ptr
<HttpTransaction
> trans(
5504 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5506 MockWrite data_writes1
[] = {
5508 "GET / HTTP/1.1\r\n"
5509 "Host: www.example.org\r\n"
5510 "Connection: keep-alive\r\n\r\n"),
5513 MockRead data_reads1
[] = {
5514 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5515 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5516 MockRead("Content-Length: 10\r\n\r\n"),
5517 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5520 // After the challenge above, the transaction will be restarted using the
5521 // identity from the url (foo, baz) to answer the challenge.
5522 MockWrite data_writes2
[] = {
5524 "GET / HTTP/1.1\r\n"
5525 "Host: www.example.org\r\n"
5526 "Connection: keep-alive\r\n"
5527 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5530 MockRead data_reads2
[] = {
5531 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5532 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5533 MockRead("Content-Length: 10\r\n\r\n"),
5534 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5537 // After the challenge above, the transaction will be restarted using the
5538 // identity supplied by the user (foo, bar) to answer the challenge.
5539 MockWrite data_writes3
[] = {
5541 "GET / HTTP/1.1\r\n"
5542 "Host: www.example.org\r\n"
5543 "Connection: keep-alive\r\n"
5544 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5547 MockRead data_reads3
[] = {
5548 MockRead("HTTP/1.0 200 OK\r\n"),
5549 MockRead("Content-Length: 100\r\n\r\n"),
5550 MockRead(SYNCHRONOUS
, OK
),
5553 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5554 data_writes1
, arraysize(data_writes1
));
5555 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5556 data_writes2
, arraysize(data_writes2
));
5557 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5558 data_writes3
, arraysize(data_writes3
));
5559 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5560 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5561 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5563 TestCompletionCallback callback1
;
5565 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5566 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5568 rv
= callback1
.WaitForResult();
5571 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5572 TestCompletionCallback callback2
;
5573 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5574 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5575 rv
= callback2
.WaitForResult();
5577 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5579 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5580 ASSERT_TRUE(response
!= NULL
);
5581 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5583 TestCompletionCallback callback3
;
5584 rv
= trans
->RestartWithAuth(
5585 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5586 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5587 rv
= callback3
.WaitForResult();
5589 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5591 response
= trans
->GetResponseInfo();
5592 ASSERT_TRUE(response
!= NULL
);
5594 // There is no challenge info, since the identity worked.
5595 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5597 EXPECT_EQ(100, response
->headers
->GetContentLength());
5599 // Empty the current queue.
5600 base::MessageLoop::current()->RunUntilIdle();
5604 // Test the request-challenge-retry sequence for basic auth when there is a
5605 // correct identity in the URL, but its use is being suppressed. The identity
5606 // from the URL should never be used.
5607 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5608 HttpRequestInfo request
;
5609 request
.method
= "GET";
5610 request
.url
= GURL("http://foo:bar@www.example.org/");
5611 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5613 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5614 scoped_ptr
<HttpTransaction
> trans(
5615 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5617 MockWrite data_writes1
[] = {
5619 "GET / HTTP/1.1\r\n"
5620 "Host: www.example.org\r\n"
5621 "Connection: keep-alive\r\n\r\n"),
5624 MockRead data_reads1
[] = {
5625 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5626 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5627 MockRead("Content-Length: 10\r\n\r\n"),
5628 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5631 // After the challenge above, the transaction will be restarted using the
5632 // identity supplied by the user, not the one in the URL, to answer the
5634 MockWrite data_writes3
[] = {
5636 "GET / HTTP/1.1\r\n"
5637 "Host: www.example.org\r\n"
5638 "Connection: keep-alive\r\n"
5639 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5642 MockRead data_reads3
[] = {
5643 MockRead("HTTP/1.0 200 OK\r\n"),
5644 MockRead("Content-Length: 100\r\n\r\n"),
5645 MockRead(SYNCHRONOUS
, OK
),
5648 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5649 data_writes1
, arraysize(data_writes1
));
5650 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5651 data_writes3
, arraysize(data_writes3
));
5652 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5653 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5655 TestCompletionCallback callback1
;
5656 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5657 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5658 rv
= callback1
.WaitForResult();
5660 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5662 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5663 ASSERT_TRUE(response
!= NULL
);
5664 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5666 TestCompletionCallback callback3
;
5667 rv
= trans
->RestartWithAuth(
5668 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5669 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5670 rv
= callback3
.WaitForResult();
5672 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5674 response
= trans
->GetResponseInfo();
5675 ASSERT_TRUE(response
!= NULL
);
5677 // There is no challenge info, since the identity worked.
5678 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5679 EXPECT_EQ(100, response
->headers
->GetContentLength());
5681 // Empty the current queue.
5682 base::MessageLoop::current()->RunUntilIdle();
5685 // Test that previously tried username/passwords for a realm get re-used.
5686 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5687 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5689 // Transaction 1: authenticate (foo, bar) on MyRealm1
5691 HttpRequestInfo request
;
5692 request
.method
= "GET";
5693 request
.url
= GURL("http://www.example.org/x/y/z");
5694 request
.load_flags
= 0;
5696 scoped_ptr
<HttpTransaction
> trans(
5697 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5699 MockWrite data_writes1
[] = {
5701 "GET /x/y/z HTTP/1.1\r\n"
5702 "Host: www.example.org\r\n"
5703 "Connection: keep-alive\r\n\r\n"),
5706 MockRead data_reads1
[] = {
5707 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5708 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5709 MockRead("Content-Length: 10000\r\n\r\n"),
5710 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5713 // Resend with authorization (username=foo, password=bar)
5714 MockWrite data_writes2
[] = {
5716 "GET /x/y/z HTTP/1.1\r\n"
5717 "Host: www.example.org\r\n"
5718 "Connection: keep-alive\r\n"
5719 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5722 // Sever accepts the authorization.
5723 MockRead data_reads2
[] = {
5724 MockRead("HTTP/1.0 200 OK\r\n"),
5725 MockRead("Content-Length: 100\r\n\r\n"),
5726 MockRead(SYNCHRONOUS
, OK
),
5729 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5730 data_writes1
, arraysize(data_writes1
));
5731 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5732 data_writes2
, arraysize(data_writes2
));
5733 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5734 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5736 TestCompletionCallback callback1
;
5738 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5739 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5741 rv
= callback1
.WaitForResult();
5744 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5745 ASSERT_TRUE(response
!= NULL
);
5746 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5748 TestCompletionCallback callback2
;
5750 rv
= trans
->RestartWithAuth(
5751 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5752 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5754 rv
= callback2
.WaitForResult();
5757 response
= trans
->GetResponseInfo();
5758 ASSERT_TRUE(response
!= NULL
);
5759 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5760 EXPECT_EQ(100, response
->headers
->GetContentLength());
5763 // ------------------------------------------------------------------------
5765 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5767 HttpRequestInfo request
;
5768 request
.method
= "GET";
5769 // Note that Transaction 1 was at /x/y/z, so this is in the same
5770 // protection space as MyRealm1.
5771 request
.url
= GURL("http://www.example.org/x/y/a/b");
5772 request
.load_flags
= 0;
5774 scoped_ptr
<HttpTransaction
> trans(
5775 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5777 MockWrite data_writes1
[] = {
5779 "GET /x/y/a/b HTTP/1.1\r\n"
5780 "Host: www.example.org\r\n"
5781 "Connection: keep-alive\r\n"
5782 // Send preemptive authorization for MyRealm1
5783 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5786 // The server didn't like the preemptive authorization, and
5787 // challenges us for a different realm (MyRealm2).
5788 MockRead data_reads1
[] = {
5789 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5790 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5791 MockRead("Content-Length: 10000\r\n\r\n"),
5792 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5795 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5796 MockWrite data_writes2
[] = {
5798 "GET /x/y/a/b HTTP/1.1\r\n"
5799 "Host: www.example.org\r\n"
5800 "Connection: keep-alive\r\n"
5801 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5804 // Sever accepts the authorization.
5805 MockRead data_reads2
[] = {
5806 MockRead("HTTP/1.0 200 OK\r\n"),
5807 MockRead("Content-Length: 100\r\n\r\n"),
5808 MockRead(SYNCHRONOUS
, OK
),
5811 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5812 data_writes1
, arraysize(data_writes1
));
5813 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5814 data_writes2
, arraysize(data_writes2
));
5815 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5816 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5818 TestCompletionCallback callback1
;
5820 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5821 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5823 rv
= callback1
.WaitForResult();
5826 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5827 ASSERT_TRUE(response
!= NULL
);
5828 ASSERT_TRUE(response
->auth_challenge
.get());
5829 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5830 EXPECT_EQ("www.example.org:80",
5831 response
->auth_challenge
->challenger
.ToString());
5832 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5833 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5835 TestCompletionCallback callback2
;
5837 rv
= trans
->RestartWithAuth(
5838 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5839 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5841 rv
= callback2
.WaitForResult();
5844 response
= trans
->GetResponseInfo();
5845 ASSERT_TRUE(response
!= NULL
);
5846 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5847 EXPECT_EQ(100, response
->headers
->GetContentLength());
5850 // ------------------------------------------------------------------------
5852 // Transaction 3: Resend a request in MyRealm's protection space --
5853 // succeed with preemptive authorization.
5855 HttpRequestInfo request
;
5856 request
.method
= "GET";
5857 request
.url
= GURL("http://www.example.org/x/y/z2");
5858 request
.load_flags
= 0;
5860 scoped_ptr
<HttpTransaction
> trans(
5861 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5863 MockWrite data_writes1
[] = {
5865 "GET /x/y/z2 HTTP/1.1\r\n"
5866 "Host: www.example.org\r\n"
5867 "Connection: keep-alive\r\n"
5868 // The authorization for MyRealm1 gets sent preemptively
5869 // (since the url is in the same protection space)
5870 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5873 // Sever accepts the preemptive authorization
5874 MockRead data_reads1
[] = {
5875 MockRead("HTTP/1.0 200 OK\r\n"),
5876 MockRead("Content-Length: 100\r\n\r\n"),
5877 MockRead(SYNCHRONOUS
, OK
),
5880 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5881 data_writes1
, arraysize(data_writes1
));
5882 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5884 TestCompletionCallback callback1
;
5886 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5887 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5889 rv
= callback1
.WaitForResult();
5892 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5893 ASSERT_TRUE(response
!= NULL
);
5895 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5896 EXPECT_EQ(100, response
->headers
->GetContentLength());
5899 // ------------------------------------------------------------------------
5901 // Transaction 4: request another URL in MyRealm (however the
5902 // url is not known to belong to the protection space, so no pre-auth).
5904 HttpRequestInfo request
;
5905 request
.method
= "GET";
5906 request
.url
= GURL("http://www.example.org/x/1");
5907 request
.load_flags
= 0;
5909 scoped_ptr
<HttpTransaction
> trans(
5910 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5912 MockWrite data_writes1
[] = {
5914 "GET /x/1 HTTP/1.1\r\n"
5915 "Host: www.example.org\r\n"
5916 "Connection: keep-alive\r\n\r\n"),
5919 MockRead data_reads1
[] = {
5920 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5921 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5922 MockRead("Content-Length: 10000\r\n\r\n"),
5923 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5926 // Resend with authorization from MyRealm's cache.
5927 MockWrite data_writes2
[] = {
5929 "GET /x/1 HTTP/1.1\r\n"
5930 "Host: www.example.org\r\n"
5931 "Connection: keep-alive\r\n"
5932 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5935 // Sever accepts the authorization.
5936 MockRead data_reads2
[] = {
5937 MockRead("HTTP/1.0 200 OK\r\n"),
5938 MockRead("Content-Length: 100\r\n\r\n"),
5939 MockRead(SYNCHRONOUS
, OK
),
5942 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5943 data_writes1
, arraysize(data_writes1
));
5944 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5945 data_writes2
, arraysize(data_writes2
));
5946 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5947 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5949 TestCompletionCallback callback1
;
5951 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5952 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5954 rv
= callback1
.WaitForResult();
5957 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5958 TestCompletionCallback callback2
;
5959 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5960 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5961 rv
= callback2
.WaitForResult();
5963 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5965 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5966 ASSERT_TRUE(response
!= NULL
);
5967 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5968 EXPECT_EQ(100, response
->headers
->GetContentLength());
5971 // ------------------------------------------------------------------------
5973 // Transaction 5: request a URL in MyRealm, but the server rejects the
5974 // cached identity. Should invalidate and re-prompt.
5976 HttpRequestInfo request
;
5977 request
.method
= "GET";
5978 request
.url
= GURL("http://www.example.org/p/q/t");
5979 request
.load_flags
= 0;
5981 scoped_ptr
<HttpTransaction
> trans(
5982 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5984 MockWrite data_writes1
[] = {
5986 "GET /p/q/t HTTP/1.1\r\n"
5987 "Host: www.example.org\r\n"
5988 "Connection: keep-alive\r\n\r\n"),
5991 MockRead data_reads1
[] = {
5992 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5993 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5994 MockRead("Content-Length: 10000\r\n\r\n"),
5995 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5998 // Resend with authorization from cache for MyRealm.
5999 MockWrite data_writes2
[] = {
6001 "GET /p/q/t HTTP/1.1\r\n"
6002 "Host: www.example.org\r\n"
6003 "Connection: keep-alive\r\n"
6004 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6007 // Sever rejects the authorization.
6008 MockRead data_reads2
[] = {
6009 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6010 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6011 MockRead("Content-Length: 10000\r\n\r\n"),
6012 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6015 // At this point we should prompt for new credentials for MyRealm.
6016 // Restart with username=foo3, password=foo4.
6017 MockWrite data_writes3
[] = {
6019 "GET /p/q/t HTTP/1.1\r\n"
6020 "Host: www.example.org\r\n"
6021 "Connection: keep-alive\r\n"
6022 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6025 // Sever accepts the authorization.
6026 MockRead data_reads3
[] = {
6027 MockRead("HTTP/1.0 200 OK\r\n"),
6028 MockRead("Content-Length: 100\r\n\r\n"),
6029 MockRead(SYNCHRONOUS
, OK
),
6032 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6033 data_writes1
, arraysize(data_writes1
));
6034 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6035 data_writes2
, arraysize(data_writes2
));
6036 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6037 data_writes3
, arraysize(data_writes3
));
6038 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6039 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6040 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6042 TestCompletionCallback callback1
;
6044 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6047 rv
= callback1
.WaitForResult();
6050 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6051 TestCompletionCallback callback2
;
6052 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6053 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6054 rv
= callback2
.WaitForResult();
6056 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6058 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6059 ASSERT_TRUE(response
!= NULL
);
6060 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6062 TestCompletionCallback callback3
;
6064 rv
= trans
->RestartWithAuth(
6065 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6066 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6068 rv
= callback3
.WaitForResult();
6071 response
= trans
->GetResponseInfo();
6072 ASSERT_TRUE(response
!= NULL
);
6073 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6074 EXPECT_EQ(100, response
->headers
->GetContentLength());
6078 // Tests that nonce count increments when multiple auth attempts
6079 // are started with the same nonce.
6080 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6081 HttpAuthHandlerDigest::Factory
* digest_factory
=
6082 new HttpAuthHandlerDigest::Factory();
6083 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6084 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6085 digest_factory
->set_nonce_generator(nonce_generator
);
6086 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6087 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6089 // Transaction 1: authenticate (foo, bar) on MyRealm1
6091 HttpRequestInfo request
;
6092 request
.method
= "GET";
6093 request
.url
= GURL("http://www.example.org/x/y/z");
6094 request
.load_flags
= 0;
6096 scoped_ptr
<HttpTransaction
> trans(
6097 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6099 MockWrite data_writes1
[] = {
6101 "GET /x/y/z HTTP/1.1\r\n"
6102 "Host: www.example.org\r\n"
6103 "Connection: keep-alive\r\n\r\n"),
6106 MockRead data_reads1
[] = {
6107 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6108 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6109 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6110 MockRead(SYNCHRONOUS
, OK
),
6113 // Resend with authorization (username=foo, password=bar)
6114 MockWrite data_writes2
[] = {
6116 "GET /x/y/z HTTP/1.1\r\n"
6117 "Host: www.example.org\r\n"
6118 "Connection: keep-alive\r\n"
6119 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6120 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6121 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6122 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6125 // Sever accepts the authorization.
6126 MockRead data_reads2
[] = {
6127 MockRead("HTTP/1.0 200 OK\r\n"),
6128 MockRead(SYNCHRONOUS
, OK
),
6131 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6132 data_writes1
, arraysize(data_writes1
));
6133 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6134 data_writes2
, arraysize(data_writes2
));
6135 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6136 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6138 TestCompletionCallback callback1
;
6140 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6141 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6143 rv
= callback1
.WaitForResult();
6146 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6147 ASSERT_TRUE(response
!= NULL
);
6148 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6150 TestCompletionCallback callback2
;
6152 rv
= trans
->RestartWithAuth(
6153 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6154 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6156 rv
= callback2
.WaitForResult();
6159 response
= trans
->GetResponseInfo();
6160 ASSERT_TRUE(response
!= NULL
);
6161 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6164 // ------------------------------------------------------------------------
6166 // Transaction 2: Request another resource in digestive's protection space.
6167 // This will preemptively add an Authorization header which should have an
6168 // "nc" value of 2 (as compared to 1 in the first use.
6170 HttpRequestInfo request
;
6171 request
.method
= "GET";
6172 // Note that Transaction 1 was at /x/y/z, so this is in the same
6173 // protection space as digest.
6174 request
.url
= GURL("http://www.example.org/x/y/a/b");
6175 request
.load_flags
= 0;
6177 scoped_ptr
<HttpTransaction
> trans(
6178 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6180 MockWrite data_writes1
[] = {
6182 "GET /x/y/a/b HTTP/1.1\r\n"
6183 "Host: www.example.org\r\n"
6184 "Connection: keep-alive\r\n"
6185 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6186 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6187 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6188 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6191 // Sever accepts the authorization.
6192 MockRead data_reads1
[] = {
6193 MockRead("HTTP/1.0 200 OK\r\n"),
6194 MockRead("Content-Length: 100\r\n\r\n"),
6195 MockRead(SYNCHRONOUS
, OK
),
6198 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6199 data_writes1
, arraysize(data_writes1
));
6200 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6202 TestCompletionCallback callback1
;
6204 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6205 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6207 rv
= callback1
.WaitForResult();
6210 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6211 ASSERT_TRUE(response
!= NULL
);
6212 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6216 // Test the ResetStateForRestart() private method.
6217 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6218 // Create a transaction (the dependencies aren't important).
6219 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6220 scoped_ptr
<HttpNetworkTransaction
> trans(
6221 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6223 // Setup some state (which we expect ResetStateForRestart() will clear).
6224 trans
->read_buf_
= new IOBuffer(15);
6225 trans
->read_buf_len_
= 15;
6226 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6228 // Setup state in response_
6229 HttpResponseInfo
* response
= &trans
->response_
;
6230 response
->auth_challenge
= new AuthChallengeInfo();
6231 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6232 response
->response_time
= base::Time::Now();
6233 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6235 { // Setup state for response_.vary_data
6236 HttpRequestInfo request
;
6237 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6238 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6239 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6240 request
.extra_headers
.SetHeader("Foo", "1");
6241 request
.extra_headers
.SetHeader("bar", "23");
6242 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6245 // Cause the above state to be reset.
6246 trans
->ResetStateForRestart();
6248 // Verify that the state that needed to be reset, has been reset.
6249 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6250 EXPECT_EQ(0, trans
->read_buf_len_
);
6251 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6252 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6253 EXPECT_TRUE(response
->headers
.get() == NULL
);
6254 EXPECT_FALSE(response
->was_cached
);
6255 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6256 EXPECT_FALSE(response
->vary_data
.is_valid());
6259 // Test HTTPS connections to a site with a bad certificate
6260 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6261 HttpRequestInfo request
;
6262 request
.method
= "GET";
6263 request
.url
= GURL("https://www.example.org/");
6264 request
.load_flags
= 0;
6266 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6267 scoped_ptr
<HttpTransaction
> trans(
6268 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6270 MockWrite data_writes
[] = {
6272 "GET / HTTP/1.1\r\n"
6273 "Host: www.example.org\r\n"
6274 "Connection: keep-alive\r\n\r\n"),
6277 MockRead data_reads
[] = {
6278 MockRead("HTTP/1.0 200 OK\r\n"),
6279 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6280 MockRead("Content-Length: 100\r\n\r\n"),
6281 MockRead(SYNCHRONOUS
, OK
),
6284 StaticSocketDataProvider ssl_bad_certificate
;
6285 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6286 data_writes
, arraysize(data_writes
));
6287 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6288 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6290 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6291 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6292 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6293 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6295 TestCompletionCallback callback
;
6297 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6298 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6300 rv
= callback
.WaitForResult();
6301 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6303 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6304 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6306 rv
= callback
.WaitForResult();
6309 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6311 ASSERT_TRUE(response
!= NULL
);
6312 EXPECT_EQ(100, response
->headers
->GetContentLength());
6315 // Test HTTPS connections to a site with a bad certificate, going through a
6317 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6318 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6320 HttpRequestInfo request
;
6321 request
.method
= "GET";
6322 request
.url
= GURL("https://www.example.org/");
6323 request
.load_flags
= 0;
6325 MockWrite proxy_writes
[] = {
6327 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6328 "Host: www.example.org\r\n"
6329 "Proxy-Connection: keep-alive\r\n\r\n"),
6332 MockRead proxy_reads
[] = {
6333 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6334 MockRead(SYNCHRONOUS
, OK
)
6337 MockWrite data_writes
[] = {
6339 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6340 "Host: www.example.org\r\n"
6341 "Proxy-Connection: keep-alive\r\n\r\n"),
6343 "GET / HTTP/1.1\r\n"
6344 "Host: www.example.org\r\n"
6345 "Connection: keep-alive\r\n\r\n"),
6348 MockRead data_reads
[] = {
6349 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6350 MockRead("HTTP/1.0 200 OK\r\n"),
6351 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6352 MockRead("Content-Length: 100\r\n\r\n"),
6353 MockRead(SYNCHRONOUS
, OK
),
6356 StaticSocketDataProvider
ssl_bad_certificate(
6357 proxy_reads
, arraysize(proxy_reads
),
6358 proxy_writes
, arraysize(proxy_writes
));
6359 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6360 data_writes
, arraysize(data_writes
));
6361 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6362 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6364 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6365 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6366 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6367 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6369 TestCompletionCallback callback
;
6371 for (int i
= 0; i
< 2; i
++) {
6372 session_deps_
.socket_factory
->ResetNextMockIndexes();
6374 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6375 scoped_ptr
<HttpTransaction
> trans(
6376 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6378 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6379 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6381 rv
= callback
.WaitForResult();
6382 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6384 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6385 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6387 rv
= callback
.WaitForResult();
6390 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6392 ASSERT_TRUE(response
!= NULL
);
6393 EXPECT_EQ(100, response
->headers
->GetContentLength());
6398 // Test HTTPS connections to a site, going through an HTTPS proxy
6399 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6400 session_deps_
.proxy_service
.reset(
6401 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6403 session_deps_
.net_log
= &net_log
;
6405 HttpRequestInfo request
;
6406 request
.method
= "GET";
6407 request
.url
= GURL("https://www.example.org/");
6408 request
.load_flags
= 0;
6410 MockWrite data_writes
[] = {
6412 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6413 "Host: www.example.org\r\n"
6414 "Proxy-Connection: keep-alive\r\n\r\n"),
6416 "GET / HTTP/1.1\r\n"
6417 "Host: www.example.org\r\n"
6418 "Connection: keep-alive\r\n\r\n"),
6421 MockRead data_reads
[] = {
6422 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6423 MockRead("HTTP/1.1 200 OK\r\n"),
6424 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6425 MockRead("Content-Length: 100\r\n\r\n"),
6426 MockRead(SYNCHRONOUS
, OK
),
6429 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6430 data_writes
, arraysize(data_writes
));
6431 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6432 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6434 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6435 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6436 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6438 TestCompletionCallback callback
;
6440 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6441 scoped_ptr
<HttpTransaction
> trans(
6442 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6444 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6445 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6447 rv
= callback
.WaitForResult();
6449 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6451 ASSERT_TRUE(response
!= NULL
);
6453 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6454 EXPECT_EQ(200, response
->headers
->response_code());
6455 EXPECT_EQ(100, response
->headers
->GetContentLength());
6456 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6458 LoadTimingInfo load_timing_info
;
6459 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6460 TestLoadTimingNotReusedWithPac(load_timing_info
,
6461 CONNECT_TIMING_HAS_SSL_TIMES
);
6464 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6465 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6466 session_deps_
.proxy_service
.reset(
6467 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6469 session_deps_
.net_log
= &net_log
;
6471 HttpRequestInfo request
;
6472 request
.method
= "GET";
6473 request
.url
= GURL("https://www.example.org/");
6474 request
.load_flags
= 0;
6476 MockWrite data_writes
[] = {
6478 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6479 "Host: www.example.org\r\n"
6480 "Proxy-Connection: keep-alive\r\n\r\n"),
6483 MockRead data_reads
[] = {
6484 MockRead("HTTP/1.1 302 Redirect\r\n"),
6485 MockRead("Location: http://login.example.com/\r\n"),
6486 MockRead("Content-Length: 0\r\n\r\n"),
6487 MockRead(SYNCHRONOUS
, OK
),
6490 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6491 data_writes
, arraysize(data_writes
));
6492 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6494 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6495 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6497 TestCompletionCallback callback
;
6499 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6500 scoped_ptr
<HttpTransaction
> trans(
6501 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6503 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6504 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6506 rv
= callback
.WaitForResult();
6508 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6510 ASSERT_TRUE(response
!= NULL
);
6512 EXPECT_EQ(302, response
->headers
->response_code());
6514 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6515 EXPECT_EQ("http://login.example.com/", url
);
6517 // In the case of redirects from proxies, HttpNetworkTransaction returns
6518 // timing for the proxy connection instead of the connection to the host,
6519 // and no send / receive times.
6520 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6521 LoadTimingInfo load_timing_info
;
6522 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6524 EXPECT_FALSE(load_timing_info
.socket_reused
);
6525 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6527 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6528 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6529 load_timing_info
.proxy_resolve_end
);
6530 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6531 load_timing_info
.connect_timing
.connect_start
);
6532 ExpectConnectTimingHasTimes(
6533 load_timing_info
.connect_timing
,
6534 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6536 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6537 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6538 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6541 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6542 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6543 session_deps_
.proxy_service
.reset(
6544 ProxyService::CreateFixed("https://proxy:70"));
6546 HttpRequestInfo request
;
6547 request
.method
= "GET";
6548 request
.url
= GURL("https://www.example.org/");
6549 request
.load_flags
= 0;
6551 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6552 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6553 scoped_ptr
<SpdyFrame
> goaway(
6554 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6555 MockWrite data_writes
[] = {
6556 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6557 CreateMockWrite(*goaway
.get(), 2, SYNCHRONOUS
),
6560 static const char* const kExtraHeaders
[] = {
6562 "http://login.example.com/",
6564 scoped_ptr
<SpdyFrame
> resp(
6565 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6566 arraysize(kExtraHeaders
)/2, 1));
6567 MockRead data_reads
[] = {
6568 CreateMockRead(*resp
.get(), 1), MockRead(ASYNC
, 0, 3), // EOF
6571 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6572 arraysize(data_writes
));
6573 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6574 proxy_ssl
.SetNextProto(GetParam());
6576 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6577 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6579 TestCompletionCallback callback
;
6581 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6582 scoped_ptr
<HttpTransaction
> trans(
6583 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6585 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6586 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6588 rv
= callback
.WaitForResult();
6590 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6592 ASSERT_TRUE(response
!= NULL
);
6594 EXPECT_EQ(302, response
->headers
->response_code());
6596 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6597 EXPECT_EQ("http://login.example.com/", url
);
6600 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6601 TEST_P(HttpNetworkTransactionTest
,
6602 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6603 session_deps_
.proxy_service
.reset(
6604 ProxyService::CreateFixed("https://proxy:70"));
6606 HttpRequestInfo request
;
6607 request
.method
= "GET";
6608 request
.url
= GURL("https://www.example.org/");
6609 request
.load_flags
= 0;
6611 MockWrite data_writes
[] = {
6613 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6614 "Host: www.example.org\r\n"
6615 "Proxy-Connection: keep-alive\r\n\r\n"),
6618 MockRead data_reads
[] = {
6619 MockRead("HTTP/1.1 404 Not Found\r\n"),
6620 MockRead("Content-Length: 23\r\n\r\n"),
6621 MockRead("The host does not exist"),
6622 MockRead(SYNCHRONOUS
, OK
),
6625 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6626 data_writes
, arraysize(data_writes
));
6627 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6629 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6630 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6632 TestCompletionCallback callback
;
6634 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6635 scoped_ptr
<HttpTransaction
> trans(
6636 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6638 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6641 rv
= callback
.WaitForResult();
6642 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6644 // TODO(ttuttle): Anything else to check here?
6647 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6648 TEST_P(HttpNetworkTransactionTest
,
6649 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6650 session_deps_
.proxy_service
.reset(
6651 ProxyService::CreateFixed("https://proxy:70"));
6653 HttpRequestInfo request
;
6654 request
.method
= "GET";
6655 request
.url
= GURL("https://www.example.org/");
6656 request
.load_flags
= 0;
6658 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6659 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6660 scoped_ptr
<SpdyFrame
> rst(
6661 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6662 MockWrite data_writes
[] = {
6663 CreateMockWrite(*conn
.get(), 0), CreateMockWrite(*rst
.get(), 3),
6666 static const char* const kExtraHeaders
[] = {
6668 "http://login.example.com/",
6670 scoped_ptr
<SpdyFrame
> resp(
6671 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6672 arraysize(kExtraHeaders
)/2, 1));
6673 scoped_ptr
<SpdyFrame
> body(
6674 spdy_util_
.ConstructSpdyBodyFrame(
6675 1, "The host does not exist", 23, true));
6676 MockRead data_reads
[] = {
6677 CreateMockRead(*resp
.get(), 1),
6678 CreateMockRead(*body
.get(), 2),
6679 MockRead(ASYNC
, 0, 4), // EOF
6682 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6683 arraysize(data_writes
));
6684 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6685 proxy_ssl
.SetNextProto(GetParam());
6687 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6688 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6690 TestCompletionCallback callback
;
6692 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6693 scoped_ptr
<HttpTransaction
> trans(
6694 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6696 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6699 rv
= callback
.WaitForResult();
6700 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6702 // TODO(ttuttle): Anything else to check here?
6705 // Test the request-challenge-retry sequence for basic auth, through
6706 // a SPDY proxy over a single SPDY session.
6707 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6708 HttpRequestInfo request
;
6709 request
.method
= "GET";
6710 request
.url
= GURL("https://www.example.org/");
6711 // when the no authentication data flag is set.
6712 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6714 // Configure against https proxy server "myproxy:70".
6715 session_deps_
.proxy_service
.reset(
6716 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6717 BoundTestNetLog log
;
6718 session_deps_
.net_log
= log
.bound().net_log();
6719 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6721 // Since we have proxy, should try to establish tunnel.
6722 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6723 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6724 scoped_ptr
<SpdyFrame
> rst(
6725 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6727 // After calling trans->RestartWithAuth(), this is the request we should
6728 // be issuing -- the final header line contains the credentials.
6729 const char* const kAuthCredentials
[] = {
6730 "proxy-authorization", "Basic Zm9vOmJhcg==",
6732 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6733 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6734 HostPortPair("www.example.org", 443)));
6735 // fetch https://www.example.org/ via HTTP
6737 "GET / HTTP/1.1\r\n"
6738 "Host: www.example.org\r\n"
6739 "Connection: keep-alive\r\n\r\n";
6740 scoped_ptr
<SpdyFrame
> wrapped_get(
6741 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6743 MockWrite spdy_writes
[] = {
6744 CreateMockWrite(*req
, 0, ASYNC
),
6745 CreateMockWrite(*rst
, 2, ASYNC
),
6746 CreateMockWrite(*connect2
, 3),
6747 CreateMockWrite(*wrapped_get
, 5),
6750 // The proxy responds to the connect with a 407, using a persistent
6752 const char kAuthStatus
[] = "407";
6753 const char* const kAuthChallenge
[] = {
6754 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6756 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6757 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6759 scoped_ptr
<SpdyFrame
> conn_resp(
6760 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6761 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6762 "Content-Length: 5\r\n\r\n";
6764 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6765 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6766 scoped_ptr
<SpdyFrame
> wrapped_body(
6767 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6768 MockRead spdy_reads
[] = {
6769 CreateMockRead(*conn_auth_resp
, 1, ASYNC
),
6770 CreateMockRead(*conn_resp
, 4, ASYNC
),
6771 CreateMockRead(*wrapped_get_resp
, 6, ASYNC
),
6772 CreateMockRead(*wrapped_body
, 7, ASYNC
),
6773 MockRead(ASYNC
, OK
, 8), // EOF. May or may not be read.
6776 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6777 arraysize(spdy_writes
));
6778 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6779 // Negotiate SPDY to the proxy
6780 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6781 proxy
.SetNextProto(GetParam());
6782 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6783 // Vanilla SSL to the server
6784 SSLSocketDataProvider
server(ASYNC
, OK
);
6785 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6787 TestCompletionCallback callback1
;
6789 scoped_ptr
<HttpTransaction
> trans(
6790 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6792 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6793 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6795 rv
= callback1
.WaitForResult();
6797 TestNetLogEntry::List entries
;
6798 log
.GetEntries(&entries
);
6799 size_t pos
= ExpectLogContainsSomewhere(
6800 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6801 NetLog::PHASE_NONE
);
6802 ExpectLogContainsSomewhere(
6804 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6805 NetLog::PHASE_NONE
);
6807 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6808 ASSERT_TRUE(response
!= NULL
);
6809 ASSERT_FALSE(response
->headers
.get() == NULL
);
6810 EXPECT_EQ(407, response
->headers
->response_code());
6811 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6812 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6813 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6815 TestCompletionCallback callback2
;
6817 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6818 callback2
.callback());
6819 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6821 rv
= callback2
.WaitForResult();
6824 response
= trans
->GetResponseInfo();
6825 ASSERT_TRUE(response
!= NULL
);
6827 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6828 EXPECT_EQ(200, response
->headers
->response_code());
6829 EXPECT_EQ(5, response
->headers
->GetContentLength());
6830 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6832 // The password prompt info should not be set.
6833 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6835 LoadTimingInfo load_timing_info
;
6836 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6837 TestLoadTimingNotReusedWithPac(load_timing_info
,
6838 CONNECT_TIMING_HAS_SSL_TIMES
);
6841 session
->CloseAllConnections();
6844 // Test that an explicitly trusted SPDY proxy can push a resource from an
6845 // origin that is different from that of its associated resource.
6846 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6847 HttpRequestInfo request
;
6848 HttpRequestInfo push_request
;
6850 request
.method
= "GET";
6851 request
.url
= GURL("http://www.example.org/");
6852 push_request
.method
= "GET";
6853 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6855 // Configure against https proxy server "myproxy:70".
6856 session_deps_
.proxy_service
.reset(
6857 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6858 BoundTestNetLog log
;
6859 session_deps_
.net_log
= log
.bound().net_log();
6861 // Enable cross-origin push.
6862 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6864 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6866 scoped_ptr
<SpdyFrame
> stream1_syn(
6867 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6869 MockWrite spdy_writes
[] = {
6870 CreateMockWrite(*stream1_syn
, 0, ASYNC
),
6873 scoped_ptr
<SpdyFrame
>
6874 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6876 scoped_ptr
<SpdyFrame
>
6877 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6879 scoped_ptr
<SpdyFrame
>
6880 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6884 "http://www.another-origin.com/foo.dat"));
6885 const char kPushedData
[] = "pushed";
6886 scoped_ptr
<SpdyFrame
> stream2_body(
6887 spdy_util_
.ConstructSpdyBodyFrame(
6888 2, kPushedData
, strlen(kPushedData
), true));
6890 MockRead spdy_reads
[] = {
6891 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6892 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6893 CreateMockRead(*stream1_body
, 3, ASYNC
),
6894 CreateMockRead(*stream2_body
, 4, ASYNC
),
6895 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
6898 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6899 arraysize(spdy_writes
));
6900 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6901 // Negotiate SPDY to the proxy
6902 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6903 proxy
.SetNextProto(GetParam());
6904 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6906 scoped_ptr
<HttpTransaction
> trans(
6907 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6908 TestCompletionCallback callback
;
6909 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6910 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6912 rv
= callback
.WaitForResult();
6914 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6916 scoped_ptr
<HttpTransaction
> push_trans(
6917 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6918 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6919 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6921 rv
= callback
.WaitForResult();
6923 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6925 ASSERT_TRUE(response
!= NULL
);
6926 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6928 EXPECT_EQ(200, response
->headers
->response_code());
6929 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6931 std::string response_data
;
6932 rv
= ReadTransaction(trans
.get(), &response_data
);
6934 EXPECT_EQ("hello!", response_data
);
6936 LoadTimingInfo load_timing_info
;
6937 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6938 TestLoadTimingNotReusedWithPac(load_timing_info
,
6939 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6941 // Verify the pushed stream.
6942 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6943 EXPECT_EQ(200, push_response
->headers
->response_code());
6945 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6947 EXPECT_EQ("pushed", response_data
);
6949 LoadTimingInfo push_load_timing_info
;
6950 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6951 TestLoadTimingReusedWithPac(push_load_timing_info
);
6952 // The transactions should share a socket ID, despite being for different
6954 EXPECT_EQ(load_timing_info
.socket_log_id
,
6955 push_load_timing_info
.socket_log_id
);
6959 session
->CloseAllConnections();
6962 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6963 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6964 HttpRequestInfo request
;
6966 request
.method
= "GET";
6967 request
.url
= GURL("http://www.example.org/");
6969 // Configure against https proxy server "myproxy:70".
6970 session_deps_
.proxy_service
.reset(
6971 ProxyService::CreateFixed("https://myproxy:70"));
6972 BoundTestNetLog log
;
6973 session_deps_
.net_log
= log
.bound().net_log();
6975 // Enable cross-origin push.
6976 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6978 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6980 scoped_ptr
<SpdyFrame
> stream1_syn(
6981 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6983 scoped_ptr
<SpdyFrame
> push_rst(
6984 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6986 MockWrite spdy_writes
[] = {
6987 CreateMockWrite(*stream1_syn
, 0, ASYNC
), CreateMockWrite(*push_rst
, 3),
6990 scoped_ptr
<SpdyFrame
>
6991 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6993 scoped_ptr
<SpdyFrame
>
6994 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6996 scoped_ptr
<SpdyFrame
>
6997 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7001 "https://www.another-origin.com/foo.dat"));
7003 MockRead spdy_reads
[] = {
7004 CreateMockRead(*stream1_reply
, 1, ASYNC
),
7005 CreateMockRead(*stream2_syn
, 2, ASYNC
),
7006 CreateMockRead(*stream1_body
, 4, ASYNC
),
7007 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7010 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7011 arraysize(spdy_writes
));
7012 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7013 // Negotiate SPDY to the proxy
7014 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7015 proxy
.SetNextProto(GetParam());
7016 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7018 scoped_ptr
<HttpTransaction
> trans(
7019 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7020 TestCompletionCallback callback
;
7021 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7022 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7024 rv
= callback
.WaitForResult();
7026 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7028 ASSERT_TRUE(response
!= NULL
);
7029 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7031 EXPECT_EQ(200, response
->headers
->response_code());
7032 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7034 std::string response_data
;
7035 rv
= ReadTransaction(trans
.get(), &response_data
);
7037 EXPECT_EQ("hello!", response_data
);
7040 session
->CloseAllConnections();
7043 // Test HTTPS connections to a site with a bad certificate, going through an
7045 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7046 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7047 "https://proxy:70"));
7049 HttpRequestInfo request
;
7050 request
.method
= "GET";
7051 request
.url
= GURL("https://www.example.org/");
7052 request
.load_flags
= 0;
7054 // Attempt to fetch the URL from a server with a bad cert
7055 MockWrite bad_cert_writes
[] = {
7057 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7058 "Host: www.example.org\r\n"
7059 "Proxy-Connection: keep-alive\r\n\r\n"),
7062 MockRead bad_cert_reads
[] = {
7063 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7064 MockRead(SYNCHRONOUS
, OK
)
7067 // Attempt to fetch the URL with a good cert
7068 MockWrite good_data_writes
[] = {
7070 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7071 "Host: www.example.org\r\n"
7072 "Proxy-Connection: keep-alive\r\n\r\n"),
7074 "GET / HTTP/1.1\r\n"
7075 "Host: www.example.org\r\n"
7076 "Connection: keep-alive\r\n\r\n"),
7079 MockRead good_cert_reads
[] = {
7080 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7081 MockRead("HTTP/1.0 200 OK\r\n"),
7082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7083 MockRead("Content-Length: 100\r\n\r\n"),
7084 MockRead(SYNCHRONOUS
, OK
),
7087 StaticSocketDataProvider
ssl_bad_certificate(
7088 bad_cert_reads
, arraysize(bad_cert_reads
),
7089 bad_cert_writes
, arraysize(bad_cert_writes
));
7090 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7091 good_data_writes
, arraysize(good_data_writes
));
7092 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7093 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7095 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7096 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7097 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7098 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7100 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7101 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7102 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7103 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7105 TestCompletionCallback callback
;
7107 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7108 scoped_ptr
<HttpTransaction
> trans(
7109 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7111 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7112 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7114 rv
= callback
.WaitForResult();
7115 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7117 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7118 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7120 rv
= callback
.WaitForResult();
7123 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7125 ASSERT_TRUE(response
!= NULL
);
7126 EXPECT_EQ(100, response
->headers
->GetContentLength());
7129 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7130 HttpRequestInfo request
;
7131 request
.method
= "GET";
7132 request
.url
= GURL("http://www.example.org/");
7133 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7134 "Chromium Ultra Awesome X Edition");
7136 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7137 scoped_ptr
<HttpTransaction
> trans(
7138 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7140 MockWrite data_writes
[] = {
7142 "GET / HTTP/1.1\r\n"
7143 "Host: www.example.org\r\n"
7144 "Connection: keep-alive\r\n"
7145 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7148 // Lastly, the server responds with the actual content.
7149 MockRead data_reads
[] = {
7150 MockRead("HTTP/1.0 200 OK\r\n"),
7151 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7152 MockRead("Content-Length: 100\r\n\r\n"),
7153 MockRead(SYNCHRONOUS
, OK
),
7156 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7157 data_writes
, arraysize(data_writes
));
7158 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7160 TestCompletionCallback callback
;
7162 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7163 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7165 rv
= callback
.WaitForResult();
7169 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7170 HttpRequestInfo request
;
7171 request
.method
= "GET";
7172 request
.url
= GURL("https://www.example.org/");
7173 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7174 "Chromium Ultra Awesome X Edition");
7176 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7177 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7178 scoped_ptr
<HttpTransaction
> trans(
7179 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7181 MockWrite data_writes
[] = {
7183 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7184 "Host: www.example.org\r\n"
7185 "Proxy-Connection: keep-alive\r\n"
7186 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7188 MockRead data_reads
[] = {
7189 // Return an error, so the transaction stops here (this test isn't
7190 // interested in the rest).
7191 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7192 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7193 MockRead("Proxy-Connection: close\r\n\r\n"),
7196 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7197 data_writes
, arraysize(data_writes
));
7198 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7200 TestCompletionCallback callback
;
7202 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7205 rv
= callback
.WaitForResult();
7209 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7210 HttpRequestInfo request
;
7211 request
.method
= "GET";
7212 request
.url
= GURL("http://www.example.org/");
7213 request
.load_flags
= 0;
7214 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7215 "http://the.previous.site.com/");
7217 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7218 scoped_ptr
<HttpTransaction
> trans(
7219 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7221 MockWrite data_writes
[] = {
7223 "GET / HTTP/1.1\r\n"
7224 "Host: www.example.org\r\n"
7225 "Connection: keep-alive\r\n"
7226 "Referer: http://the.previous.site.com/\r\n\r\n"),
7229 // Lastly, the server responds with the actual content.
7230 MockRead data_reads
[] = {
7231 MockRead("HTTP/1.0 200 OK\r\n"),
7232 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7233 MockRead("Content-Length: 100\r\n\r\n"),
7234 MockRead(SYNCHRONOUS
, OK
),
7237 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7238 data_writes
, arraysize(data_writes
));
7239 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7241 TestCompletionCallback callback
;
7243 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7244 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7246 rv
= callback
.WaitForResult();
7250 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7251 HttpRequestInfo request
;
7252 request
.method
= "POST";
7253 request
.url
= GURL("http://www.example.org/");
7255 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7256 scoped_ptr
<HttpTransaction
> trans(
7257 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7259 MockWrite data_writes
[] = {
7261 "POST / HTTP/1.1\r\n"
7262 "Host: www.example.org\r\n"
7263 "Connection: keep-alive\r\n"
7264 "Content-Length: 0\r\n\r\n"),
7267 // Lastly, the server responds with the actual content.
7268 MockRead data_reads
[] = {
7269 MockRead("HTTP/1.0 200 OK\r\n"),
7270 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7271 MockRead("Content-Length: 100\r\n\r\n"),
7272 MockRead(SYNCHRONOUS
, OK
),
7275 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7276 data_writes
, arraysize(data_writes
));
7277 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7279 TestCompletionCallback callback
;
7281 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7282 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7284 rv
= callback
.WaitForResult();
7288 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7289 HttpRequestInfo request
;
7290 request
.method
= "PUT";
7291 request
.url
= GURL("http://www.example.org/");
7293 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7294 scoped_ptr
<HttpTransaction
> trans(
7295 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7297 MockWrite data_writes
[] = {
7299 "PUT / HTTP/1.1\r\n"
7300 "Host: www.example.org\r\n"
7301 "Connection: keep-alive\r\n"
7302 "Content-Length: 0\r\n\r\n"),
7305 // Lastly, the server responds with the actual content.
7306 MockRead data_reads
[] = {
7307 MockRead("HTTP/1.0 200 OK\r\n"),
7308 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7309 MockRead("Content-Length: 100\r\n\r\n"),
7310 MockRead(SYNCHRONOUS
, OK
),
7313 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7314 data_writes
, arraysize(data_writes
));
7315 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7317 TestCompletionCallback callback
;
7319 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7320 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7322 rv
= callback
.WaitForResult();
7326 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7327 HttpRequestInfo request
;
7328 request
.method
= "HEAD";
7329 request
.url
= GURL("http://www.example.org/");
7331 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7332 scoped_ptr
<HttpTransaction
> trans(
7333 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7335 MockWrite data_writes
[] = {
7336 MockWrite("HEAD / HTTP/1.1\r\n"
7337 "Host: www.example.org\r\n"
7338 "Connection: keep-alive\r\n\r\n"),
7341 // Lastly, the server responds with the actual content.
7342 MockRead data_reads
[] = {
7343 MockRead("HTTP/1.0 200 OK\r\n"),
7344 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7345 MockRead("Content-Length: 100\r\n\r\n"),
7346 MockRead(SYNCHRONOUS
, OK
),
7349 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7350 data_writes
, arraysize(data_writes
));
7351 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7353 TestCompletionCallback callback
;
7355 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7356 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7358 rv
= callback
.WaitForResult();
7362 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7363 HttpRequestInfo request
;
7364 request
.method
= "GET";
7365 request
.url
= GURL("http://www.example.org/");
7366 request
.load_flags
= LOAD_BYPASS_CACHE
;
7368 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7369 scoped_ptr
<HttpTransaction
> trans(
7370 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7372 MockWrite data_writes
[] = {
7374 "GET / HTTP/1.1\r\n"
7375 "Host: www.example.org\r\n"
7376 "Connection: keep-alive\r\n"
7377 "Pragma: no-cache\r\n"
7378 "Cache-Control: no-cache\r\n\r\n"),
7381 // Lastly, the server responds with the actual content.
7382 MockRead data_reads
[] = {
7383 MockRead("HTTP/1.0 200 OK\r\n"),
7384 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7385 MockRead("Content-Length: 100\r\n\r\n"),
7386 MockRead(SYNCHRONOUS
, OK
),
7389 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7390 data_writes
, arraysize(data_writes
));
7391 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7393 TestCompletionCallback callback
;
7395 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7396 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7398 rv
= callback
.WaitForResult();
7402 TEST_P(HttpNetworkTransactionTest
,
7403 BuildRequest_CacheControlValidateCache
) {
7404 HttpRequestInfo request
;
7405 request
.method
= "GET";
7406 request
.url
= GURL("http://www.example.org/");
7407 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7409 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7410 scoped_ptr
<HttpTransaction
> trans(
7411 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7413 MockWrite data_writes
[] = {
7415 "GET / HTTP/1.1\r\n"
7416 "Host: www.example.org\r\n"
7417 "Connection: keep-alive\r\n"
7418 "Cache-Control: max-age=0\r\n\r\n"),
7421 // Lastly, the server responds with the actual content.
7422 MockRead data_reads
[] = {
7423 MockRead("HTTP/1.0 200 OK\r\n"),
7424 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7425 MockRead("Content-Length: 100\r\n\r\n"),
7426 MockRead(SYNCHRONOUS
, OK
),
7429 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7430 data_writes
, arraysize(data_writes
));
7431 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7433 TestCompletionCallback callback
;
7435 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7436 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7438 rv
= callback
.WaitForResult();
7442 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7443 HttpRequestInfo request
;
7444 request
.method
= "GET";
7445 request
.url
= GURL("http://www.example.org/");
7446 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7448 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7449 scoped_ptr
<HttpTransaction
> trans(
7450 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7452 MockWrite data_writes
[] = {
7454 "GET / HTTP/1.1\r\n"
7455 "Host: www.example.org\r\n"
7456 "Connection: keep-alive\r\n"
7457 "FooHeader: Bar\r\n\r\n"),
7460 // Lastly, the server responds with the actual content.
7461 MockRead data_reads
[] = {
7462 MockRead("HTTP/1.0 200 OK\r\n"),
7463 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7464 MockRead("Content-Length: 100\r\n\r\n"),
7465 MockRead(SYNCHRONOUS
, OK
),
7468 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7469 data_writes
, arraysize(data_writes
));
7470 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7472 TestCompletionCallback callback
;
7474 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7475 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7477 rv
= callback
.WaitForResult();
7481 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7482 HttpRequestInfo request
;
7483 request
.method
= "GET";
7484 request
.url
= GURL("http://www.example.org/");
7485 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7486 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7487 request
.extra_headers
.SetHeader("FoO", "bar");
7489 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7490 scoped_ptr
<HttpTransaction
> trans(
7491 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7493 MockWrite data_writes
[] = {
7495 "GET / HTTP/1.1\r\n"
7496 "Host: www.example.org\r\n"
7497 "Connection: keep-alive\r\n"
7498 "referer: www.foo.com\r\n"
7500 "FoO: bar\r\n\r\n"),
7503 // Lastly, the server responds with the actual content.
7504 MockRead data_reads
[] = {
7505 MockRead("HTTP/1.0 200 OK\r\n"),
7506 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7507 MockRead("Content-Length: 100\r\n\r\n"),
7508 MockRead(SYNCHRONOUS
, OK
),
7511 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7512 data_writes
, arraysize(data_writes
));
7513 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7515 TestCompletionCallback callback
;
7517 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7518 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7520 rv
= callback
.WaitForResult();
7524 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7525 HttpRequestInfo request
;
7526 request
.method
= "GET";
7527 request
.url
= GURL("http://www.example.org/");
7528 request
.load_flags
= 0;
7530 session_deps_
.proxy_service
.reset(
7531 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7533 session_deps_
.net_log
= &net_log
;
7535 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7536 scoped_ptr
<HttpTransaction
> trans(
7537 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7539 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7540 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7542 MockWrite data_writes
[] = {
7543 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7545 "GET / HTTP/1.1\r\n"
7546 "Host: www.example.org\r\n"
7547 "Connection: keep-alive\r\n\r\n")};
7549 MockRead data_reads
[] = {
7550 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7551 MockRead("HTTP/1.0 200 OK\r\n"),
7552 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7553 MockRead("Payload"),
7554 MockRead(SYNCHRONOUS
, OK
)
7557 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7558 data_writes
, arraysize(data_writes
));
7559 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7561 TestCompletionCallback callback
;
7563 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7564 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7566 rv
= callback
.WaitForResult();
7569 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7570 ASSERT_TRUE(response
!= NULL
);
7572 LoadTimingInfo load_timing_info
;
7573 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7574 TestLoadTimingNotReusedWithPac(load_timing_info
,
7575 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7577 std::string response_text
;
7578 rv
= ReadTransaction(trans
.get(), &response_text
);
7580 EXPECT_EQ("Payload", response_text
);
7583 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7584 HttpRequestInfo request
;
7585 request
.method
= "GET";
7586 request
.url
= GURL("https://www.example.org/");
7587 request
.load_flags
= 0;
7589 session_deps_
.proxy_service
.reset(
7590 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7592 session_deps_
.net_log
= &net_log
;
7594 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7595 scoped_ptr
<HttpTransaction
> trans(
7596 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7598 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7599 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7601 MockWrite data_writes
[] = {
7602 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7603 arraysize(write_buffer
)),
7605 "GET / HTTP/1.1\r\n"
7606 "Host: www.example.org\r\n"
7607 "Connection: keep-alive\r\n\r\n")};
7609 MockRead data_reads
[] = {
7610 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7611 arraysize(read_buffer
)),
7612 MockRead("HTTP/1.0 200 OK\r\n"),
7613 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7614 MockRead("Payload"),
7615 MockRead(SYNCHRONOUS
, OK
)
7618 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7619 data_writes
, arraysize(data_writes
));
7620 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7622 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7623 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7625 TestCompletionCallback callback
;
7627 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7628 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7630 rv
= callback
.WaitForResult();
7633 LoadTimingInfo load_timing_info
;
7634 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7635 TestLoadTimingNotReusedWithPac(load_timing_info
,
7636 CONNECT_TIMING_HAS_SSL_TIMES
);
7638 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7639 ASSERT_TRUE(response
!= NULL
);
7641 std::string response_text
;
7642 rv
= ReadTransaction(trans
.get(), &response_text
);
7644 EXPECT_EQ("Payload", response_text
);
7647 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7648 HttpRequestInfo request
;
7649 request
.method
= "GET";
7650 request
.url
= GURL("http://www.example.org/");
7651 request
.load_flags
= 0;
7653 session_deps_
.proxy_service
.reset(
7654 ProxyService::CreateFixed("socks4://myproxy:1080"));
7656 session_deps_
.net_log
= &net_log
;
7658 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7659 scoped_ptr
<HttpTransaction
> trans(
7660 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7662 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7663 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7665 MockWrite data_writes
[] = {
7666 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7668 "GET / HTTP/1.1\r\n"
7669 "Host: www.example.org\r\n"
7670 "Connection: keep-alive\r\n\r\n")};
7672 MockRead data_reads
[] = {
7673 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7674 MockRead("HTTP/1.0 200 OK\r\n"),
7675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7676 MockRead("Payload"),
7677 MockRead(SYNCHRONOUS
, OK
)
7680 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7681 data_writes
, arraysize(data_writes
));
7682 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7684 TestCompletionCallback callback
;
7686 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7687 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7689 rv
= callback
.WaitForResult();
7692 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7693 ASSERT_TRUE(response
!= NULL
);
7695 LoadTimingInfo load_timing_info
;
7696 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7697 TestLoadTimingNotReused(load_timing_info
,
7698 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7700 std::string response_text
;
7701 rv
= ReadTransaction(trans
.get(), &response_text
);
7703 EXPECT_EQ("Payload", response_text
);
7706 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7707 HttpRequestInfo request
;
7708 request
.method
= "GET";
7709 request
.url
= GURL("http://www.example.org/");
7710 request
.load_flags
= 0;
7712 session_deps_
.proxy_service
.reset(
7713 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7715 session_deps_
.net_log
= &net_log
;
7717 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7718 scoped_ptr
<HttpTransaction
> trans(
7719 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7721 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7722 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7723 const char kSOCKS5OkRequest
[] = {
7725 0x01, // Command (CONNECT)
7727 0x03, // Address type (DOMAINNAME).
7728 0x0F, // Length of domain (15)
7729 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7730 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7732 const char kSOCKS5OkResponse
[] =
7733 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7735 MockWrite data_writes
[] = {
7736 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7737 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7739 "GET / HTTP/1.1\r\n"
7740 "Host: www.example.org\r\n"
7741 "Connection: keep-alive\r\n\r\n")};
7743 MockRead data_reads
[] = {
7744 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7745 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7746 MockRead("HTTP/1.0 200 OK\r\n"),
7747 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7748 MockRead("Payload"),
7749 MockRead(SYNCHRONOUS
, OK
)
7752 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7753 data_writes
, arraysize(data_writes
));
7754 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7756 TestCompletionCallback callback
;
7758 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7759 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7761 rv
= callback
.WaitForResult();
7764 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7765 ASSERT_TRUE(response
!= NULL
);
7767 LoadTimingInfo load_timing_info
;
7768 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7769 TestLoadTimingNotReusedWithPac(load_timing_info
,
7770 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7772 std::string response_text
;
7773 rv
= ReadTransaction(trans
.get(), &response_text
);
7775 EXPECT_EQ("Payload", response_text
);
7778 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7779 HttpRequestInfo request
;
7780 request
.method
= "GET";
7781 request
.url
= GURL("https://www.example.org/");
7782 request
.load_flags
= 0;
7784 session_deps_
.proxy_service
.reset(
7785 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7787 session_deps_
.net_log
= &net_log
;
7789 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7790 scoped_ptr
<HttpTransaction
> trans(
7791 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7793 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7794 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7795 const unsigned char kSOCKS5OkRequest
[] = {
7797 0x01, // Command (CONNECT)
7799 0x03, // Address type (DOMAINNAME).
7800 0x0F, // Length of domain (15)
7801 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7802 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7805 const char kSOCKS5OkResponse
[] =
7806 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7808 MockWrite data_writes
[] = {
7809 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7810 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7811 arraysize(kSOCKS5OkRequest
)),
7813 "GET / HTTP/1.1\r\n"
7814 "Host: www.example.org\r\n"
7815 "Connection: keep-alive\r\n\r\n")};
7817 MockRead data_reads
[] = {
7818 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7819 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7820 MockRead("HTTP/1.0 200 OK\r\n"),
7821 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7822 MockRead("Payload"),
7823 MockRead(SYNCHRONOUS
, OK
)
7826 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7827 data_writes
, arraysize(data_writes
));
7828 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7830 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7831 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7833 TestCompletionCallback callback
;
7835 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7836 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7838 rv
= callback
.WaitForResult();
7841 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7842 ASSERT_TRUE(response
!= NULL
);
7844 LoadTimingInfo load_timing_info
;
7845 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7846 TestLoadTimingNotReusedWithPac(load_timing_info
,
7847 CONNECT_TIMING_HAS_SSL_TIMES
);
7849 std::string response_text
;
7850 rv
= ReadTransaction(trans
.get(), &response_text
);
7852 EXPECT_EQ("Payload", response_text
);
7857 // Tests that for connection endpoints the group names are correctly set.
7859 struct GroupNameTest
{
7860 std::string proxy_server
;
7862 std::string expected_group_name
;
7866 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7867 NextProto next_proto
,
7868 SpdySessionDependencies
* session_deps_
) {
7869 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7871 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7872 session
->http_server_properties();
7873 AlternativeService
alternative_service(
7874 AlternateProtocolFromNextProto(next_proto
), "", 443);
7875 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
7876 http_server_properties
->SetAlternativeService(
7877 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0,
7883 int GroupNameTransactionHelper(
7884 const std::string
& url
,
7885 const scoped_refptr
<HttpNetworkSession
>& session
) {
7886 HttpRequestInfo request
;
7887 request
.method
= "GET";
7888 request
.url
= GURL(url
);
7889 request
.load_flags
= 0;
7891 scoped_ptr
<HttpTransaction
> trans(
7892 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7894 TestCompletionCallback callback
;
7896 // We do not complete this request, the dtor will clean the transaction up.
7897 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7902 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7903 const GroupNameTest tests
[] = {
7906 "http://www.example.org/direct",
7907 "www.example.org:80",
7912 "http://[2001:1418:13:1::25]/direct",
7913 "[2001:1418:13:1::25]:80",
7920 "https://www.example.org/direct_ssl",
7921 "ssl/www.example.org:443",
7926 "https://[2001:1418:13:1::25]/direct",
7927 "ssl/[2001:1418:13:1::25]:443",
7932 "http://host.with.alternate/direct",
7933 "ssl/host.with.alternate:443",
7938 session_deps_
.use_alternative_services
= true;
7940 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7941 session_deps_
.proxy_service
.reset(
7942 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7943 scoped_refptr
<HttpNetworkSession
> session(
7944 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7946 HttpNetworkSessionPeer
peer(session
);
7947 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7948 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7949 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7950 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7951 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7952 new MockClientSocketPoolManager
);
7953 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7954 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7955 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7957 EXPECT_EQ(ERR_IO_PENDING
,
7958 GroupNameTransactionHelper(tests
[i
].url
, session
));
7960 EXPECT_EQ(tests
[i
].expected_group_name
,
7961 ssl_conn_pool
->last_group_name_received());
7963 EXPECT_EQ(tests
[i
].expected_group_name
,
7964 transport_conn_pool
->last_group_name_received());
7968 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7969 const GroupNameTest tests
[] = {
7972 "http://www.example.org/http_proxy_normal",
7973 "www.example.org:80",
7980 "https://www.example.org/http_connect_ssl",
7981 "ssl/www.example.org:443",
7987 "http://host.with.alternate/direct",
7988 "ssl/host.with.alternate:443",
7994 "ftp://ftp.google.com/http_proxy_normal",
7995 "ftp/ftp.google.com:21",
8000 session_deps_
.use_alternative_services
= true;
8002 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8003 session_deps_
.proxy_service
.reset(
8004 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8005 scoped_refptr
<HttpNetworkSession
> session(
8006 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8008 HttpNetworkSessionPeer
peer(session
);
8010 HostPortPair
proxy_host("http_proxy", 80);
8011 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8012 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8013 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8014 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8016 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8017 new MockClientSocketPoolManager
);
8018 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8019 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8020 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8022 EXPECT_EQ(ERR_IO_PENDING
,
8023 GroupNameTransactionHelper(tests
[i
].url
, session
));
8025 EXPECT_EQ(tests
[i
].expected_group_name
,
8026 ssl_conn_pool
->last_group_name_received());
8028 EXPECT_EQ(tests
[i
].expected_group_name
,
8029 http_proxy_pool
->last_group_name_received());
8033 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8034 const GroupNameTest tests
[] = {
8036 "socks4://socks_proxy:1080",
8037 "http://www.example.org/socks4_direct",
8038 "socks4/www.example.org:80",
8042 "socks5://socks_proxy:1080",
8043 "http://www.example.org/socks5_direct",
8044 "socks5/www.example.org:80",
8050 "socks4://socks_proxy:1080",
8051 "https://www.example.org/socks4_ssl",
8052 "socks4/ssl/www.example.org:443",
8056 "socks5://socks_proxy:1080",
8057 "https://www.example.org/socks5_ssl",
8058 "socks5/ssl/www.example.org:443",
8063 "socks4://socks_proxy:1080",
8064 "http://host.with.alternate/direct",
8065 "socks4/ssl/host.with.alternate:443",
8070 session_deps_
.use_alternative_services
= true;
8072 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8073 session_deps_
.proxy_service
.reset(
8074 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8075 scoped_refptr
<HttpNetworkSession
> session(
8076 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8078 HttpNetworkSessionPeer
peer(session
);
8080 HostPortPair
proxy_host("socks_proxy", 1080);
8081 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8082 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8083 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8084 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8086 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8087 new MockClientSocketPoolManager
);
8088 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8089 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8090 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8092 scoped_ptr
<HttpTransaction
> trans(
8093 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8095 EXPECT_EQ(ERR_IO_PENDING
,
8096 GroupNameTransactionHelper(tests
[i
].url
, session
));
8098 EXPECT_EQ(tests
[i
].expected_group_name
,
8099 ssl_conn_pool
->last_group_name_received());
8101 EXPECT_EQ(tests
[i
].expected_group_name
,
8102 socks_conn_pool
->last_group_name_received());
8106 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8107 HttpRequestInfo request
;
8108 request
.method
= "GET";
8109 request
.url
= GURL("http://www.example.org/");
8111 session_deps_
.proxy_service
.reset(
8112 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8114 // This simulates failure resolving all hostnames; that means we will fail
8115 // connecting to both proxies (myproxy:70 and foobar:80).
8116 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8118 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8119 scoped_ptr
<HttpTransaction
> trans(
8120 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8122 TestCompletionCallback callback
;
8124 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8125 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8127 rv
= callback
.WaitForResult();
8128 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8131 // Base test to make sure that when the load flags for a request specify to
8132 // bypass the cache, the DNS cache is not used.
8133 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8135 // Issue a request, asking to bypass the cache(s).
8136 HttpRequestInfo request
;
8137 request
.method
= "GET";
8138 request
.load_flags
= load_flags
;
8139 request
.url
= GURL("http://www.example.org/");
8141 // Select a host resolver that does caching.
8142 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8144 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8145 scoped_ptr
<HttpTransaction
> trans(
8146 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8148 // Warm up the host cache so it has an entry for "www.example.org".
8149 AddressList addrlist
;
8150 TestCompletionCallback callback
;
8151 int rv
= session_deps_
.host_resolver
->Resolve(
8152 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8153 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8154 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8155 rv
= callback
.WaitForResult();
8158 // Verify that it was added to host cache, by doing a subsequent async lookup
8159 // and confirming it completes synchronously.
8160 rv
= session_deps_
.host_resolver
->Resolve(
8161 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8162 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8165 // Inject a failure the next time that "www.example.org" is resolved. This way
8166 // we can tell if the next lookup hit the cache, or the "network".
8167 // (cache --> success, "network" --> failure).
8168 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8170 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8171 // first read -- this won't be reached as the host resolution will fail first.
8172 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8173 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8174 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8177 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8178 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8179 rv
= callback
.WaitForResult();
8181 // If we bypassed the cache, we would have gotten a failure while resolving
8182 // "www.example.org".
8183 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8186 // There are multiple load flags that should trigger the host cache bypass.
8187 // Test each in isolation:
8188 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8189 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8192 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8193 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8196 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8197 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8200 // Make sure we can handle an error when writing the request.
8201 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8202 HttpRequestInfo request
;
8203 request
.method
= "GET";
8204 request
.url
= GURL("http://www.foo.com/");
8205 request
.load_flags
= 0;
8207 MockWrite write_failure
[] = {
8208 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8210 StaticSocketDataProvider
data(NULL
, 0,
8211 write_failure
, arraysize(write_failure
));
8212 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8213 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8215 TestCompletionCallback callback
;
8217 scoped_ptr
<HttpTransaction
> trans(
8218 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8220 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8221 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8223 rv
= callback
.WaitForResult();
8224 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8227 // Check that a connection closed after the start of the headers finishes ok.
8228 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8229 HttpRequestInfo request
;
8230 request
.method
= "GET";
8231 request
.url
= GURL("http://www.foo.com/");
8232 request
.load_flags
= 0;
8234 MockRead data_reads
[] = {
8235 MockRead("HTTP/1."),
8236 MockRead(SYNCHRONOUS
, OK
),
8239 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8240 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8241 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8243 TestCompletionCallback callback
;
8245 scoped_ptr
<HttpTransaction
> trans(
8246 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8248 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8249 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8251 rv
= callback
.WaitForResult();
8254 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8255 ASSERT_TRUE(response
!= NULL
);
8257 EXPECT_TRUE(response
->headers
.get() != NULL
);
8258 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8260 std::string response_data
;
8261 rv
= ReadTransaction(trans
.get(), &response_data
);
8263 EXPECT_EQ("", response_data
);
8266 // Make sure that a dropped connection while draining the body for auth
8267 // restart does the right thing.
8268 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8269 HttpRequestInfo request
;
8270 request
.method
= "GET";
8271 request
.url
= GURL("http://www.example.org/");
8272 request
.load_flags
= 0;
8274 MockWrite data_writes1
[] = {
8276 "GET / HTTP/1.1\r\n"
8277 "Host: www.example.org\r\n"
8278 "Connection: keep-alive\r\n\r\n"),
8281 MockRead data_reads1
[] = {
8282 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8283 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8284 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8285 MockRead("Content-Length: 14\r\n\r\n"),
8287 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8290 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8291 data_writes1
, arraysize(data_writes1
));
8292 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8294 // After calling trans->RestartWithAuth(), this is the request we should
8295 // be issuing -- the final header line contains the credentials.
8296 MockWrite data_writes2
[] = {
8298 "GET / HTTP/1.1\r\n"
8299 "Host: www.example.org\r\n"
8300 "Connection: keep-alive\r\n"
8301 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8304 // Lastly, the server responds with the actual content.
8305 MockRead data_reads2
[] = {
8306 MockRead("HTTP/1.1 200 OK\r\n"),
8307 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8308 MockRead("Content-Length: 100\r\n\r\n"),
8309 MockRead(SYNCHRONOUS
, OK
),
8312 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8313 data_writes2
, arraysize(data_writes2
));
8314 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8315 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8317 TestCompletionCallback callback1
;
8319 scoped_ptr
<HttpTransaction
> trans(
8320 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8322 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8323 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8325 rv
= callback1
.WaitForResult();
8328 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8329 ASSERT_TRUE(response
!= NULL
);
8330 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8332 TestCompletionCallback callback2
;
8334 rv
= trans
->RestartWithAuth(
8335 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8336 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8338 rv
= callback2
.WaitForResult();
8341 response
= trans
->GetResponseInfo();
8342 ASSERT_TRUE(response
!= NULL
);
8343 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8344 EXPECT_EQ(100, response
->headers
->GetContentLength());
8347 // Test HTTPS connections going through a proxy that sends extra data.
8348 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8349 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8351 HttpRequestInfo request
;
8352 request
.method
= "GET";
8353 request
.url
= GURL("https://www.example.org/");
8354 request
.load_flags
= 0;
8356 MockRead proxy_reads
[] = {
8357 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8358 MockRead(SYNCHRONOUS
, OK
)
8361 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8362 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8364 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8365 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8367 TestCompletionCallback callback
;
8369 session_deps_
.socket_factory
->ResetNextMockIndexes();
8371 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8372 scoped_ptr
<HttpTransaction
> trans(
8373 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8375 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8376 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8378 rv
= callback
.WaitForResult();
8379 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8382 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8383 HttpRequestInfo request
;
8384 request
.method
= "GET";
8385 request
.url
= GURL("http://www.example.org/");
8386 request
.load_flags
= 0;
8388 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8389 scoped_ptr
<HttpTransaction
> trans(
8390 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8392 MockRead data_reads
[] = {
8393 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8394 MockRead(SYNCHRONOUS
, OK
),
8397 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8398 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8400 TestCompletionCallback callback
;
8402 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8403 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8405 EXPECT_EQ(OK
, callback
.WaitForResult());
8407 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8408 ASSERT_TRUE(response
!= NULL
);
8410 EXPECT_TRUE(response
->headers
.get() != NULL
);
8411 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8413 std::string response_data
;
8414 rv
= ReadTransaction(trans
.get(), &response_data
);
8415 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8418 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8419 base::FilePath temp_file_path
;
8420 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8421 const uint64 kFakeSize
= 100000; // file is actually blank
8422 UploadFileElementReader::ScopedOverridingContentLengthForTests
8423 overriding_content_length(kFakeSize
);
8425 ScopedVector
<UploadElementReader
> element_readers
;
8426 element_readers
.push_back(
8427 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8428 temp_file_path
, 0, kuint64max
, base::Time()));
8429 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8431 HttpRequestInfo request
;
8432 request
.method
= "POST";
8433 request
.url
= GURL("http://www.example.org/upload");
8434 request
.upload_data_stream
= &upload_data_stream
;
8435 request
.load_flags
= 0;
8437 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8438 scoped_ptr
<HttpTransaction
> trans(
8439 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8441 MockRead data_reads
[] = {
8442 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8443 MockRead("hello world"),
8444 MockRead(SYNCHRONOUS
, OK
),
8446 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8447 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8449 TestCompletionCallback callback
;
8451 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8452 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8454 rv
= callback
.WaitForResult();
8457 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8458 ASSERT_TRUE(response
!= NULL
);
8460 EXPECT_TRUE(response
->headers
.get() != NULL
);
8461 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8463 std::string response_data
;
8464 rv
= ReadTransaction(trans
.get(), &response_data
);
8466 EXPECT_EQ("hello world", response_data
);
8468 base::DeleteFile(temp_file_path
, false);
8471 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8472 base::FilePath temp_file
;
8473 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8474 std::string
temp_file_content("Unreadable file.");
8475 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8476 temp_file_content
.length()));
8477 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8479 ScopedVector
<UploadElementReader
> element_readers
;
8480 element_readers
.push_back(
8481 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8482 temp_file
, 0, kuint64max
, base::Time()));
8483 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8485 HttpRequestInfo request
;
8486 request
.method
= "POST";
8487 request
.url
= GURL("http://www.example.org/upload");
8488 request
.upload_data_stream
= &upload_data_stream
;
8489 request
.load_flags
= 0;
8491 // If we try to upload an unreadable file, the transaction should fail.
8492 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8493 scoped_ptr
<HttpTransaction
> trans(
8494 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8496 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8497 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8499 TestCompletionCallback callback
;
8501 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8502 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8504 rv
= callback
.WaitForResult();
8505 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8507 base::DeleteFile(temp_file
, false);
8510 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8511 class FakeUploadElementReader
: public UploadElementReader
{
8513 FakeUploadElementReader() {}
8514 ~FakeUploadElementReader() override
{}
8516 const CompletionCallback
& callback() const { return callback_
; }
8518 // UploadElementReader overrides:
8519 int Init(const CompletionCallback
& callback
) override
{
8520 callback_
= callback
;
8521 return ERR_IO_PENDING
;
8523 uint64
GetContentLength() const override
{ return 0; }
8524 uint64
BytesRemaining() const override
{ return 0; }
8525 int Read(IOBuffer
* buf
,
8527 const CompletionCallback
& callback
) override
{
8532 CompletionCallback callback_
;
8535 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8536 ScopedVector
<UploadElementReader
> element_readers
;
8537 element_readers
.push_back(fake_reader
);
8538 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8540 HttpRequestInfo request
;
8541 request
.method
= "POST";
8542 request
.url
= GURL("http://www.example.org/upload");
8543 request
.upload_data_stream
= &upload_data_stream
;
8544 request
.load_flags
= 0;
8546 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8547 scoped_ptr
<HttpTransaction
> trans(
8548 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8550 StaticSocketDataProvider data
;
8551 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8553 TestCompletionCallback callback
;
8554 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8555 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8556 base::MessageLoop::current()->RunUntilIdle();
8558 // Transaction is pending on request body initialization.
8559 ASSERT_FALSE(fake_reader
->callback().is_null());
8561 // Return Init()'s result after the transaction gets destroyed.
8563 fake_reader
->callback().Run(OK
); // Should not crash.
8566 // Tests that changes to Auth realms are treated like auth rejections.
8567 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8568 HttpRequestInfo request
;
8569 request
.method
= "GET";
8570 request
.url
= GURL("http://www.example.org/");
8571 request
.load_flags
= 0;
8573 // First transaction will request a resource and receive a Basic challenge
8574 // with realm="first_realm".
8575 MockWrite data_writes1
[] = {
8577 "GET / HTTP/1.1\r\n"
8578 "Host: www.example.org\r\n"
8579 "Connection: keep-alive\r\n"
8582 MockRead data_reads1
[] = {
8583 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8584 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8588 // After calling trans->RestartWithAuth(), provide an Authentication header
8589 // for first_realm. The server will reject and provide a challenge with
8591 MockWrite data_writes2
[] = {
8593 "GET / HTTP/1.1\r\n"
8594 "Host: www.example.org\r\n"
8595 "Connection: keep-alive\r\n"
8596 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8599 MockRead data_reads2
[] = {
8600 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8601 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8605 // This again fails, and goes back to first_realm. Make sure that the
8606 // entry is removed from cache.
8607 MockWrite data_writes3
[] = {
8609 "GET / HTTP/1.1\r\n"
8610 "Host: www.example.org\r\n"
8611 "Connection: keep-alive\r\n"
8612 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8615 MockRead data_reads3
[] = {
8616 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8617 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8621 // Try one last time (with the correct password) and get the resource.
8622 MockWrite data_writes4
[] = {
8624 "GET / HTTP/1.1\r\n"
8625 "Host: www.example.org\r\n"
8626 "Connection: keep-alive\r\n"
8627 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8630 MockRead data_reads4
[] = {
8631 MockRead("HTTP/1.1 200 OK\r\n"
8632 "Content-Type: text/html; charset=iso-8859-1\r\n"
8633 "Content-Length: 5\r\n"
8638 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8639 data_writes1
, arraysize(data_writes1
));
8640 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8641 data_writes2
, arraysize(data_writes2
));
8642 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8643 data_writes3
, arraysize(data_writes3
));
8644 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8645 data_writes4
, arraysize(data_writes4
));
8646 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8647 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8648 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8649 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8651 TestCompletionCallback callback1
;
8653 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8654 scoped_ptr
<HttpTransaction
> trans(
8655 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8657 // Issue the first request with Authorize headers. There should be a
8658 // password prompt for first_realm waiting to be filled in after the
8659 // transaction completes.
8660 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8661 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8662 rv
= callback1
.WaitForResult();
8664 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8665 ASSERT_TRUE(response
!= NULL
);
8666 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8667 ASSERT_FALSE(challenge
== NULL
);
8668 EXPECT_FALSE(challenge
->is_proxy
);
8669 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8670 EXPECT_EQ("first_realm", challenge
->realm
);
8671 EXPECT_EQ("basic", challenge
->scheme
);
8673 // Issue the second request with an incorrect password. There should be a
8674 // password prompt for second_realm waiting to be filled in after the
8675 // transaction completes.
8676 TestCompletionCallback callback2
;
8677 rv
= trans
->RestartWithAuth(
8678 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8679 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8680 rv
= callback2
.WaitForResult();
8682 response
= trans
->GetResponseInfo();
8683 ASSERT_TRUE(response
!= NULL
);
8684 challenge
= response
->auth_challenge
.get();
8685 ASSERT_FALSE(challenge
== NULL
);
8686 EXPECT_FALSE(challenge
->is_proxy
);
8687 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8688 EXPECT_EQ("second_realm", challenge
->realm
);
8689 EXPECT_EQ("basic", challenge
->scheme
);
8691 // Issue the third request with another incorrect password. There should be
8692 // a password prompt for first_realm waiting to be filled in. If the password
8693 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8694 // first_realm was not correctly removed.
8695 TestCompletionCallback callback3
;
8696 rv
= trans
->RestartWithAuth(
8697 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8698 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8699 rv
= callback3
.WaitForResult();
8701 response
= trans
->GetResponseInfo();
8702 ASSERT_TRUE(response
!= NULL
);
8703 challenge
= response
->auth_challenge
.get();
8704 ASSERT_FALSE(challenge
== NULL
);
8705 EXPECT_FALSE(challenge
->is_proxy
);
8706 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8707 EXPECT_EQ("first_realm", challenge
->realm
);
8708 EXPECT_EQ("basic", challenge
->scheme
);
8710 // Issue the fourth request with the correct password and username.
8711 TestCompletionCallback callback4
;
8712 rv
= trans
->RestartWithAuth(
8713 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8714 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8715 rv
= callback4
.WaitForResult();
8717 response
= trans
->GetResponseInfo();
8718 ASSERT_TRUE(response
!= NULL
);
8719 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8722 TEST_P(HttpNetworkTransactionTest
, HonorAlternativeServiceHeader
) {
8723 session_deps_
.next_protos
= SpdyNextProtos();
8724 session_deps_
.use_alternative_services
= true;
8726 std::string alternative_service_http_header
=
8727 GetAlternativeServiceHttpHeader();
8729 MockRead data_reads
[] = {
8730 MockRead("HTTP/1.1 200 OK\r\n"),
8731 MockRead(alternative_service_http_header
.c_str()),
8733 MockRead("hello world"),
8734 MockRead(SYNCHRONOUS
, OK
),
8737 HttpRequestInfo request
;
8738 request
.method
= "GET";
8739 request
.url
= GURL("http://www.example.org/");
8740 request
.load_flags
= 0;
8742 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8744 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8746 TestCompletionCallback callback
;
8748 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8749 scoped_ptr
<HttpTransaction
> trans(
8750 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8752 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8753 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8755 HostPortPair
http_host_port_pair("www.example.org", 80);
8756 HttpServerProperties
& http_server_properties
=
8757 *session
->http_server_properties();
8758 AlternativeServiceVector alternative_service_vector
=
8759 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8760 EXPECT_TRUE(alternative_service_vector
.empty());
8762 EXPECT_EQ(OK
, callback
.WaitForResult());
8764 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8765 ASSERT_TRUE(response
!= NULL
);
8766 ASSERT_TRUE(response
->headers
.get() != NULL
);
8767 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8768 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8769 EXPECT_FALSE(response
->was_npn_negotiated
);
8771 std::string response_data
;
8772 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8773 EXPECT_EQ("hello world", response_data
);
8775 alternative_service_vector
=
8776 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8777 ASSERT_EQ(1u, alternative_service_vector
.size());
8778 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8779 alternative_service_vector
[0].protocol
);
8780 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
8781 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8784 TEST_P(HttpNetworkTransactionTest
, HonorMultipleAlternativeServiceHeader
) {
8785 session_deps_
.next_protos
= SpdyNextProtos();
8786 session_deps_
.use_alternative_services
= true;
8788 MockRead data_reads
[] = {
8789 MockRead("HTTP/1.1 200 OK\r\n"),
8790 MockRead("Alt-Svc: "),
8791 MockRead(GetAlternateProtocolFromParam()),
8792 MockRead("=\"www.example.com:443\";p=1.0,"),
8793 MockRead("quic=\":1234\"\r\n\r\n"),
8794 MockRead("hello world"),
8795 MockRead(SYNCHRONOUS
, OK
),
8798 HttpRequestInfo request
;
8799 request
.method
= "GET";
8800 request
.url
= GURL("http://www.example.org/");
8801 request
.load_flags
= 0;
8803 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8805 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8807 TestCompletionCallback callback
;
8809 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8810 scoped_ptr
<HttpTransaction
> trans(
8811 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8813 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8814 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8816 HostPortPair
http_host_port_pair("www.example.org", 80);
8817 HttpServerProperties
& http_server_properties
=
8818 *session
->http_server_properties();
8819 AlternativeServiceVector alternative_service_vector
=
8820 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8821 EXPECT_TRUE(alternative_service_vector
.empty());
8823 EXPECT_EQ(OK
, callback
.WaitForResult());
8825 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8826 ASSERT_TRUE(response
!= NULL
);
8827 ASSERT_TRUE(response
->headers
.get() != NULL
);
8828 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8829 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8830 EXPECT_FALSE(response
->was_npn_negotiated
);
8832 std::string response_data
;
8833 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8834 EXPECT_EQ("hello world", response_data
);
8836 alternative_service_vector
=
8837 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8838 ASSERT_EQ(2u, alternative_service_vector
.size());
8839 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8840 alternative_service_vector
[0].protocol
);
8841 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
8842 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8843 EXPECT_EQ(QUIC
, alternative_service_vector
[1].protocol
);
8844 EXPECT_EQ("www.example.org", alternative_service_vector
[1].host
);
8845 EXPECT_EQ(1234, alternative_service_vector
[1].port
);
8848 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8849 session_deps_
.next_protos
= SpdyNextProtos();
8850 session_deps_
.use_alternative_services
= true;
8852 std::string alternate_protocol_http_header
=
8853 GetAlternateProtocolHttpHeader();
8855 MockRead data_reads
[] = {
8856 MockRead("HTTP/1.1 200 OK\r\n"),
8857 MockRead(alternate_protocol_http_header
.c_str()),
8859 MockRead("hello world"),
8860 MockRead(SYNCHRONOUS
, OK
),
8863 HttpRequestInfo request
;
8864 request
.method
= "GET";
8865 request
.url
= GURL("http://www.example.org/");
8866 request
.load_flags
= 0;
8868 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8870 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8872 TestCompletionCallback callback
;
8874 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8875 scoped_ptr
<HttpTransaction
> trans(
8876 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8878 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8879 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8881 HostPortPair
http_host_port_pair("www.example.org", 80);
8882 HttpServerProperties
& http_server_properties
=
8883 *session
->http_server_properties();
8884 AlternativeServiceVector alternative_service_vector
=
8885 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8886 EXPECT_TRUE(alternative_service_vector
.empty());
8888 EXPECT_EQ(OK
, callback
.WaitForResult());
8890 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8891 ASSERT_TRUE(response
!= NULL
);
8892 ASSERT_TRUE(response
->headers
.get() != NULL
);
8893 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8894 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8895 EXPECT_FALSE(response
->was_npn_negotiated
);
8897 std::string response_data
;
8898 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8899 EXPECT_EQ("hello world", response_data
);
8901 alternative_service_vector
=
8902 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8903 ASSERT_EQ(1u, alternative_service_vector
.size());
8904 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8905 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8906 alternative_service_vector
[0].protocol
);
8909 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
8910 session_deps_
.next_protos
= SpdyNextProtos();
8911 session_deps_
.use_alternative_services
= true;
8913 MockRead data_reads
[] = {
8914 MockRead("HTTP/1.1 200 OK\r\n"),
8915 MockRead("Alternate-Protocol: \r\n\r\n"),
8916 MockRead("hello world"),
8917 MockRead(SYNCHRONOUS
, OK
),
8920 HttpRequestInfo request
;
8921 request
.method
= "GET";
8922 request
.url
= GURL("http://www.example.org/");
8923 request
.load_flags
= 0;
8925 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8927 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8929 TestCompletionCallback callback
;
8931 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8933 HostPortPair
http_host_port_pair("www.example.org", 80);
8934 HttpServerProperties
& http_server_properties
=
8935 *session
->http_server_properties();
8936 AlternativeService
alternative_service(QUIC
, "", 80);
8937 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
8938 http_server_properties
.SetAlternativeService(
8939 http_host_port_pair
, alternative_service
, 1.0, expiration
);
8941 AlternativeServiceVector alternative_service_vector
=
8942 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8943 ASSERT_EQ(1u, alternative_service_vector
.size());
8944 EXPECT_EQ(QUIC
, alternative_service_vector
[0].protocol
);
8946 scoped_ptr
<HttpTransaction
> trans(
8947 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8949 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8950 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8952 EXPECT_EQ(OK
, callback
.WaitForResult());
8954 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8955 ASSERT_TRUE(response
!= NULL
);
8956 ASSERT_TRUE(response
->headers
.get() != NULL
);
8957 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8958 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8959 EXPECT_FALSE(response
->was_npn_negotiated
);
8961 std::string response_data
;
8962 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8963 EXPECT_EQ("hello world", response_data
);
8965 alternative_service_vector
=
8966 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8967 EXPECT_TRUE(alternative_service_vector
.empty());
8970 TEST_P(HttpNetworkTransactionTest
, AltSvcOverwritesAlternateProtocol
) {
8971 session_deps_
.next_protos
= SpdyNextProtos();
8972 session_deps_
.use_alternative_services
= true;
8974 std::string alternative_service_http_header
=
8975 GetAlternativeServiceHttpHeader();
8976 std::string alternate_protocol_http_header
= GetAlternateProtocolHttpHeader();
8978 MockRead data_reads
[] = {
8979 MockRead("HTTP/1.1 200 OK\r\n"),
8980 MockRead(alternative_service_http_header
.c_str()),
8981 MockRead(alternate_protocol_http_header
.c_str()),
8983 MockRead("hello world"),
8984 MockRead(SYNCHRONOUS
, OK
),
8987 HttpRequestInfo request
;
8988 request
.method
= "GET";
8989 request
.url
= GURL("http://www.example.org/");
8990 request
.load_flags
= 0;
8992 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8994 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8996 TestCompletionCallback callback
;
8998 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8999 scoped_ptr
<HttpTransaction
> trans(
9000 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9002 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9003 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9005 HostPortPair
http_host_port_pair("www.example.org", 80);
9006 HttpServerProperties
& http_server_properties
=
9007 *session
->http_server_properties();
9008 AlternativeServiceVector alternative_service_vector
=
9009 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9010 EXPECT_TRUE(alternative_service_vector
.empty());
9012 EXPECT_EQ(OK
, callback
.WaitForResult());
9014 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9015 ASSERT_TRUE(response
!= NULL
);
9016 ASSERT_TRUE(response
->headers
.get() != NULL
);
9017 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9018 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9019 EXPECT_FALSE(response
->was_npn_negotiated
);
9021 std::string response_data
;
9022 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9023 EXPECT_EQ("hello world", response_data
);
9025 alternative_service_vector
=
9026 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9027 ASSERT_EQ(1u, alternative_service_vector
.size());
9028 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9029 alternative_service_vector
[0].protocol
);
9030 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
9031 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9034 TEST_P(HttpNetworkTransactionTest
,
9035 MarkBrokenAlternateProtocolAndFallback
) {
9036 session_deps_
.use_alternative_services
= true;
9038 HttpRequestInfo request
;
9039 request
.method
= "GET";
9040 request
.url
= GURL("http://www.example.org/");
9041 request
.load_flags
= 0;
9043 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9044 StaticSocketDataProvider first_data
;
9045 first_data
.set_connect_data(mock_connect
);
9046 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9048 MockRead data_reads
[] = {
9049 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9050 MockRead("hello world"),
9051 MockRead(ASYNC
, OK
),
9053 StaticSocketDataProvider
second_data(
9054 data_reads
, arraysize(data_reads
), NULL
, 0);
9055 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9057 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9059 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9060 session
->http_server_properties();
9061 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
9062 // Port must be < 1024, or the header will be ignored (since initial port was
9063 // port 80 (another restricted port).
9064 const AlternativeService
alternative_service(
9065 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9066 666); // Port is ignored by MockConnect anyway.
9067 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9068 http_server_properties
->SetAlternativeService(
9069 host_port_pair
, alternative_service
, 1.0, expiration
);
9071 scoped_ptr
<HttpTransaction
> trans(
9072 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9073 TestCompletionCallback callback
;
9075 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9076 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9077 EXPECT_EQ(OK
, callback
.WaitForResult());
9079 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9080 ASSERT_TRUE(response
!= NULL
);
9081 ASSERT_TRUE(response
->headers
.get() != NULL
);
9082 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9084 std::string response_data
;
9085 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9086 EXPECT_EQ("hello world", response_data
);
9088 const AlternativeServiceVector alternative_service_vector
=
9089 http_server_properties
->GetAlternativeServices(host_port_pair
);
9090 ASSERT_EQ(1u, alternative_service_vector
.size());
9091 EXPECT_EQ(alternative_service
, alternative_service_vector
[0]);
9092 EXPECT_TRUE(http_server_properties
->IsAlternativeServiceBroken(
9093 alternative_service_vector
[0]));
9096 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9097 // to an unrestricted (port >= 1024) when the original traffic was on a
9098 // restricted port (port < 1024). Ensure that we can redirect in all other
9100 TEST_P(HttpNetworkTransactionTest
,
9101 AlternateProtocolPortRestrictedBlocked
) {
9102 session_deps_
.use_alternative_services
= true;
9104 HttpRequestInfo restricted_port_request
;
9105 restricted_port_request
.method
= "GET";
9106 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9107 restricted_port_request
.load_flags
= 0;
9109 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9110 StaticSocketDataProvider first_data
;
9111 first_data
.set_connect_data(mock_connect
);
9112 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9114 MockRead data_reads
[] = {
9115 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9116 MockRead("hello world"),
9117 MockRead(ASYNC
, OK
),
9119 StaticSocketDataProvider
second_data(
9120 data_reads
, arraysize(data_reads
), NULL
, 0);
9121 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9123 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9125 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9126 session
->http_server_properties();
9127 const int kUnrestrictedAlternatePort
= 1024;
9128 AlternativeService
alternative_service(
9129 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9130 kUnrestrictedAlternatePort
);
9131 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9132 http_server_properties
->SetAlternativeService(
9133 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9136 scoped_ptr
<HttpTransaction
> trans(
9137 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9138 TestCompletionCallback callback
;
9140 int rv
= trans
->Start(
9141 &restricted_port_request
,
9142 callback
.callback(), BoundNetLog());
9143 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9144 // Invalid change to unrestricted port should fail.
9145 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
9148 // Ensure that we are allowed to redirect traffic via an alternate protocol to
9149 // an unrestricted (port >= 1024) when the original traffic was on a restricted
9150 // port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
9151 TEST_P(HttpNetworkTransactionTest
,
9152 AlternateProtocolPortRestrictedPermitted
) {
9153 session_deps_
.use_alternative_services
= true;
9154 session_deps_
.enable_user_alternate_protocol_ports
= true;
9156 HttpRequestInfo restricted_port_request
;
9157 restricted_port_request
.method
= "GET";
9158 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9159 restricted_port_request
.load_flags
= 0;
9161 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9162 StaticSocketDataProvider first_data
;
9163 first_data
.set_connect_data(mock_connect
);
9164 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9166 MockRead data_reads
[] = {
9167 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9168 MockRead("hello world"),
9169 MockRead(ASYNC
, OK
),
9171 StaticSocketDataProvider
second_data(
9172 data_reads
, arraysize(data_reads
), NULL
, 0);
9173 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9175 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9177 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9178 session
->http_server_properties();
9179 const int kUnrestrictedAlternatePort
= 1024;
9180 AlternativeService
alternative_service(
9181 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9182 kUnrestrictedAlternatePort
);
9183 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9184 http_server_properties
->SetAlternativeService(
9185 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9188 scoped_ptr
<HttpTransaction
> trans(
9189 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9190 TestCompletionCallback callback
;
9192 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9193 &restricted_port_request
,
9194 callback
.callback(), BoundNetLog()));
9195 // Change to unrestricted port should succeed.
9196 EXPECT_EQ(OK
, callback
.WaitForResult());
9199 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9200 // to an unrestricted (port >= 1024) when the original traffic was on a
9201 // restricted port (port < 1024). Ensure that we can redirect in all other
9203 TEST_P(HttpNetworkTransactionTest
,
9204 AlternateProtocolPortRestrictedAllowed
) {
9205 session_deps_
.use_alternative_services
= true;
9207 HttpRequestInfo restricted_port_request
;
9208 restricted_port_request
.method
= "GET";
9209 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9210 restricted_port_request
.load_flags
= 0;
9212 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9213 StaticSocketDataProvider first_data
;
9214 first_data
.set_connect_data(mock_connect
);
9215 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9217 MockRead data_reads
[] = {
9218 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9219 MockRead("hello world"),
9220 MockRead(ASYNC
, OK
),
9222 StaticSocketDataProvider
second_data(
9223 data_reads
, arraysize(data_reads
), NULL
, 0);
9224 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9226 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9228 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9229 session
->http_server_properties();
9230 const int kRestrictedAlternatePort
= 80;
9231 AlternativeService
alternative_service(
9232 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9233 kRestrictedAlternatePort
);
9234 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9235 http_server_properties
->SetAlternativeService(
9236 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9239 scoped_ptr
<HttpTransaction
> trans(
9240 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9241 TestCompletionCallback callback
;
9243 int rv
= trans
->Start(
9244 &restricted_port_request
,
9245 callback
.callback(), BoundNetLog());
9246 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9247 // Valid change to restricted port should pass.
9248 EXPECT_EQ(OK
, callback
.WaitForResult());
9251 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9252 // to an unrestricted (port >= 1024) when the original traffic was on a
9253 // restricted port (port < 1024). Ensure that we can redirect in all other
9255 TEST_P(HttpNetworkTransactionTest
,
9256 AlternateProtocolPortUnrestrictedAllowed1
) {
9257 session_deps_
.use_alternative_services
= true;
9259 HttpRequestInfo unrestricted_port_request
;
9260 unrestricted_port_request
.method
= "GET";
9261 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9262 unrestricted_port_request
.load_flags
= 0;
9264 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9265 StaticSocketDataProvider first_data
;
9266 first_data
.set_connect_data(mock_connect
);
9267 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9269 MockRead data_reads
[] = {
9270 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9271 MockRead("hello world"),
9272 MockRead(ASYNC
, OK
),
9274 StaticSocketDataProvider
second_data(
9275 data_reads
, arraysize(data_reads
), NULL
, 0);
9276 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9278 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9280 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9281 session
->http_server_properties();
9282 const int kRestrictedAlternatePort
= 80;
9283 AlternativeService
alternative_service(
9284 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9285 kRestrictedAlternatePort
);
9286 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9287 http_server_properties
->SetAlternativeService(
9288 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9291 scoped_ptr
<HttpTransaction
> trans(
9292 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9293 TestCompletionCallback callback
;
9295 int rv
= trans
->Start(
9296 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9297 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9298 // Valid change to restricted port should pass.
9299 EXPECT_EQ(OK
, callback
.WaitForResult());
9302 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9303 // to an unrestricted (port >= 1024) when the original traffic was on a
9304 // restricted port (port < 1024). Ensure that we can redirect in all other
9306 TEST_P(HttpNetworkTransactionTest
,
9307 AlternateProtocolPortUnrestrictedAllowed2
) {
9308 session_deps_
.use_alternative_services
= true;
9310 HttpRequestInfo unrestricted_port_request
;
9311 unrestricted_port_request
.method
= "GET";
9312 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9313 unrestricted_port_request
.load_flags
= 0;
9315 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9316 StaticSocketDataProvider first_data
;
9317 first_data
.set_connect_data(mock_connect
);
9318 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9320 MockRead data_reads
[] = {
9321 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9322 MockRead("hello world"),
9323 MockRead(ASYNC
, OK
),
9325 StaticSocketDataProvider
second_data(
9326 data_reads
, arraysize(data_reads
), NULL
, 0);
9327 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9329 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9331 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9332 session
->http_server_properties();
9333 const int kUnrestrictedAlternatePort
= 1025;
9334 AlternativeService
alternative_service(
9335 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9336 kUnrestrictedAlternatePort
);
9337 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9338 http_server_properties
->SetAlternativeService(
9339 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9342 scoped_ptr
<HttpTransaction
> trans(
9343 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9344 TestCompletionCallback callback
;
9346 int rv
= trans
->Start(
9347 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9348 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9349 // Valid change to an unrestricted port should pass.
9350 EXPECT_EQ(OK
, callback
.WaitForResult());
9353 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9354 // to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
9355 // once the alternate protocol request fails.
9356 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9357 session_deps_
.use_alternative_services
= true;
9359 HttpRequestInfo request
;
9360 request
.method
= "GET";
9361 request
.url
= GURL("http://www.example.org/");
9362 request
.load_flags
= 0;
9364 // The alternate protocol request will error out before we attempt to connect,
9365 // so only the standard HTTP request will try to connect.
9366 MockRead data_reads
[] = {
9367 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9368 MockRead("hello world"),
9369 MockRead(ASYNC
, OK
),
9371 StaticSocketDataProvider
data(
9372 data_reads
, arraysize(data_reads
), NULL
, 0);
9373 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9375 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9377 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9378 session
->http_server_properties();
9379 const int kUnsafePort
= 7;
9380 AlternativeService
alternative_service(
9381 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9383 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9384 http_server_properties
->SetAlternativeService(
9385 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0, expiration
);
9387 scoped_ptr
<HttpTransaction
> trans(
9388 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9389 TestCompletionCallback callback
;
9391 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9392 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9393 // The HTTP request should succeed.
9394 EXPECT_EQ(OK
, callback
.WaitForResult());
9396 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9397 ASSERT_TRUE(response
!= NULL
);
9398 ASSERT_TRUE(response
->headers
.get() != NULL
);
9399 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9401 std::string response_data
;
9402 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9403 EXPECT_EQ("hello world", response_data
);
9406 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9407 session_deps_
.use_alternative_services
= true;
9408 session_deps_
.next_protos
= SpdyNextProtos();
9410 HttpRequestInfo request
;
9411 request
.method
= "GET";
9412 request
.url
= GURL("http://www.example.org/");
9413 request
.load_flags
= 0;
9415 std::string alternate_protocol_http_header
=
9416 GetAlternateProtocolHttpHeader();
9418 MockRead data_reads
[] = {
9419 MockRead("HTTP/1.1 200 OK\r\n"),
9420 MockRead(alternate_protocol_http_header
.c_str()),
9422 MockRead("hello world"),
9423 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9424 MockRead(ASYNC
, OK
)};
9426 StaticSocketDataProvider
first_transaction(
9427 data_reads
, arraysize(data_reads
), NULL
, 0);
9428 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9430 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9431 ssl
.SetNextProto(GetParam());
9432 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9433 ASSERT_TRUE(ssl
.cert
.get());
9434 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9436 scoped_ptr
<SpdyFrame
> req(
9437 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9438 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9440 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9441 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9442 MockRead spdy_reads
[] = {
9443 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9446 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9447 arraysize(spdy_writes
));
9448 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9450 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9451 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9453 hanging_non_alternate_protocol_socket
.set_connect_data(
9454 never_finishing_connect
);
9455 session_deps_
.socket_factory
->AddSocketDataProvider(
9456 &hanging_non_alternate_protocol_socket
);
9458 TestCompletionCallback callback
;
9460 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9461 scoped_ptr
<HttpTransaction
> trans(
9462 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9464 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9465 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9466 EXPECT_EQ(OK
, callback
.WaitForResult());
9468 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9469 ASSERT_TRUE(response
!= NULL
);
9470 ASSERT_TRUE(response
->headers
.get() != NULL
);
9471 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9473 std::string response_data
;
9474 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9475 EXPECT_EQ("hello world", response_data
);
9477 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9479 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9480 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9481 EXPECT_EQ(OK
, callback
.WaitForResult());
9483 response
= trans
->GetResponseInfo();
9484 ASSERT_TRUE(response
!= NULL
);
9485 ASSERT_TRUE(response
->headers
.get() != NULL
);
9486 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9487 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9488 EXPECT_TRUE(response
->was_npn_negotiated
);
9490 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9491 EXPECT_EQ("hello!", response_data
);
9494 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9495 session_deps_
.use_alternative_services
= true;
9496 session_deps_
.next_protos
= SpdyNextProtos();
9498 HttpRequestInfo request
;
9499 request
.method
= "GET";
9500 request
.url
= GURL("http://www.example.org/");
9501 request
.load_flags
= 0;
9503 std::string alternate_protocol_http_header
=
9504 GetAlternateProtocolHttpHeader();
9506 MockRead data_reads
[] = {
9507 MockRead("HTTP/1.1 200 OK\r\n"),
9508 MockRead(alternate_protocol_http_header
.c_str()),
9510 MockRead("hello world"),
9511 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9512 MockRead(ASYNC
, OK
),
9515 StaticSocketDataProvider
first_transaction(
9516 data_reads
, arraysize(data_reads
), NULL
, 0);
9517 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9518 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9520 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9521 StaticSocketDataProvider
hanging_socket(
9523 hanging_socket
.set_connect_data(never_finishing_connect
);
9524 // Socket 2 and 3 are the hanging Alternate-Protocol and
9525 // non-Alternate-Protocol jobs from the 2nd transaction.
9526 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9527 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9529 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9530 ssl
.SetNextProto(GetParam());
9531 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9532 ASSERT_TRUE(ssl
.cert
.get());
9533 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9535 scoped_ptr
<SpdyFrame
> req1(
9536 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9537 scoped_ptr
<SpdyFrame
> req2(
9538 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9539 MockWrite spdy_writes
[] = {
9540 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
9542 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9543 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9544 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9545 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9546 MockRead spdy_reads
[] = {
9547 CreateMockRead(*resp1
, 2),
9548 CreateMockRead(*data1
, 3),
9549 CreateMockRead(*resp2
, 4),
9550 CreateMockRead(*data2
, 5),
9551 MockRead(ASYNC
, 0, 6),
9554 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9555 arraysize(spdy_writes
));
9556 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9557 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9559 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9560 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9562 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9563 TestCompletionCallback callback1
;
9564 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9566 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9567 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9568 EXPECT_EQ(OK
, callback1
.WaitForResult());
9570 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9571 ASSERT_TRUE(response
!= NULL
);
9572 ASSERT_TRUE(response
->headers
.get() != NULL
);
9573 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9575 std::string response_data
;
9576 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9577 EXPECT_EQ("hello world", response_data
);
9579 TestCompletionCallback callback2
;
9580 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9581 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9584 TestCompletionCallback callback3
;
9585 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9586 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9587 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9589 EXPECT_EQ(OK
, callback2
.WaitForResult());
9590 EXPECT_EQ(OK
, callback3
.WaitForResult());
9592 response
= trans2
.GetResponseInfo();
9593 ASSERT_TRUE(response
!= NULL
);
9594 ASSERT_TRUE(response
->headers
.get() != NULL
);
9595 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9596 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9597 EXPECT_TRUE(response
->was_npn_negotiated
);
9598 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9599 EXPECT_EQ("hello!", response_data
);
9601 response
= trans3
.GetResponseInfo();
9602 ASSERT_TRUE(response
!= NULL
);
9603 ASSERT_TRUE(response
->headers
.get() != NULL
);
9604 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9605 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9606 EXPECT_TRUE(response
->was_npn_negotiated
);
9607 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9608 EXPECT_EQ("hello!", response_data
);
9611 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9612 session_deps_
.use_alternative_services
= true;
9613 session_deps_
.next_protos
= SpdyNextProtos();
9615 HttpRequestInfo request
;
9616 request
.method
= "GET";
9617 request
.url
= GURL("http://www.example.org/");
9618 request
.load_flags
= 0;
9620 std::string alternate_protocol_http_header
=
9621 GetAlternateProtocolHttpHeader();
9623 MockRead data_reads
[] = {
9624 MockRead("HTTP/1.1 200 OK\r\n"),
9625 MockRead(alternate_protocol_http_header
.c_str()),
9627 MockRead("hello world"),
9628 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9629 MockRead(ASYNC
, OK
),
9632 StaticSocketDataProvider
first_transaction(
9633 data_reads
, arraysize(data_reads
), NULL
, 0);
9634 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9636 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9637 ssl
.SetNextProto(GetParam());
9638 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9640 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9641 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9643 hanging_alternate_protocol_socket
.set_connect_data(
9644 never_finishing_connect
);
9645 session_deps_
.socket_factory
->AddSocketDataProvider(
9646 &hanging_alternate_protocol_socket
);
9648 // 2nd request is just a copy of the first one, over HTTP again.
9649 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9651 TestCompletionCallback callback
;
9653 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9654 scoped_ptr
<HttpTransaction
> trans(
9655 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9657 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9658 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9659 EXPECT_EQ(OK
, callback
.WaitForResult());
9661 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9662 ASSERT_TRUE(response
!= NULL
);
9663 ASSERT_TRUE(response
->headers
.get() != NULL
);
9664 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9666 std::string response_data
;
9667 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9668 EXPECT_EQ("hello world", response_data
);
9670 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9672 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9673 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9674 EXPECT_EQ(OK
, callback
.WaitForResult());
9676 response
= trans
->GetResponseInfo();
9677 ASSERT_TRUE(response
!= NULL
);
9678 ASSERT_TRUE(response
->headers
.get() != NULL
);
9679 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9680 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9681 EXPECT_FALSE(response
->was_npn_negotiated
);
9683 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9684 EXPECT_EQ("hello world", response_data
);
9687 class CapturingProxyResolver
: public ProxyResolver
{
9689 CapturingProxyResolver() {}
9690 ~CapturingProxyResolver() override
{}
9692 int GetProxyForURL(const GURL
& url
,
9694 const CompletionCallback
& callback
,
9695 RequestHandle
* request
,
9696 const BoundNetLog
& net_log
) override
{
9697 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9698 HostPortPair("myproxy", 80));
9699 results
->UseProxyServer(proxy_server
);
9700 resolved_
.push_back(url
);
9704 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9706 LoadState
GetLoadState(RequestHandle request
) const override
{
9708 return LOAD_STATE_IDLE
;
9711 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9714 std::vector
<GURL
> resolved_
;
9716 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9719 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9721 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9722 : ProxyResolverFactory(false), resolver_(resolver
) {}
9724 int CreateProxyResolver(
9725 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9726 scoped_ptr
<ProxyResolver
>* resolver
,
9727 const net::CompletionCallback
& callback
,
9728 scoped_ptr
<Request
>* request
) override
{
9729 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9734 ProxyResolver
* resolver_
;
9737 TEST_P(HttpNetworkTransactionTest
,
9738 UseAlternateProtocolForTunneledNpnSpdy
) {
9739 session_deps_
.use_alternative_services
= true;
9740 session_deps_
.next_protos
= SpdyNextProtos();
9742 ProxyConfig proxy_config
;
9743 proxy_config
.set_auto_detect(true);
9744 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9746 CapturingProxyResolver capturing_proxy_resolver
;
9747 session_deps_
.proxy_service
.reset(new ProxyService(
9748 new ProxyConfigServiceFixed(proxy_config
),
9750 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9753 session_deps_
.net_log
= &net_log
;
9755 HttpRequestInfo request
;
9756 request
.method
= "GET";
9757 request
.url
= GURL("http://www.example.org/");
9758 request
.load_flags
= 0;
9760 std::string alternate_protocol_http_header
=
9761 GetAlternateProtocolHttpHeader();
9763 MockRead data_reads
[] = {
9764 MockRead("HTTP/1.1 200 OK\r\n"),
9765 MockRead(alternate_protocol_http_header
.c_str()),
9767 MockRead("hello world"),
9768 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9769 MockRead(ASYNC
, OK
),
9772 StaticSocketDataProvider
first_transaction(
9773 data_reads
, arraysize(data_reads
), NULL
, 0);
9774 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9776 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9777 ssl
.SetNextProto(GetParam());
9778 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9779 ASSERT_TRUE(ssl
.cert
.get());
9780 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9782 scoped_ptr
<SpdyFrame
> req(
9783 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9784 MockWrite spdy_writes
[] = {
9786 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9787 "Host: www.example.org\r\n"
9788 "Proxy-Connection: keep-alive\r\n\r\n"),
9789 CreateMockWrite(*req
, 2),
9792 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9794 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9795 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9796 MockRead spdy_reads
[] = {
9797 MockRead(ASYNC
, 1, kCONNECTResponse
),
9798 CreateMockRead(*resp
.get(), 3),
9799 CreateMockRead(*data
.get(), 4),
9800 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
9803 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9804 arraysize(spdy_writes
));
9805 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9807 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9808 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9810 hanging_non_alternate_protocol_socket
.set_connect_data(
9811 never_finishing_connect
);
9812 session_deps_
.socket_factory
->AddSocketDataProvider(
9813 &hanging_non_alternate_protocol_socket
);
9815 TestCompletionCallback callback
;
9817 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9818 scoped_ptr
<HttpTransaction
> trans(
9819 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9821 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9822 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9823 EXPECT_EQ(OK
, callback
.WaitForResult());
9825 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9826 ASSERT_TRUE(response
!= NULL
);
9827 ASSERT_TRUE(response
->headers
.get() != NULL
);
9828 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9829 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9830 EXPECT_FALSE(response
->was_npn_negotiated
);
9832 std::string response_data
;
9833 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9834 EXPECT_EQ("hello world", response_data
);
9836 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9838 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9839 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9840 EXPECT_EQ(OK
, callback
.WaitForResult());
9842 response
= trans
->GetResponseInfo();
9843 ASSERT_TRUE(response
!= NULL
);
9844 ASSERT_TRUE(response
->headers
.get() != NULL
);
9845 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9846 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9847 EXPECT_TRUE(response
->was_npn_negotiated
);
9849 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9850 EXPECT_EQ("hello!", response_data
);
9851 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
9852 EXPECT_EQ("http://www.example.org/",
9853 capturing_proxy_resolver
.resolved()[0].spec());
9854 EXPECT_EQ("https://www.example.org/",
9855 capturing_proxy_resolver
.resolved()[1].spec());
9857 LoadTimingInfo load_timing_info
;
9858 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9859 TestLoadTimingNotReusedWithPac(load_timing_info
,
9860 CONNECT_TIMING_HAS_SSL_TIMES
);
9863 TEST_P(HttpNetworkTransactionTest
,
9864 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9865 session_deps_
.use_alternative_services
= true;
9866 session_deps_
.next_protos
= SpdyNextProtos();
9868 HttpRequestInfo request
;
9869 request
.method
= "GET";
9870 request
.url
= GURL("http://www.example.org/");
9871 request
.load_flags
= 0;
9873 std::string alternate_protocol_http_header
=
9874 GetAlternateProtocolHttpHeader();
9876 MockRead data_reads
[] = {
9877 MockRead("HTTP/1.1 200 OK\r\n"),
9878 MockRead(alternate_protocol_http_header
.c_str()),
9880 MockRead("hello world"),
9881 MockRead(ASYNC
, OK
),
9884 StaticSocketDataProvider
first_transaction(
9885 data_reads
, arraysize(data_reads
), NULL
, 0);
9886 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9888 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9889 ssl
.SetNextProto(GetParam());
9890 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9891 ASSERT_TRUE(ssl
.cert
.get());
9892 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9894 scoped_ptr
<SpdyFrame
> req(
9895 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9896 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9898 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9899 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9900 MockRead spdy_reads
[] = {
9901 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9904 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9905 arraysize(spdy_writes
));
9906 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9908 TestCompletionCallback callback
;
9910 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9912 scoped_ptr
<HttpTransaction
> trans(
9913 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9915 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9916 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9917 EXPECT_EQ(OK
, callback
.WaitForResult());
9919 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9920 ASSERT_TRUE(response
!= NULL
);
9921 ASSERT_TRUE(response
->headers
.get() != NULL
);
9922 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9924 std::string response_data
;
9925 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9926 EXPECT_EQ("hello world", response_data
);
9928 // Set up an initial SpdySession in the pool to reuse.
9929 HostPortPair
host_port_pair("www.example.org", 443);
9930 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9931 PRIVACY_MODE_DISABLED
);
9932 base::WeakPtr
<SpdySession
> spdy_session
=
9933 CreateSecureSpdySession(session
, key
, BoundNetLog());
9935 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9937 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9938 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9939 EXPECT_EQ(OK
, callback
.WaitForResult());
9941 response
= trans
->GetResponseInfo();
9942 ASSERT_TRUE(response
!= NULL
);
9943 ASSERT_TRUE(response
->headers
.get() != NULL
);
9944 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9945 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9946 EXPECT_TRUE(response
->was_npn_negotiated
);
9948 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9949 EXPECT_EQ("hello!", response_data
);
9952 // GenerateAuthToken is a mighty big test.
9953 // It tests all permutation of GenerateAuthToken behavior:
9954 // - Synchronous and Asynchronous completion.
9955 // - OK or error on completion.
9956 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9957 // - HTTP or HTTPS backend (to include proxy tunneling).
9958 // - Non-authenticating and authenticating backend.
9960 // In all, there are 44 reasonable permuations (for example, if there are
9961 // problems generating an auth token for an authenticating proxy, we don't
9962 // need to test all permutations of the backend server).
9964 // The test proceeds by going over each of the configuration cases, and
9965 // potentially running up to three rounds in each of the tests. The TestConfig
9966 // specifies both the configuration for the test as well as the expectations
9968 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9969 static const char kServer
[] = "http://www.example.com";
9970 static const char kSecureServer
[] = "https://www.example.com";
9971 static const char kProxy
[] = "myproxy:70";
9972 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9980 const MockWrite
kGet(
9981 "GET / HTTP/1.1\r\n"
9982 "Host: www.example.com\r\n"
9983 "Connection: keep-alive\r\n\r\n");
9984 const MockWrite
kGetProxy(
9985 "GET http://www.example.com/ HTTP/1.1\r\n"
9986 "Host: www.example.com\r\n"
9987 "Proxy-Connection: keep-alive\r\n\r\n");
9988 const MockWrite
kGetAuth(
9989 "GET / HTTP/1.1\r\n"
9990 "Host: www.example.com\r\n"
9991 "Connection: keep-alive\r\n"
9992 "Authorization: auth_token\r\n\r\n");
9993 const MockWrite
kGetProxyAuth(
9994 "GET http://www.example.com/ HTTP/1.1\r\n"
9995 "Host: www.example.com\r\n"
9996 "Proxy-Connection: keep-alive\r\n"
9997 "Proxy-Authorization: auth_token\r\n\r\n");
9998 const MockWrite
kGetAuthThroughProxy(
9999 "GET http://www.example.com/ HTTP/1.1\r\n"
10000 "Host: www.example.com\r\n"
10001 "Proxy-Connection: keep-alive\r\n"
10002 "Authorization: auth_token\r\n\r\n");
10003 const MockWrite
kGetAuthWithProxyAuth(
10004 "GET http://www.example.com/ HTTP/1.1\r\n"
10005 "Host: www.example.com\r\n"
10006 "Proxy-Connection: keep-alive\r\n"
10007 "Proxy-Authorization: auth_token\r\n"
10008 "Authorization: auth_token\r\n\r\n");
10009 const MockWrite
kConnect(
10010 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10011 "Host: www.example.com\r\n"
10012 "Proxy-Connection: keep-alive\r\n\r\n");
10013 const MockWrite
kConnectProxyAuth(
10014 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10015 "Host: www.example.com\r\n"
10016 "Proxy-Connection: keep-alive\r\n"
10017 "Proxy-Authorization: auth_token\r\n\r\n");
10019 const MockRead
kSuccess(
10020 "HTTP/1.1 200 OK\r\n"
10021 "Content-Type: text/html; charset=iso-8859-1\r\n"
10022 "Content-Length: 3\r\n\r\n"
10024 const MockRead
kFailure(
10025 "Should not be called.");
10026 const MockRead
kServerChallenge(
10027 "HTTP/1.1 401 Unauthorized\r\n"
10028 "WWW-Authenticate: Mock realm=server\r\n"
10029 "Content-Type: text/html; charset=iso-8859-1\r\n"
10030 "Content-Length: 14\r\n\r\n"
10031 "Unauthorized\r\n");
10032 const MockRead
kProxyChallenge(
10033 "HTTP/1.1 407 Unauthorized\r\n"
10034 "Proxy-Authenticate: Mock realm=proxy\r\n"
10035 "Proxy-Connection: close\r\n"
10036 "Content-Type: text/html; charset=iso-8859-1\r\n"
10037 "Content-Length: 14\r\n\r\n"
10038 "Unauthorized\r\n");
10039 const MockRead
kProxyConnected(
10040 "HTTP/1.1 200 Connection Established\r\n\r\n");
10042 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10043 // no constructors, but the C++ compiler on Windows warns about
10044 // unspecified data in compound literals. So, moved to using constructors,
10045 // and TestRound's created with the default constructor should not be used.
10048 : expected_rv(ERR_UNEXPECTED
),
10052 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10053 int expected_rv_arg
)
10054 : write(write_arg
),
10056 expected_rv(expected_rv_arg
),
10060 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10061 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
10062 const MockRead
* extra_read_arg
)
10063 : write(write_arg
),
10065 expected_rv(expected_rv_arg
),
10066 extra_write(extra_write_arg
),
10067 extra_read(extra_read_arg
) {
10072 const MockWrite
* extra_write
;
10073 const MockRead
* extra_read
;
10076 static const int kNoSSL
= 500;
10078 struct TestConfig
{
10079 const char* const proxy_url
;
10080 AuthTiming proxy_auth_timing
;
10082 const char* const server_url
;
10083 AuthTiming server_auth_timing
;
10084 int server_auth_rv
;
10085 int num_auth_rounds
;
10086 int first_ssl_round
;
10087 TestRound rounds
[3];
10088 } test_configs
[] = {
10089 // Non-authenticating HTTP server with a direct connection.
10090 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10091 { TestRound(kGet
, kSuccess
, OK
)}},
10092 // Authenticating HTTP server with a direct connection.
10093 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10094 { TestRound(kGet
, kServerChallenge
, OK
),
10095 TestRound(kGetAuth
, kSuccess
, OK
)}},
10096 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10097 { TestRound(kGet
, kServerChallenge
, OK
),
10098 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10099 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10100 { TestRound(kGet
, kServerChallenge
, OK
),
10101 TestRound(kGetAuth
, kSuccess
, OK
)}},
10102 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10103 { TestRound(kGet
, kServerChallenge
, OK
),
10104 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10105 // Non-authenticating HTTP server through a non-authenticating proxy.
10106 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10107 { TestRound(kGetProxy
, kSuccess
, OK
)}},
10108 // Authenticating HTTP server through a non-authenticating proxy.
10109 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10110 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10111 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10112 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10113 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10114 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10115 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10116 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10117 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10118 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10119 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10120 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10121 // Non-authenticating HTTP server through an authenticating proxy.
10122 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10123 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10124 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10125 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10126 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10127 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10128 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10129 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10130 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10131 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10132 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10133 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10134 // Authenticating HTTP server through an authenticating proxy.
10135 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10136 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10137 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10138 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10139 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10140 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10141 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10142 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10143 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10144 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10145 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10146 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10147 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10148 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10149 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10150 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10151 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10152 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10153 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10154 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10155 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10156 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10157 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10158 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10159 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10160 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10161 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10162 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10163 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10164 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10165 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10166 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10167 // Non-authenticating HTTPS server with a direct connection.
10168 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10169 { TestRound(kGet
, kSuccess
, OK
)}},
10170 // Authenticating HTTPS server with a direct connection.
10171 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10172 { TestRound(kGet
, kServerChallenge
, OK
),
10173 TestRound(kGetAuth
, kSuccess
, OK
)}},
10174 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10175 { TestRound(kGet
, kServerChallenge
, OK
),
10176 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10177 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10178 { TestRound(kGet
, kServerChallenge
, OK
),
10179 TestRound(kGetAuth
, kSuccess
, OK
)}},
10180 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10181 { TestRound(kGet
, kServerChallenge
, OK
),
10182 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10183 // Non-authenticating HTTPS server with a non-authenticating proxy.
10184 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10185 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10186 // Authenticating HTTPS server through a non-authenticating proxy.
10187 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10188 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10189 TestRound(kGetAuth
, kSuccess
, OK
)}},
10190 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10191 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10192 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10193 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10194 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10195 TestRound(kGetAuth
, kSuccess
, OK
)}},
10196 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10197 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10198 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10199 // Non-Authenticating HTTPS server through an authenticating proxy.
10200 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10201 { TestRound(kConnect
, kProxyChallenge
, OK
),
10202 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10203 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10204 { TestRound(kConnect
, kProxyChallenge
, OK
),
10205 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10206 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10207 { TestRound(kConnect
, kProxyChallenge
, OK
),
10208 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10209 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10210 { TestRound(kConnect
, kProxyChallenge
, OK
),
10211 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10212 // Authenticating HTTPS server through an authenticating proxy.
10213 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10214 { TestRound(kConnect
, kProxyChallenge
, OK
),
10215 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10216 &kGet
, &kServerChallenge
),
10217 TestRound(kGetAuth
, kSuccess
, OK
)}},
10218 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10219 { TestRound(kConnect
, kProxyChallenge
, OK
),
10220 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10221 &kGet
, &kServerChallenge
),
10222 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10223 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10224 { TestRound(kConnect
, kProxyChallenge
, OK
),
10225 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10226 &kGet
, &kServerChallenge
),
10227 TestRound(kGetAuth
, kSuccess
, OK
)}},
10228 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10229 { TestRound(kConnect
, kProxyChallenge
, OK
),
10230 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10231 &kGet
, &kServerChallenge
),
10232 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10233 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10234 { TestRound(kConnect
, kProxyChallenge
, OK
),
10235 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10236 &kGet
, &kServerChallenge
),
10237 TestRound(kGetAuth
, kSuccess
, OK
)}},
10238 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10239 { TestRound(kConnect
, kProxyChallenge
, OK
),
10240 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10241 &kGet
, &kServerChallenge
),
10242 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10243 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10244 { TestRound(kConnect
, kProxyChallenge
, OK
),
10245 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10246 &kGet
, &kServerChallenge
),
10247 TestRound(kGetAuth
, kSuccess
, OK
)}},
10248 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10249 { TestRound(kConnect
, kProxyChallenge
, OK
),
10250 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10251 &kGet
, &kServerChallenge
),
10252 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10255 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10256 HttpAuthHandlerMock::Factory
* auth_factory(
10257 new HttpAuthHandlerMock::Factory());
10258 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10259 const TestConfig
& test_config
= test_configs
[i
];
10261 // Set up authentication handlers as necessary.
10262 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10263 for (int n
= 0; n
< 2; n
++) {
10264 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10265 std::string auth_challenge
= "Mock realm=proxy";
10266 GURL
origin(test_config
.proxy_url
);
10267 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10268 auth_challenge
.end());
10269 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10270 origin
, BoundNetLog());
10271 auth_handler
->SetGenerateExpectation(
10272 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10273 test_config
.proxy_auth_rv
);
10274 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10277 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10278 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10279 std::string auth_challenge
= "Mock realm=server";
10280 GURL
origin(test_config
.server_url
);
10281 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10282 auth_challenge
.end());
10283 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10284 origin
, BoundNetLog());
10285 auth_handler
->SetGenerateExpectation(
10286 test_config
.server_auth_timing
== AUTH_ASYNC
,
10287 test_config
.server_auth_rv
);
10288 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10290 if (test_config
.proxy_url
) {
10291 session_deps_
.proxy_service
.reset(
10292 ProxyService::CreateFixed(test_config
.proxy_url
));
10294 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10297 HttpRequestInfo request
;
10298 request
.method
= "GET";
10299 request
.url
= GURL(test_config
.server_url
);
10300 request
.load_flags
= 0;
10302 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10303 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10305 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10307 std::vector
<std::vector
<MockRead
>> mock_reads(1);
10308 std::vector
<std::vector
<MockWrite
>> mock_writes(1);
10309 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10310 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10312 // Set up expected reads and writes.
10313 mock_reads
.back().push_back(read_write_round
.read
);
10314 mock_writes
.back().push_back(read_write_round
.write
);
10316 // kProxyChallenge uses Proxy-Connection: close which means that the
10317 // socket is closed and a new one will be created for the next request.
10318 if (read_write_round
.read
.data
== kProxyChallenge
.data
&&
10319 read_write_round
.write
.data
!= kConnect
.data
) {
10320 mock_reads
.push_back(std::vector
<MockRead
>());
10321 mock_writes
.push_back(std::vector
<MockWrite
>());
10324 if (read_write_round
.extra_read
) {
10325 mock_reads
.back().push_back(*read_write_round
.extra_read
);
10327 if (read_write_round
.extra_write
) {
10328 mock_writes
.back().push_back(*read_write_round
.extra_write
);
10331 // Add an SSL sequence if necessary.
10332 if (round
>= test_config
.first_ssl_round
)
10333 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10334 &ssl_socket_data_provider
);
10337 ScopedVector
<StaticSocketDataProvider
> data_providers
;
10338 for (size_t i
= 0; i
< mock_reads
.size(); ++i
) {
10339 data_providers
.push_back(new StaticSocketDataProvider(
10340 vector_as_array(&mock_reads
[i
]), mock_reads
[i
].size(),
10341 vector_as_array(&mock_writes
[i
]), mock_writes
[i
].size()));
10342 session_deps_
.socket_factory
->AddSocketDataProvider(
10343 data_providers
.back());
10346 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10347 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10348 // Start or restart the transaction.
10349 TestCompletionCallback callback
;
10352 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10354 rv
= trans
.RestartWithAuth(
10355 AuthCredentials(kFoo
, kBar
), callback
.callback());
10357 if (rv
== ERR_IO_PENDING
)
10358 rv
= callback
.WaitForResult();
10360 // Compare results with expected data.
10361 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10362 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10363 if (read_write_round
.expected_rv
!= OK
) {
10364 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10367 if (round
+ 1 < test_config
.num_auth_rounds
) {
10368 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10370 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10376 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10377 // Do multi-round authentication and make sure it works correctly.
10378 HttpAuthHandlerMock::Factory
* auth_factory(
10379 new HttpAuthHandlerMock::Factory());
10380 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10381 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10382 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10383 session_deps_
.host_resolver
->set_synchronous_mode(true);
10385 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10386 auth_handler
->set_connection_based(true);
10387 std::string auth_challenge
= "Mock realm=server";
10388 GURL
origin("http://www.example.com");
10389 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10390 auth_challenge
.end());
10391 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10392 origin
, BoundNetLog());
10393 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10396 const HttpResponseInfo
* response
= NULL
;
10397 HttpRequestInfo request
;
10398 request
.method
= "GET";
10399 request
.url
= origin
;
10400 request
.load_flags
= 0;
10402 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10404 // Use a TCP Socket Pool with only one connection per group. This is used
10405 // to validate that the TCP socket is not released to the pool between
10406 // each round of multi-round authentication.
10407 HttpNetworkSessionPeer
session_peer(session
);
10408 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10409 50, // Max sockets for pool
10410 1, // Max sockets per group
10411 session_deps_
.host_resolver
.get(),
10412 session_deps_
.socket_factory
.get(),
10413 session_deps_
.net_log
);
10414 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10415 new MockClientSocketPoolManager
);
10416 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10417 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10419 scoped_ptr
<HttpTransaction
> trans(
10420 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10421 TestCompletionCallback callback
;
10423 const MockWrite
kGet(
10424 "GET / HTTP/1.1\r\n"
10425 "Host: www.example.com\r\n"
10426 "Connection: keep-alive\r\n\r\n");
10427 const MockWrite
kGetAuth(
10428 "GET / HTTP/1.1\r\n"
10429 "Host: www.example.com\r\n"
10430 "Connection: keep-alive\r\n"
10431 "Authorization: auth_token\r\n\r\n");
10433 const MockRead
kServerChallenge(
10434 "HTTP/1.1 401 Unauthorized\r\n"
10435 "WWW-Authenticate: Mock realm=server\r\n"
10436 "Content-Type: text/html; charset=iso-8859-1\r\n"
10437 "Content-Length: 14\r\n\r\n"
10438 "Unauthorized\r\n");
10439 const MockRead
kSuccess(
10440 "HTTP/1.1 200 OK\r\n"
10441 "Content-Type: text/html; charset=iso-8859-1\r\n"
10442 "Content-Length: 3\r\n\r\n"
10445 MockWrite writes
[] = {
10454 // Competing request
10457 MockRead reads
[] = {
10466 // Competing response
10469 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10470 writes
, arraysize(writes
));
10471 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10473 const char kSocketGroup
[] = "www.example.com:80";
10475 // First round of authentication.
10476 auth_handler
->SetGenerateExpectation(false, OK
);
10477 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10478 if (rv
== ERR_IO_PENDING
)
10479 rv
= callback
.WaitForResult();
10481 response
= trans
->GetResponseInfo();
10482 ASSERT_TRUE(response
!= NULL
);
10483 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10484 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10486 // In between rounds, another request comes in for the same domain.
10487 // It should not be able to grab the TCP socket that trans has already
10489 scoped_ptr
<HttpTransaction
> trans_compete(
10490 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10491 TestCompletionCallback callback_compete
;
10492 rv
= trans_compete
->Start(
10493 &request
, callback_compete
.callback(), BoundNetLog());
10494 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10495 // callback_compete.WaitForResult at this point would stall forever,
10496 // since the HttpNetworkTransaction does not release the request back to
10497 // the pool until after authentication completes.
10499 // Second round of authentication.
10500 auth_handler
->SetGenerateExpectation(false, OK
);
10501 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10502 if (rv
== ERR_IO_PENDING
)
10503 rv
= callback
.WaitForResult();
10505 response
= trans
->GetResponseInfo();
10506 ASSERT_TRUE(response
!= NULL
);
10507 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10508 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10510 // Third round of authentication.
10511 auth_handler
->SetGenerateExpectation(false, OK
);
10512 rv
= trans
->RestartWithAuth(AuthCredentials(), 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 // Fourth round of authentication, which completes successfully.
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 // Read the body since the fourth round was successful. This will also
10533 // release the socket back to the pool.
10534 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10535 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10536 if (rv
== ERR_IO_PENDING
)
10537 rv
= callback
.WaitForResult();
10539 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10541 // There are still 0 idle sockets, since the trans_compete transaction
10542 // will be handed it immediately after trans releases it to the group.
10543 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10545 // The competing request can now finish. Wait for the headers and then
10547 rv
= callback_compete
.WaitForResult();
10549 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10550 if (rv
== ERR_IO_PENDING
)
10551 rv
= callback
.WaitForResult();
10553 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10556 // Finally, the socket is released to the group.
10557 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10560 // This tests the case that a request is issued via http instead of spdy after
10561 // npn is negotiated.
10562 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10563 session_deps_
.use_alternative_services
= true;
10564 NextProtoVector next_protos
;
10565 next_protos
.push_back(kProtoHTTP11
);
10566 session_deps_
.next_protos
= next_protos
;
10568 HttpRequestInfo request
;
10569 request
.method
= "GET";
10570 request
.url
= GURL("https://www.example.org/");
10571 request
.load_flags
= 0;
10573 MockWrite data_writes
[] = {
10575 "GET / HTTP/1.1\r\n"
10576 "Host: www.example.org\r\n"
10577 "Connection: keep-alive\r\n\r\n"),
10580 std::string alternate_protocol_http_header
=
10581 GetAlternateProtocolHttpHeader();
10583 MockRead data_reads
[] = {
10584 MockRead("HTTP/1.1 200 OK\r\n"),
10585 MockRead(alternate_protocol_http_header
.c_str()),
10587 MockRead("hello world"),
10588 MockRead(SYNCHRONOUS
, OK
),
10591 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10592 ssl
.SetNextProto(kProtoHTTP11
);
10594 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10596 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10597 data_writes
, arraysize(data_writes
));
10598 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10600 TestCompletionCallback callback
;
10602 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10603 scoped_ptr
<HttpTransaction
> trans(
10604 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10606 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10608 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10609 EXPECT_EQ(OK
, callback
.WaitForResult());
10611 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10612 ASSERT_TRUE(response
!= NULL
);
10613 ASSERT_TRUE(response
->headers
.get() != NULL
);
10614 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10616 std::string response_data
;
10617 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10618 EXPECT_EQ("hello world", response_data
);
10620 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10621 EXPECT_TRUE(response
->was_npn_negotiated
);
10624 // Simulate the SSL handshake completing with an NPN negotiation followed by an
10625 // immediate server closing of the socket.
10626 // Regression test for https://crbug.com/46369.
10627 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10628 session_deps_
.use_alternative_services
= true;
10629 session_deps_
.next_protos
= SpdyNextProtos();
10631 HttpRequestInfo request
;
10632 request
.method
= "GET";
10633 request
.url
= GURL("https://www.example.org/");
10634 request
.load_flags
= 0;
10636 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10637 ssl
.SetNextProto(GetParam());
10638 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10640 scoped_ptr
<SpdyFrame
> req(
10641 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10642 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 1)};
10644 MockRead spdy_reads
[] = {
10645 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10648 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10649 arraysize(spdy_writes
));
10650 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10652 TestCompletionCallback callback
;
10654 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10655 scoped_ptr
<HttpTransaction
> trans(
10656 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10658 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10659 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10660 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10663 // A subclass of HttpAuthHandlerMock that records the request URL when
10664 // it gets it. This is needed since the auth handler may get destroyed
10665 // before we get a chance to query it.
10666 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10668 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10670 ~UrlRecordingHttpAuthHandlerMock() override
{}
10673 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10674 const HttpRequestInfo
* request
,
10675 const CompletionCallback
& callback
,
10676 std::string
* auth_token
) override
{
10677 *url_
= request
->url
;
10678 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10679 credentials
, request
, callback
, auth_token
);
10686 // This test ensures that the URL passed into the proxy is upgraded to https
10687 // when doing an Alternate Protocol upgrade.
10688 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10689 session_deps_
.use_alternative_services
= true;
10690 session_deps_
.next_protos
= SpdyNextProtos();
10692 session_deps_
.proxy_service
.reset(
10693 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10694 TestNetLog net_log
;
10695 session_deps_
.net_log
= &net_log
;
10698 HttpAuthHandlerMock::Factory
* auth_factory
=
10699 new HttpAuthHandlerMock::Factory();
10700 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10701 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10702 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10703 auth_factory
->set_do_init_from_challenge(true);
10704 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10707 HttpRequestInfo request
;
10708 request
.method
= "GET";
10709 request
.url
= GURL("http://www.example.org");
10710 request
.load_flags
= 0;
10712 // First round goes unauthenticated through the proxy.
10713 MockWrite data_writes_1
[] = {
10715 "GET http://www.example.org/ HTTP/1.1\r\n"
10716 "Host: www.example.org\r\n"
10717 "Proxy-Connection: keep-alive\r\n"
10720 MockRead data_reads_1
[] = {
10721 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10722 MockRead("HTTP/1.1 200 OK\r\n"),
10723 MockRead("Alternate-Protocol: 443:"),
10724 MockRead(GetAlternateProtocolFromParam()),
10726 MockRead("Proxy-Connection: close\r\n"),
10729 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10730 data_writes_1
, arraysize(data_writes_1
));
10732 // Second round tries to tunnel to www.example.org due to the
10733 // Alternate-Protocol announcement in the first round. It fails due
10734 // to a proxy authentication challenge.
10735 // After the failure, a tunnel is established to www.example.org using
10736 // Proxy-Authorization headers. There is then a SPDY request round.
10738 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10739 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10740 // does a Disconnect and Connect on the same socket, rather than trying
10741 // to obtain a new one.
10743 // NOTE: Originally, the proxy response to the second CONNECT request
10744 // simply returned another 407 so the unit test could skip the SSL connection
10745 // establishment and SPDY framing issues. Alas, the
10746 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10747 // complicated to set up expectations for than the SPDY session.
10749 scoped_ptr
<SpdyFrame
> req(
10750 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10751 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10752 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10754 MockWrite data_writes_2
[] = {
10755 // First connection attempt without Proxy-Authorization.
10756 MockWrite(ASYNC
, 0,
10757 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10758 "Host: www.example.org\r\n"
10759 "Proxy-Connection: keep-alive\r\n"
10762 // Second connection attempt with Proxy-Authorization.
10763 MockWrite(ASYNC
, 2,
10764 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10765 "Host: www.example.org\r\n"
10766 "Proxy-Connection: keep-alive\r\n"
10767 "Proxy-Authorization: auth_token\r\n"
10771 CreateMockWrite(*req
, 4),
10773 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10774 "Proxy-Authenticate: Mock\r\n"
10775 "Proxy-Connection: close\r\n"
10777 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10778 MockRead data_reads_2
[] = {
10779 // First connection attempt fails
10780 MockRead(ASYNC
, kRejectConnectResponse
,
10781 arraysize(kRejectConnectResponse
) - 1, 1),
10783 // Second connection attempt passes
10784 MockRead(ASYNC
, kAcceptConnectResponse
,
10785 arraysize(kAcceptConnectResponse
) - 1, 3),
10788 CreateMockRead(*resp
.get(), 5),
10789 CreateMockRead(*data
.get(), 6),
10790 MockRead(ASYNC
, 0, 0, 7),
10792 SequencedSocketData
data_2(data_reads_2
, arraysize(data_reads_2
),
10793 data_writes_2
, arraysize(data_writes_2
));
10795 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10796 ssl
.SetNextProto(GetParam());
10797 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10798 ASSERT_TRUE(ssl
.cert
.get());
10800 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10801 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10803 hanging_non_alternate_protocol_socket
.set_connect_data(
10804 never_finishing_connect
);
10806 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10807 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10808 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10809 session_deps_
.socket_factory
->AddSocketDataProvider(
10810 &hanging_non_alternate_protocol_socket
);
10811 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10813 // First round should work and provide the Alternate-Protocol state.
10814 TestCompletionCallback callback_1
;
10815 scoped_ptr
<HttpTransaction
> trans_1(
10816 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10817 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10818 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10819 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10821 // Second round should attempt a tunnel connect and get an auth challenge.
10822 TestCompletionCallback callback_2
;
10823 scoped_ptr
<HttpTransaction
> trans_2(
10824 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10825 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10826 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10827 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10828 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10829 ASSERT_TRUE(response
!= NULL
);
10830 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10832 // Restart with auth. Tunnel should work and response received.
10833 TestCompletionCallback callback_3
;
10834 rv
= trans_2
->RestartWithAuth(
10835 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10836 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10837 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10839 // After all that work, these two lines (or actually, just the scheme) are
10840 // what this test is all about. Make sure it happens correctly.
10841 EXPECT_EQ("https", request_url
.scheme());
10842 EXPECT_EQ("www.example.org", request_url
.host());
10844 LoadTimingInfo load_timing_info
;
10845 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10846 TestLoadTimingNotReusedWithPac(load_timing_info
,
10847 CONNECT_TIMING_HAS_SSL_TIMES
);
10850 // Test that if we cancel the transaction as the connection is completing, that
10851 // everything tears down correctly.
10852 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10853 // Setup everything about the connection to complete synchronously, so that
10854 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10855 // for is the callback from the HttpStreamRequest.
10856 // Then cancel the transaction.
10857 // Verify that we don't crash.
10858 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10859 MockRead data_reads
[] = {
10860 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10861 MockRead(SYNCHRONOUS
, "hello world"),
10862 MockRead(SYNCHRONOUS
, OK
),
10865 HttpRequestInfo request
;
10866 request
.method
= "GET";
10867 request
.url
= GURL("http://www.example.org/");
10868 request
.load_flags
= 0;
10870 session_deps_
.host_resolver
->set_synchronous_mode(true);
10871 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10872 scoped_ptr
<HttpTransaction
> trans(
10873 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10875 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10876 data
.set_connect_data(mock_connect
);
10877 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10879 TestCompletionCallback callback
;
10881 BoundTestNetLog log
;
10882 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10883 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10884 trans
.reset(); // Cancel the transaction here.
10886 base::MessageLoop::current()->RunUntilIdle();
10889 // Test that if a transaction is cancelled after receiving the headers, the
10890 // stream is drained properly and added back to the socket pool. The main
10891 // purpose of this test is to make sure that an HttpStreamParser can be read
10892 // from after the HttpNetworkTransaction and the objects it owns have been
10894 // See http://crbug.com/368418
10895 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10896 MockRead data_reads
[] = {
10897 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10898 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10899 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10900 MockRead(ASYNC
, "1"),
10901 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10902 // HttpNetworkTransaction has been deleted.
10903 MockRead(ASYNC
, "2"),
10904 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10906 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10907 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10909 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10912 HttpRequestInfo request
;
10913 request
.method
= "GET";
10914 request
.url
= GURL("http://www.example.org/");
10915 request
.load_flags
= 0;
10917 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10918 TestCompletionCallback callback
;
10920 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10922 callback
.WaitForResult();
10924 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10925 ASSERT_TRUE(response
!= NULL
);
10926 EXPECT_TRUE(response
->headers
.get() != NULL
);
10927 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10929 // The transaction and HttpRequestInfo are deleted.
10932 // Let the HttpResponseBodyDrainer drain the socket.
10933 base::MessageLoop::current()->RunUntilIdle();
10935 // Socket should now be idle, waiting to be reused.
10936 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10939 // Test a basic GET request through a proxy.
10940 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10941 session_deps_
.proxy_service
.reset(
10942 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10943 BoundTestNetLog log
;
10944 session_deps_
.net_log
= log
.bound().net_log();
10945 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10947 HttpRequestInfo request
;
10948 request
.method
= "GET";
10949 request
.url
= GURL("http://www.example.org/");
10951 MockWrite data_writes1
[] = {
10953 "GET http://www.example.org/ HTTP/1.1\r\n"
10954 "Host: www.example.org\r\n"
10955 "Proxy-Connection: keep-alive\r\n\r\n"),
10958 MockRead data_reads1
[] = {
10959 MockRead("HTTP/1.1 200 OK\r\n"),
10960 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10961 MockRead("Content-Length: 100\r\n\r\n"),
10962 MockRead(SYNCHRONOUS
, OK
),
10965 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10966 data_writes1
, arraysize(data_writes1
));
10967 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10969 TestCompletionCallback callback1
;
10971 scoped_ptr
<HttpTransaction
> trans(
10972 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10973 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10974 trans
->SetBeforeProxyHeadersSentCallback(
10975 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10976 base::Unretained(&proxy_headers_handler
)));
10978 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10981 rv
= callback1
.WaitForResult();
10984 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10985 ASSERT_TRUE(response
!= NULL
);
10987 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10988 EXPECT_EQ(200, response
->headers
->response_code());
10989 EXPECT_EQ(100, response
->headers
->GetContentLength());
10990 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10992 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10993 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10994 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10995 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10997 LoadTimingInfo load_timing_info
;
10998 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10999 TestLoadTimingNotReusedWithPac(load_timing_info
,
11000 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
11003 // Test a basic HTTPS GET request through a proxy.
11004 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
11005 session_deps_
.proxy_service
.reset(
11006 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11007 BoundTestNetLog log
;
11008 session_deps_
.net_log
= log
.bound().net_log();
11009 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11011 HttpRequestInfo request
;
11012 request
.method
= "GET";
11013 request
.url
= GURL("https://www.example.org/");
11015 // Since we have proxy, should try to establish tunnel.
11016 MockWrite data_writes1
[] = {
11018 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11019 "Host: www.example.org\r\n"
11020 "Proxy-Connection: keep-alive\r\n\r\n"),
11023 "GET / HTTP/1.1\r\n"
11024 "Host: www.example.org\r\n"
11025 "Connection: keep-alive\r\n\r\n"),
11028 MockRead data_reads1
[] = {
11029 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11031 MockRead("HTTP/1.1 200 OK\r\n"),
11032 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11033 MockRead("Content-Length: 100\r\n\r\n"),
11034 MockRead(SYNCHRONOUS
, OK
),
11037 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11038 data_writes1
, arraysize(data_writes1
));
11039 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11040 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11041 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11043 TestCompletionCallback callback1
;
11045 scoped_ptr
<HttpTransaction
> trans(
11046 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11048 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11049 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11051 rv
= callback1
.WaitForResult();
11053 TestNetLogEntry::List entries
;
11054 log
.GetEntries(&entries
);
11055 size_t pos
= ExpectLogContainsSomewhere(
11056 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11057 NetLog::PHASE_NONE
);
11058 ExpectLogContainsSomewhere(
11060 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11061 NetLog::PHASE_NONE
);
11063 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11064 ASSERT_TRUE(response
!= NULL
);
11066 EXPECT_TRUE(response
->headers
->IsKeepAlive());
11067 EXPECT_EQ(200, response
->headers
->response_code());
11068 EXPECT_EQ(100, response
->headers
->GetContentLength());
11069 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11070 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11072 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11074 LoadTimingInfo load_timing_info
;
11075 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11076 TestLoadTimingNotReusedWithPac(load_timing_info
,
11077 CONNECT_TIMING_HAS_SSL_TIMES
);
11080 // Test a basic HTTPS GET request through a proxy, but the server hangs up
11081 // while establishing the tunnel.
11082 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
11083 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
11084 BoundTestNetLog log
;
11085 session_deps_
.net_log
= log
.bound().net_log();
11086 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11088 HttpRequestInfo request
;
11089 request
.method
= "GET";
11090 request
.url
= GURL("https://www.example.org/");
11092 // Since we have proxy, should try to establish tunnel.
11093 MockWrite data_writes1
[] = {
11095 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11096 "Host: www.example.org\r\n"
11097 "Proxy-Connection: keep-alive\r\n\r\n"),
11100 "GET / HTTP/1.1\r\n"
11101 "Host: www.example.org\r\n"
11102 "Connection: keep-alive\r\n\r\n"),
11105 MockRead data_reads1
[] = {
11106 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
11107 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11108 MockRead(ASYNC
, 0, 0), // EOF
11111 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11112 data_writes1
, arraysize(data_writes1
));
11113 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11114 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11115 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11117 TestCompletionCallback callback1
;
11119 scoped_ptr
<HttpTransaction
> trans(
11120 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11122 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11125 rv
= callback1
.WaitForResult();
11126 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
11127 TestNetLogEntry::List entries
;
11128 log
.GetEntries(&entries
);
11129 size_t pos
= ExpectLogContainsSomewhere(
11130 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11131 NetLog::PHASE_NONE
);
11132 ExpectLogContainsSomewhere(
11134 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11135 NetLog::PHASE_NONE
);
11138 // Test for crbug.com/55424.
11139 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
11140 scoped_ptr
<SpdyFrame
> req(
11141 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11142 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
11144 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11145 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11146 MockRead spdy_reads
[] = {
11147 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
11150 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
11151 arraysize(spdy_writes
));
11152 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11154 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11155 ssl
.SetNextProto(GetParam());
11156 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11158 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11160 // Set up an initial SpdySession in the pool to reuse.
11161 HostPortPair
host_port_pair("www.example.org", 443);
11162 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
11163 PRIVACY_MODE_DISABLED
);
11164 base::WeakPtr
<SpdySession
> spdy_session
=
11165 CreateInsecureSpdySession(session
, key
, BoundNetLog());
11167 HttpRequestInfo request
;
11168 request
.method
= "GET";
11169 request
.url
= GURL("https://www.example.org/");
11170 request
.load_flags
= 0;
11172 // This is the important line that marks this as a preconnect.
11173 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11175 scoped_ptr
<HttpTransaction
> trans(
11176 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11178 TestCompletionCallback callback
;
11179 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11181 EXPECT_EQ(OK
, callback
.WaitForResult());
11184 // Given a net error, cause that error to be returned from the first Write()
11185 // call and verify that the HttpTransaction fails with that error.
11186 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11187 int error
, IoMode mode
) {
11188 HttpRequestInfo request_info
;
11189 request_info
.url
= GURL("https://www.example.com/");
11190 request_info
.method
= "GET";
11191 request_info
.load_flags
= LOAD_NORMAL
;
11193 SSLSocketDataProvider
ssl_data(mode
, OK
);
11194 MockWrite data_writes
[] = {
11195 MockWrite(mode
, error
),
11197 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11198 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11199 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11201 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11202 scoped_ptr
<HttpTransaction
> trans(
11203 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11205 TestCompletionCallback callback
;
11206 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11207 if (rv
== ERR_IO_PENDING
)
11208 rv
= callback
.WaitForResult();
11209 ASSERT_EQ(error
, rv
);
11212 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11213 // Just check a grab bag of cert errors.
11214 static const int kErrors
[] = {
11215 ERR_CERT_COMMON_NAME_INVALID
,
11216 ERR_CERT_AUTHORITY_INVALID
,
11217 ERR_CERT_DATE_INVALID
,
11219 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11220 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11221 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11225 // Ensure that a client certificate is removed from the SSL client auth
11227 // 1) No proxy is involved.
11228 // 2) TLS False Start is disabled.
11229 // 3) The initial TLS handshake requests a client certificate.
11230 // 4) The client supplies an invalid/unacceptable certificate.
11231 TEST_P(HttpNetworkTransactionTest
,
11232 ClientAuthCertCache_Direct_NoFalseStart
) {
11233 HttpRequestInfo request_info
;
11234 request_info
.url
= GURL("https://www.example.com/");
11235 request_info
.method
= "GET";
11236 request_info
.load_flags
= LOAD_NORMAL
;
11238 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11239 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11241 // [ssl_]data1 contains the data for the first SSL handshake. When a
11242 // CertificateRequest is received for the first time, the handshake will
11243 // be aborted to allow the caller to provide a certificate.
11244 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11245 ssl_data1
.cert_request_info
= cert_request
.get();
11246 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11247 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11248 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11250 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11251 // False Start is not being used, the result of the SSL handshake will be
11252 // returned as part of the SSLClientSocket::Connect() call. This test
11253 // matches the result of a server sending a handshake_failure alert,
11254 // rather than a Finished message, because it requires a client
11255 // certificate and none was supplied.
11256 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11257 ssl_data2
.cert_request_info
= cert_request
.get();
11258 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11259 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11260 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11262 // [ssl_]data3 contains the data for the third SSL handshake. When a
11263 // connection to a server fails during an SSL handshake,
11264 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11265 // connection was attempted with TLSv1.2. This is transparent to the caller
11266 // of the HttpNetworkTransaction. Because this test failure is due to
11267 // requiring a client certificate, this fallback handshake should also
11269 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11270 ssl_data3
.cert_request_info
= cert_request
.get();
11271 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11272 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11273 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11275 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11276 // connection to a server fails during an SSL handshake,
11277 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11278 // connection was attempted with TLSv1.1. This is transparent to the caller
11279 // of the HttpNetworkTransaction. Because this test failure is due to
11280 // requiring a client certificate, this fallback handshake should also
11282 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11283 ssl_data4
.cert_request_info
= cert_request
.get();
11284 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11285 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11286 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11288 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11289 scoped_ptr
<HttpTransaction
> trans(
11290 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11292 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11293 TestCompletionCallback callback
;
11294 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11295 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11297 // Complete the SSL handshake, which should abort due to requiring a
11298 // client certificate.
11299 rv
= callback
.WaitForResult();
11300 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11302 // Indicate that no certificate should be supplied. From the perspective
11303 // of SSLClientCertCache, NULL is just as meaningful as a real
11304 // certificate, so this is the same as supply a
11305 // legitimate-but-unacceptable certificate.
11306 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11307 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11309 // Ensure the certificate was added to the client auth cache before
11310 // allowing the connection to continue restarting.
11311 scoped_refptr
<X509Certificate
> client_cert
;
11312 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11313 HostPortPair("www.example.com", 443), &client_cert
));
11314 ASSERT_EQ(NULL
, client_cert
.get());
11316 // Restart the handshake. This will consume ssl_data2, which fails, and
11317 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11318 // The result code is checked against what ssl_data4 should return.
11319 rv
= callback
.WaitForResult();
11320 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11322 // Ensure that the client certificate is removed from the cache on a
11323 // handshake failure.
11324 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11325 HostPortPair("www.example.com", 443), &client_cert
));
11328 // Ensure that a client certificate is removed from the SSL client auth
11330 // 1) No proxy is involved.
11331 // 2) TLS False Start is enabled.
11332 // 3) The initial TLS handshake requests a client certificate.
11333 // 4) The client supplies an invalid/unacceptable certificate.
11334 TEST_P(HttpNetworkTransactionTest
,
11335 ClientAuthCertCache_Direct_FalseStart
) {
11336 HttpRequestInfo request_info
;
11337 request_info
.url
= GURL("https://www.example.com/");
11338 request_info
.method
= "GET";
11339 request_info
.load_flags
= LOAD_NORMAL
;
11341 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11342 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11344 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11345 // return successfully after reading up to the peer's Certificate message.
11346 // This is to allow the caller to call SSLClientSocket::Write(), which can
11347 // enqueue application data to be sent in the same packet as the
11348 // ChangeCipherSpec and Finished messages.
11349 // The actual handshake will be finished when SSLClientSocket::Read() is
11350 // called, which expects to process the peer's ChangeCipherSpec and
11351 // Finished messages. If there was an error negotiating with the peer,
11352 // such as due to the peer requiring a client certificate when none was
11353 // supplied, the alert sent by the peer won't be processed until Read() is
11356 // Like the non-False Start case, when a client certificate is requested by
11357 // the peer, the handshake is aborted during the Connect() call.
11358 // [ssl_]data1 represents the initial SSL handshake with the peer.
11359 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11360 ssl_data1
.cert_request_info
= cert_request
.get();
11361 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11362 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11363 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11365 // When a client certificate is supplied, Connect() will not be aborted
11366 // when the peer requests the certificate. Instead, the handshake will
11367 // artificially succeed, allowing the caller to write the HTTP request to
11368 // the socket. The handshake messages are not processed until Read() is
11369 // called, which then detects that the handshake was aborted, due to the
11370 // peer sending a handshake_failure because it requires a client
11372 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11373 ssl_data2
.cert_request_info
= cert_request
.get();
11374 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11375 MockRead data2_reads
[] = {
11376 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11378 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11379 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11381 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11382 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11383 // TLSv1. It has the same behaviour as [ssl_]data2.
11384 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11385 ssl_data3
.cert_request_info
= cert_request
.get();
11386 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11387 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11388 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11390 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11391 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11392 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11393 ssl_data4
.cert_request_info
= cert_request
.get();
11394 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11395 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11396 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11398 // Need one more if TLSv1.2 is enabled.
11399 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11400 ssl_data5
.cert_request_info
= cert_request
.get();
11401 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11402 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11403 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11405 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11406 scoped_ptr
<HttpTransaction
> trans(
11407 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11409 // Begin the initial SSL handshake.
11410 TestCompletionCallback callback
;
11411 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11412 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11414 // Complete the SSL handshake, which should abort due to requiring a
11415 // client certificate.
11416 rv
= callback
.WaitForResult();
11417 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11419 // Indicate that no certificate should be supplied. From the perspective
11420 // of SSLClientCertCache, NULL is just as meaningful as a real
11421 // certificate, so this is the same as supply a
11422 // legitimate-but-unacceptable certificate.
11423 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11424 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11426 // Ensure the certificate was added to the client auth cache before
11427 // allowing the connection to continue restarting.
11428 scoped_refptr
<X509Certificate
> client_cert
;
11429 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11430 HostPortPair("www.example.com", 443), &client_cert
));
11431 ASSERT_EQ(NULL
, client_cert
.get());
11433 // Restart the handshake. This will consume ssl_data2, which fails, and
11434 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11435 // The result code is checked against what ssl_data4 should return.
11436 rv
= callback
.WaitForResult();
11437 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11439 // Ensure that the client certificate is removed from the cache on a
11440 // handshake failure.
11441 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11442 HostPortPair("www.example.com", 443), &client_cert
));
11445 // Ensure that a client certificate is removed from the SSL client auth
11447 // 1) An HTTPS proxy is involved.
11448 // 3) The HTTPS proxy requests a client certificate.
11449 // 4) The client supplies an invalid/unacceptable certificate for the
11451 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11452 // then for connecting to an HTTP endpoint.
11453 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11454 session_deps_
.proxy_service
.reset(
11455 ProxyService::CreateFixed("https://proxy:70"));
11456 BoundTestNetLog log
;
11457 session_deps_
.net_log
= log
.bound().net_log();
11459 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11460 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11462 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11463 // [ssl_]data[1-3]. Rather than represending the endpoint
11464 // (www.example.com:443), they represent failures with the HTTPS proxy
11466 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11467 ssl_data1
.cert_request_info
= cert_request
.get();
11468 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11469 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11470 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11472 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11473 ssl_data2
.cert_request_info
= cert_request
.get();
11474 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11475 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11476 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11478 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11480 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11481 ssl_data3
.cert_request_info
= cert_request
.get();
11482 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11483 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11484 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11487 HttpRequestInfo requests
[2];
11488 requests
[0].url
= GURL("https://www.example.com/");
11489 requests
[0].method
= "GET";
11490 requests
[0].load_flags
= LOAD_NORMAL
;
11492 requests
[1].url
= GURL("http://www.example.com/");
11493 requests
[1].method
= "GET";
11494 requests
[1].load_flags
= LOAD_NORMAL
;
11496 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11497 session_deps_
.socket_factory
->ResetNextMockIndexes();
11498 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11499 scoped_ptr
<HttpNetworkTransaction
> trans(
11500 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11502 // Begin the SSL handshake with the proxy.
11503 TestCompletionCallback callback
;
11504 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11505 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11507 // Complete the SSL handshake, which should abort due to requiring a
11508 // client certificate.
11509 rv
= callback
.WaitForResult();
11510 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11512 // Indicate that no certificate should be supplied. From the perspective
11513 // of SSLClientCertCache, NULL is just as meaningful as a real
11514 // certificate, so this is the same as supply a
11515 // legitimate-but-unacceptable certificate.
11516 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11517 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11519 // Ensure the certificate was added to the client auth cache before
11520 // allowing the connection to continue restarting.
11521 scoped_refptr
<X509Certificate
> client_cert
;
11522 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11523 HostPortPair("proxy", 70), &client_cert
));
11524 ASSERT_EQ(NULL
, client_cert
.get());
11525 // Ensure the certificate was NOT cached for the endpoint. This only
11526 // applies to HTTPS requests, but is fine to check for HTTP requests.
11527 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11528 HostPortPair("www.example.com", 443), &client_cert
));
11530 // Restart the handshake. This will consume ssl_data2, which fails, and
11531 // then consume ssl_data3, which should also fail. The result code is
11532 // checked against what ssl_data3 should return.
11533 rv
= callback
.WaitForResult();
11534 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11536 // Now that the new handshake has failed, ensure that the client
11537 // certificate was removed from the client auth cache.
11538 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11539 HostPortPair("proxy", 70), &client_cert
));
11540 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11541 HostPortPair("www.example.com", 443), &client_cert
));
11545 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPooling
) {
11546 session_deps_
.use_alternative_services
= true;
11547 session_deps_
.next_protos
= SpdyNextProtos();
11549 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11550 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11551 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11552 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11553 pool_peer
.DisableDomainAuthenticationVerification();
11555 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11556 ssl
.SetNextProto(GetParam());
11557 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11559 scoped_ptr
<SpdyFrame
> host1_req(
11560 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11561 scoped_ptr
<SpdyFrame
> host2_req(
11562 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11563 MockWrite spdy_writes
[] = {
11564 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11566 scoped_ptr
<SpdyFrame
> host1_resp(
11567 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11568 scoped_ptr
<SpdyFrame
> host1_resp_body(
11569 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11570 scoped_ptr
<SpdyFrame
> host2_resp(
11571 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11572 scoped_ptr
<SpdyFrame
> host2_resp_body(
11573 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11574 MockRead spdy_reads
[] = {
11575 CreateMockRead(*host1_resp
, 1),
11576 CreateMockRead(*host1_resp_body
, 2),
11577 CreateMockRead(*host2_resp
, 4),
11578 CreateMockRead(*host2_resp_body
, 5),
11579 MockRead(ASYNC
, 0, 6),
11582 IPAddressNumber ip
;
11583 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11584 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11585 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11586 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11587 spdy_writes
, arraysize(spdy_writes
));
11588 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11590 TestCompletionCallback callback
;
11591 HttpRequestInfo request1
;
11592 request1
.method
= "GET";
11593 request1
.url
= GURL("https://www.example.org/");
11594 request1
.load_flags
= 0;
11595 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11597 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11598 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11599 EXPECT_EQ(OK
, callback
.WaitForResult());
11601 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11602 ASSERT_TRUE(response
!= NULL
);
11603 ASSERT_TRUE(response
->headers
.get() != NULL
);
11604 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11606 std::string response_data
;
11607 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11608 EXPECT_EQ("hello!", response_data
);
11610 // Preload www.gmail.com into HostCache.
11611 HostPortPair
host_port("www.gmail.com", 443);
11612 HostResolver::RequestInfo
resolve_info(host_port
);
11613 AddressList ignored
;
11614 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11617 callback
.callback(),
11620 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11621 rv
= callback
.WaitForResult();
11624 HttpRequestInfo request2
;
11625 request2
.method
= "GET";
11626 request2
.url
= GURL("https://www.gmail.com/");
11627 request2
.load_flags
= 0;
11628 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11630 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11631 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11632 EXPECT_EQ(OK
, callback
.WaitForResult());
11634 response
= trans2
.GetResponseInfo();
11635 ASSERT_TRUE(response
!= NULL
);
11636 ASSERT_TRUE(response
->headers
.get() != NULL
);
11637 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11638 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11639 EXPECT_TRUE(response
->was_npn_negotiated
);
11640 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11641 EXPECT_EQ("hello!", response_data
);
11644 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11645 session_deps_
.use_alternative_services
= true;
11646 session_deps_
.next_protos
= SpdyNextProtos();
11648 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11649 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11650 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11651 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11652 pool_peer
.DisableDomainAuthenticationVerification();
11654 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11655 ssl
.SetNextProto(GetParam());
11656 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11658 scoped_ptr
<SpdyFrame
> host1_req(
11659 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11660 scoped_ptr
<SpdyFrame
> host2_req(
11661 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11662 MockWrite spdy_writes
[] = {
11663 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11665 scoped_ptr
<SpdyFrame
> host1_resp(
11666 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11667 scoped_ptr
<SpdyFrame
> host1_resp_body(
11668 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11669 scoped_ptr
<SpdyFrame
> host2_resp(
11670 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11671 scoped_ptr
<SpdyFrame
> host2_resp_body(
11672 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11673 MockRead spdy_reads
[] = {
11674 CreateMockRead(*host1_resp
, 1),
11675 CreateMockRead(*host1_resp_body
, 2),
11676 CreateMockRead(*host2_resp
, 4),
11677 CreateMockRead(*host2_resp_body
, 5),
11678 MockRead(ASYNC
, 0, 6),
11681 IPAddressNumber ip
;
11682 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11683 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11684 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11685 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11686 spdy_writes
, arraysize(spdy_writes
));
11687 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11689 TestCompletionCallback callback
;
11690 HttpRequestInfo request1
;
11691 request1
.method
= "GET";
11692 request1
.url
= GURL("https://www.example.org/");
11693 request1
.load_flags
= 0;
11694 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11696 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11698 EXPECT_EQ(OK
, callback
.WaitForResult());
11700 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11701 ASSERT_TRUE(response
!= NULL
);
11702 ASSERT_TRUE(response
->headers
.get() != NULL
);
11703 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11705 std::string response_data
;
11706 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11707 EXPECT_EQ("hello!", response_data
);
11709 HttpRequestInfo request2
;
11710 request2
.method
= "GET";
11711 request2
.url
= GURL("https://www.gmail.com/");
11712 request2
.load_flags
= 0;
11713 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11715 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11716 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11717 EXPECT_EQ(OK
, callback
.WaitForResult());
11719 response
= trans2
.GetResponseInfo();
11720 ASSERT_TRUE(response
!= NULL
);
11721 ASSERT_TRUE(response
->headers
.get() != NULL
);
11722 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11723 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11724 EXPECT_TRUE(response
->was_npn_negotiated
);
11725 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11726 EXPECT_EQ("hello!", response_data
);
11729 class OneTimeCachingHostResolver
: public HostResolver
{
11731 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11732 : host_port_(host_port
) {}
11733 ~OneTimeCachingHostResolver() override
{}
11735 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11737 // HostResolver methods:
11738 int Resolve(const RequestInfo
& info
,
11739 RequestPriority priority
,
11740 AddressList
* addresses
,
11741 const CompletionCallback
& callback
,
11742 RequestHandle
* out_req
,
11743 const BoundNetLog
& net_log
) override
{
11744 return host_resolver_
.Resolve(
11745 info
, priority
, addresses
, callback
, out_req
, net_log
);
11748 int ResolveFromCache(const RequestInfo
& info
,
11749 AddressList
* addresses
,
11750 const BoundNetLog
& net_log
) override
{
11751 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11752 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11753 host_resolver_
.GetHostCache()->clear();
11757 void CancelRequest(RequestHandle req
) override
{
11758 host_resolver_
.CancelRequest(req
);
11761 MockCachingHostResolver
* GetMockHostResolver() {
11762 return &host_resolver_
;
11766 MockCachingHostResolver host_resolver_
;
11767 const HostPortPair host_port_
;
11770 TEST_P(HttpNetworkTransactionTest
,
11771 UseIPConnectionPoolingWithHostCacheExpiration
) {
11772 session_deps_
.use_alternative_services
= true;
11773 session_deps_
.next_protos
= SpdyNextProtos();
11775 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11776 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11777 HttpNetworkSession::Params params
=
11778 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11779 params
.host_resolver
= &host_resolver
;
11780 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11781 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11782 pool_peer
.DisableDomainAuthenticationVerification();
11784 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11785 ssl
.SetNextProto(GetParam());
11786 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11788 scoped_ptr
<SpdyFrame
> host1_req(
11789 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11790 scoped_ptr
<SpdyFrame
> host2_req(
11791 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11792 MockWrite spdy_writes
[] = {
11793 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11795 scoped_ptr
<SpdyFrame
> host1_resp(
11796 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11797 scoped_ptr
<SpdyFrame
> host1_resp_body(
11798 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11799 scoped_ptr
<SpdyFrame
> host2_resp(
11800 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11801 scoped_ptr
<SpdyFrame
> host2_resp_body(
11802 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11803 MockRead spdy_reads
[] = {
11804 CreateMockRead(*host1_resp
, 1),
11805 CreateMockRead(*host1_resp_body
, 2),
11806 CreateMockRead(*host2_resp
, 4),
11807 CreateMockRead(*host2_resp_body
, 5),
11808 MockRead(ASYNC
, 0, 6),
11811 IPAddressNumber ip
;
11812 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11813 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11814 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11815 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11816 spdy_writes
, arraysize(spdy_writes
));
11817 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11819 TestCompletionCallback callback
;
11820 HttpRequestInfo request1
;
11821 request1
.method
= "GET";
11822 request1
.url
= GURL("https://www.example.org/");
11823 request1
.load_flags
= 0;
11824 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11826 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11827 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11828 EXPECT_EQ(OK
, callback
.WaitForResult());
11830 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11831 ASSERT_TRUE(response
!= NULL
);
11832 ASSERT_TRUE(response
->headers
.get() != NULL
);
11833 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11835 std::string response_data
;
11836 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11837 EXPECT_EQ("hello!", response_data
);
11839 // Preload cache entries into HostCache.
11840 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11841 AddressList ignored
;
11842 rv
= host_resolver
.Resolve(resolve_info
,
11845 callback
.callback(),
11848 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11849 rv
= callback
.WaitForResult();
11852 HttpRequestInfo request2
;
11853 request2
.method
= "GET";
11854 request2
.url
= GURL("https://www.gmail.com/");
11855 request2
.load_flags
= 0;
11856 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11858 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11859 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11860 EXPECT_EQ(OK
, callback
.WaitForResult());
11862 response
= trans2
.GetResponseInfo();
11863 ASSERT_TRUE(response
!= NULL
);
11864 ASSERT_TRUE(response
->headers
.get() != NULL
);
11865 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11866 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11867 EXPECT_TRUE(response
->was_npn_negotiated
);
11868 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11869 EXPECT_EQ("hello!", response_data
);
11872 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11873 const std::string https_url
= "https://www.example.org:8080/";
11874 const std::string http_url
= "http://www.example.org:8080/";
11876 // SPDY GET for HTTPS URL
11877 scoped_ptr
<SpdyFrame
> req1(
11878 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11880 MockWrite writes1
[] = {
11881 CreateMockWrite(*req1
, 0),
11884 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11885 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11886 MockRead reads1
[] = {
11887 CreateMockRead(*resp1
, 1),
11888 CreateMockRead(*body1
, 2),
11889 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11892 SequencedSocketData
data1(reads1
, arraysize(reads1
), writes1
,
11893 arraysize(writes1
));
11894 MockConnect
connect_data1(ASYNC
, OK
);
11895 data1
.set_connect_data(connect_data1
);
11897 // HTTP GET for the HTTP URL
11898 MockWrite writes2
[] = {
11899 MockWrite(ASYNC
, 0,
11900 "GET / HTTP/1.1\r\n"
11901 "Host: www.example.org:8080\r\n"
11902 "Connection: keep-alive\r\n\r\n"),
11905 MockRead reads2
[] = {
11906 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11907 MockRead(ASYNC
, 2, "hello"),
11908 MockRead(ASYNC
, OK
, 3),
11911 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
11912 arraysize(writes2
));
11914 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11915 ssl
.SetNextProto(GetParam());
11916 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11917 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11918 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11920 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11922 // Start the first transaction to set up the SpdySession
11923 HttpRequestInfo request1
;
11924 request1
.method
= "GET";
11925 request1
.url
= GURL(https_url
);
11926 request1
.load_flags
= 0;
11927 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11928 TestCompletionCallback callback1
;
11929 EXPECT_EQ(ERR_IO_PENDING
,
11930 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11931 base::MessageLoop::current()->RunUntilIdle();
11933 EXPECT_EQ(OK
, callback1
.WaitForResult());
11934 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11936 // Now, start the HTTP request
11937 HttpRequestInfo request2
;
11938 request2
.method
= "GET";
11939 request2
.url
= GURL(http_url
);
11940 request2
.load_flags
= 0;
11941 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11942 TestCompletionCallback callback2
;
11943 EXPECT_EQ(ERR_IO_PENDING
,
11944 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11945 base::MessageLoop::current()->RunUntilIdle();
11947 EXPECT_EQ(OK
, callback2
.WaitForResult());
11948 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11951 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
11953 void Run(bool pooling
, bool valid
) {
11954 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
11956 HostPortPair
alternative("www.example.org", 443);
11958 base::FilePath certs_dir
= GetTestCertsDirectory();
11959 scoped_refptr
<X509Certificate
> cert(
11960 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
11961 ASSERT_TRUE(cert
.get());
11962 bool common_name_fallback_used
;
11964 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
11966 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
11967 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11968 ssl
.SetNextProto(GetParam());
11970 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11972 // If pooling, then start a request to alternative first to create a
11974 std::string url0
= "https://www.example.org:443";
11975 // Second request to origin, which has an alternative service, and could
11976 // open a connection to the alternative host or pool to the existing one.
11977 std::string
url1("https://");
11978 url1
.append(origin
.host());
11979 url1
.append(":443");
11981 scoped_ptr
<SpdyFrame
> req0
;
11982 scoped_ptr
<SpdyFrame
> req1
;
11983 scoped_ptr
<SpdyFrame
> resp0
;
11984 scoped_ptr
<SpdyFrame
> body0
;
11985 scoped_ptr
<SpdyFrame
> resp1
;
11986 scoped_ptr
<SpdyFrame
> body1
;
11987 std::vector
<MockWrite
> writes
;
11988 std::vector
<MockRead
> reads
;
11991 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
11992 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
11994 writes
.push_back(CreateMockWrite(*req0
, 0));
11995 writes
.push_back(CreateMockWrite(*req1
, 3));
11997 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11998 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11999 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12000 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12002 reads
.push_back(CreateMockRead(*resp0
, 1));
12003 reads
.push_back(CreateMockRead(*body0
, 2));
12004 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
12005 reads
.push_back(CreateMockRead(*resp1
, 5));
12006 reads
.push_back(CreateMockRead(*body1
, 6));
12007 reads
.push_back(MockRead(ASYNC
, OK
, 7));
12009 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
12011 writes
.push_back(CreateMockWrite(*req1
, 0));
12013 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12014 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12016 reads
.push_back(CreateMockRead(*resp1
, 1));
12017 reads
.push_back(CreateMockRead(*body1
, 2));
12018 reads
.push_back(MockRead(ASYNC
, OK
, 3));
12021 SequencedSocketData
data(vector_as_array(&reads
), reads
.size(),
12022 vector_as_array(&writes
), writes
.size());
12023 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12025 // Connection to the origin fails.
12026 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12027 StaticSocketDataProvider data_refused
;
12028 data_refused
.set_connect_data(mock_connect
);
12029 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12031 session_deps_
.use_alternative_services
= true;
12032 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12033 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12034 session
->http_server_properties();
12035 AlternativeService
alternative_service(
12036 AlternateProtocolFromNextProto(GetParam()), alternative
);
12037 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12038 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12041 // First request to alternative.
12043 scoped_ptr
<HttpTransaction
> trans0(
12044 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12045 HttpRequestInfo request0
;
12046 request0
.method
= "GET";
12047 request0
.url
= GURL(url0
);
12048 request0
.load_flags
= 0;
12049 TestCompletionCallback callback0
;
12051 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
12052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12053 rv
= callback0
.WaitForResult();
12057 // Second request to origin.
12058 scoped_ptr
<HttpTransaction
> trans1(
12059 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12060 HttpRequestInfo request1
;
12061 request1
.method
= "GET";
12062 request1
.url
= GURL(url1
);
12063 request1
.load_flags
= 0;
12064 TestCompletionCallback callback1
;
12066 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12067 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12068 base::MessageLoop::current()->RunUntilIdle();
12069 if (data
.IsReadPaused()) {
12070 data
.CompleteRead();
12072 rv
= callback1
.WaitForResult();
12077 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12079 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
12085 INSTANTIATE_TEST_CASE_P(NextProto
,
12086 AltSvcCertificateVerificationTest
,
12087 testing::Values(kProtoSPDY31
,
12091 // The alternative service host must exhibit a certificate that is valid for the
12092 // origin host. Test that this is enforced when pooling to an existing
12094 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
12098 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
12102 // The alternative service host must exhibit a certificate that is valid for the
12103 // origin host. Test that this is enforced when opening a new connection.
12104 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
12108 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
12112 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12113 // with the alternative server. That connection should not be used.
12114 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceNotOnHttp11
) {
12115 HostPortPair
origin("origin.example.org", 443);
12116 HostPortPair
alternative("alternative.example.org", 443);
12118 // Negotiate HTTP/1.1 with alternative.example.org.
12119 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12120 ssl
.SetNextProto(kProtoHTTP11
);
12121 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12123 // No data should be read from the alternative, because HTTP/1.1 is
12125 StaticSocketDataProvider data
;
12126 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12128 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12129 // negotiated. In order to test this, a failed connection to the origin is
12130 // mocked. This way the request relies on the alternate Job.
12131 StaticSocketDataProvider data_refused
;
12132 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12133 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12135 // Set up alternative service for origin.
12136 session_deps_
.use_alternative_services
= true;
12137 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12138 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12139 session
->http_server_properties();
12140 AlternativeService
alternative_service(
12141 AlternateProtocolFromNextProto(GetParam()), alternative
);
12142 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12143 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12146 scoped_ptr
<HttpTransaction
> trans(
12147 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12148 HttpRequestInfo request
;
12149 request
.method
= "GET";
12150 request
.url
= GURL("https://origin.example.org:443");
12151 request
.load_flags
= 0;
12152 TestCompletionCallback callback
;
12154 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12155 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12156 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12157 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED
, callback
.GetResult(rv
));
12160 // A request to a server with an alternative service fires two Jobs: one to the
12161 // origin, and an alternate one to the alternative server. If the former
12162 // succeeds, the request should succeed, even if the latter fails because
12163 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12164 TEST_P(HttpNetworkTransactionTest
, FailedAlternativeServiceIsNotUserVisible
) {
12165 HostPortPair
origin("origin.example.org", 443);
12166 HostPortPair
alternative("alternative.example.org", 443);
12168 // Negotiate HTTP/1.1 with alternative.
12169 SSLSocketDataProvider
alternative_ssl(ASYNC
, OK
);
12170 alternative_ssl
.SetNextProto(kProtoHTTP11
);
12171 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&alternative_ssl
);
12173 // No data should be read from the alternative, because HTTP/1.1 is
12175 StaticSocketDataProvider data
;
12176 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12178 // Negotiate HTTP/1.1 with origin.
12179 SSLSocketDataProvider
origin_ssl(ASYNC
, OK
);
12180 origin_ssl
.SetNextProto(kProtoHTTP11
);
12181 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&origin_ssl
);
12183 MockWrite http_writes
[] = {
12185 "GET / HTTP/1.1\r\n"
12186 "Host: origin.example.org\r\n"
12187 "Connection: keep-alive\r\n\r\n"),
12189 "GET /second HTTP/1.1\r\n"
12190 "Host: origin.example.org\r\n"
12191 "Connection: keep-alive\r\n\r\n"),
12194 MockRead http_reads
[] = {
12195 MockRead("HTTP/1.1 200 OK\r\n"),
12196 MockRead("Content-Type: text/html\r\n"),
12197 MockRead("Content-Length: 6\r\n\r\n"),
12198 MockRead("foobar"),
12199 MockRead("HTTP/1.1 200 OK\r\n"),
12200 MockRead("Content-Type: text/html\r\n"),
12201 MockRead("Content-Length: 7\r\n\r\n"),
12202 MockRead("another"),
12204 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12205 http_writes
, arraysize(http_writes
));
12206 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12208 // Set up alternative service for origin.
12209 session_deps_
.use_alternative_services
= true;
12210 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12211 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12212 session
->http_server_properties();
12213 AlternativeService
alternative_service(
12214 AlternateProtocolFromNextProto(GetParam()), alternative
);
12215 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12216 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12219 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12220 HttpRequestInfo request1
;
12221 request1
.method
= "GET";
12222 request1
.url
= GURL("https://origin.example.org:443");
12223 request1
.load_flags
= 0;
12224 TestCompletionCallback callback1
;
12226 int rv
= trans1
.Start(&request1
, callback1
.callback(), BoundNetLog());
12227 rv
= callback1
.GetResult(rv
);
12230 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
12231 ASSERT_TRUE(response1
!= nullptr);
12232 ASSERT_TRUE(response1
->headers
.get() != nullptr);
12233 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12235 std::string response_data1
;
12236 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data1
));
12237 EXPECT_EQ("foobar", response_data1
);
12239 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12240 // for alternative service.
12242 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
12244 // Since |alternative_service| is broken, a second transaction to origin
12245 // should not start an alternate Job. It should pool to existing connection
12247 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12248 HttpRequestInfo request2
;
12249 request2
.method
= "GET";
12250 request2
.url
= GURL("https://origin.example.org:443/second");
12251 request2
.load_flags
= 0;
12252 TestCompletionCallback callback2
;
12254 rv
= trans2
.Start(&request2
, callback2
.callback(), BoundNetLog());
12255 rv
= callback2
.GetResult(rv
);
12258 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
12259 ASSERT_TRUE(response2
!= nullptr);
12260 ASSERT_TRUE(response2
->headers
.get() != nullptr);
12261 EXPECT_EQ("HTTP/1.1 200 OK", response2
->headers
->GetStatusLine());
12263 std::string response_data2
;
12264 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data2
));
12265 EXPECT_EQ("another", response_data2
);
12268 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12269 // HTTP/1.1 socket open to the alternative server. That socket should not be
12271 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceShouldNotPoolToHttp11
) {
12272 HostPortPair
origin("origin.example.org", 443);
12273 HostPortPair
alternative("alternative.example.org", 443);
12274 std::string origin_url
= "https://origin.example.org:443";
12275 std::string alternative_url
= "https://alternative.example.org:443";
12277 // Negotiate HTTP/1.1 with alternative.example.org.
12278 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12279 ssl
.SetNextProto(kProtoHTTP11
);
12280 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12282 // HTTP/1.1 data for |request1| and |request2|.
12283 MockWrite http_writes
[] = {
12285 "GET / HTTP/1.1\r\n"
12286 "Host: alternative.example.org\r\n"
12287 "Connection: keep-alive\r\n\r\n"),
12289 "GET / HTTP/1.1\r\n"
12290 "Host: alternative.example.org\r\n"
12291 "Connection: keep-alive\r\n\r\n"),
12294 MockRead http_reads
[] = {
12296 "HTTP/1.1 200 OK\r\n"
12297 "Content-Type: text/html; charset=iso-8859-1\r\n"
12298 "Content-Length: 40\r\n\r\n"
12299 "first HTTP/1.1 response from alternative"),
12301 "HTTP/1.1 200 OK\r\n"
12302 "Content-Type: text/html; charset=iso-8859-1\r\n"
12303 "Content-Length: 41\r\n\r\n"
12304 "second HTTP/1.1 response from alternative"),
12306 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12307 http_writes
, arraysize(http_writes
));
12308 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12310 // This test documents that an alternate Job should not pool to an already
12311 // existing HTTP/1.1 connection. In order to test this, a failed connection
12312 // to the origin is mocked. This way |request2| relies on the alternate Job.
12313 StaticSocketDataProvider data_refused
;
12314 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12315 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12317 // Set up alternative service for origin.
12318 session_deps_
.use_alternative_services
= true;
12319 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12320 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12321 session
->http_server_properties();
12322 AlternativeService
alternative_service(
12323 AlternateProtocolFromNextProto(GetParam()), alternative
);
12324 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12325 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12328 // First transaction to alternative to open an HTTP/1.1 socket.
12329 scoped_ptr
<HttpTransaction
> trans1(
12330 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12331 HttpRequestInfo request1
;
12332 request1
.method
= "GET";
12333 request1
.url
= GURL(alternative_url
);
12334 request1
.load_flags
= 0;
12335 TestCompletionCallback callback1
;
12337 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12338 EXPECT_EQ(OK
, callback1
.GetResult(rv
));
12339 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12340 ASSERT_TRUE(response1
);
12341 ASSERT_TRUE(response1
->headers
.get());
12342 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12343 EXPECT_TRUE(response1
->was_npn_negotiated
);
12344 EXPECT_FALSE(response1
->was_fetched_via_spdy
);
12345 std::string response_data1
;
12346 ASSERT_EQ(OK
, ReadTransaction(trans1
.get(), &response_data1
));
12347 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1
);
12349 // Request for origin.example.org, which has an alternative service. This
12350 // will start two Jobs: the alternative looks for connections to pool to,
12351 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12352 // open other connections to alternative server. The Job to origin fails, so
12353 // this request fails.
12354 scoped_ptr
<HttpTransaction
> trans2(
12355 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12356 HttpRequestInfo request2
;
12357 request2
.method
= "GET";
12358 request2
.url
= GURL(origin_url
);
12359 request2
.load_flags
= 0;
12360 TestCompletionCallback callback2
;
12362 rv
= trans2
->Start(&request2
, callback2
.callback(), BoundNetLog());
12363 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback2
.GetResult(rv
));
12365 // Another transaction to alternative. This is to test that the HTTP/1.1
12366 // socket is still open and in the pool.
12367 scoped_ptr
<HttpTransaction
> trans3(
12368 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12369 HttpRequestInfo request3
;
12370 request3
.method
= "GET";
12371 request3
.url
= GURL(alternative_url
);
12372 request3
.load_flags
= 0;
12373 TestCompletionCallback callback3
;
12375 rv
= trans3
->Start(&request3
, callback3
.callback(), BoundNetLog());
12376 EXPECT_EQ(OK
, callback3
.GetResult(rv
));
12377 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
12378 ASSERT_TRUE(response3
);
12379 ASSERT_TRUE(response3
->headers
.get());
12380 EXPECT_EQ("HTTP/1.1 200 OK", response3
->headers
->GetStatusLine());
12381 EXPECT_TRUE(response3
->was_npn_negotiated
);
12382 EXPECT_FALSE(response3
->was_fetched_via_spdy
);
12383 std::string response_data3
;
12384 ASSERT_EQ(OK
, ReadTransaction(trans3
.get(), &response_data3
));
12385 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3
);
12388 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
12389 const std::string https_url
= "https://www.example.org:8080/";
12390 const std::string http_url
= "http://www.example.org:8080/";
12392 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12393 const HostPortPair
host_port_pair("www.example.org", 8080);
12394 scoped_ptr
<SpdyFrame
> connect(
12395 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
12396 scoped_ptr
<SpdyFrame
> req1(
12397 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12398 scoped_ptr
<SpdyFrame
> wrapped_req1(
12399 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
12401 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12402 SpdyHeaderBlock req2_block
;
12403 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
12404 req2_block
[spdy_util_
.GetPathKey()] = "/";
12405 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
12406 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
12407 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
12408 scoped_ptr
<SpdyFrame
> req2(
12409 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
12411 MockWrite writes1
[] = {
12412 CreateMockWrite(*connect
, 0),
12413 CreateMockWrite(*wrapped_req1
, 2),
12414 CreateMockWrite(*req2
, 5),
12417 scoped_ptr
<SpdyFrame
> conn_resp(
12418 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12419 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12420 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12421 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12422 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12423 scoped_ptr
<SpdyFrame
> wrapped_body1(
12424 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12425 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12426 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12427 MockRead reads1
[] = {
12428 CreateMockRead(*conn_resp
, 1),
12429 CreateMockRead(*wrapped_resp1
, 3),
12430 CreateMockRead(*wrapped_body1
, 4),
12431 CreateMockRead(*resp2
, 6),
12432 CreateMockRead(*body2
, 7),
12433 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12436 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12437 writes1
, arraysize(writes1
));
12438 MockConnect
connect_data1(ASYNC
, OK
);
12439 data1
.set_connect_data(connect_data1
);
12441 session_deps_
.proxy_service
.reset(
12442 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12444 session_deps_
.net_log
= &log
;
12445 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12446 ssl1
.SetNextProto(GetParam());
12447 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12448 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12449 ssl2
.SetNextProto(GetParam());
12450 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12451 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12453 scoped_refptr
<HttpNetworkSession
> session(
12454 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12456 // Start the first transaction to set up the SpdySession
12457 HttpRequestInfo request1
;
12458 request1
.method
= "GET";
12459 request1
.url
= GURL(https_url
);
12460 request1
.load_flags
= 0;
12461 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12462 TestCompletionCallback callback1
;
12463 EXPECT_EQ(ERR_IO_PENDING
,
12464 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12465 base::MessageLoop::current()->RunUntilIdle();
12468 EXPECT_EQ(OK
, callback1
.WaitForResult());
12469 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12471 LoadTimingInfo load_timing_info1
;
12472 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12473 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12474 CONNECT_TIMING_HAS_SSL_TIMES
);
12476 // Now, start the HTTP request
12477 HttpRequestInfo request2
;
12478 request2
.method
= "GET";
12479 request2
.url
= GURL(http_url
);
12480 request2
.load_flags
= 0;
12481 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12482 TestCompletionCallback callback2
;
12483 EXPECT_EQ(ERR_IO_PENDING
,
12484 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12485 base::MessageLoop::current()->RunUntilIdle();
12488 EXPECT_EQ(OK
, callback2
.WaitForResult());
12489 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12491 LoadTimingInfo load_timing_info2
;
12492 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12493 // The established SPDY sessions is considered reused by the HTTP request.
12494 TestLoadTimingReusedWithPac(load_timing_info2
);
12495 // HTTP requests over a SPDY session should have a different connection
12496 // socket_log_id than requests over a tunnel.
12497 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12500 // Test that in the case where we have a SPDY session to a SPDY proxy
12501 // that we do not pool other origins that resolve to the same IP when
12502 // the certificate does not match the new origin.
12503 // http://crbug.com/134690
12504 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12505 const std::string url1
= "http://www.example.org/";
12506 const std::string url2
= "https://news.example.org/";
12507 const std::string ip_addr
= "1.2.3.4";
12509 // SPDY GET for HTTP URL (through SPDY proxy)
12510 scoped_ptr
<SpdyHeaderBlock
> headers(
12511 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12512 scoped_ptr
<SpdyFrame
> req1(
12513 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12515 MockWrite writes1
[] = {
12516 CreateMockWrite(*req1
, 0),
12519 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12520 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12521 MockRead reads1
[] = {
12522 CreateMockRead(*resp1
, 1),
12523 CreateMockRead(*body1
, 2),
12524 MockRead(ASYNC
, OK
, 3) // EOF
12527 scoped_ptr
<DeterministicSocketData
> data1(
12528 new DeterministicSocketData(reads1
, arraysize(reads1
),
12529 writes1
, arraysize(writes1
)));
12530 IPAddressNumber ip
;
12531 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12532 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12533 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12534 data1
->set_connect_data(connect_data1
);
12536 // SPDY GET for HTTPS URL (direct)
12537 scoped_ptr
<SpdyFrame
> req2(
12538 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12540 MockWrite writes2
[] = {
12541 CreateMockWrite(*req2
, 0),
12544 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12545 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12546 MockRead reads2
[] = {
12547 CreateMockRead(*resp2
, 1),
12548 CreateMockRead(*body2
, 2),
12549 MockRead(ASYNC
, OK
, 3) // EOF
12552 scoped_ptr
<DeterministicSocketData
> data2(
12553 new DeterministicSocketData(reads2
, arraysize(reads2
),
12554 writes2
, arraysize(writes2
)));
12555 MockConnect
connect_data2(ASYNC
, OK
);
12556 data2
->set_connect_data(connect_data2
);
12558 // Set up a proxy config that sends HTTP requests to a proxy, and
12559 // all others direct.
12560 ProxyConfig proxy_config
;
12561 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12562 session_deps_
.proxy_service
.reset(new ProxyService(
12563 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12565 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12566 ssl1
.SetNextProto(GetParam());
12567 // Load a valid cert. Note, that this does not need to
12568 // be valid for proxy because the MockSSLClientSocket does
12569 // not actually verify it. But SpdySession will use this
12570 // to see if it is valid for the new origin
12571 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12572 ASSERT_TRUE(ssl1
.cert
.get());
12573 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12574 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12577 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12578 ssl2
.SetNextProto(GetParam());
12579 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12580 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12583 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12584 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12585 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12587 scoped_refptr
<HttpNetworkSession
> session(
12588 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12590 // Start the first transaction to set up the SpdySession
12591 HttpRequestInfo request1
;
12592 request1
.method
= "GET";
12593 request1
.url
= GURL(url1
);
12594 request1
.load_flags
= 0;
12595 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12596 TestCompletionCallback callback1
;
12597 ASSERT_EQ(ERR_IO_PENDING
,
12598 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12601 ASSERT_TRUE(callback1
.have_result());
12602 EXPECT_EQ(OK
, callback1
.WaitForResult());
12603 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12605 // Now, start the HTTP request
12606 HttpRequestInfo request2
;
12607 request2
.method
= "GET";
12608 request2
.url
= GURL(url2
);
12609 request2
.load_flags
= 0;
12610 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12611 TestCompletionCallback callback2
;
12612 EXPECT_EQ(ERR_IO_PENDING
,
12613 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12614 base::MessageLoop::current()->RunUntilIdle();
12617 ASSERT_TRUE(callback2
.have_result());
12618 EXPECT_EQ(OK
, callback2
.WaitForResult());
12619 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12622 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12623 // error) in SPDY session, removes the socket from pool and closes the SPDY
12624 // session. Verify that new url's from the same HttpNetworkSession (and a new
12625 // SpdySession) do work. http://crbug.com/224701
12626 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12627 const std::string https_url
= "https://www.example.org/";
12629 MockRead reads1
[] = {
12630 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12633 SequencedSocketData
data1(reads1
, arraysize(reads1
), NULL
, 0);
12635 scoped_ptr
<SpdyFrame
> req2(
12636 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12637 MockWrite writes2
[] = {
12638 CreateMockWrite(*req2
, 0),
12641 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12642 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12643 MockRead reads2
[] = {
12644 CreateMockRead(*resp2
, 1),
12645 CreateMockRead(*body2
, 2),
12646 MockRead(ASYNC
, OK
, 3) // EOF
12649 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12650 arraysize(writes2
));
12652 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12653 ssl1
.SetNextProto(GetParam());
12654 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12655 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12657 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12658 ssl2
.SetNextProto(GetParam());
12659 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12660 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12662 scoped_refptr
<HttpNetworkSession
> session(
12663 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
12665 // Start the first transaction to set up the SpdySession and verify that
12666 // connection was closed.
12667 HttpRequestInfo request1
;
12668 request1
.method
= "GET";
12669 request1
.url
= GURL(https_url
);
12670 request1
.load_flags
= 0;
12671 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12672 TestCompletionCallback callback1
;
12673 EXPECT_EQ(ERR_IO_PENDING
,
12674 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12675 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12677 // Now, start the second request and make sure it succeeds.
12678 HttpRequestInfo request2
;
12679 request2
.method
= "GET";
12680 request2
.url
= GURL(https_url
);
12681 request2
.load_flags
= 0;
12682 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12683 TestCompletionCallback callback2
;
12684 EXPECT_EQ(ERR_IO_PENDING
,
12685 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12687 ASSERT_EQ(OK
, callback2
.WaitForResult());
12688 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12691 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12692 session_deps_
.next_protos
= SpdyNextProtos();
12693 ClientSocketPoolManager::set_max_sockets_per_group(
12694 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12695 ClientSocketPoolManager::set_max_sockets_per_pool(
12696 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12698 // Use two different hosts with different IPs so they don't get pooled.
12699 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12700 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12701 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12703 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12704 ssl1
.SetNextProto(GetParam());
12705 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12706 ssl2
.SetNextProto(GetParam());
12707 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12708 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12710 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12711 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12712 MockWrite spdy1_writes
[] = {
12713 CreateMockWrite(*host1_req
, 0),
12715 scoped_ptr
<SpdyFrame
> host1_resp(
12716 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12717 scoped_ptr
<SpdyFrame
> host1_resp_body(
12718 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12719 MockRead spdy1_reads
[] = {
12720 CreateMockRead(*host1_resp
, 1),
12721 CreateMockRead(*host1_resp_body
, 2),
12722 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12725 scoped_ptr
<SequencedSocketData
> spdy1_data(
12726 new SequencedSocketData(spdy1_reads
, arraysize(spdy1_reads
), spdy1_writes
,
12727 arraysize(spdy1_writes
)));
12728 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12730 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12731 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12732 MockWrite spdy2_writes
[] = {
12733 CreateMockWrite(*host2_req
, 0),
12735 scoped_ptr
<SpdyFrame
> host2_resp(
12736 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12737 scoped_ptr
<SpdyFrame
> host2_resp_body(
12738 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12739 MockRead spdy2_reads
[] = {
12740 CreateMockRead(*host2_resp
, 1),
12741 CreateMockRead(*host2_resp_body
, 2),
12742 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12745 scoped_ptr
<SequencedSocketData
> spdy2_data(
12746 new SequencedSocketData(spdy2_reads
, arraysize(spdy2_reads
), spdy2_writes
,
12747 arraysize(spdy2_writes
)));
12748 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12750 MockWrite http_write
[] = {
12751 MockWrite("GET / HTTP/1.1\r\n"
12752 "Host: www.a.com\r\n"
12753 "Connection: keep-alive\r\n\r\n"),
12756 MockRead http_read
[] = {
12757 MockRead("HTTP/1.1 200 OK\r\n"),
12758 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12759 MockRead("Content-Length: 6\r\n\r\n"),
12760 MockRead("hello!"),
12762 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12763 http_write
, arraysize(http_write
));
12764 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12766 HostPortPair
host_port_pair_a("www.a.com", 443);
12767 SpdySessionKey
spdy_session_key_a(
12768 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12770 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12772 TestCompletionCallback callback
;
12773 HttpRequestInfo request1
;
12774 request1
.method
= "GET";
12775 request1
.url
= GURL("https://www.a.com/");
12776 request1
.load_flags
= 0;
12777 scoped_ptr
<HttpNetworkTransaction
> trans(
12778 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12780 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12781 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12782 EXPECT_EQ(OK
, callback
.WaitForResult());
12784 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12785 ASSERT_TRUE(response
!= NULL
);
12786 ASSERT_TRUE(response
->headers
.get() != NULL
);
12787 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12788 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12789 EXPECT_TRUE(response
->was_npn_negotiated
);
12791 std::string response_data
;
12792 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12793 EXPECT_EQ("hello!", response_data
);
12796 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12798 HostPortPair
host_port_pair_b("www.b.com", 443);
12799 SpdySessionKey
spdy_session_key_b(
12800 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12802 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12803 HttpRequestInfo request2
;
12804 request2
.method
= "GET";
12805 request2
.url
= GURL("https://www.b.com/");
12806 request2
.load_flags
= 0;
12807 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12809 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
12810 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12811 EXPECT_EQ(OK
, callback
.WaitForResult());
12813 response
= trans
->GetResponseInfo();
12814 ASSERT_TRUE(response
!= NULL
);
12815 ASSERT_TRUE(response
->headers
.get() != NULL
);
12816 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12817 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12818 EXPECT_TRUE(response
->was_npn_negotiated
);
12819 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12820 EXPECT_EQ("hello!", response_data
);
12822 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12824 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12826 HostPortPair
host_port_pair_a1("www.a.com", 80);
12827 SpdySessionKey
spdy_session_key_a1(
12828 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12830 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
12831 HttpRequestInfo request3
;
12832 request3
.method
= "GET";
12833 request3
.url
= GURL("http://www.a.com/");
12834 request3
.load_flags
= 0;
12835 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12837 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
12838 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12839 EXPECT_EQ(OK
, callback
.WaitForResult());
12841 response
= trans
->GetResponseInfo();
12842 ASSERT_TRUE(response
!= NULL
);
12843 ASSERT_TRUE(response
->headers
.get() != NULL
);
12844 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12845 EXPECT_FALSE(response
->was_fetched_via_spdy
);
12846 EXPECT_FALSE(response
->was_npn_negotiated
);
12847 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12848 EXPECT_EQ("hello!", response_data
);
12850 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12852 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12855 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
12856 HttpRequestInfo request
;
12857 request
.method
= "GET";
12858 request
.url
= GURL("http://www.example.org/");
12859 request
.load_flags
= 0;
12861 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12862 scoped_ptr
<HttpTransaction
> trans(
12863 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12865 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
12866 StaticSocketDataProvider data
;
12867 data
.set_connect_data(mock_connect
);
12868 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12870 TestCompletionCallback callback
;
12872 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12873 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12875 rv
= callback
.WaitForResult();
12876 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12878 // We don't care whether this succeeds or fails, but it shouldn't crash.
12879 HttpRequestHeaders request_headers
;
12880 trans
->GetFullRequestHeaders(&request_headers
);
12882 ConnectionAttempts attempts
;
12883 trans
->GetConnectionAttempts(&attempts
);
12884 ASSERT_EQ(1u, attempts
.size());
12885 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12888 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
12889 HttpRequestInfo request
;
12890 request
.method
= "GET";
12891 request
.url
= GURL("http://www.example.org/");
12892 request
.load_flags
= 0;
12894 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12895 scoped_ptr
<HttpTransaction
> trans(
12896 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12898 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12899 StaticSocketDataProvider data
;
12900 data
.set_connect_data(mock_connect
);
12901 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12903 TestCompletionCallback callback
;
12905 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12906 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12908 rv
= callback
.WaitForResult();
12909 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12911 // We don't care whether this succeeds or fails, but it shouldn't crash.
12912 HttpRequestHeaders request_headers
;
12913 trans
->GetFullRequestHeaders(&request_headers
);
12915 ConnectionAttempts attempts
;
12916 trans
->GetConnectionAttempts(&attempts
);
12917 ASSERT_EQ(1u, attempts
.size());
12918 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12921 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12922 HttpRequestInfo request
;
12923 request
.method
= "GET";
12924 request
.url
= GURL("http://www.example.org/");
12925 request
.load_flags
= 0;
12927 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12928 scoped_ptr
<HttpTransaction
> trans(
12929 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12931 MockWrite data_writes
[] = {
12932 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12934 MockRead data_reads
[] = {
12935 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12938 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12939 data_writes
, arraysize(data_writes
));
12940 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12942 TestCompletionCallback callback
;
12944 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12947 rv
= callback
.WaitForResult();
12948 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12950 HttpRequestHeaders request_headers
;
12951 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12952 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12955 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12956 HttpRequestInfo request
;
12957 request
.method
= "GET";
12958 request
.url
= GURL("http://www.example.org/");
12959 request
.load_flags
= 0;
12961 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12962 scoped_ptr
<HttpTransaction
> trans(
12963 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12965 MockWrite data_writes
[] = {
12966 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12968 MockRead data_reads
[] = {
12969 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12972 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12973 data_writes
, arraysize(data_writes
));
12974 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12976 TestCompletionCallback callback
;
12978 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12981 rv
= callback
.WaitForResult();
12982 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12984 HttpRequestHeaders request_headers
;
12985 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12986 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12989 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12990 HttpRequestInfo request
;
12991 request
.method
= "GET";
12992 request
.url
= GURL("http://www.example.org/");
12993 request
.load_flags
= 0;
12995 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12996 scoped_ptr
<HttpTransaction
> trans(
12997 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12999 MockWrite data_writes
[] = {
13001 "GET / HTTP/1.1\r\n"
13002 "Host: www.example.org\r\n"
13003 "Connection: keep-alive\r\n\r\n"),
13005 MockRead data_reads
[] = {
13006 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13009 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13010 data_writes
, arraysize(data_writes
));
13011 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13013 TestCompletionCallback callback
;
13015 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13016 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13018 rv
= callback
.WaitForResult();
13019 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13021 HttpRequestHeaders request_headers
;
13022 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13023 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13026 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
13027 HttpRequestInfo request
;
13028 request
.method
= "GET";
13029 request
.url
= GURL("http://www.example.org/");
13030 request
.load_flags
= 0;
13032 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13033 scoped_ptr
<HttpTransaction
> trans(
13034 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13036 MockWrite data_writes
[] = {
13038 "GET / HTTP/1.1\r\n"
13039 "Host: www.example.org\r\n"
13040 "Connection: keep-alive\r\n\r\n"),
13042 MockRead data_reads
[] = {
13043 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
13046 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13047 data_writes
, arraysize(data_writes
));
13048 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13050 TestCompletionCallback callback
;
13052 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13053 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13055 rv
= callback
.WaitForResult();
13056 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13058 HttpRequestHeaders request_headers
;
13059 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13060 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13063 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
13064 HttpRequestInfo request
;
13065 request
.method
= "GET";
13066 request
.url
= GURL("http://www.example.org/");
13067 request
.load_flags
= 0;
13068 request
.extra_headers
.SetHeader("X-Foo", "bar");
13070 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13071 scoped_ptr
<HttpTransaction
> trans(
13072 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13074 MockWrite data_writes
[] = {
13076 "GET / HTTP/1.1\r\n"
13077 "Host: www.example.org\r\n"
13078 "Connection: keep-alive\r\n"
13079 "X-Foo: bar\r\n\r\n"),
13081 MockRead data_reads
[] = {
13082 MockRead("HTTP/1.1 200 OK\r\n"
13083 "Content-Length: 5\r\n\r\n"
13085 MockRead(ASYNC
, ERR_UNEXPECTED
),
13088 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13089 data_writes
, arraysize(data_writes
));
13090 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13092 TestCompletionCallback callback
;
13094 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13095 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13097 rv
= callback
.WaitForResult();
13100 HttpRequestHeaders request_headers
;
13101 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13103 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
13104 EXPECT_EQ("bar", foo
);
13109 // Fake HttpStream that simply records calls to SetPriority().
13110 class FakeStream
: public HttpStream
,
13111 public base::SupportsWeakPtr
<FakeStream
> {
13113 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
13114 ~FakeStream() override
{}
13116 RequestPriority
priority() const { return priority_
; }
13118 int InitializeStream(const HttpRequestInfo
* request_info
,
13119 RequestPriority priority
,
13120 const BoundNetLog
& net_log
,
13121 const CompletionCallback
& callback
) override
{
13122 return ERR_IO_PENDING
;
13125 int SendRequest(const HttpRequestHeaders
& request_headers
,
13126 HttpResponseInfo
* response
,
13127 const CompletionCallback
& callback
) override
{
13129 return ERR_UNEXPECTED
;
13132 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13134 return ERR_UNEXPECTED
;
13137 int ReadResponseBody(IOBuffer
* buf
,
13139 const CompletionCallback
& callback
) override
{
13141 return ERR_UNEXPECTED
;
13144 void Close(bool not_reusable
) override
{}
13146 bool IsResponseBodyComplete() const override
{
13151 bool CanFindEndOfResponse() const override
{ return false; }
13153 bool IsConnectionReused() const override
{
13158 void SetConnectionReused() override
{ ADD_FAILURE(); }
13160 bool IsConnectionReusable() const override
{
13165 int64
GetTotalReceivedBytes() const override
{
13170 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13175 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
13177 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13181 bool IsSpdyHttpStream() const override
{
13186 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
13188 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13190 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
13192 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
13195 RequestPriority priority_
;
13197 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
13200 // Fake HttpStreamRequest that simply records calls to SetPriority()
13201 // and vends FakeStreams with its current priority.
13202 class FakeStreamRequest
: public HttpStreamRequest
,
13203 public base::SupportsWeakPtr
<FakeStreamRequest
> {
13205 FakeStreamRequest(RequestPriority priority
,
13206 HttpStreamRequest::Delegate
* delegate
)
13207 : priority_(priority
),
13208 delegate_(delegate
),
13209 websocket_stream_create_helper_(NULL
) {}
13211 FakeStreamRequest(RequestPriority priority
,
13212 HttpStreamRequest::Delegate
* delegate
,
13213 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
13214 : priority_(priority
),
13215 delegate_(delegate
),
13216 websocket_stream_create_helper_(create_helper
) {}
13218 ~FakeStreamRequest() override
{}
13220 RequestPriority
priority() const { return priority_
; }
13222 const WebSocketHandshakeStreamBase::CreateHelper
*
13223 websocket_stream_create_helper() const {
13224 return websocket_stream_create_helper_
;
13227 // Create a new FakeStream and pass it to the request's
13228 // delegate. Returns a weak pointer to the FakeStream.
13229 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
13230 FakeStream
* fake_stream
= new FakeStream(priority_
);
13231 // Do this before calling OnStreamReady() as OnStreamReady() may
13232 // immediately delete |fake_stream|.
13233 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
13234 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
13235 return weak_stream
;
13238 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
13240 return ERR_UNEXPECTED
;
13243 LoadState
GetLoadState() const override
{
13245 return LoadState();
13248 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13250 bool was_npn_negotiated() const override
{ return false; }
13252 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
13254 bool using_spdy() const override
{ return false; }
13256 const ConnectionAttempts
& connection_attempts() const override
{
13257 static ConnectionAttempts no_attempts
;
13258 return no_attempts
;
13262 RequestPriority priority_
;
13263 HttpStreamRequest::Delegate
* const delegate_
;
13264 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
13266 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
13269 // Fake HttpStreamFactory that vends FakeStreamRequests.
13270 class FakeStreamFactory
: public HttpStreamFactory
{
13272 FakeStreamFactory() {}
13273 ~FakeStreamFactory() override
{}
13275 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13276 // RequestStream() (which may be NULL if it was destroyed already).
13277 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
13278 return last_stream_request_
;
13281 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
13282 RequestPriority priority
,
13283 const SSLConfig
& server_ssl_config
,
13284 const SSLConfig
& proxy_ssl_config
,
13285 HttpStreamRequest::Delegate
* delegate
,
13286 const BoundNetLog
& net_log
) override
{
13287 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
13288 last_stream_request_
= fake_request
->AsWeakPtr();
13289 return fake_request
;
13292 HttpStreamRequest
* RequestWebSocketHandshakeStream(
13293 const HttpRequestInfo
& info
,
13294 RequestPriority priority
,
13295 const SSLConfig
& server_ssl_config
,
13296 const SSLConfig
& proxy_ssl_config
,
13297 HttpStreamRequest::Delegate
* delegate
,
13298 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
13299 const BoundNetLog
& net_log
) override
{
13300 FakeStreamRequest
* fake_request
=
13301 new FakeStreamRequest(priority
, delegate
, create_helper
);
13302 last_stream_request_
= fake_request
->AsWeakPtr();
13303 return fake_request
;
13306 void PreconnectStreams(int num_streams
,
13307 const HttpRequestInfo
& info
,
13308 const SSLConfig
& server_ssl_config
,
13309 const SSLConfig
& proxy_ssl_config
) override
{
13313 const HostMappingRules
* GetHostMappingRules() const override
{
13319 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
13321 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
13324 // TODO(ricea): Maybe unify this with the one in
13325 // url_request_http_job_unittest.cc ?
13326 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
13328 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
13330 : state_(connection
.release(), using_proxy
) {}
13332 // Fake implementation of HttpStreamBase methods.
13333 // This ends up being quite "real" because this object has to really send data
13334 // on the mock socket. It might be easier to use the real implementation, but
13335 // the fact that the WebSocket code is not compiled on iOS makes that
13337 int InitializeStream(const HttpRequestInfo
* request_info
,
13338 RequestPriority priority
,
13339 const BoundNetLog
& net_log
,
13340 const CompletionCallback
& callback
) override
{
13341 state_
.Initialize(request_info
, priority
, net_log
, callback
);
13345 int SendRequest(const HttpRequestHeaders
& request_headers
,
13346 HttpResponseInfo
* response
,
13347 const CompletionCallback
& callback
) override
{
13348 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
13349 response
, callback
);
13352 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13353 return parser()->ReadResponseHeaders(callback
);
13356 int ReadResponseBody(IOBuffer
* buf
,
13358 const CompletionCallback
& callback
) override
{
13360 return ERR_IO_PENDING
;
13363 void Close(bool not_reusable
) override
{
13365 parser()->Close(true);
13368 bool IsResponseBodyComplete() const override
{
13373 bool CanFindEndOfResponse() const override
{
13374 return parser()->CanFindEndOfResponse();
13377 bool IsConnectionReused() const override
{
13381 void SetConnectionReused() override
{ NOTREACHED(); }
13383 bool IsConnectionReusable() const override
{
13388 int64
GetTotalReceivedBytes() const override
{
13393 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13398 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13400 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13404 bool IsSpdyHttpStream() const override
{
13409 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13411 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13413 UploadProgress
GetUploadProgress() const override
{
13415 return UploadProgress();
13418 HttpStream
* RenewStreamForAuth() override
{
13423 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13424 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13426 return scoped_ptr
<WebSocketStream
>();
13430 HttpStreamParser
* parser() const { return state_
.parser(); }
13431 HttpBasicState state_
;
13433 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13436 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13438 class FakeWebSocketStreamCreateHelper
:
13439 public WebSocketHandshakeStreamBase::CreateHelper
{
13441 WebSocketHandshakeStreamBase
* CreateBasicStream(
13442 scoped_ptr
<ClientSocketHandle
> connection
,
13443 bool using_proxy
) override
{
13444 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13448 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13449 const base::WeakPtr
<SpdySession
>& session
,
13450 bool use_relative_url
) override
{
13455 ~FakeWebSocketStreamCreateHelper() override
{}
13457 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13459 return scoped_ptr
<WebSocketStream
>();
13465 // Make sure that HttpNetworkTransaction passes on its priority to its
13466 // stream request on start.
13467 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13468 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13469 HttpNetworkSessionPeer
peer(session
);
13470 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13471 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13473 HttpNetworkTransaction
trans(LOW
, session
.get());
13475 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13477 HttpRequestInfo request
;
13478 TestCompletionCallback callback
;
13479 EXPECT_EQ(ERR_IO_PENDING
,
13480 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13482 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13483 fake_factory
->last_stream_request();
13484 ASSERT_TRUE(fake_request
!= NULL
);
13485 EXPECT_EQ(LOW
, fake_request
->priority());
13488 // Make sure that HttpNetworkTransaction passes on its priority
13489 // updates to its stream request.
13490 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13491 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13492 HttpNetworkSessionPeer
peer(session
);
13493 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13494 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13496 HttpNetworkTransaction
trans(LOW
, session
.get());
13498 HttpRequestInfo request
;
13499 TestCompletionCallback callback
;
13500 EXPECT_EQ(ERR_IO_PENDING
,
13501 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13503 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13504 fake_factory
->last_stream_request();
13505 ASSERT_TRUE(fake_request
!= NULL
);
13506 EXPECT_EQ(LOW
, fake_request
->priority());
13508 trans
.SetPriority(LOWEST
);
13509 ASSERT_TRUE(fake_request
!= NULL
);
13510 EXPECT_EQ(LOWEST
, fake_request
->priority());
13513 // Make sure that HttpNetworkTransaction passes on its priority
13514 // updates to its stream.
13515 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13516 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13517 HttpNetworkSessionPeer
peer(session
);
13518 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13519 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13521 HttpNetworkTransaction
trans(LOW
, session
.get());
13523 HttpRequestInfo request
;
13524 TestCompletionCallback callback
;
13525 EXPECT_EQ(ERR_IO_PENDING
,
13526 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13528 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13529 fake_factory
->last_stream_request();
13530 ASSERT_TRUE(fake_request
!= NULL
);
13531 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13532 ASSERT_TRUE(fake_stream
!= NULL
);
13533 EXPECT_EQ(LOW
, fake_stream
->priority());
13535 trans
.SetPriority(LOWEST
);
13536 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13539 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13540 // The same logic needs to be tested for both ws: and wss: schemes, but this
13541 // test is already parameterised on NextProto, so it uses a loop to verify
13542 // that the different schemes work.
13543 std::string test_cases
[] = {"ws://www.example.org/",
13544 "wss://www.example.org/"};
13545 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13546 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13547 HttpNetworkSessionPeer
peer(session
);
13548 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13549 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13550 peer
.SetHttpStreamFactoryForWebSocket(
13551 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13553 HttpNetworkTransaction
trans(LOW
, session
.get());
13554 trans
.SetWebSocketHandshakeStreamCreateHelper(
13555 &websocket_stream_create_helper
);
13557 HttpRequestInfo request
;
13558 TestCompletionCallback callback
;
13559 request
.method
= "GET";
13560 request
.url
= GURL(test_cases
[i
]);
13562 EXPECT_EQ(ERR_IO_PENDING
,
13563 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13565 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13566 fake_factory
->last_stream_request();
13567 ASSERT_TRUE(fake_request
!= NULL
);
13568 EXPECT_EQ(&websocket_stream_create_helper
,
13569 fake_request
->websocket_stream_create_helper());
13573 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13574 // if the transport socket pool is stalled on the global socket limit.
13575 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13576 ClientSocketPoolManager::set_max_sockets_per_group(
13577 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13578 ClientSocketPoolManager::set_max_sockets_per_pool(
13579 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13581 // Set up SSL request.
13583 HttpRequestInfo ssl_request
;
13584 ssl_request
.method
= "GET";
13585 ssl_request
.url
= GURL("https://www.example.org/");
13587 MockWrite ssl_writes
[] = {
13589 "GET / HTTP/1.1\r\n"
13590 "Host: www.example.org\r\n"
13591 "Connection: keep-alive\r\n\r\n"),
13593 MockRead ssl_reads
[] = {
13594 MockRead("HTTP/1.1 200 OK\r\n"),
13595 MockRead("Content-Length: 11\r\n\r\n"),
13596 MockRead("hello world"),
13597 MockRead(SYNCHRONOUS
, OK
),
13599 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13600 ssl_writes
, arraysize(ssl_writes
));
13601 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13603 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13604 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13606 // Set up HTTP request.
13608 HttpRequestInfo http_request
;
13609 http_request
.method
= "GET";
13610 http_request
.url
= GURL("http://www.example.org/");
13612 MockWrite http_writes
[] = {
13614 "GET / HTTP/1.1\r\n"
13615 "Host: www.example.org\r\n"
13616 "Connection: keep-alive\r\n\r\n"),
13618 MockRead http_reads
[] = {
13619 MockRead("HTTP/1.1 200 OK\r\n"),
13620 MockRead("Content-Length: 7\r\n\r\n"),
13621 MockRead("falafel"),
13622 MockRead(SYNCHRONOUS
, OK
),
13624 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13625 http_writes
, arraysize(http_writes
));
13626 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13628 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13630 // Start the SSL request.
13631 TestCompletionCallback ssl_callback
;
13632 scoped_ptr
<HttpTransaction
> ssl_trans(
13633 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13634 ASSERT_EQ(ERR_IO_PENDING
,
13635 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13638 // Start the HTTP request. Pool should stall.
13639 TestCompletionCallback http_callback
;
13640 scoped_ptr
<HttpTransaction
> http_trans(
13641 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13642 ASSERT_EQ(ERR_IO_PENDING
,
13643 http_trans
->Start(&http_request
, http_callback
.callback(),
13645 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13647 // Wait for response from SSL request.
13648 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13649 std::string response_data
;
13650 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13651 EXPECT_EQ("hello world", response_data
);
13653 // The SSL socket should automatically be closed, so the HTTP request can
13655 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13656 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13658 // The HTTP request can now complete.
13659 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13660 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13661 EXPECT_EQ("falafel", response_data
);
13663 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13666 // Tests that when a SSL connection is established but there's no corresponding
13667 // request that needs it, the new socket is closed if the transport socket pool
13668 // is stalled on the global socket limit.
13669 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13670 ClientSocketPoolManager::set_max_sockets_per_group(
13671 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13672 ClientSocketPoolManager::set_max_sockets_per_pool(
13673 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13675 // Set up an ssl request.
13677 HttpRequestInfo ssl_request
;
13678 ssl_request
.method
= "GET";
13679 ssl_request
.url
= GURL("https://www.foopy.com/");
13681 // No data will be sent on the SSL socket.
13682 StaticSocketDataProvider ssl_data
;
13683 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13685 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13686 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13688 // Set up HTTP request.
13690 HttpRequestInfo http_request
;
13691 http_request
.method
= "GET";
13692 http_request
.url
= GURL("http://www.example.org/");
13694 MockWrite http_writes
[] = {
13696 "GET / HTTP/1.1\r\n"
13697 "Host: www.example.org\r\n"
13698 "Connection: keep-alive\r\n\r\n"),
13700 MockRead http_reads
[] = {
13701 MockRead("HTTP/1.1 200 OK\r\n"),
13702 MockRead("Content-Length: 7\r\n\r\n"),
13703 MockRead("falafel"),
13704 MockRead(SYNCHRONOUS
, OK
),
13706 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13707 http_writes
, arraysize(http_writes
));
13708 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13710 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13712 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13713 // cancelled when a normal transaction is cancelled.
13714 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13715 SSLConfig ssl_config
;
13716 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13717 http_stream_factory
->PreconnectStreams(1, ssl_request
, ssl_config
,
13719 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13721 // Start the HTTP request. Pool should stall.
13722 TestCompletionCallback http_callback
;
13723 scoped_ptr
<HttpTransaction
> http_trans(
13724 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13725 ASSERT_EQ(ERR_IO_PENDING
,
13726 http_trans
->Start(&http_request
, http_callback
.callback(),
13728 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13730 // The SSL connection will automatically be closed once the connection is
13731 // established, to let the HTTP request start.
13732 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13733 std::string response_data
;
13734 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13735 EXPECT_EQ("falafel", response_data
);
13737 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13740 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13741 ScopedVector
<UploadElementReader
> element_readers
;
13742 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13743 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13745 HttpRequestInfo request
;
13746 request
.method
= "POST";
13747 request
.url
= GURL("http://www.foo.com/");
13748 request
.upload_data_stream
= &upload_data_stream
;
13749 request
.load_flags
= 0;
13751 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13752 scoped_ptr
<HttpTransaction
> trans(
13753 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13754 // Send headers successfully, but get an error while sending the body.
13755 MockWrite data_writes
[] = {
13756 MockWrite("POST / HTTP/1.1\r\n"
13757 "Host: www.foo.com\r\n"
13758 "Connection: keep-alive\r\n"
13759 "Content-Length: 3\r\n\r\n"),
13760 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13763 MockRead data_reads
[] = {
13764 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13765 MockRead("hello world"),
13766 MockRead(SYNCHRONOUS
, OK
),
13768 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13769 arraysize(data_writes
));
13770 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13772 TestCompletionCallback callback
;
13774 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13777 rv
= callback
.WaitForResult();
13780 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13781 ASSERT_TRUE(response
!= NULL
);
13783 EXPECT_TRUE(response
->headers
.get() != NULL
);
13784 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13786 std::string response_data
;
13787 rv
= ReadTransaction(trans
.get(), &response_data
);
13789 EXPECT_EQ("hello world", response_data
);
13792 // This test makes sure the retry logic doesn't trigger when reading an error
13793 // response from a server that rejected a POST with a CONNECTION_RESET.
13794 TEST_P(HttpNetworkTransactionTest
,
13795 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13796 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13797 MockWrite data_writes
[] = {
13798 MockWrite("GET / HTTP/1.1\r\n"
13799 "Host: www.foo.com\r\n"
13800 "Connection: keep-alive\r\n\r\n"),
13801 MockWrite("POST / HTTP/1.1\r\n"
13802 "Host: www.foo.com\r\n"
13803 "Connection: keep-alive\r\n"
13804 "Content-Length: 3\r\n\r\n"),
13805 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13808 MockRead data_reads
[] = {
13809 MockRead("HTTP/1.1 200 Peachy\r\n"
13810 "Content-Length: 14\r\n\r\n"),
13811 MockRead("first response"),
13812 MockRead("HTTP/1.1 400 Not OK\r\n"
13813 "Content-Length: 15\r\n\r\n"),
13814 MockRead("second response"),
13815 MockRead(SYNCHRONOUS
, OK
),
13817 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13818 arraysize(data_writes
));
13819 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13821 TestCompletionCallback callback
;
13822 HttpRequestInfo request1
;
13823 request1
.method
= "GET";
13824 request1
.url
= GURL("http://www.foo.com/");
13825 request1
.load_flags
= 0;
13827 scoped_ptr
<HttpTransaction
> trans1(
13828 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13829 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
13830 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13832 rv
= callback
.WaitForResult();
13835 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
13836 ASSERT_TRUE(response1
!= NULL
);
13838 EXPECT_TRUE(response1
->headers
.get() != NULL
);
13839 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
13841 std::string response_data1
;
13842 rv
= ReadTransaction(trans1
.get(), &response_data1
);
13844 EXPECT_EQ("first response", response_data1
);
13845 // Delete the transaction to release the socket back into the socket pool.
13848 ScopedVector
<UploadElementReader
> element_readers
;
13849 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13850 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13852 HttpRequestInfo request2
;
13853 request2
.method
= "POST";
13854 request2
.url
= GURL("http://www.foo.com/");
13855 request2
.upload_data_stream
= &upload_data_stream
;
13856 request2
.load_flags
= 0;
13858 scoped_ptr
<HttpTransaction
> trans2(
13859 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13860 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
13861 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13863 rv
= callback
.WaitForResult();
13866 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
13867 ASSERT_TRUE(response2
!= NULL
);
13869 EXPECT_TRUE(response2
->headers
.get() != NULL
);
13870 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
13872 std::string response_data2
;
13873 rv
= ReadTransaction(trans2
.get(), &response_data2
);
13875 EXPECT_EQ("second response", response_data2
);
13878 TEST_P(HttpNetworkTransactionTest
,
13879 PostReadsErrorResponseAfterResetPartialBodySent
) {
13880 ScopedVector
<UploadElementReader
> element_readers
;
13881 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13882 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13884 HttpRequestInfo request
;
13885 request
.method
= "POST";
13886 request
.url
= GURL("http://www.foo.com/");
13887 request
.upload_data_stream
= &upload_data_stream
;
13888 request
.load_flags
= 0;
13890 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13891 scoped_ptr
<HttpTransaction
> trans(
13892 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13893 // Send headers successfully, but get an error while sending the body.
13894 MockWrite data_writes
[] = {
13895 MockWrite("POST / HTTP/1.1\r\n"
13896 "Host: www.foo.com\r\n"
13897 "Connection: keep-alive\r\n"
13898 "Content-Length: 3\r\n\r\n"
13900 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13903 MockRead data_reads
[] = {
13904 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13905 MockRead("hello world"),
13906 MockRead(SYNCHRONOUS
, OK
),
13908 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13909 arraysize(data_writes
));
13910 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13912 TestCompletionCallback callback
;
13914 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13915 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13917 rv
= callback
.WaitForResult();
13920 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13921 ASSERT_TRUE(response
!= NULL
);
13923 EXPECT_TRUE(response
->headers
.get() != NULL
);
13924 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13926 std::string response_data
;
13927 rv
= ReadTransaction(trans
.get(), &response_data
);
13929 EXPECT_EQ("hello world", response_data
);
13932 // This tests the more common case than the previous test, where headers and
13933 // body are not merged into a single request.
13934 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
13935 ScopedVector
<UploadElementReader
> element_readers
;
13936 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13937 ChunkedUploadDataStream
upload_data_stream(0);
13939 HttpRequestInfo request
;
13940 request
.method
= "POST";
13941 request
.url
= GURL("http://www.foo.com/");
13942 request
.upload_data_stream
= &upload_data_stream
;
13943 request
.load_flags
= 0;
13945 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13946 scoped_ptr
<HttpTransaction
> trans(
13947 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13948 // Send headers successfully, but get an error while sending the body.
13949 MockWrite data_writes
[] = {
13950 MockWrite("POST / HTTP/1.1\r\n"
13951 "Host: www.foo.com\r\n"
13952 "Connection: keep-alive\r\n"
13953 "Transfer-Encoding: chunked\r\n\r\n"),
13954 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13957 MockRead data_reads
[] = {
13958 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13959 MockRead("hello world"),
13960 MockRead(SYNCHRONOUS
, OK
),
13962 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13963 arraysize(data_writes
));
13964 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13966 TestCompletionCallback callback
;
13968 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13969 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13970 // Make sure the headers are sent before adding a chunk. This ensures that
13971 // they can't be merged with the body in a single send. Not currently
13972 // necessary since a chunked body is never merged with headers, but this makes
13973 // the test more future proof.
13974 base::RunLoop().RunUntilIdle();
13976 upload_data_stream
.AppendData("last chunk", 10, true);
13978 rv
= callback
.WaitForResult();
13981 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13982 ASSERT_TRUE(response
!= NULL
);
13984 EXPECT_TRUE(response
->headers
.get() != NULL
);
13985 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13987 std::string response_data
;
13988 rv
= ReadTransaction(trans
.get(), &response_data
);
13990 EXPECT_EQ("hello world", response_data
);
13993 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
13994 ScopedVector
<UploadElementReader
> element_readers
;
13995 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13996 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13998 HttpRequestInfo request
;
13999 request
.method
= "POST";
14000 request
.url
= GURL("http://www.foo.com/");
14001 request
.upload_data_stream
= &upload_data_stream
;
14002 request
.load_flags
= 0;
14004 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14005 scoped_ptr
<HttpTransaction
> trans(
14006 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14008 MockWrite data_writes
[] = {
14009 MockWrite("POST / HTTP/1.1\r\n"
14010 "Host: www.foo.com\r\n"
14011 "Connection: keep-alive\r\n"
14012 "Content-Length: 3\r\n\r\n"),
14013 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14016 MockRead data_reads
[] = {
14017 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14018 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14019 MockRead("hello world"),
14020 MockRead(SYNCHRONOUS
, OK
),
14022 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14023 arraysize(data_writes
));
14024 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14026 TestCompletionCallback callback
;
14028 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14029 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14031 rv
= callback
.WaitForResult();
14034 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14035 ASSERT_TRUE(response
!= NULL
);
14037 EXPECT_TRUE(response
->headers
.get() != NULL
);
14038 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14040 std::string response_data
;
14041 rv
= ReadTransaction(trans
.get(), &response_data
);
14043 EXPECT_EQ("hello world", response_data
);
14046 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
14047 ScopedVector
<UploadElementReader
> element_readers
;
14048 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14049 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14051 HttpRequestInfo request
;
14052 request
.method
= "POST";
14053 request
.url
= GURL("http://www.foo.com/");
14054 request
.upload_data_stream
= &upload_data_stream
;
14055 request
.load_flags
= 0;
14057 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14058 scoped_ptr
<HttpTransaction
> trans(
14059 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14060 // Send headers successfully, but get an error while sending the body.
14061 MockWrite data_writes
[] = {
14062 MockWrite("POST / HTTP/1.1\r\n"
14063 "Host: www.foo.com\r\n"
14064 "Connection: keep-alive\r\n"
14065 "Content-Length: 3\r\n\r\n"),
14066 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14069 MockRead data_reads
[] = {
14070 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14071 MockRead("hello world"),
14072 MockRead(SYNCHRONOUS
, OK
),
14074 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14075 arraysize(data_writes
));
14076 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14078 TestCompletionCallback callback
;
14080 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14081 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14083 rv
= callback
.WaitForResult();
14084 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14087 TEST_P(HttpNetworkTransactionTest
,
14088 PostIgnoresNonErrorResponseAfterResetAnd100
) {
14089 ScopedVector
<UploadElementReader
> element_readers
;
14090 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14091 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14093 HttpRequestInfo request
;
14094 request
.method
= "POST";
14095 request
.url
= GURL("http://www.foo.com/");
14096 request
.upload_data_stream
= &upload_data_stream
;
14097 request
.load_flags
= 0;
14099 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14100 scoped_ptr
<HttpTransaction
> trans(
14101 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14102 // Send headers successfully, but get an error while sending the body.
14103 MockWrite data_writes
[] = {
14104 MockWrite("POST / HTTP/1.1\r\n"
14105 "Host: www.foo.com\r\n"
14106 "Connection: keep-alive\r\n"
14107 "Content-Length: 3\r\n\r\n"),
14108 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14111 MockRead data_reads
[] = {
14112 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14113 MockRead("HTTP/1.0 302 Redirect\r\n"),
14114 MockRead("Location: http://somewhere-else.com/\r\n"),
14115 MockRead("Content-Length: 0\r\n\r\n"),
14116 MockRead(SYNCHRONOUS
, OK
),
14118 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14119 arraysize(data_writes
));
14120 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14122 TestCompletionCallback callback
;
14124 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14125 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14127 rv
= callback
.WaitForResult();
14128 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14131 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
14132 ScopedVector
<UploadElementReader
> element_readers
;
14133 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14134 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14136 HttpRequestInfo request
;
14137 request
.method
= "POST";
14138 request
.url
= GURL("http://www.foo.com/");
14139 request
.upload_data_stream
= &upload_data_stream
;
14140 request
.load_flags
= 0;
14142 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14143 scoped_ptr
<HttpTransaction
> trans(
14144 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14145 // Send headers successfully, but get an error while sending the body.
14146 MockWrite data_writes
[] = {
14147 MockWrite("POST / HTTP/1.1\r\n"
14148 "Host: www.foo.com\r\n"
14149 "Connection: keep-alive\r\n"
14150 "Content-Length: 3\r\n\r\n"),
14151 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14154 MockRead data_reads
[] = {
14155 MockRead("HTTP 0.9 rocks!"),
14156 MockRead(SYNCHRONOUS
, OK
),
14158 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14159 arraysize(data_writes
));
14160 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14162 TestCompletionCallback callback
;
14164 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14167 rv
= callback
.WaitForResult();
14168 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14171 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
14172 ScopedVector
<UploadElementReader
> element_readers
;
14173 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14174 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14176 HttpRequestInfo request
;
14177 request
.method
= "POST";
14178 request
.url
= GURL("http://www.foo.com/");
14179 request
.upload_data_stream
= &upload_data_stream
;
14180 request
.load_flags
= 0;
14182 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14183 scoped_ptr
<HttpTransaction
> trans(
14184 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14185 // Send headers successfully, but get an error while sending the body.
14186 MockWrite data_writes
[] = {
14187 MockWrite("POST / HTTP/1.1\r\n"
14188 "Host: www.foo.com\r\n"
14189 "Connection: keep-alive\r\n"
14190 "Content-Length: 3\r\n\r\n"),
14191 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14194 MockRead data_reads
[] = {
14195 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14196 MockRead(SYNCHRONOUS
, OK
),
14198 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14199 arraysize(data_writes
));
14200 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14202 TestCompletionCallback callback
;
14204 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14205 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14207 rv
= callback
.WaitForResult();
14208 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14211 // Verify that proxy headers are not sent to the destination server when
14212 // establishing a tunnel for a secure WebSocket connection.
14213 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
14214 HttpRequestInfo request
;
14215 request
.method
= "GET";
14216 request
.url
= GURL("wss://www.example.org/");
14217 AddWebSocketHeaders(&request
.extra_headers
);
14219 // Configure against proxy server "myproxy:70".
14220 session_deps_
.proxy_service
.reset(
14221 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14223 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14225 // Since a proxy is configured, try to establish a tunnel.
14226 MockWrite data_writes
[] = {
14228 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14229 "Host: www.example.org\r\n"
14230 "Proxy-Connection: keep-alive\r\n\r\n"),
14232 // After calling trans->RestartWithAuth(), this is the request we should
14233 // be issuing -- the final header line contains the credentials.
14235 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14236 "Host: www.example.org\r\n"
14237 "Proxy-Connection: keep-alive\r\n"
14238 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14241 "GET / HTTP/1.1\r\n"
14242 "Host: www.example.org\r\n"
14243 "Connection: Upgrade\r\n"
14244 "Upgrade: websocket\r\n"
14245 "Origin: http://www.example.org\r\n"
14246 "Sec-WebSocket-Version: 13\r\n"
14247 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14250 // The proxy responds to the connect with a 407, using a persistent
14252 MockRead data_reads
[] = {
14254 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14255 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14256 MockRead("Proxy-Connection: close\r\n\r\n"),
14258 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14260 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14261 MockRead("Upgrade: websocket\r\n"),
14262 MockRead("Connection: Upgrade\r\n"),
14263 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14266 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14267 arraysize(data_writes
));
14268 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14269 SSLSocketDataProvider
ssl(ASYNC
, OK
);
14270 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
14272 scoped_ptr
<HttpTransaction
> trans(
14273 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14274 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14275 trans
->SetWebSocketHandshakeStreamCreateHelper(
14276 &websocket_stream_create_helper
);
14279 TestCompletionCallback callback
;
14281 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14282 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14284 rv
= callback
.WaitForResult();
14288 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14289 ASSERT_TRUE(response
);
14290 ASSERT_TRUE(response
->headers
.get());
14291 EXPECT_EQ(407, response
->headers
->response_code());
14294 TestCompletionCallback callback
;
14296 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
14297 callback
.callback());
14298 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14300 rv
= callback
.WaitForResult();
14304 response
= trans
->GetResponseInfo();
14305 ASSERT_TRUE(response
);
14306 ASSERT_TRUE(response
->headers
.get());
14308 EXPECT_EQ(101, response
->headers
->response_code());
14311 session
->CloseAllConnections();
14314 // Verify that proxy headers are not sent to the destination server when
14315 // establishing a tunnel for an insecure WebSocket connection.
14316 // This requires the authentication info to be injected into the auth cache
14317 // due to crbug.com/395064
14318 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14319 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
14320 HttpRequestInfo request
;
14321 request
.method
= "GET";
14322 request
.url
= GURL("ws://www.example.org/");
14323 AddWebSocketHeaders(&request
.extra_headers
);
14325 // Configure against proxy server "myproxy:70".
14326 session_deps_
.proxy_service
.reset(
14327 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14329 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14331 MockWrite data_writes
[] = {
14332 // Try to establish a tunnel for the WebSocket connection, with
14333 // credentials. Because WebSockets have a separate set of socket pools,
14334 // they cannot and will not use the same TCP/IP connection as the
14335 // preflight HTTP request.
14337 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14338 "Host: www.example.org:80\r\n"
14339 "Proxy-Connection: keep-alive\r\n"
14340 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14343 "GET / HTTP/1.1\r\n"
14344 "Host: www.example.org\r\n"
14345 "Connection: Upgrade\r\n"
14346 "Upgrade: websocket\r\n"
14347 "Origin: http://www.example.org\r\n"
14348 "Sec-WebSocket-Version: 13\r\n"
14349 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14352 MockRead data_reads
[] = {
14353 // HTTP CONNECT with credentials.
14354 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14356 // WebSocket connection established inside tunnel.
14357 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14358 MockRead("Upgrade: websocket\r\n"),
14359 MockRead("Connection: Upgrade\r\n"),
14360 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14363 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14364 arraysize(data_writes
));
14365 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14367 session
->http_auth_cache()->Add(
14368 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
14369 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
14371 scoped_ptr
<HttpTransaction
> trans(
14372 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14373 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14374 trans
->SetWebSocketHandshakeStreamCreateHelper(
14375 &websocket_stream_create_helper
);
14377 TestCompletionCallback callback
;
14379 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14380 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14382 rv
= callback
.WaitForResult();
14385 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14386 ASSERT_TRUE(response
);
14387 ASSERT_TRUE(response
->headers
.get());
14389 EXPECT_EQ(101, response
->headers
->response_code());
14392 session
->CloseAllConnections();