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
14 #include "base/basictypes.h"
15 #include "base/compiler_specific.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/json/json_writer.h"
19 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/weak_ptr.h"
22 #include "base/run_loop.h"
23 #include "base/stl_util.h"
24 #include "base/strings/string_util.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/test/test_file_util.h"
27 #include "base/thread_task_runner_handle.h"
28 #include "net/base/auth.h"
29 #include "net/base/chunked_upload_data_stream.h"
30 #include "net/base/completion_callback.h"
31 #include "net/base/elements_upload_data_stream.h"
32 #include "net/base/load_timing_info.h"
33 #include "net/base/load_timing_info_test_util.h"
34 #include "net/base/net_errors.h"
35 #include "net/base/request_priority.h"
36 #include "net/base/test_completion_callback.h"
37 #include "net/base/test_data_directory.h"
38 #include "net/base/upload_bytes_element_reader.h"
39 #include "net/base/upload_file_element_reader.h"
40 #include "net/cert/mock_cert_verifier.h"
41 #include "net/dns/host_cache.h"
42 #include "net/dns/mock_host_resolver.h"
43 #include "net/http/http_auth_challenge_tokenizer.h"
44 #include "net/http/http_auth_handler_digest.h"
45 #include "net/http/http_auth_handler_mock.h"
46 #include "net/http/http_auth_handler_ntlm.h"
47 #include "net/http/http_basic_state.h"
48 #include "net/http/http_basic_stream.h"
49 #include "net/http/http_network_session.h"
50 #include "net/http/http_network_session_peer.h"
51 #include "net/http/http_request_headers.h"
52 #include "net/http/http_server_properties_impl.h"
53 #include "net/http/http_stream.h"
54 #include "net/http/http_stream_factory.h"
55 #include "net/http/http_stream_parser.h"
56 #include "net/http/http_transaction_test_util.h"
57 #include "net/log/net_log.h"
58 #include "net/log/test_net_log.h"
59 #include "net/log/test_net_log_entry.h"
60 #include "net/log/test_net_log_util.h"
61 #include "net/proxy/mock_proxy_resolver.h"
62 #include "net/proxy/proxy_config_service_fixed.h"
63 #include "net/proxy/proxy_info.h"
64 #include "net/proxy/proxy_resolver.h"
65 #include "net/proxy/proxy_service.h"
66 #include "net/socket/client_socket_factory.h"
67 #include "net/socket/client_socket_pool_manager.h"
68 #include "net/socket/connection_attempts.h"
69 #include "net/socket/mock_client_socket_pool_manager.h"
70 #include "net/socket/next_proto.h"
71 #include "net/socket/socket_test_util.h"
72 #include "net/socket/ssl_client_socket.h"
73 #include "net/spdy/spdy_framer.h"
74 #include "net/spdy/spdy_session.h"
75 #include "net/spdy/spdy_session_pool.h"
76 #include "net/spdy/spdy_test_util_common.h"
77 #include "net/ssl/ssl_cert_request_info.h"
78 #include "net/ssl/ssl_config_service.h"
79 #include "net/ssl/ssl_config_service_defaults.h"
80 #include "net/ssl/ssl_info.h"
81 #include "net/test/cert_test_util.h"
82 #include "net/websockets/websocket_handshake_stream_base.h"
83 #include "testing/gtest/include/gtest/gtest.h"
84 #include "testing/platform_test.h"
87 using base::ASCIIToUTF16
;
89 //-----------------------------------------------------------------------------
95 const base::string16
kBar(ASCIIToUTF16("bar"));
96 const base::string16
kBar2(ASCIIToUTF16("bar2"));
97 const base::string16
kBar3(ASCIIToUTF16("bar3"));
98 const base::string16
kBaz(ASCIIToUTF16("baz"));
99 const base::string16
kFirst(ASCIIToUTF16("first"));
100 const base::string16
kFoo(ASCIIToUTF16("foo"));
101 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
102 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
103 const base::string16
kFou(ASCIIToUTF16("fou"));
104 const base::string16
kSecond(ASCIIToUTF16("second"));
105 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
106 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
108 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession
* session
) {
109 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
113 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession
* session
) {
114 return session
->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
118 bool IsTransportSocketPoolStalled(HttpNetworkSession
* session
) {
119 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
123 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
124 // a JSONified list of headers as a single string. Uses single quotes instead
125 // of double quotes for easier comparison. Returns false on failure.
126 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
129 base::ListValue
* header_list
;
130 if (!params
->GetList("headers", &header_list
))
132 std::string double_quote_headers
;
133 base::JSONWriter::Write(*header_list
, &double_quote_headers
);
134 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
138 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
140 void TestLoadTimingReused(const LoadTimingInfo
& load_timing_info
) {
141 EXPECT_TRUE(load_timing_info
.socket_reused
);
142 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
144 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
145 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
147 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
148 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
150 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
152 // Set at a higher level.
153 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
154 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
155 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
158 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
160 void TestLoadTimingNotReused(const LoadTimingInfo
& load_timing_info
,
161 int connect_timing_flags
) {
162 EXPECT_FALSE(load_timing_info
.socket_reused
);
163 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
165 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
166 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
168 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
169 connect_timing_flags
);
170 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
171 load_timing_info
.send_start
);
173 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
175 // Set at a higher level.
176 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
177 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
178 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
181 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
183 void TestLoadTimingReusedWithPac(const LoadTimingInfo
& load_timing_info
) {
184 EXPECT_TRUE(load_timing_info
.socket_reused
);
185 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
187 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
189 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
190 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
191 load_timing_info
.proxy_resolve_end
);
192 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
193 load_timing_info
.send_start
);
194 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
196 // Set at a higher level.
197 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
198 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
199 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
202 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
204 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo
& load_timing_info
,
205 int connect_timing_flags
) {
206 EXPECT_FALSE(load_timing_info
.socket_reused
);
207 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
209 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
210 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
211 load_timing_info
.proxy_resolve_end
);
212 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
213 load_timing_info
.connect_timing
.connect_start
);
214 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
215 connect_timing_flags
);
216 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
217 load_timing_info
.send_start
);
219 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
221 // Set at a higher level.
222 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
223 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
224 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
227 void AddWebSocketHeaders(HttpRequestHeaders
* headers
) {
228 headers
->SetHeader("Connection", "Upgrade");
229 headers
->SetHeader("Upgrade", "websocket");
230 headers
->SetHeader("Origin", "http://www.example.org");
231 headers
->SetHeader("Sec-WebSocket-Version", "13");
232 headers
->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
235 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
236 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
241 class HttpNetworkTransactionTest
242 : public PlatformTest
,
243 public ::testing::WithParamInterface
<NextProto
> {
245 virtual ~HttpNetworkTransactionTest() {
246 // Important to restore the per-pool limit first, since the pool limit must
247 // always be greater than group limit, and the tests reduce both limits.
248 ClientSocketPoolManager::set_max_sockets_per_pool(
249 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
250 ClientSocketPoolManager::set_max_sockets_per_group(
251 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
255 HttpNetworkTransactionTest()
256 : spdy_util_(GetParam()),
257 session_deps_(GetParam()),
258 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
259 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
260 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
261 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
264 struct SimpleGetHelperResult
{
266 std::string status_line
;
267 std::string response_data
;
268 int64_t total_received_bytes
;
269 int64_t total_sent_bytes
;
270 LoadTimingInfo load_timing_info
;
271 ConnectionAttempts connection_attempts
;
274 void SetUp() override
{
275 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
276 base::MessageLoop::current()->RunUntilIdle();
279 void TearDown() override
{
280 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
281 base::MessageLoop::current()->RunUntilIdle();
282 // Empty the current queue.
283 base::MessageLoop::current()->RunUntilIdle();
284 PlatformTest::TearDown();
285 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
286 base::MessageLoop::current()->RunUntilIdle();
289 const char* GetAlternateProtocolFromParam() {
291 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
294 std::string
GetAlternativeServiceHttpHeader() {
295 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
296 "=\"www.example.com:443\"\r\n";
299 std::string
GetAlternateProtocolHttpHeader() {
300 return std::string("Alternate-Protocol: 443:") +
301 GetAlternateProtocolFromParam() + "\r\n";
304 // Either |write_failure| specifies a write failure or |read_failure|
305 // specifies a read failure when using a reused socket. In either case, the
306 // failure should cause the network transaction to resend the request, and the
307 // other argument should be NULL.
308 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
309 const MockRead
* read_failure
);
311 // Either |write_failure| specifies a write failure or |read_failure|
312 // specifies a read failure when using a reused socket. In either case, the
313 // failure should cause the network transaction to resend the request, and the
314 // other argument should be NULL.
315 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
316 const MockRead
* read_failure
,
319 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
321 SimpleGetHelperResult out
;
323 HttpRequestInfo request
;
324 request
.method
= "GET";
325 request
.url
= GURL("http://www.example.org/");
326 request
.load_flags
= 0;
329 session_deps_
.net_log
= log
.bound().net_log();
330 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
331 scoped_ptr
<HttpTransaction
> trans(
332 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
334 for (size_t i
= 0; i
< data_count
; ++i
) {
335 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
338 TestCompletionCallback callback
;
340 EXPECT_TRUE(log
.bound().IsCapturing());
341 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
342 EXPECT_EQ(ERR_IO_PENDING
, rv
);
344 out
.rv
= callback
.WaitForResult();
345 out
.total_received_bytes
= trans
->GetTotalReceivedBytes();
346 out
.total_sent_bytes
= trans
->GetTotalSentBytes();
348 // Even in the failure cases that use this function, connections are always
349 // successfully established before the error.
350 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
351 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
356 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
357 // Can't use ASSERT_* inside helper functions like this, so
359 if (response
== NULL
|| response
->headers
.get() == NULL
) {
360 out
.rv
= ERR_UNEXPECTED
;
363 out
.status_line
= response
->headers
->GetStatusLine();
365 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
366 EXPECT_EQ(80, response
->socket_address
.port());
368 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
371 TestNetLogEntry::List entries
;
372 log
.GetEntries(&entries
);
373 size_t pos
= ExpectLogContainsSomewhere(
374 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
376 ExpectLogContainsSomewhere(
378 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
382 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
383 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
385 HttpRequestHeaders request_headers
;
386 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
388 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
389 EXPECT_EQ("www.example.org", value
);
390 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
391 EXPECT_EQ("keep-alive", value
);
393 std::string response_headers
;
394 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
395 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
398 out
.total_received_bytes
= trans
->GetTotalReceivedBytes();
399 // The total number of sent bytes should not have changed.
400 EXPECT_EQ(out
.total_sent_bytes
, trans
->GetTotalSentBytes());
402 trans
->GetConnectionAttempts(&out
.connection_attempts
);
406 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
407 size_t reads_count
) {
408 MockWrite data_writes
[] = {
409 MockWrite("GET / HTTP/1.1\r\n"
410 "Host: www.example.org\r\n"
411 "Connection: keep-alive\r\n\r\n"),
414 StaticSocketDataProvider
reads(data_reads
, reads_count
, data_writes
,
415 arraysize(data_writes
));
416 StaticSocketDataProvider
* data
[] = {&reads
};
417 SimpleGetHelperResult out
= SimpleGetHelperForData(data
, 1);
419 EXPECT_EQ(CountWriteBytes(data_writes
, arraysize(data_writes
)),
420 out
.total_sent_bytes
);
424 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
425 int expected_status
);
427 void ConnectStatusHelper(const MockRead
& status
);
429 void BypassHostCacheOnRefreshHelper(int load_flags
);
431 void CheckErrorIsPassedBack(int error
, IoMode mode
);
433 SpdyTestUtil spdy_util_
;
434 SpdySessionDependencies session_deps_
;
436 // Original socket limits. Some tests set these. Safest to always restore
437 // them once each test has been run.
438 int old_max_group_sockets_
;
439 int old_max_pool_sockets_
;
442 INSTANTIATE_TEST_CASE_P(NextProto
,
443 HttpNetworkTransactionTest
,
444 testing::Values(kProtoSPDY31
,
449 class BeforeNetworkStartHandler
{
451 explicit BeforeNetworkStartHandler(bool defer
)
452 : defer_on_before_network_start_(defer
),
453 observed_before_network_start_(false) {}
455 void OnBeforeNetworkStart(bool* defer
) {
456 *defer
= defer_on_before_network_start_
;
457 observed_before_network_start_
= true;
460 bool observed_before_network_start() const {
461 return observed_before_network_start_
;
465 const bool defer_on_before_network_start_
;
466 bool observed_before_network_start_
;
468 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
471 class BeforeProxyHeadersSentHandler
{
473 BeforeProxyHeadersSentHandler()
474 : observed_before_proxy_headers_sent_(false) {}
476 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
477 HttpRequestHeaders
* request_headers
) {
478 observed_before_proxy_headers_sent_
= true;
479 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
482 bool observed_before_proxy_headers_sent() const {
483 return observed_before_proxy_headers_sent_
;
486 std::string
observed_proxy_server_uri() const {
487 return observed_proxy_server_uri_
;
491 bool observed_before_proxy_headers_sent_
;
492 std::string observed_proxy_server_uri_
;
494 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
497 // Fill |str| with a long header list that consumes >= |size| bytes.
498 void FillLargeHeadersString(std::string
* str
, int size
) {
500 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
501 const int sizeof_row
= strlen(row
);
502 const int num_rows
= static_cast<int>(
503 ceil(static_cast<float>(size
) / sizeof_row
));
504 const int sizeof_data
= num_rows
* sizeof_row
;
505 DCHECK(sizeof_data
>= size
);
506 str
->reserve(sizeof_data
);
508 for (int i
= 0; i
< num_rows
; ++i
)
509 str
->append(row
, sizeof_row
);
512 #if defined(NTLM_PORTABLE)
513 // Alternative functions that eliminate randomness and dependency on the local
514 // host name so that the generated NTLM messages are reproducible.
515 void MockGenerateRandom1(uint8
* output
, size_t n
) {
516 static const uint8 bytes
[] = {
517 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
519 static size_t current_byte
= 0;
520 for (size_t i
= 0; i
< n
; ++i
) {
521 output
[i
] = bytes
[current_byte
++];
522 current_byte
%= arraysize(bytes
);
526 void MockGenerateRandom2(uint8
* output
, size_t n
) {
527 static const uint8 bytes
[] = {
528 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
529 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
531 static size_t current_byte
= 0;
532 for (size_t i
= 0; i
< n
; ++i
) {
533 output
[i
] = bytes
[current_byte
++];
534 current_byte
%= arraysize(bytes
);
538 std::string
MockGetHostName() {
541 #endif // defined(NTLM_PORTABLE)
543 template<typename ParentPool
>
544 class CaptureGroupNameSocketPool
: public ParentPool
{
546 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
547 CertVerifier
* cert_verifier
);
549 const std::string
last_group_name_received() const {
550 return last_group_name_
;
553 int RequestSocket(const std::string
& group_name
,
554 const void* socket_params
,
555 RequestPriority priority
,
556 ClientSocketHandle
* handle
,
557 const CompletionCallback
& callback
,
558 const BoundNetLog
& net_log
) override
{
559 last_group_name_
= group_name
;
560 return ERR_IO_PENDING
;
562 void CancelRequest(const std::string
& group_name
,
563 ClientSocketHandle
* handle
) override
{}
564 void ReleaseSocket(const std::string
& group_name
,
565 scoped_ptr
<StreamSocket
> socket
,
567 void CloseIdleSockets() override
{}
568 int IdleSocketCount() const override
{ return 0; }
569 int IdleSocketCountInGroup(const std::string
& group_name
) const override
{
572 LoadState
GetLoadState(const std::string
& group_name
,
573 const ClientSocketHandle
* handle
) const override
{
574 return LOAD_STATE_IDLE
;
576 base::TimeDelta
ConnectionTimeout() const override
{
577 return base::TimeDelta();
581 std::string last_group_name_
;
584 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
585 CaptureGroupNameTransportSocketPool
;
586 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
587 CaptureGroupNameHttpProxySocketPool
;
588 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
589 CaptureGroupNameSOCKSSocketPool
;
590 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
591 CaptureGroupNameSSLSocketPool
;
593 template <typename ParentPool
>
594 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
595 HostResolver
* host_resolver
,
596 CertVerifier
* /* cert_verifier */)
597 : ParentPool(0, 0, host_resolver
, NULL
, NULL
) {
601 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
602 HostResolver
* /* host_resolver */,
603 CertVerifier
* /* cert_verifier */)
604 : HttpProxyClientSocketPool(0, 0, NULL
, NULL
, NULL
) {
608 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
609 HostResolver
* /* host_resolver */,
610 CertVerifier
* cert_verifier
)
611 : SSLClientSocketPool(0,
627 //-----------------------------------------------------------------------------
629 // Helper functions for validating that AuthChallengeInfo's are correctly
630 // configured for common cases.
631 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
634 EXPECT_FALSE(auth_challenge
->is_proxy
);
635 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
636 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
637 EXPECT_EQ("basic", auth_challenge
->scheme
);
641 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
644 EXPECT_TRUE(auth_challenge
->is_proxy
);
645 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
646 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
647 EXPECT_EQ("basic", auth_challenge
->scheme
);
651 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
654 EXPECT_FALSE(auth_challenge
->is_proxy
);
655 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
656 EXPECT_EQ("digestive", auth_challenge
->realm
);
657 EXPECT_EQ("digest", auth_challenge
->scheme
);
661 #if defined(NTLM_PORTABLE)
662 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
665 EXPECT_FALSE(auth_challenge
->is_proxy
);
666 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
667 EXPECT_EQ(std::string(), auth_challenge
->realm
);
668 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
671 #endif // defined(NTLM_PORTABLE)
675 TEST_P(HttpNetworkTransactionTest
, Basic
) {
676 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
677 scoped_ptr
<HttpTransaction
> trans(
678 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
681 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
682 MockRead data_reads
[] = {
683 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
684 MockRead("hello world"),
685 MockRead(SYNCHRONOUS
, OK
),
687 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
688 arraysize(data_reads
));
689 EXPECT_EQ(OK
, out
.rv
);
690 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
691 EXPECT_EQ("hello world", out
.response_data
);
692 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
693 EXPECT_EQ(reads_size
, out
.total_received_bytes
);
694 EXPECT_EQ(0u, out
.connection_attempts
.size());
697 // Response with no status line.
698 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
699 MockRead data_reads
[] = {
700 MockRead("hello world"),
701 MockRead(SYNCHRONOUS
, OK
),
703 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
704 arraysize(data_reads
));
705 EXPECT_EQ(OK
, out
.rv
);
706 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
707 EXPECT_EQ("hello world", out
.response_data
);
708 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
709 EXPECT_EQ(reads_size
, out
.total_received_bytes
);
712 // Allow up to 4 bytes of junk to precede status line.
713 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
714 MockRead data_reads
[] = {
715 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
716 MockRead(SYNCHRONOUS
, OK
),
718 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
719 arraysize(data_reads
));
720 EXPECT_EQ(OK
, out
.rv
);
721 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
722 EXPECT_EQ("DATA", out
.response_data
);
723 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
724 EXPECT_EQ(reads_size
, out
.total_received_bytes
);
727 // Allow up to 4 bytes of junk to precede status line.
728 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
729 MockRead data_reads
[] = {
730 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
731 MockRead(SYNCHRONOUS
, OK
),
733 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
734 arraysize(data_reads
));
735 EXPECT_EQ(OK
, out
.rv
);
736 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
737 EXPECT_EQ("DATA", out
.response_data
);
738 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
739 EXPECT_EQ(reads_size
, out
.total_received_bytes
);
742 // Beyond 4 bytes of slop and it should fail to find a status line.
743 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
744 MockRead data_reads
[] = {
745 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
746 MockRead(SYNCHRONOUS
, OK
),
748 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
749 arraysize(data_reads
));
750 EXPECT_EQ(OK
, out
.rv
);
751 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
752 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
753 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
754 EXPECT_EQ(reads_size
, out
.total_received_bytes
);
757 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
758 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
759 MockRead data_reads
[] = {
764 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
765 MockRead(SYNCHRONOUS
, OK
),
767 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
768 arraysize(data_reads
));
769 EXPECT_EQ(OK
, out
.rv
);
770 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
771 EXPECT_EQ("DATA", out
.response_data
);
772 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
773 EXPECT_EQ(reads_size
, out
.total_received_bytes
);
776 // Close the connection before enough bytes to have a status line.
777 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
778 MockRead data_reads
[] = {
780 MockRead(SYNCHRONOUS
, OK
),
782 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
783 arraysize(data_reads
));
784 EXPECT_EQ(OK
, out
.rv
);
785 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
786 EXPECT_EQ("HTT", out
.response_data
);
787 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
788 EXPECT_EQ(reads_size
, out
.total_received_bytes
);
791 // Simulate a 204 response, lacking a Content-Length header, sent over a
792 // persistent connection. The response should still terminate since a 204
793 // cannot have a response body.
794 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
795 char junk
[] = "junk";
796 MockRead data_reads
[] = {
797 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
798 MockRead(junk
), // Should not be read!!
799 MockRead(SYNCHRONOUS
, OK
),
801 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
802 arraysize(data_reads
));
803 EXPECT_EQ(OK
, out
.rv
);
804 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
805 EXPECT_EQ("", out
.response_data
);
806 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
807 int64_t response_size
= reads_size
- strlen(junk
);
808 EXPECT_EQ(response_size
, out
.total_received_bytes
);
811 // A simple request using chunked encoding with some extra data after.
812 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
813 std::string final_chunk
= "0\r\n\r\n";
814 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
815 std::string last_read
= final_chunk
+ extra_data
;
816 MockRead data_reads
[] = {
817 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
818 MockRead("5\r\nHello\r\n"),
821 MockRead("5\r\nworld\r\n"),
822 MockRead(last_read
.data()),
823 MockRead(SYNCHRONOUS
, OK
),
825 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
826 arraysize(data_reads
));
827 EXPECT_EQ(OK
, out
.rv
);
828 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
829 EXPECT_EQ("Hello world", out
.response_data
);
830 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
831 int64_t response_size
= reads_size
- extra_data
.size();
832 EXPECT_EQ(response_size
, out
.total_received_bytes
);
835 // Next tests deal with http://crbug.com/56344.
837 TEST_P(HttpNetworkTransactionTest
,
838 MultipleContentLengthHeadersNoTransferEncoding
) {
839 MockRead data_reads
[] = {
840 MockRead("HTTP/1.1 200 OK\r\n"),
841 MockRead("Content-Length: 10\r\n"),
842 MockRead("Content-Length: 5\r\n\r\n"),
844 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
845 arraysize(data_reads
));
846 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
849 TEST_P(HttpNetworkTransactionTest
,
850 DuplicateContentLengthHeadersNoTransferEncoding
) {
851 MockRead data_reads
[] = {
852 MockRead("HTTP/1.1 200 OK\r\n"),
853 MockRead("Content-Length: 5\r\n"),
854 MockRead("Content-Length: 5\r\n\r\n"),
857 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
858 arraysize(data_reads
));
859 EXPECT_EQ(OK
, out
.rv
);
860 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
861 EXPECT_EQ("Hello", out
.response_data
);
864 TEST_P(HttpNetworkTransactionTest
,
865 ComplexContentLengthHeadersNoTransferEncoding
) {
866 // More than 2 dupes.
868 MockRead data_reads
[] = {
869 MockRead("HTTP/1.1 200 OK\r\n"),
870 MockRead("Content-Length: 5\r\n"),
871 MockRead("Content-Length: 5\r\n"),
872 MockRead("Content-Length: 5\r\n\r\n"),
875 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
876 arraysize(data_reads
));
877 EXPECT_EQ(OK
, out
.rv
);
878 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
879 EXPECT_EQ("Hello", out
.response_data
);
883 MockRead data_reads
[] = {
884 MockRead("HTTP/1.0 200 OK\r\n"),
885 MockRead("Content-Length: 5\r\n"),
886 MockRead("Content-Length: 5\r\n"),
887 MockRead("Content-Length: 5\r\n\r\n"),
890 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
891 arraysize(data_reads
));
892 EXPECT_EQ(OK
, out
.rv
);
893 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
894 EXPECT_EQ("Hello", out
.response_data
);
896 // 2 dupes and one mismatched.
898 MockRead data_reads
[] = {
899 MockRead("HTTP/1.1 200 OK\r\n"),
900 MockRead("Content-Length: 10\r\n"),
901 MockRead("Content-Length: 10\r\n"),
902 MockRead("Content-Length: 5\r\n\r\n"),
904 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
905 arraysize(data_reads
));
906 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
910 TEST_P(HttpNetworkTransactionTest
,
911 MultipleContentLengthHeadersTransferEncoding
) {
912 MockRead data_reads
[] = {
913 MockRead("HTTP/1.1 200 OK\r\n"),
914 MockRead("Content-Length: 666\r\n"),
915 MockRead("Content-Length: 1337\r\n"),
916 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
917 MockRead("5\r\nHello\r\n"),
920 MockRead("5\r\nworld\r\n"),
921 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
922 MockRead(SYNCHRONOUS
, OK
),
924 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
925 arraysize(data_reads
));
926 EXPECT_EQ(OK
, out
.rv
);
927 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
928 EXPECT_EQ("Hello world", out
.response_data
);
931 // Next tests deal with http://crbug.com/98895.
933 // Checks that a single Content-Disposition header results in no error.
934 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
935 MockRead data_reads
[] = {
936 MockRead("HTTP/1.1 200 OK\r\n"),
937 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
938 MockRead("Content-Length: 5\r\n\r\n"),
941 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
942 arraysize(data_reads
));
943 EXPECT_EQ(OK
, out
.rv
);
944 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
945 EXPECT_EQ("Hello", out
.response_data
);
948 // Checks that two identical Content-Disposition headers result in no error.
949 TEST_P(HttpNetworkTransactionTest
,
950 TwoIdenticalContentDispositionHeaders
) {
951 MockRead data_reads
[] = {
952 MockRead("HTTP/1.1 200 OK\r\n"),
953 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
954 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
955 MockRead("Content-Length: 5\r\n\r\n"),
958 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
959 arraysize(data_reads
));
960 EXPECT_EQ(OK
, out
.rv
);
961 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
962 EXPECT_EQ("Hello", out
.response_data
);
965 // Checks that two distinct Content-Disposition headers result in an error.
966 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
967 MockRead data_reads
[] = {
968 MockRead("HTTP/1.1 200 OK\r\n"),
969 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
970 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
971 MockRead("Content-Length: 5\r\n\r\n"),
974 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
975 arraysize(data_reads
));
976 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
979 // Checks that two identical Location headers result in no error.
980 // Also tests Location header behavior.
981 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
982 MockRead data_reads
[] = {
983 MockRead("HTTP/1.1 302 Redirect\r\n"),
984 MockRead("Location: http://good.com/\r\n"),
985 MockRead("Location: http://good.com/\r\n"),
986 MockRead("Content-Length: 0\r\n\r\n"),
987 MockRead(SYNCHRONOUS
, OK
),
990 HttpRequestInfo request
;
991 request
.method
= "GET";
992 request
.url
= GURL("http://redirect.com/");
993 request
.load_flags
= 0;
995 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
996 scoped_ptr
<HttpTransaction
> trans(
997 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
999 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1000 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1002 TestCompletionCallback callback
;
1004 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1005 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1007 EXPECT_EQ(OK
, callback
.WaitForResult());
1009 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1010 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
1011 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
1013 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
1014 EXPECT_EQ("http://good.com/", url
);
1015 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1018 // Checks that two distinct Location headers result in an error.
1019 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
1020 MockRead data_reads
[] = {
1021 MockRead("HTTP/1.1 302 Redirect\r\n"),
1022 MockRead("Location: http://good.com/\r\n"),
1023 MockRead("Location: http://evil.com/\r\n"),
1024 MockRead("Content-Length: 0\r\n\r\n"),
1025 MockRead(SYNCHRONOUS
, OK
),
1027 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1028 arraysize(data_reads
));
1029 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
1032 // Do a request using the HEAD method. Verify that we don't try to read the
1033 // message body (since HEAD has none).
1034 TEST_P(HttpNetworkTransactionTest
, Head
) {
1035 HttpRequestInfo request
;
1036 request
.method
= "HEAD";
1037 request
.url
= GURL("http://www.example.org/");
1038 request
.load_flags
= 0;
1040 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1041 scoped_ptr
<HttpTransaction
> trans(
1042 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1043 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1044 trans
->SetBeforeProxyHeadersSentCallback(
1045 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1046 base::Unretained(&proxy_headers_handler
)));
1048 MockWrite data_writes1
[] = {
1049 MockWrite("HEAD / HTTP/1.1\r\n"
1050 "Host: www.example.org\r\n"
1051 "Connection: keep-alive\r\n\r\n"),
1053 MockRead data_reads1
[] = {
1054 MockRead("HTTP/1.1 404 Not Found\r\n"),
1055 MockRead("Server: Blah\r\n"),
1056 MockRead("Content-Length: 1234\r\n\r\n"),
1058 // No response body because the test stops reading here.
1059 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1062 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1063 data_writes1
, arraysize(data_writes1
));
1064 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1066 TestCompletionCallback callback1
;
1068 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1071 rv
= callback1
.WaitForResult();
1074 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1075 ASSERT_TRUE(response
!= NULL
);
1077 // Check that the headers got parsed.
1078 EXPECT_TRUE(response
->headers
.get() != NULL
);
1079 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1080 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1081 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1082 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1084 std::string server_header
;
1086 bool has_server_header
= response
->headers
->EnumerateHeader(
1087 &iter
, "Server", &server_header
);
1088 EXPECT_TRUE(has_server_header
);
1089 EXPECT_EQ("Blah", server_header
);
1091 // Reading should give EOF right away, since there is no message body
1092 // (despite non-zero content-length).
1093 std::string response_data
;
1094 rv
= ReadTransaction(trans
.get(), &response_data
);
1096 EXPECT_EQ("", response_data
);
1099 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1100 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1102 MockRead data_reads
[] = {
1103 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1105 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1107 MockRead(SYNCHRONOUS
, OK
),
1109 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1110 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1112 const char* const kExpectedResponseData
[] = {
1116 for (int i
= 0; i
< 2; ++i
) {
1117 HttpRequestInfo request
;
1118 request
.method
= "GET";
1119 request
.url
= GURL("http://www.example.org/");
1120 request
.load_flags
= 0;
1122 scoped_ptr
<HttpTransaction
> trans(
1123 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1125 TestCompletionCallback callback
;
1127 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1128 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1130 rv
= callback
.WaitForResult();
1133 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1134 ASSERT_TRUE(response
!= NULL
);
1136 EXPECT_TRUE(response
->headers
.get() != NULL
);
1137 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1138 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1140 std::string response_data
;
1141 rv
= ReadTransaction(trans
.get(), &response_data
);
1143 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1147 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1148 ScopedVector
<UploadElementReader
> element_readers
;
1149 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1150 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1152 HttpRequestInfo request
;
1153 request
.method
= "POST";
1154 request
.url
= GURL("http://www.foo.com/");
1155 request
.upload_data_stream
= &upload_data_stream
;
1156 request
.load_flags
= 0;
1158 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1159 scoped_ptr
<HttpTransaction
> trans(
1160 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1162 MockRead data_reads
[] = {
1163 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1164 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1165 MockRead("hello world"),
1166 MockRead(SYNCHRONOUS
, OK
),
1168 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1169 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1171 TestCompletionCallback callback
;
1173 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1174 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1176 rv
= callback
.WaitForResult();
1179 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1180 ASSERT_TRUE(response
!= NULL
);
1182 EXPECT_TRUE(response
->headers
.get() != NULL
);
1183 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1185 std::string response_data
;
1186 rv
= ReadTransaction(trans
.get(), &response_data
);
1188 EXPECT_EQ("hello world", response_data
);
1191 // This test is almost the same as Ignores100 above, but the response contains
1192 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1193 // HTTP/1.1 and the two status headers are read in one read.
1194 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1195 HttpRequestInfo request
;
1196 request
.method
= "GET";
1197 request
.url
= GURL("http://www.foo.com/");
1198 request
.load_flags
= 0;
1200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1201 scoped_ptr
<HttpTransaction
> trans(
1202 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1204 MockRead data_reads
[] = {
1205 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1206 "HTTP/1.1 200 OK\r\n\r\n"),
1207 MockRead("hello world"),
1208 MockRead(SYNCHRONOUS
, OK
),
1210 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1211 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1213 TestCompletionCallback callback
;
1215 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1216 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1218 rv
= callback
.WaitForResult();
1221 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1222 ASSERT_TRUE(response
!= NULL
);
1224 EXPECT_TRUE(response
->headers
.get() != NULL
);
1225 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1227 std::string response_data
;
1228 rv
= ReadTransaction(trans
.get(), &response_data
);
1230 EXPECT_EQ("hello world", response_data
);
1233 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1234 HttpRequestInfo request
;
1235 request
.method
= "POST";
1236 request
.url
= GURL("http://www.foo.com/");
1237 request
.load_flags
= 0;
1239 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1240 scoped_ptr
<HttpTransaction
> trans(
1241 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1243 MockRead data_reads
[] = {
1244 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1247 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1248 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1250 TestCompletionCallback callback
;
1252 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1255 rv
= callback
.WaitForResult();
1258 std::string response_data
;
1259 rv
= ReadTransaction(trans
.get(), &response_data
);
1261 EXPECT_EQ("", response_data
);
1264 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1265 HttpRequestInfo request
;
1266 request
.method
= "POST";
1267 request
.url
= GURL("http://www.foo.com/");
1268 request
.load_flags
= 0;
1270 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1271 scoped_ptr
<HttpTransaction
> trans(
1272 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1274 MockRead data_reads
[] = {
1277 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1278 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1280 TestCompletionCallback callback
;
1282 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1283 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1285 rv
= callback
.WaitForResult();
1286 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1289 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1290 const MockWrite
* write_failure
,
1291 const MockRead
* read_failure
) {
1292 HttpRequestInfo request
;
1293 request
.method
= "GET";
1294 request
.url
= GURL("http://www.foo.com/");
1295 request
.load_flags
= 0;
1298 session_deps_
.net_log
= &net_log
;
1299 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1301 // Written data for successfully sending both requests.
1302 MockWrite data1_writes
[] = {
1303 MockWrite("GET / HTTP/1.1\r\n"
1304 "Host: www.foo.com\r\n"
1305 "Connection: keep-alive\r\n\r\n"),
1306 MockWrite("GET / HTTP/1.1\r\n"
1307 "Host: www.foo.com\r\n"
1308 "Connection: keep-alive\r\n\r\n")
1311 // Read results for the first request.
1312 MockRead data1_reads
[] = {
1313 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1315 MockRead(ASYNC
, OK
),
1318 if (write_failure
) {
1319 ASSERT_FALSE(read_failure
);
1320 data1_writes
[1] = *write_failure
;
1322 ASSERT_TRUE(read_failure
);
1323 data1_reads
[2] = *read_failure
;
1326 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1327 data1_writes
, arraysize(data1_writes
));
1328 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1330 MockRead data2_reads
[] = {
1331 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1333 MockRead(ASYNC
, OK
),
1335 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1336 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1338 const char* const kExpectedResponseData
[] = {
1342 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1343 for (int i
= 0; i
< 2; ++i
) {
1344 TestCompletionCallback callback
;
1346 scoped_ptr
<HttpTransaction
> trans(
1347 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1349 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1350 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1352 rv
= callback
.WaitForResult();
1355 LoadTimingInfo load_timing_info
;
1356 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1357 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1359 first_socket_log_id
= load_timing_info
.socket_log_id
;
1361 // The second request should be using a new socket.
1362 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1365 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1366 ASSERT_TRUE(response
!= NULL
);
1368 EXPECT_TRUE(response
->headers
.get() != NULL
);
1369 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1371 std::string response_data
;
1372 rv
= ReadTransaction(trans
.get(), &response_data
);
1374 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1378 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1379 const MockWrite
* write_failure
,
1380 const MockRead
* read_failure
,
1382 HttpRequestInfo request
;
1383 request
.method
= "GET";
1384 request
.url
= GURL("https://www.foo.com/");
1385 request
.load_flags
= 0;
1388 session_deps_
.net_log
= &net_log
;
1389 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1391 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1392 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1394 ssl1
.SetNextProto(GetParam());
1395 ssl2
.SetNextProto(GetParam());
1397 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1398 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1400 // SPDY versions of the request and response.
1401 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1402 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1403 scoped_ptr
<SpdyFrame
> spdy_response(
1404 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1405 scoped_ptr
<SpdyFrame
> spdy_data(
1406 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1408 // HTTP/1.1 versions of the request and response.
1409 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1410 "Host: www.foo.com\r\n"
1411 "Connection: keep-alive\r\n\r\n";
1412 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1413 const char kHttpData
[] = "hello";
1415 std::vector
<MockRead
> data1_reads
;
1416 std::vector
<MockWrite
> data1_writes
;
1417 if (write_failure
) {
1418 ASSERT_FALSE(read_failure
);
1419 data1_writes
.push_back(*write_failure
);
1420 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1422 ASSERT_TRUE(read_failure
);
1424 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1426 data1_writes
.push_back(MockWrite(kHttpRequest
));
1428 data1_reads
.push_back(*read_failure
);
1431 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1432 &data1_writes
[0], data1_writes
.size());
1433 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1435 std::vector
<MockRead
> data2_reads
;
1436 std::vector
<MockWrite
> data2_writes
;
1439 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1441 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1442 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1443 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1445 data2_writes
.push_back(
1446 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1448 data2_reads
.push_back(
1449 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1450 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1451 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1453 SequencedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1454 &data2_writes
[0], data2_writes
.size());
1455 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1457 // Preconnect a socket.
1458 SSLConfig ssl_config
;
1459 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1460 session
->GetNextProtos(&ssl_config
.next_protos
);
1461 session
->http_stream_factory()->PreconnectStreams(1, request
, ssl_config
,
1463 // Wait for the preconnect to complete.
1464 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1465 base::RunLoop().RunUntilIdle();
1466 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1468 // Make the request.
1469 TestCompletionCallback callback
;
1471 scoped_ptr
<HttpTransaction
> trans(
1472 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1474 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1475 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1477 rv
= callback
.WaitForResult();
1480 LoadTimingInfo load_timing_info
;
1481 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1482 TestLoadTimingNotReused(
1484 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1486 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1487 ASSERT_TRUE(response
!= NULL
);
1489 EXPECT_TRUE(response
->headers
.get() != NULL
);
1490 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1492 std::string response_data
;
1493 rv
= ReadTransaction(trans
.get(), &response_data
);
1495 EXPECT_EQ(kHttpData
, response_data
);
1498 TEST_P(HttpNetworkTransactionTest
,
1499 KeepAliveConnectionNotConnectedOnWrite
) {
1500 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1501 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1504 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1505 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1506 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1509 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1510 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1511 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1514 // Make sure that on a 408 response (Request Timeout), the request is retried,
1515 // if the socket was a reused keep alive socket.
1516 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1517 MockRead
read_failure(SYNCHRONOUS
,
1518 "HTTP/1.1 408 Request Timeout\r\n"
1519 "Connection: Keep-Alive\r\n"
1520 "Content-Length: 6\r\n\r\n"
1522 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1525 TEST_P(HttpNetworkTransactionTest
,
1526 PreconnectErrorNotConnectedOnWrite
) {
1527 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1528 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1531 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1532 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1533 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1536 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1537 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1538 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1541 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1542 MockRead
read_failure(ASYNC
, OK
); // EOF
1543 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1546 // Make sure that on a 408 response (Request Timeout), the request is retried,
1547 // if the socket was a preconnected (UNUSED_IDLE) socket.
1548 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1549 MockRead
read_failure(SYNCHRONOUS
,
1550 "HTTP/1.1 408 Request Timeout\r\n"
1551 "Connection: Keep-Alive\r\n"
1552 "Content-Length: 6\r\n\r\n"
1554 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1555 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1558 TEST_P(HttpNetworkTransactionTest
,
1559 SpdyPreconnectErrorNotConnectedOnWrite
) {
1560 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1561 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1564 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1565 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1566 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1569 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1570 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1571 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1574 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1575 MockRead
read_failure(ASYNC
, OK
); // EOF
1576 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1579 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1580 HttpRequestInfo request
;
1581 request
.method
= "GET";
1582 request
.url
= GURL("http://www.example.org/");
1583 request
.load_flags
= 0;
1585 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1586 scoped_ptr
<HttpTransaction
> trans(
1587 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1589 MockRead data_reads
[] = {
1590 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1591 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1592 MockRead("hello world"),
1593 MockRead(SYNCHRONOUS
, OK
),
1595 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1596 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1598 TestCompletionCallback callback
;
1600 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1601 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1603 rv
= callback
.WaitForResult();
1604 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1607 // What do various browsers do when the server closes a non-keepalive
1608 // connection without sending any response header or body?
1611 // Safari 3.1.2 (Windows): error page
1612 // Firefox 3.0.1: blank page
1613 // Opera 9.52: after five attempts, blank page
1614 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1615 // Us: error page (EMPTY_RESPONSE)
1616 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1617 MockRead data_reads
[] = {
1618 MockRead(SYNCHRONOUS
, OK
), // EOF
1619 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1620 MockRead("hello world"),
1621 MockRead(SYNCHRONOUS
, OK
),
1623 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1624 arraysize(data_reads
));
1625 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1628 // Test that network access can be deferred and resumed.
1629 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1630 HttpRequestInfo request
;
1631 request
.method
= "GET";
1632 request
.url
= GURL("http://www.example.org/");
1633 request
.load_flags
= 0;
1635 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1636 scoped_ptr
<HttpTransaction
> trans(
1637 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1639 // Defer on OnBeforeNetworkStart.
1640 BeforeNetworkStartHandler
net_start_handler(true); // defer
1641 trans
->SetBeforeNetworkStartCallback(
1642 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1643 base::Unretained(&net_start_handler
)));
1645 MockRead data_reads
[] = {
1646 MockRead("HTTP/1.0 200 OK\r\n"),
1647 MockRead("Content-Length: 5\r\n\r\n"),
1649 MockRead(SYNCHRONOUS
, 0),
1651 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1652 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1654 TestCompletionCallback callback
;
1656 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1657 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1658 base::MessageLoop::current()->RunUntilIdle();
1660 // Should have deferred for network start.
1661 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1662 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1664 trans
->ResumeNetworkStart();
1665 rv
= callback
.WaitForResult();
1667 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1669 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1670 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1671 if (rv
== ERR_IO_PENDING
)
1672 rv
= callback
.WaitForResult();
1677 // Test that network use can be deferred and canceled.
1678 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1679 HttpRequestInfo request
;
1680 request
.method
= "GET";
1681 request
.url
= GURL("http://www.example.org/");
1682 request
.load_flags
= 0;
1684 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1685 scoped_ptr
<HttpTransaction
> trans(
1686 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1688 // Defer on OnBeforeNetworkStart.
1689 BeforeNetworkStartHandler
net_start_handler(true); // defer
1690 trans
->SetBeforeNetworkStartCallback(
1691 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1692 base::Unretained(&net_start_handler
)));
1694 TestCompletionCallback callback
;
1696 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1698 base::MessageLoop::current()->RunUntilIdle();
1700 // Should have deferred for network start.
1701 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1702 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1705 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1706 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1707 // destructor in such situations.
1708 // See http://crbug.com/154712 and http://crbug.com/156609.
1709 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1710 HttpRequestInfo request
;
1711 request
.method
= "GET";
1712 request
.url
= GURL("http://www.example.org/");
1713 request
.load_flags
= 0;
1715 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1716 scoped_ptr
<HttpTransaction
> trans(
1717 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1719 MockRead data_reads
[] = {
1720 MockRead("HTTP/1.0 200 OK\r\n"),
1721 MockRead("Connection: keep-alive\r\n"),
1722 MockRead("Content-Length: 100\r\n\r\n"),
1724 MockRead(SYNCHRONOUS
, 0),
1726 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1727 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1729 TestCompletionCallback callback
;
1731 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1732 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1734 rv
= callback
.WaitForResult();
1737 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1738 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1739 if (rv
== ERR_IO_PENDING
)
1740 rv
= callback
.WaitForResult();
1742 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1743 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1746 base::MessageLoop::current()->RunUntilIdle();
1747 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1750 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1751 HttpRequestInfo request
;
1752 request
.method
= "GET";
1753 request
.url
= GURL("http://www.example.org/");
1754 request
.load_flags
= 0;
1756 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1757 scoped_ptr
<HttpTransaction
> trans(
1758 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1760 MockRead data_reads
[] = {
1761 MockRead("HTTP/1.0 200 OK\r\n"),
1762 MockRead("Connection: keep-alive\r\n"),
1763 MockRead("Content-Length: 100\r\n\r\n"),
1764 MockRead(SYNCHRONOUS
, 0),
1766 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1767 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1769 TestCompletionCallback callback
;
1771 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1772 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1774 rv
= callback
.WaitForResult();
1777 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1778 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1779 if (rv
== ERR_IO_PENDING
)
1780 rv
= callback
.WaitForResult();
1781 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1784 base::MessageLoop::current()->RunUntilIdle();
1785 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1788 // Test that we correctly reuse a keep-alive connection after not explicitly
1789 // reading the body.
1790 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1791 HttpRequestInfo request
;
1792 request
.method
= "GET";
1793 request
.url
= GURL("http://www.foo.com/");
1794 request
.load_flags
= 0;
1797 session_deps_
.net_log
= &net_log
;
1798 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1800 // Note that because all these reads happen in the same
1801 // StaticSocketDataProvider, it shows that the same socket is being reused for
1802 // all transactions.
1803 MockRead data1_reads
[] = {
1804 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1805 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1806 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1807 MockRead("HTTP/1.1 302 Found\r\n"
1808 "Content-Length: 0\r\n\r\n"),
1809 MockRead("HTTP/1.1 302 Found\r\n"
1810 "Content-Length: 5\r\n\r\n"
1812 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1813 "Content-Length: 0\r\n\r\n"),
1814 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1815 "Content-Length: 5\r\n\r\n"
1817 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1820 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1821 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1823 MockRead data2_reads
[] = {
1824 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1826 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1827 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1829 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1830 std::string response_lines
[kNumUnreadBodies
];
1832 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1833 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1834 TestCompletionCallback callback
;
1836 scoped_ptr
<HttpTransaction
> trans(
1837 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1839 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1840 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1842 rv
= callback
.WaitForResult();
1845 LoadTimingInfo load_timing_info
;
1846 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1848 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1849 first_socket_log_id
= load_timing_info
.socket_log_id
;
1851 TestLoadTimingReused(load_timing_info
);
1852 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1855 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1856 ASSERT_TRUE(response
!= NULL
);
1858 ASSERT_TRUE(response
->headers
.get() != NULL
);
1859 response_lines
[i
] = response
->headers
->GetStatusLine();
1861 // We intentionally don't read the response bodies.
1864 const char* const kStatusLines
[] = {
1865 "HTTP/1.1 204 No Content",
1866 "HTTP/1.1 205 Reset Content",
1867 "HTTP/1.1 304 Not Modified",
1868 "HTTP/1.1 302 Found",
1869 "HTTP/1.1 302 Found",
1870 "HTTP/1.1 301 Moved Permanently",
1871 "HTTP/1.1 301 Moved Permanently",
1874 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1875 "forgot to update kStatusLines");
1877 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1878 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1880 TestCompletionCallback callback
;
1881 scoped_ptr
<HttpTransaction
> trans(
1882 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1883 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1884 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1885 rv
= callback
.WaitForResult();
1887 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1888 ASSERT_TRUE(response
!= NULL
);
1889 ASSERT_TRUE(response
->headers
.get() != NULL
);
1890 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1891 std::string response_data
;
1892 rv
= ReadTransaction(trans
.get(), &response_data
);
1894 EXPECT_EQ("hello", response_data
);
1897 // Test the request-challenge-retry sequence for basic auth.
1898 // (basic auth is the easiest to mock, because it has no randomness).
1899 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1900 HttpRequestInfo request
;
1901 request
.method
= "GET";
1902 request
.url
= GURL("http://www.example.org/");
1903 request
.load_flags
= 0;
1906 session_deps_
.net_log
= &log
;
1907 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1908 scoped_ptr
<HttpTransaction
> trans(
1909 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1911 MockWrite data_writes1
[] = {
1913 "GET / HTTP/1.1\r\n"
1914 "Host: www.example.org\r\n"
1915 "Connection: keep-alive\r\n\r\n"),
1918 MockRead data_reads1
[] = {
1919 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1920 // Give a couple authenticate options (only the middle one is actually
1922 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1923 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1924 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1925 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1926 // Large content-length -- won't matter, as connection will be reset.
1927 MockRead("Content-Length: 10000\r\n\r\n"),
1928 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1931 // After calling trans->RestartWithAuth(), this is the request we should
1932 // be issuing -- the final header line contains the credentials.
1933 MockWrite data_writes2
[] = {
1935 "GET / HTTP/1.1\r\n"
1936 "Host: www.example.org\r\n"
1937 "Connection: keep-alive\r\n"
1938 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1941 // Lastly, the server responds with the actual content.
1942 MockRead data_reads2
[] = {
1943 MockRead("HTTP/1.0 200 OK\r\n"),
1944 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1945 MockRead("Content-Length: 100\r\n\r\n"),
1946 MockRead(SYNCHRONOUS
, OK
),
1949 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1950 data_writes1
, arraysize(data_writes1
));
1951 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1952 data_writes2
, arraysize(data_writes2
));
1953 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1954 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1956 TestCompletionCallback callback1
;
1958 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1959 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1961 rv
= callback1
.WaitForResult();
1964 LoadTimingInfo load_timing_info1
;
1965 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1966 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1968 int64_t writes_size1
= CountWriteBytes(data_writes1
, arraysize(data_writes1
));
1969 EXPECT_EQ(writes_size1
, trans
->GetTotalSentBytes());
1970 int64_t reads_size1
= CountReadBytes(data_reads1
, arraysize(data_reads1
));
1971 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1973 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1974 ASSERT_TRUE(response
!= NULL
);
1975 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1977 TestCompletionCallback callback2
;
1979 rv
= trans
->RestartWithAuth(
1980 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1981 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1983 rv
= callback2
.WaitForResult();
1986 LoadTimingInfo load_timing_info2
;
1987 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1988 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1989 // The load timing after restart should have a new socket ID, and times after
1990 // those of the first load timing.
1991 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1992 load_timing_info2
.connect_timing
.connect_start
);
1993 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1995 int64_t writes_size2
= CountWriteBytes(data_writes2
, arraysize(data_writes2
));
1996 EXPECT_EQ(writes_size1
+ writes_size2
, trans
->GetTotalSentBytes());
1997 int64_t reads_size2
= CountReadBytes(data_reads2
, arraysize(data_reads2
));
1998 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
2000 response
= trans
->GetResponseInfo();
2001 ASSERT_TRUE(response
!= NULL
);
2002 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2003 EXPECT_EQ(100, response
->headers
->GetContentLength());
2006 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
2007 HttpRequestInfo request
;
2008 request
.method
= "GET";
2009 request
.url
= GURL("http://www.example.org/");
2010 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2012 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2013 scoped_ptr
<HttpTransaction
> trans(
2014 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2016 MockWrite data_writes
[] = {
2018 "GET / HTTP/1.1\r\n"
2019 "Host: www.example.org\r\n"
2020 "Connection: keep-alive\r\n\r\n"),
2023 MockRead data_reads
[] = {
2024 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2025 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2026 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2027 // Large content-length -- won't matter, as connection will be reset.
2028 MockRead("Content-Length: 10000\r\n\r\n"),
2029 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2032 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2033 data_writes
, arraysize(data_writes
));
2034 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2035 TestCompletionCallback callback
;
2037 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2038 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2040 rv
= callback
.WaitForResult();
2043 int64_t writes_size
= CountWriteBytes(data_writes
, arraysize(data_writes
));
2044 EXPECT_EQ(writes_size
, trans
->GetTotalSentBytes());
2045 int64_t reads_size
= CountReadBytes(data_reads
, arraysize(data_reads
));
2046 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2048 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2049 ASSERT_TRUE(response
!= NULL
);
2050 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2053 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2055 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2056 HttpRequestInfo request
;
2057 request
.method
= "GET";
2058 request
.url
= GURL("http://www.example.org/");
2059 request
.load_flags
= 0;
2062 session_deps_
.net_log
= &log
;
2063 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2065 MockWrite data_writes1
[] = {
2067 "GET / HTTP/1.1\r\n"
2068 "Host: www.example.org\r\n"
2069 "Connection: keep-alive\r\n\r\n"),
2071 // After calling trans->RestartWithAuth(), this is the request we should
2072 // be issuing -- the final header line contains the credentials.
2074 "GET / HTTP/1.1\r\n"
2075 "Host: www.example.org\r\n"
2076 "Connection: keep-alive\r\n"
2077 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2080 MockRead data_reads1
[] = {
2081 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2082 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2083 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2084 MockRead("Content-Length: 14\r\n\r\n"),
2085 MockRead("Unauthorized\r\n"),
2087 // Lastly, the server responds with the actual content.
2088 MockRead("HTTP/1.1 200 OK\r\n"),
2089 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2090 MockRead("Content-Length: 5\r\n\r\n"),
2094 // If there is a regression where we disconnect a Keep-Alive
2095 // connection during an auth roundtrip, we'll end up reading this.
2096 MockRead data_reads2
[] = {
2097 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2100 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2101 data_writes1
, arraysize(data_writes1
));
2102 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2104 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2105 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2107 TestCompletionCallback callback1
;
2109 scoped_ptr
<HttpTransaction
> trans(
2110 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2111 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2112 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2114 rv
= callback1
.WaitForResult();
2117 LoadTimingInfo load_timing_info1
;
2118 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2119 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2121 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2122 ASSERT_TRUE(response
!= NULL
);
2123 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2125 TestCompletionCallback callback2
;
2127 rv
= trans
->RestartWithAuth(
2128 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2129 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2131 rv
= callback2
.WaitForResult();
2134 LoadTimingInfo load_timing_info2
;
2135 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2136 TestLoadTimingReused(load_timing_info2
);
2137 // The load timing after restart should have the same socket ID, and times
2138 // those of the first load timing.
2139 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2140 load_timing_info2
.send_start
);
2141 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2143 response
= trans
->GetResponseInfo();
2144 ASSERT_TRUE(response
!= NULL
);
2145 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2146 EXPECT_EQ(5, response
->headers
->GetContentLength());
2148 std::string response_data
;
2149 rv
= ReadTransaction(trans
.get(), &response_data
);
2152 int64_t writes_size1
= CountWriteBytes(data_writes1
, arraysize(data_writes1
));
2153 EXPECT_EQ(writes_size1
, trans
->GetTotalSentBytes());
2154 int64_t reads_size1
= CountReadBytes(data_reads1
, arraysize(data_reads1
));
2155 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2158 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2159 // connection and with no response body to drain.
2160 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2161 HttpRequestInfo request
;
2162 request
.method
= "GET";
2163 request
.url
= GURL("http://www.example.org/");
2164 request
.load_flags
= 0;
2166 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2168 MockWrite data_writes1
[] = {
2170 "GET / HTTP/1.1\r\n"
2171 "Host: www.example.org\r\n"
2172 "Connection: keep-alive\r\n\r\n"),
2174 // After calling trans->RestartWithAuth(), this is the request we should
2175 // be issuing -- the final header line contains the credentials.
2177 "GET / HTTP/1.1\r\n"
2178 "Host: www.example.org\r\n"
2179 "Connection: keep-alive\r\n"
2180 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2183 MockRead data_reads1
[] = {
2184 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2185 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2186 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2188 // Lastly, the server responds with the actual content.
2189 MockRead("HTTP/1.1 200 OK\r\n"),
2190 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2191 MockRead("Content-Length: 5\r\n\r\n"),
2195 // An incorrect reconnect would cause this to be read.
2196 MockRead data_reads2
[] = {
2197 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2200 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2201 data_writes1
, arraysize(data_writes1
));
2202 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2204 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2205 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2207 TestCompletionCallback callback1
;
2209 scoped_ptr
<HttpTransaction
> trans(
2210 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2211 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2212 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2214 rv
= callback1
.WaitForResult();
2217 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2218 ASSERT_TRUE(response
!= NULL
);
2219 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2221 TestCompletionCallback callback2
;
2223 rv
= trans
->RestartWithAuth(
2224 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2225 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2227 rv
= callback2
.WaitForResult();
2230 response
= trans
->GetResponseInfo();
2231 ASSERT_TRUE(response
!= NULL
);
2232 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2233 EXPECT_EQ(5, response
->headers
->GetContentLength());
2236 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2237 // connection and with a large response body to drain.
2238 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2239 HttpRequestInfo request
;
2240 request
.method
= "GET";
2241 request
.url
= GURL("http://www.example.org/");
2242 request
.load_flags
= 0;
2244 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2246 MockWrite data_writes1
[] = {
2248 "GET / HTTP/1.1\r\n"
2249 "Host: www.example.org\r\n"
2250 "Connection: keep-alive\r\n\r\n"),
2252 // After calling trans->RestartWithAuth(), this is the request we should
2253 // be issuing -- the final header line contains the credentials.
2255 "GET / HTTP/1.1\r\n"
2256 "Host: www.example.org\r\n"
2257 "Connection: keep-alive\r\n"
2258 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2261 // Respond with 5 kb of response body.
2262 std::string
large_body_string("Unauthorized");
2263 large_body_string
.append(5 * 1024, ' ');
2264 large_body_string
.append("\r\n");
2266 MockRead data_reads1
[] = {
2267 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2268 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2269 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2270 // 5134 = 12 + 5 * 1024 + 2
2271 MockRead("Content-Length: 5134\r\n\r\n"),
2272 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2274 // Lastly, the server responds with the actual content.
2275 MockRead("HTTP/1.1 200 OK\r\n"),
2276 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2277 MockRead("Content-Length: 5\r\n\r\n"),
2281 // An incorrect reconnect would cause this to be read.
2282 MockRead data_reads2
[] = {
2283 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2286 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2287 data_writes1
, arraysize(data_writes1
));
2288 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2290 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2291 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2293 TestCompletionCallback callback1
;
2295 scoped_ptr
<HttpTransaction
> trans(
2296 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2297 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2298 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2300 rv
= callback1
.WaitForResult();
2303 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2304 ASSERT_TRUE(response
!= NULL
);
2305 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2307 TestCompletionCallback callback2
;
2309 rv
= trans
->RestartWithAuth(
2310 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2311 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2313 rv
= callback2
.WaitForResult();
2316 response
= trans
->GetResponseInfo();
2317 ASSERT_TRUE(response
!= NULL
);
2318 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2319 EXPECT_EQ(5, response
->headers
->GetContentLength());
2322 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2323 // connection, but the server gets impatient and closes the connection.
2324 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2325 HttpRequestInfo request
;
2326 request
.method
= "GET";
2327 request
.url
= GURL("http://www.example.org/");
2328 request
.load_flags
= 0;
2330 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2332 MockWrite data_writes1
[] = {
2334 "GET / HTTP/1.1\r\n"
2335 "Host: www.example.org\r\n"
2336 "Connection: keep-alive\r\n\r\n"),
2337 // This simulates the seemingly successful write to a closed connection
2338 // if the bug is not fixed.
2340 "GET / HTTP/1.1\r\n"
2341 "Host: www.example.org\r\n"
2342 "Connection: keep-alive\r\n"
2343 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2346 MockRead data_reads1
[] = {
2347 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2348 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2349 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2350 MockRead("Content-Length: 14\r\n\r\n"),
2351 // Tell MockTCPClientSocket to simulate the server closing the connection.
2352 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2353 MockRead("Unauthorized\r\n"),
2354 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2357 // After calling trans->RestartWithAuth(), this is the request we should
2358 // be issuing -- the final header line contains the credentials.
2359 MockWrite data_writes2
[] = {
2361 "GET / HTTP/1.1\r\n"
2362 "Host: www.example.org\r\n"
2363 "Connection: keep-alive\r\n"
2364 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2367 // Lastly, the server responds with the actual content.
2368 MockRead data_reads2
[] = {
2369 MockRead("HTTP/1.1 200 OK\r\n"),
2370 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2371 MockRead("Content-Length: 5\r\n\r\n"),
2375 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2376 data_writes1
, arraysize(data_writes1
));
2377 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2378 data_writes2
, arraysize(data_writes2
));
2379 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2380 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2382 TestCompletionCallback callback1
;
2384 scoped_ptr
<HttpTransaction
> trans(
2385 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2386 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2387 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2389 rv
= callback1
.WaitForResult();
2392 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2393 ASSERT_TRUE(response
!= NULL
);
2394 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2396 TestCompletionCallback callback2
;
2398 rv
= trans
->RestartWithAuth(
2399 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2400 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2402 rv
= callback2
.WaitForResult();
2405 response
= trans
->GetResponseInfo();
2406 ASSERT_TRUE(response
!= NULL
);
2407 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2408 EXPECT_EQ(5, response
->headers
->GetContentLength());
2411 // Test the request-challenge-retry sequence for basic auth, over a connection
2412 // that requires a restart when setting up an SSL tunnel.
2413 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2414 HttpRequestInfo request
;
2415 request
.method
= "GET";
2416 request
.url
= GURL("https://www.example.org/");
2417 // when the no authentication data flag is set.
2418 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2420 // Configure against proxy server "myproxy:70".
2421 session_deps_
.proxy_service
=
2422 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
2423 BoundTestNetLog log
;
2424 session_deps_
.net_log
= log
.bound().net_log();
2425 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2427 // Since we have proxy, should try to establish tunnel.
2428 MockWrite data_writes1
[] = {
2429 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2430 "Host: www.example.org\r\n"
2431 "Proxy-Connection: keep-alive\r\n\r\n"),
2434 // The proxy responds to the connect with a 407, using a non-persistent
2436 MockRead data_reads1
[] = {
2438 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2439 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2442 // Since the first connection couldn't be reused, need to establish another
2443 // once given credentials.
2444 MockWrite data_writes2
[] = {
2445 // After calling trans->RestartWithAuth(), this is the request we should
2446 // be issuing -- the final header line contains the credentials.
2447 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2448 "Host: www.example.org\r\n"
2449 "Proxy-Connection: keep-alive\r\n"
2450 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2452 MockWrite("GET / HTTP/1.1\r\n"
2453 "Host: www.example.org\r\n"
2454 "Connection: keep-alive\r\n\r\n"),
2457 MockRead data_reads2
[] = {
2458 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2460 MockRead("HTTP/1.1 200 OK\r\n"),
2461 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2462 MockRead("Content-Length: 5\r\n\r\n"),
2463 MockRead(SYNCHRONOUS
, "hello"),
2466 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2467 data_writes1
, arraysize(data_writes1
));
2468 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2469 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2470 data_writes2
, arraysize(data_writes2
));
2471 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2472 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2473 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2475 TestCompletionCallback callback1
;
2477 scoped_ptr
<HttpTransaction
> trans(
2478 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2480 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2481 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2483 rv
= callback1
.WaitForResult();
2485 TestNetLogEntry::List entries
;
2486 log
.GetEntries(&entries
);
2487 size_t pos
= ExpectLogContainsSomewhere(
2488 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2489 NetLog::PHASE_NONE
);
2490 ExpectLogContainsSomewhere(
2491 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2492 NetLog::PHASE_NONE
);
2494 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2495 ASSERT_TRUE(response
!= NULL
);
2496 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2497 ASSERT_FALSE(response
->headers
.get() == NULL
);
2498 EXPECT_EQ(407, response
->headers
->response_code());
2499 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2500 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2502 LoadTimingInfo load_timing_info
;
2503 // CONNECT requests and responses are handled at the connect job level, so
2504 // the transaction does not yet have a connection.
2505 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2507 TestCompletionCallback callback2
;
2510 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2511 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2513 rv
= callback2
.WaitForResult();
2516 response
= trans
->GetResponseInfo();
2517 ASSERT_TRUE(response
!= NULL
);
2519 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2520 EXPECT_EQ(200, response
->headers
->response_code());
2521 EXPECT_EQ(5, response
->headers
->GetContentLength());
2522 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2524 // The password prompt info should not be set.
2525 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2527 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2528 TestLoadTimingNotReusedWithPac(load_timing_info
,
2529 CONNECT_TIMING_HAS_SSL_TIMES
);
2532 session
->CloseAllConnections();
2535 // Test the request-challenge-retry sequence for basic auth, over a connection
2536 // that requires a restart when setting up an SSL tunnel.
2537 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2538 HttpRequestInfo request
;
2539 request
.method
= "GET";
2540 request
.url
= GURL("https://www.example.org/");
2541 // when the no authentication data flag is set.
2542 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2544 // Configure against proxy server "myproxy:70".
2545 session_deps_
.proxy_service
=
2546 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
2547 BoundTestNetLog log
;
2548 session_deps_
.net_log
= log
.bound().net_log();
2549 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2551 // Since we have proxy, should try to establish tunnel.
2552 MockWrite data_writes1
[] = {
2553 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2554 "Host: www.example.org\r\n"
2555 "Proxy-Connection: keep-alive\r\n\r\n"),
2558 // The proxy responds to the connect with a 407, using a non-persistent
2560 MockRead data_reads1
[] = {
2562 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2563 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2564 MockRead("Proxy-Connection: close\r\n\r\n"),
2567 MockWrite data_writes2
[] = {
2568 // After calling trans->RestartWithAuth(), this is the request we should
2569 // be issuing -- the final header line contains the credentials.
2570 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2571 "Host: www.example.org\r\n"
2572 "Proxy-Connection: keep-alive\r\n"
2573 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2575 MockWrite("GET / HTTP/1.1\r\n"
2576 "Host: www.example.org\r\n"
2577 "Connection: keep-alive\r\n\r\n"),
2580 MockRead data_reads2
[] = {
2581 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2583 MockRead("HTTP/1.1 200 OK\r\n"),
2584 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2585 MockRead("Content-Length: 5\r\n\r\n"),
2586 MockRead(SYNCHRONOUS
, "hello"),
2589 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2590 data_writes1
, arraysize(data_writes1
));
2591 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2592 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2593 data_writes2
, arraysize(data_writes2
));
2594 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2595 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2596 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2598 TestCompletionCallback callback1
;
2600 scoped_ptr
<HttpTransaction
> trans(
2601 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2603 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2604 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2606 rv
= callback1
.WaitForResult();
2608 TestNetLogEntry::List entries
;
2609 log
.GetEntries(&entries
);
2610 size_t pos
= ExpectLogContainsSomewhere(
2611 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2612 NetLog::PHASE_NONE
);
2613 ExpectLogContainsSomewhere(
2615 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2616 NetLog::PHASE_NONE
);
2618 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2619 ASSERT_TRUE(response
!= NULL
);
2620 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2621 ASSERT_FALSE(response
->headers
.get() == NULL
);
2622 EXPECT_EQ(407, response
->headers
->response_code());
2623 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2624 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2626 LoadTimingInfo load_timing_info
;
2627 // CONNECT requests and responses are handled at the connect job level, so
2628 // the transaction does not yet have a connection.
2629 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2631 TestCompletionCallback callback2
;
2633 rv
= trans
->RestartWithAuth(
2634 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2635 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2637 rv
= callback2
.WaitForResult();
2640 response
= trans
->GetResponseInfo();
2641 ASSERT_TRUE(response
!= NULL
);
2643 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2644 EXPECT_EQ(200, response
->headers
->response_code());
2645 EXPECT_EQ(5, response
->headers
->GetContentLength());
2646 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2648 // The password prompt info should not be set.
2649 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2651 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2652 TestLoadTimingNotReusedWithPac(load_timing_info
,
2653 CONNECT_TIMING_HAS_SSL_TIMES
);
2656 session
->CloseAllConnections();
2659 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2660 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2661 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2662 HttpRequestInfo request
;
2663 request
.method
= "GET";
2664 request
.url
= GURL("https://www.example.org/");
2665 // Ensure that proxy authentication is attempted even
2666 // when the no authentication data flag is set.
2667 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2669 // Configure against proxy server "myproxy:70".
2670 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
2671 BoundTestNetLog log
;
2672 session_deps_
.net_log
= log
.bound().net_log();
2673 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2675 scoped_ptr
<HttpTransaction
> trans(
2676 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2678 // Since we have proxy, should try to establish tunnel.
2679 MockWrite data_writes1
[] = {
2681 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2682 "Host: www.example.org\r\n"
2683 "Proxy-Connection: keep-alive\r\n\r\n"),
2685 // After calling trans->RestartWithAuth(), this is the request we should
2686 // be issuing -- the final header line contains the credentials.
2688 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2689 "Host: www.example.org\r\n"
2690 "Proxy-Connection: keep-alive\r\n"
2691 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2694 // The proxy responds to the connect with a 407, using a persistent
2695 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2696 MockRead data_reads1
[] = {
2698 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2699 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2700 MockRead("Proxy-Connection: keep-alive\r\n"),
2701 MockRead("Content-Length: 10\r\n\r\n"),
2702 MockRead("0123456789"),
2704 // Wrong credentials (wrong password).
2705 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2706 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2707 MockRead("Proxy-Connection: keep-alive\r\n"),
2708 MockRead("Content-Length: 10\r\n\r\n"),
2709 // No response body because the test stops reading here.
2710 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2713 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2714 data_writes1
, arraysize(data_writes1
));
2715 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2717 TestCompletionCallback callback1
;
2719 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2720 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2722 rv
= callback1
.WaitForResult();
2724 TestNetLogEntry::List entries
;
2725 log
.GetEntries(&entries
);
2726 size_t pos
= ExpectLogContainsSomewhere(
2727 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2728 NetLog::PHASE_NONE
);
2729 ExpectLogContainsSomewhere(
2730 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2731 NetLog::PHASE_NONE
);
2733 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2734 ASSERT_TRUE(response
);
2735 ASSERT_TRUE(response
->headers
);
2736 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2737 EXPECT_EQ(407, response
->headers
->response_code());
2738 EXPECT_EQ(10, response
->headers
->GetContentLength());
2739 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2740 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2742 TestCompletionCallback callback2
;
2744 // Wrong password (should be "bar").
2746 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2747 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2749 rv
= callback2
.WaitForResult();
2752 response
= trans
->GetResponseInfo();
2753 ASSERT_TRUE(response
);
2754 ASSERT_TRUE(response
->headers
);
2755 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2756 EXPECT_EQ(407, response
->headers
->response_code());
2757 EXPECT_EQ(10, response
->headers
->GetContentLength());
2758 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2759 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2761 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2763 session
->CloseAllConnections();
2766 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2767 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2768 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2769 HttpRequestInfo request
;
2770 request
.method
= "GET";
2771 request
.url
= GURL("https://www.example.org/");
2772 // Ensure that proxy authentication is attempted even
2773 // when the no authentication data flag is set.
2774 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2776 // Configure against proxy server "myproxy:70".
2777 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
2778 BoundTestNetLog log
;
2779 session_deps_
.net_log
= log
.bound().net_log();
2780 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2782 scoped_ptr
<HttpTransaction
> trans(
2783 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2785 // Since we have proxy, should try to establish tunnel.
2786 MockWrite data_writes1
[] = {
2788 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2789 "Host: www.example.org\r\n"
2790 "Proxy-Connection: keep-alive\r\n\r\n"),
2792 // After calling trans->RestartWithAuth(), this is the request we should
2793 // be issuing -- the final header line contains the credentials.
2795 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2796 "Host: www.example.org\r\n"
2797 "Proxy-Connection: keep-alive\r\n"
2798 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2801 // The proxy responds to the connect with a 407, using a persistent
2803 MockRead data_reads1
[] = {
2805 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2806 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2807 MockRead("Content-Length: 10\r\n\r\n"),
2808 MockRead("0123456789"),
2810 // Wrong credentials (wrong password).
2811 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2812 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2813 MockRead("Content-Length: 10\r\n\r\n"),
2814 // No response body because the test stops reading here.
2815 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2818 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2819 data_writes1
, arraysize(data_writes1
));
2820 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2822 TestCompletionCallback callback1
;
2824 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2825 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2827 rv
= callback1
.WaitForResult();
2829 TestNetLogEntry::List entries
;
2830 log
.GetEntries(&entries
);
2831 size_t pos
= ExpectLogContainsSomewhere(
2832 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2833 NetLog::PHASE_NONE
);
2834 ExpectLogContainsSomewhere(
2836 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2837 NetLog::PHASE_NONE
);
2839 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2840 ASSERT_TRUE(response
);
2841 ASSERT_TRUE(response
->headers
);
2842 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2843 EXPECT_EQ(407, response
->headers
->response_code());
2844 EXPECT_EQ(10, response
->headers
->GetContentLength());
2845 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2846 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2848 TestCompletionCallback callback2
;
2850 // Wrong password (should be "bar").
2851 rv
= trans
->RestartWithAuth(
2852 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2853 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2855 rv
= callback2
.WaitForResult();
2858 response
= trans
->GetResponseInfo();
2859 ASSERT_TRUE(response
);
2860 ASSERT_TRUE(response
->headers
);
2861 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2862 EXPECT_EQ(407, response
->headers
->response_code());
2863 EXPECT_EQ(10, response
->headers
->GetContentLength());
2864 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2865 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2867 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2869 session
->CloseAllConnections();
2872 // Test the case a proxy closes a socket while the challenge body is being
2874 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHangupDuringBody
) {
2875 HttpRequestInfo request
;
2876 request
.method
= "GET";
2877 request
.url
= GURL("https://www.example.org/");
2878 // Ensure that proxy authentication is attempted even
2879 // when the no authentication data flag is set.
2880 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2882 // Configure against proxy server "myproxy:70".
2883 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
2884 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2886 scoped_ptr
<HttpTransaction
> trans(
2887 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2889 // Since we have proxy, should try to establish tunnel.
2890 MockWrite data_writes1
[] = {
2891 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2892 "Host: www.example.org\r\n"
2893 "Proxy-Connection: keep-alive\r\n\r\n"),
2896 // The proxy responds to the connect with a 407, using a persistent
2898 MockRead data_reads1
[] = {
2900 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2901 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2902 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
2903 // Server hands up in the middle of the body.
2904 MockRead(ASYNC
, ERR_CONNECTION_CLOSED
),
2907 MockWrite data_writes2
[] = {
2908 // After calling trans->RestartWithAuth(), this is the request we should
2909 // be issuing -- the final header line contains the credentials.
2910 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2911 "Host: www.example.org\r\n"
2912 "Proxy-Connection: keep-alive\r\n"
2913 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2915 MockWrite("GET / HTTP/1.1\r\n"
2916 "Host: www.example.org\r\n"
2917 "Connection: keep-alive\r\n\r\n"),
2920 MockRead data_reads2
[] = {
2921 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2923 MockRead("HTTP/1.1 200 OK\r\n"),
2924 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2925 MockRead("Content-Length: 5\r\n\r\n"),
2926 MockRead(SYNCHRONOUS
, "hello"),
2929 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2930 data_writes1
, arraysize(data_writes1
));
2931 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2932 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2933 data_writes2
, arraysize(data_writes2
));
2934 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2935 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2936 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2938 TestCompletionCallback callback
;
2940 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2941 EXPECT_EQ(OK
, callback
.GetResult(rv
));
2943 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2944 ASSERT_TRUE(response
);
2945 ASSERT_TRUE(response
->headers
);
2946 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2947 EXPECT_EQ(407, response
->headers
->response_code());
2948 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2950 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
2951 EXPECT_EQ(OK
, callback
.GetResult(rv
));
2953 response
= trans
->GetResponseInfo();
2954 ASSERT_TRUE(response
);
2955 ASSERT_TRUE(response
->headers
);
2956 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2957 EXPECT_EQ(200, response
->headers
->response_code());
2959 EXPECT_EQ(OK
, ReadTransaction(trans
.get(), &body
));
2960 EXPECT_EQ("hello", body
);
2963 // Test that we don't read the response body when we fail to establish a tunnel,
2964 // even if the user cancels the proxy's auth attempt.
2965 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2966 HttpRequestInfo request
;
2967 request
.method
= "GET";
2968 request
.url
= GURL("https://www.example.org/");
2969 request
.load_flags
= 0;
2971 // Configure against proxy server "myproxy:70".
2972 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
2974 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2976 scoped_ptr
<HttpTransaction
> trans(
2977 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2979 // Since we have proxy, should try to establish tunnel.
2980 MockWrite data_writes
[] = {
2982 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2983 "Host: www.example.org\r\n"
2984 "Proxy-Connection: keep-alive\r\n\r\n"),
2987 // The proxy responds to the connect with a 407.
2988 MockRead data_reads
[] = {
2989 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2990 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2991 MockRead("Content-Length: 10\r\n\r\n"),
2992 MockRead("0123456789"), // Should not be reached.
2993 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2996 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2997 data_writes
, arraysize(data_writes
));
2998 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3000 TestCompletionCallback callback
;
3002 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3003 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3005 rv
= callback
.WaitForResult();
3008 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3009 ASSERT_TRUE(response
);
3010 ASSERT_TRUE(response
->headers
);
3011 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3012 EXPECT_EQ(407, response
->headers
->response_code());
3013 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3015 std::string response_data
;
3016 rv
= ReadTransaction(trans
.get(), &response_data
);
3017 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3019 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3020 session
->CloseAllConnections();
3023 // Test that we don't pass extraneous headers from the proxy's response to the
3024 // caller when the proxy responds to CONNECT with 407.
3025 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
3026 HttpRequestInfo request
;
3027 request
.method
= "GET";
3028 request
.url
= GURL("https://www.example.org/");
3029 request
.load_flags
= 0;
3031 // Configure against proxy server "myproxy:70".
3032 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
3034 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3036 scoped_ptr
<HttpTransaction
> trans(
3037 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3039 // Since we have proxy, should try to establish tunnel.
3040 MockWrite data_writes
[] = {
3042 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3043 "Host: www.example.org\r\n"
3044 "Proxy-Connection: keep-alive\r\n\r\n"),
3047 // The proxy responds to the connect with a 407.
3048 MockRead data_reads
[] = {
3049 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3050 MockRead("X-Foo: bar\r\n"),
3051 MockRead("Set-Cookie: foo=bar\r\n"),
3052 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3053 MockRead("Content-Length: 10\r\n\r\n"),
3054 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3057 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
3058 arraysize(data_writes
));
3059 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3061 TestCompletionCallback callback
;
3063 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3064 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3066 rv
= callback
.WaitForResult();
3069 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3070 ASSERT_TRUE(response
);
3071 ASSERT_TRUE(response
->headers
);
3072 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3073 EXPECT_EQ(407, response
->headers
->response_code());
3074 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3075 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
3076 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
3078 std::string response_data
;
3079 rv
= ReadTransaction(trans
.get(), &response_data
);
3080 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3082 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3083 session
->CloseAllConnections();
3086 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3087 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
3088 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
3089 HttpRequestInfo request
;
3090 request
.method
= "GET";
3091 request
.url
= GURL("http://www.example.org/");
3092 request
.load_flags
= 0;
3094 // We are using a DIRECT connection (i.e. no proxy) for this session.
3095 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3096 scoped_ptr
<HttpTransaction
> trans(
3097 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3099 MockWrite data_writes1
[] = {
3101 "GET / HTTP/1.1\r\n"
3102 "Host: www.example.org\r\n"
3103 "Connection: keep-alive\r\n\r\n"),
3106 MockRead data_reads1
[] = {
3107 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3108 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3109 // Large content-length -- won't matter, as connection will be reset.
3110 MockRead("Content-Length: 10000\r\n\r\n"),
3111 MockRead(SYNCHRONOUS
, ERR_FAILED
),
3114 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3115 data_writes1
, arraysize(data_writes1
));
3116 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3118 TestCompletionCallback callback
;
3120 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3121 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3123 rv
= callback
.WaitForResult();
3124 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3127 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3128 // through a non-authenticating proxy. The request should fail with
3129 // ERR_UNEXPECTED_PROXY_AUTH.
3130 // Note that it is impossible to detect if an HTTP server returns a 407 through
3131 // a non-authenticating proxy - there is nothing to indicate whether the
3132 // response came from the proxy or the server, so it is treated as if the proxy
3133 // issued the challenge.
3134 TEST_P(HttpNetworkTransactionTest
,
3135 HttpsServerRequestsProxyAuthThroughProxy
) {
3136 HttpRequestInfo request
;
3137 request
.method
= "GET";
3138 request
.url
= GURL("https://www.example.org/");
3140 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
3141 BoundTestNetLog log
;
3142 session_deps_
.net_log
= log
.bound().net_log();
3143 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3145 // Since we have proxy, should try to establish tunnel.
3146 MockWrite data_writes1
[] = {
3148 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3149 "Host: www.example.org\r\n"
3150 "Proxy-Connection: keep-alive\r\n\r\n"),
3153 "GET / HTTP/1.1\r\n"
3154 "Host: www.example.org\r\n"
3155 "Connection: keep-alive\r\n\r\n"),
3158 MockRead data_reads1
[] = {
3159 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3161 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3162 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3164 MockRead(SYNCHRONOUS
, OK
),
3167 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3168 data_writes1
, arraysize(data_writes1
));
3169 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3170 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3171 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3173 TestCompletionCallback callback1
;
3175 scoped_ptr
<HttpTransaction
> trans(
3176 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3178 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3179 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3181 rv
= callback1
.WaitForResult();
3182 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3183 TestNetLogEntry::List entries
;
3184 log
.GetEntries(&entries
);
3185 size_t pos
= ExpectLogContainsSomewhere(
3186 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3187 NetLog::PHASE_NONE
);
3188 ExpectLogContainsSomewhere(
3190 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3191 NetLog::PHASE_NONE
);
3194 // Test the load timing for HTTPS requests with an HTTP proxy.
3195 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3196 HttpRequestInfo request1
;
3197 request1
.method
= "GET";
3198 request1
.url
= GURL("https://www.example.org/1");
3200 HttpRequestInfo request2
;
3201 request2
.method
= "GET";
3202 request2
.url
= GURL("https://www.example.org/2");
3204 // Configure against proxy server "myproxy:70".
3205 session_deps_
.proxy_service
= ProxyService::CreateFixed("PROXY myproxy:70");
3206 BoundTestNetLog log
;
3207 session_deps_
.net_log
= log
.bound().net_log();
3208 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3210 // Since we have proxy, should try to establish tunnel.
3211 MockWrite data_writes1
[] = {
3213 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3214 "Host: www.example.org\r\n"
3215 "Proxy-Connection: keep-alive\r\n\r\n"),
3218 "GET /1 HTTP/1.1\r\n"
3219 "Host: www.example.org\r\n"
3220 "Connection: keep-alive\r\n\r\n"),
3223 "GET /2 HTTP/1.1\r\n"
3224 "Host: www.example.org\r\n"
3225 "Connection: keep-alive\r\n\r\n"),
3228 // The proxy responds to the connect with a 407, using a persistent
3230 MockRead data_reads1
[] = {
3231 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3233 MockRead("HTTP/1.1 200 OK\r\n"),
3234 MockRead("Content-Length: 1\r\n\r\n"),
3235 MockRead(SYNCHRONOUS
, "1"),
3237 MockRead("HTTP/1.1 200 OK\r\n"),
3238 MockRead("Content-Length: 2\r\n\r\n"),
3239 MockRead(SYNCHRONOUS
, "22"),
3242 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3243 data_writes1
, arraysize(data_writes1
));
3244 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3245 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3246 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3248 TestCompletionCallback callback1
;
3249 scoped_ptr
<HttpTransaction
> trans1(
3250 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3252 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3255 rv
= callback1
.WaitForResult();
3258 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3259 ASSERT_TRUE(response1
!= NULL
);
3260 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3261 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3263 LoadTimingInfo load_timing_info1
;
3264 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3265 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3269 TestCompletionCallback callback2
;
3270 scoped_ptr
<HttpTransaction
> trans2(
3271 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3273 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3274 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3276 rv
= callback2
.WaitForResult();
3279 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3280 ASSERT_TRUE(response2
!= NULL
);
3281 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3282 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3284 LoadTimingInfo load_timing_info2
;
3285 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3286 TestLoadTimingReused(load_timing_info2
);
3288 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3291 session
->CloseAllConnections();
3294 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3295 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3296 HttpRequestInfo request1
;
3297 request1
.method
= "GET";
3298 request1
.url
= GURL("https://www.example.org/1");
3300 HttpRequestInfo request2
;
3301 request2
.method
= "GET";
3302 request2
.url
= GURL("https://www.example.org/2");
3304 // Configure against proxy server "myproxy:70".
3305 session_deps_
.proxy_service
=
3306 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3307 BoundTestNetLog log
;
3308 session_deps_
.net_log
= log
.bound().net_log();
3309 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3311 // Since we have proxy, should try to establish tunnel.
3312 MockWrite data_writes1
[] = {
3314 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3315 "Host: www.example.org\r\n"
3316 "Proxy-Connection: keep-alive\r\n\r\n"),
3319 "GET /1 HTTP/1.1\r\n"
3320 "Host: www.example.org\r\n"
3321 "Connection: keep-alive\r\n\r\n"),
3324 "GET /2 HTTP/1.1\r\n"
3325 "Host: www.example.org\r\n"
3326 "Connection: keep-alive\r\n\r\n"),
3329 // The proxy responds to the connect with a 407, using a persistent
3331 MockRead data_reads1
[] = {
3332 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3334 MockRead("HTTP/1.1 200 OK\r\n"),
3335 MockRead("Content-Length: 1\r\n\r\n"),
3336 MockRead(SYNCHRONOUS
, "1"),
3338 MockRead("HTTP/1.1 200 OK\r\n"),
3339 MockRead("Content-Length: 2\r\n\r\n"),
3340 MockRead(SYNCHRONOUS
, "22"),
3343 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3344 data_writes1
, arraysize(data_writes1
));
3345 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3346 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3347 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3349 TestCompletionCallback callback1
;
3350 scoped_ptr
<HttpTransaction
> trans1(
3351 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3353 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3354 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3356 rv
= callback1
.WaitForResult();
3359 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3360 ASSERT_TRUE(response1
!= NULL
);
3361 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3362 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3364 LoadTimingInfo load_timing_info1
;
3365 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3366 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3367 CONNECT_TIMING_HAS_SSL_TIMES
);
3371 TestCompletionCallback callback2
;
3372 scoped_ptr
<HttpTransaction
> trans2(
3373 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3375 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3376 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3378 rv
= callback2
.WaitForResult();
3381 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3382 ASSERT_TRUE(response2
!= NULL
);
3383 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3384 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3386 LoadTimingInfo load_timing_info2
;
3387 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3388 TestLoadTimingReusedWithPac(load_timing_info2
);
3390 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3393 session
->CloseAllConnections();
3396 // Test a simple get through an HTTPS Proxy.
3397 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3398 HttpRequestInfo request
;
3399 request
.method
= "GET";
3400 request
.url
= GURL("http://www.example.org/");
3402 // Configure against https proxy server "proxy:70".
3403 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
3404 BoundTestNetLog log
;
3405 session_deps_
.net_log
= log
.bound().net_log();
3406 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3408 // Since we have proxy, should use full url
3409 MockWrite data_writes1
[] = {
3411 "GET http://www.example.org/ HTTP/1.1\r\n"
3412 "Host: www.example.org\r\n"
3413 "Proxy-Connection: keep-alive\r\n\r\n"),
3416 MockRead data_reads1
[] = {
3417 MockRead("HTTP/1.1 200 OK\r\n"),
3418 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3419 MockRead("Content-Length: 100\r\n\r\n"),
3420 MockRead(SYNCHRONOUS
, OK
),
3423 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3424 data_writes1
, arraysize(data_writes1
));
3425 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3426 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3427 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3429 TestCompletionCallback callback1
;
3431 scoped_ptr
<HttpTransaction
> trans(
3432 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3434 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3435 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3437 rv
= callback1
.WaitForResult();
3440 LoadTimingInfo load_timing_info
;
3441 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3442 TestLoadTimingNotReused(load_timing_info
,
3443 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3445 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3446 ASSERT_TRUE(response
!= NULL
);
3448 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3449 EXPECT_EQ(200, response
->headers
->response_code());
3450 EXPECT_EQ(100, response
->headers
->GetContentLength());
3451 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3453 // The password prompt info should not be set.
3454 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3457 // Test a SPDY get through an HTTPS Proxy.
3458 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3459 HttpRequestInfo request
;
3460 request
.method
= "GET";
3461 request
.url
= GURL("http://www.example.org/");
3462 request
.load_flags
= 0;
3464 // Configure against https proxy server "proxy:70".
3465 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
3466 BoundTestNetLog log
;
3467 session_deps_
.net_log
= log
.bound().net_log();
3468 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3470 // fetch http://www.example.org/ via SPDY
3471 scoped_ptr
<SpdyFrame
> req(
3472 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3473 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3475 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3476 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3477 MockRead spdy_reads
[] = {
3478 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3481 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3482 arraysize(spdy_writes
));
3483 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3485 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3486 ssl
.SetNextProto(GetParam());
3487 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3489 TestCompletionCallback callback1
;
3491 scoped_ptr
<HttpTransaction
> trans(
3492 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3494 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3495 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3497 rv
= callback1
.WaitForResult();
3500 LoadTimingInfo load_timing_info
;
3501 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3502 TestLoadTimingNotReused(load_timing_info
,
3503 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3505 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3506 ASSERT_TRUE(response
!= NULL
);
3507 ASSERT_TRUE(response
->headers
.get() != NULL
);
3508 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3510 std::string response_data
;
3511 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3512 EXPECT_EQ(kUploadData
, response_data
);
3515 // Verifies that a session which races and wins against the owning transaction
3516 // (completing prior to host resolution), doesn't fail the transaction.
3517 // Regression test for crbug.com/334413.
3518 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3519 HttpRequestInfo request
;
3520 request
.method
= "GET";
3521 request
.url
= GURL("http://www.example.org/");
3522 request
.load_flags
= 0;
3524 // Configure SPDY proxy server "proxy:70".
3525 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
3526 BoundTestNetLog log
;
3527 session_deps_
.net_log
= log
.bound().net_log();
3528 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3530 // Fetch http://www.example.org/ through the SPDY proxy.
3531 scoped_ptr
<SpdyFrame
> req(
3532 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3533 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3535 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3536 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3537 MockRead spdy_reads
[] = {
3538 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3541 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3542 arraysize(spdy_writes
));
3543 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3545 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3546 ssl
.SetNextProto(GetParam());
3547 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3549 TestCompletionCallback callback1
;
3551 scoped_ptr
<HttpTransaction
> trans(
3552 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3554 // Stall the hostname resolution begun by the transaction.
3555 session_deps_
.host_resolver
->set_synchronous_mode(false);
3556 session_deps_
.host_resolver
->set_ondemand_mode(true);
3558 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3559 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3561 // Race a session to the proxy, which completes first.
3562 session_deps_
.host_resolver
->set_ondemand_mode(false);
3564 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3565 base::WeakPtr
<SpdySession
> spdy_session
=
3566 CreateSecureSpdySession(session
, key
, log
.bound());
3568 // Unstall the resolution begun by the transaction.
3569 session_deps_
.host_resolver
->set_ondemand_mode(true);
3570 session_deps_
.host_resolver
->ResolveAllPending();
3572 EXPECT_FALSE(callback1
.have_result());
3573 rv
= callback1
.WaitForResult();
3576 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3577 ASSERT_TRUE(response
!= NULL
);
3578 ASSERT_TRUE(response
->headers
.get() != NULL
);
3579 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3581 std::string response_data
;
3582 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3583 EXPECT_EQ(kUploadData
, response_data
);
3586 // Test a SPDY get through an HTTPS Proxy.
3587 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3588 HttpRequestInfo request
;
3589 request
.method
= "GET";
3590 request
.url
= GURL("http://www.example.org/");
3591 request
.load_flags
= 0;
3593 // Configure against https proxy server "myproxy:70".
3594 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://myproxy:70");
3595 BoundTestNetLog log
;
3596 session_deps_
.net_log
= log
.bound().net_log();
3597 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3599 // The first request will be a bare GET, the second request will be a
3600 // GET with a Proxy-Authorization header.
3601 scoped_ptr
<SpdyFrame
> req_get(
3602 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3603 const char* const kExtraAuthorizationHeaders
[] = {
3604 "proxy-authorization", "Basic Zm9vOmJhcg=="
3606 scoped_ptr
<SpdyFrame
> req_get_authorization(
3607 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3608 arraysize(kExtraAuthorizationHeaders
) / 2,
3613 MockWrite spdy_writes
[] = {
3614 CreateMockWrite(*req_get
, 0), CreateMockWrite(*req_get_authorization
, 3),
3617 // The first response is a 407 proxy authentication challenge, and the second
3618 // response will be a 200 response since the second request includes a valid
3619 // Authorization header.
3620 const char* const kExtraAuthenticationHeaders
[] = {
3621 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3623 scoped_ptr
<SpdyFrame
> resp_authentication(
3624 spdy_util_
.ConstructSpdySynReplyError(
3625 "407 Proxy Authentication Required",
3626 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3628 scoped_ptr
<SpdyFrame
> body_authentication(
3629 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3630 scoped_ptr
<SpdyFrame
> resp_data(
3631 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3632 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3633 MockRead spdy_reads
[] = {
3634 CreateMockRead(*resp_authentication
, 1),
3635 CreateMockRead(*body_authentication
, 2),
3636 CreateMockRead(*resp_data
, 4),
3637 CreateMockRead(*body_data
, 5),
3638 MockRead(ASYNC
, 0, 6),
3641 SequencedSocketData
data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3642 arraysize(spdy_writes
));
3643 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3645 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3646 ssl
.SetNextProto(GetParam());
3647 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3649 TestCompletionCallback callback1
;
3651 scoped_ptr
<HttpTransaction
> trans(
3652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3654 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3655 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3657 rv
= callback1
.WaitForResult();
3660 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3662 ASSERT_TRUE(response
!= NULL
);
3663 ASSERT_TRUE(response
->headers
.get() != NULL
);
3664 EXPECT_EQ(407, response
->headers
->response_code());
3665 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3666 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3668 TestCompletionCallback callback2
;
3670 rv
= trans
->RestartWithAuth(
3671 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3672 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3674 rv
= callback2
.WaitForResult();
3677 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3679 ASSERT_TRUE(response_restart
!= NULL
);
3680 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3681 EXPECT_EQ(200, response_restart
->headers
->response_code());
3682 // The password prompt info should not be set.
3683 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3686 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3687 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3688 HttpRequestInfo request
;
3689 request
.method
= "GET";
3690 request
.url
= GURL("https://www.example.org/");
3691 request
.load_flags
= 0;
3693 // Configure against https proxy server "proxy:70".
3694 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
3695 BoundTestNetLog log
;
3696 session_deps_
.net_log
= log
.bound().net_log();
3697 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3699 scoped_ptr
<HttpTransaction
> trans(
3700 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3702 // CONNECT to www.example.org:443 via SPDY
3703 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3704 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3705 // fetch https://www.example.org/ via HTTP
3708 "GET / HTTP/1.1\r\n"
3709 "Host: www.example.org\r\n"
3710 "Connection: keep-alive\r\n\r\n";
3711 scoped_ptr
<SpdyFrame
> wrapped_get(
3712 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3713 scoped_ptr
<SpdyFrame
> conn_resp(
3714 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3715 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3716 "Content-Length: 10\r\n\r\n";
3717 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3718 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3719 scoped_ptr
<SpdyFrame
> wrapped_body(
3720 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3721 scoped_ptr
<SpdyFrame
> window_update(
3722 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3724 MockWrite spdy_writes
[] = {
3725 CreateMockWrite(*connect
, 0),
3726 CreateMockWrite(*wrapped_get
, 2),
3727 CreateMockWrite(*window_update
, 6),
3730 MockRead spdy_reads
[] = {
3731 CreateMockRead(*conn_resp
, 1, ASYNC
),
3732 CreateMockRead(*wrapped_get_resp
, 3, ASYNC
),
3733 CreateMockRead(*wrapped_body
, 4, ASYNC
),
3734 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3735 MockRead(ASYNC
, 0, 7),
3738 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3739 arraysize(spdy_writes
));
3740 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3742 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3743 ssl
.SetNextProto(GetParam());
3744 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3745 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3746 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3748 TestCompletionCallback callback1
;
3750 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3751 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3753 rv
= callback1
.WaitForResult();
3756 LoadTimingInfo load_timing_info
;
3757 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3758 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3760 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3761 ASSERT_TRUE(response
!= NULL
);
3762 ASSERT_TRUE(response
->headers
.get() != NULL
);
3763 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3765 std::string response_data
;
3766 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3767 EXPECT_EQ("1234567890", response_data
);
3770 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3771 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3772 HttpRequestInfo request
;
3773 request
.method
= "GET";
3774 request
.url
= GURL("https://www.example.org/");
3775 request
.load_flags
= 0;
3777 // Configure against https proxy server "proxy:70".
3778 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
3779 BoundTestNetLog log
;
3780 session_deps_
.net_log
= log
.bound().net_log();
3781 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3783 scoped_ptr
<HttpTransaction
> trans(
3784 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3786 // CONNECT to www.example.org:443 via SPDY
3787 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3788 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3789 // fetch https://www.example.org/ via SPDY
3790 const char kMyUrl
[] = "https://www.example.org/";
3791 scoped_ptr
<SpdyFrame
> get(
3792 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3793 scoped_ptr
<SpdyFrame
> wrapped_get(
3794 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3795 scoped_ptr
<SpdyFrame
> conn_resp(
3796 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3797 scoped_ptr
<SpdyFrame
> get_resp(
3798 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3799 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3800 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3801 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3802 scoped_ptr
<SpdyFrame
> wrapped_body(
3803 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3804 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3805 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3806 scoped_ptr
<SpdyFrame
> window_update_body(
3807 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3809 MockWrite spdy_writes
[] = {
3810 CreateMockWrite(*connect
, 0),
3811 CreateMockWrite(*wrapped_get
, 2),
3812 CreateMockWrite(*window_update_get_resp
, 6),
3813 CreateMockWrite(*window_update_body
, 7),
3816 MockRead spdy_reads
[] = {
3817 CreateMockRead(*conn_resp
, 1, ASYNC
),
3818 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3819 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3820 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3821 MockRead(ASYNC
, 0, 8),
3824 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3825 arraysize(spdy_writes
));
3826 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3828 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3829 ssl
.SetNextProto(GetParam());
3830 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3831 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3832 ssl2
.SetNextProto(GetParam());
3833 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3835 TestCompletionCallback callback1
;
3837 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3838 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3840 // Allow the SpdyProxyClientSocket's write callback to complete.
3841 base::MessageLoop::current()->RunUntilIdle();
3842 // Now allow the read of the response to complete.
3843 spdy_data
.CompleteRead();
3844 rv
= callback1
.WaitForResult();
3847 LoadTimingInfo load_timing_info
;
3848 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3849 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3851 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3852 ASSERT_TRUE(response
!= NULL
);
3853 ASSERT_TRUE(response
->headers
.get() != NULL
);
3854 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3856 std::string response_data
;
3857 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3858 EXPECT_EQ(kUploadData
, response_data
);
3861 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3862 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3863 HttpRequestInfo request
;
3864 request
.method
= "GET";
3865 request
.url
= GURL("https://www.example.org/");
3866 request
.load_flags
= 0;
3868 // Configure against https proxy server "proxy:70".
3869 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
3870 BoundTestNetLog log
;
3871 session_deps_
.net_log
= log
.bound().net_log();
3872 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3874 scoped_ptr
<HttpTransaction
> trans(
3875 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3877 // CONNECT to www.example.org:443 via SPDY
3878 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3879 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3880 scoped_ptr
<SpdyFrame
> get(
3881 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3883 MockWrite spdy_writes
[] = {
3884 CreateMockWrite(*connect
, 0), CreateMockWrite(*get
, 2),
3887 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3888 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3889 MockRead spdy_reads
[] = {
3890 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3),
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 ssl2
.SetNextProto(GetParam());
3902 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3904 TestCompletionCallback callback1
;
3906 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3907 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3909 rv
= callback1
.WaitForResult();
3910 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3912 // TODO(ttuttle): Anything else to check here?
3915 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3916 // HTTPS Proxy to different servers.
3917 TEST_P(HttpNetworkTransactionTest
,
3918 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3919 // Configure against https proxy server "proxy:70".
3920 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
3921 BoundTestNetLog log
;
3922 session_deps_
.net_log
= log
.bound().net_log();
3923 scoped_refptr
<HttpNetworkSession
> session(
3924 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3926 HttpRequestInfo request1
;
3927 request1
.method
= "GET";
3928 request1
.url
= GURL("https://www.example.org/");
3929 request1
.load_flags
= 0;
3931 HttpRequestInfo request2
;
3932 request2
.method
= "GET";
3933 request2
.url
= GURL("https://mail.example.org/");
3934 request2
.load_flags
= 0;
3936 // CONNECT to www.example.org:443 via SPDY.
3937 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3938 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3939 scoped_ptr
<SpdyFrame
> conn_resp1(
3940 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3942 // Fetch https://www.example.org/ via HTTP.
3944 "GET / HTTP/1.1\r\n"
3945 "Host: www.example.org\r\n"
3946 "Connection: keep-alive\r\n\r\n";
3947 scoped_ptr
<SpdyFrame
> wrapped_get1(
3948 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3949 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3950 "Content-Length: 1\r\n\r\n";
3951 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3952 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3953 scoped_ptr
<SpdyFrame
> wrapped_body1(
3954 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3955 scoped_ptr
<SpdyFrame
> window_update(
3956 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3958 // CONNECT to mail.example.org:443 via SPDY.
3959 SpdyHeaderBlock connect2_block
;
3960 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3961 if (GetParam() == kProtoHTTP2
) {
3962 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org:443";
3964 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3965 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3967 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3968 scoped_ptr
<SpdyFrame
> connect2(
3969 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3971 scoped_ptr
<SpdyFrame
> conn_resp2(
3972 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3974 // Fetch https://mail.example.org/ via HTTP.
3976 "GET / HTTP/1.1\r\n"
3977 "Host: mail.example.org\r\n"
3978 "Connection: keep-alive\r\n\r\n";
3979 scoped_ptr
<SpdyFrame
> wrapped_get2(
3980 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3981 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3982 "Content-Length: 2\r\n\r\n";
3983 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3984 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3985 scoped_ptr
<SpdyFrame
> wrapped_body2(
3986 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3988 MockWrite spdy_writes
[] = {
3989 CreateMockWrite(*connect1
, 0),
3990 CreateMockWrite(*wrapped_get1
, 2),
3991 CreateMockWrite(*connect2
, 5),
3992 CreateMockWrite(*wrapped_get2
, 7),
3995 MockRead spdy_reads
[] = {
3996 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3997 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3998 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3999 CreateMockRead(*conn_resp2
, 6, ASYNC
),
4000 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
4001 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
4002 MockRead(ASYNC
, 0, 10),
4005 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4006 arraysize(spdy_writes
));
4007 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4009 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4010 ssl
.SetNextProto(GetParam());
4011 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4012 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4013 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4014 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
4015 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl3
);
4017 TestCompletionCallback callback
;
4019 scoped_ptr
<HttpTransaction
> trans(
4020 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4021 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4022 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4024 LoadTimingInfo load_timing_info
;
4025 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4026 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4028 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4029 ASSERT_TRUE(response
!= NULL
);
4030 ASSERT_TRUE(response
->headers
.get() != NULL
);
4031 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4033 std::string response_data
;
4034 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4035 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4036 EXPECT_EQ(1, callback
.GetResult(rv
));
4038 scoped_ptr
<HttpTransaction
> trans2(
4039 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4040 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4041 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4043 LoadTimingInfo load_timing_info2
;
4044 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4045 // Even though the SPDY connection is reused, a new tunnelled connection has
4046 // to be created, so the socket's load timing looks like a fresh connection.
4047 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
4049 // The requests should have different IDs, since they each are using their own
4051 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4053 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4054 EXPECT_EQ(2, callback
.GetResult(rv
));
4057 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4058 // HTTPS Proxy to the same server.
4059 TEST_P(HttpNetworkTransactionTest
,
4060 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
4061 // Configure against https proxy server "proxy:70".
4062 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
4063 BoundTestNetLog log
;
4064 session_deps_
.net_log
= log
.bound().net_log();
4065 scoped_refptr
<HttpNetworkSession
> session(
4066 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4068 HttpRequestInfo request1
;
4069 request1
.method
= "GET";
4070 request1
.url
= GURL("https://www.example.org/");
4071 request1
.load_flags
= 0;
4073 HttpRequestInfo request2
;
4074 request2
.method
= "GET";
4075 request2
.url
= GURL("https://www.example.org/2");
4076 request2
.load_flags
= 0;
4078 // CONNECT to www.example.org:443 via SPDY.
4079 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
4080 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
4081 scoped_ptr
<SpdyFrame
> conn_resp1(
4082 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4084 // Fetch https://www.example.org/ via HTTP.
4086 "GET / HTTP/1.1\r\n"
4087 "Host: www.example.org\r\n"
4088 "Connection: keep-alive\r\n\r\n";
4089 scoped_ptr
<SpdyFrame
> wrapped_get1(
4090 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
4091 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
4092 "Content-Length: 1\r\n\r\n";
4093 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
4094 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
4095 scoped_ptr
<SpdyFrame
> wrapped_body1(
4096 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
4097 scoped_ptr
<SpdyFrame
> window_update(
4098 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
4100 // Fetch https://www.example.org/2 via HTTP.
4102 "GET /2 HTTP/1.1\r\n"
4103 "Host: www.example.org\r\n"
4104 "Connection: keep-alive\r\n\r\n";
4105 scoped_ptr
<SpdyFrame
> wrapped_get2(
4106 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
4107 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
4108 "Content-Length: 2\r\n\r\n";
4109 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
4110 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
4111 scoped_ptr
<SpdyFrame
> wrapped_body2(
4112 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4114 MockWrite spdy_writes
[] = {
4115 CreateMockWrite(*connect1
, 0),
4116 CreateMockWrite(*wrapped_get1
, 2),
4117 CreateMockWrite(*wrapped_get2
, 5),
4120 MockRead spdy_reads
[] = {
4121 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4122 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4123 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4124 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4125 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4126 MockRead(ASYNC
, 0, 8),
4129 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4130 arraysize(spdy_writes
));
4131 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4133 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4134 ssl
.SetNextProto(GetParam());
4135 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4136 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4137 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4139 TestCompletionCallback callback
;
4141 scoped_ptr
<HttpTransaction
> trans(
4142 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4143 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4144 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4146 rv
= callback
.WaitForResult();
4149 LoadTimingInfo load_timing_info
;
4150 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4151 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4153 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4154 ASSERT_TRUE(response
!= NULL
);
4155 ASSERT_TRUE(response
->headers
.get() != NULL
);
4156 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4158 std::string response_data
;
4159 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4160 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4163 scoped_ptr
<HttpTransaction
> trans2(
4164 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4165 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4166 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4168 rv
= callback
.WaitForResult();
4171 LoadTimingInfo load_timing_info2
;
4172 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4173 TestLoadTimingReused(load_timing_info2
);
4175 // The requests should have the same ID.
4176 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4178 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4181 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4182 // Proxy to different servers.
4183 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4184 // Configure against https proxy server "proxy:70".
4185 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
4186 BoundTestNetLog log
;
4187 session_deps_
.net_log
= log
.bound().net_log();
4188 scoped_refptr
<HttpNetworkSession
> session(
4189 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4191 HttpRequestInfo request1
;
4192 request1
.method
= "GET";
4193 request1
.url
= GURL("http://www.example.org/");
4194 request1
.load_flags
= 0;
4196 HttpRequestInfo request2
;
4197 request2
.method
= "GET";
4198 request2
.url
= GURL("http://mail.example.org/");
4199 request2
.load_flags
= 0;
4201 // http://www.example.org/
4202 scoped_ptr
<SpdyHeaderBlock
> headers(
4203 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4204 scoped_ptr
<SpdyFrame
> get1(
4205 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4206 scoped_ptr
<SpdyFrame
> get_resp1(
4207 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4208 scoped_ptr
<SpdyFrame
> body1(
4209 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4211 // http://mail.example.org/
4212 scoped_ptr
<SpdyHeaderBlock
> headers2(
4213 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4214 scoped_ptr
<SpdyFrame
> get2(
4215 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4216 scoped_ptr
<SpdyFrame
> get_resp2(
4217 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4218 scoped_ptr
<SpdyFrame
> body2(
4219 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4221 MockWrite spdy_writes
[] = {
4222 CreateMockWrite(*get1
, 0),
4223 CreateMockWrite(*get2
, 3),
4226 MockRead spdy_reads
[] = {
4227 CreateMockRead(*get_resp1
, 1, ASYNC
),
4228 CreateMockRead(*body1
, 2, ASYNC
),
4229 CreateMockRead(*get_resp2
, 4, ASYNC
),
4230 CreateMockRead(*body2
, 5, ASYNC
),
4231 MockRead(ASYNC
, 0, 6),
4234 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4235 arraysize(spdy_writes
));
4236 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4238 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4239 ssl
.SetNextProto(GetParam());
4240 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4242 TestCompletionCallback callback
;
4244 scoped_ptr
<HttpTransaction
> trans(
4245 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4246 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4247 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4249 LoadTimingInfo load_timing_info
;
4250 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4251 TestLoadTimingNotReused(load_timing_info
,
4252 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4254 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4255 ASSERT_TRUE(response
!= NULL
);
4256 ASSERT_TRUE(response
->headers
.get() != NULL
);
4257 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4259 std::string response_data
;
4260 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4261 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4262 EXPECT_EQ(1, callback
.GetResult(rv
));
4263 // Delete the first request, so the second one can reuse the socket.
4266 scoped_ptr
<HttpTransaction
> trans2(
4267 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4268 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4269 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4271 LoadTimingInfo load_timing_info2
;
4272 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4273 TestLoadTimingReused(load_timing_info2
);
4275 // The requests should have the same ID.
4276 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4278 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4279 EXPECT_EQ(2, callback
.GetResult(rv
));
4282 // Test the challenge-response-retry sequence through an HTTPS Proxy
4283 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4284 HttpRequestInfo request
;
4285 request
.method
= "GET";
4286 request
.url
= GURL("http://www.example.org/");
4287 // when the no authentication data flag is set.
4288 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4290 // Configure against https proxy server "myproxy:70".
4291 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://myproxy:70");
4292 BoundTestNetLog log
;
4293 session_deps_
.net_log
= log
.bound().net_log();
4294 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4296 // Since we have proxy, should use full url
4297 MockWrite data_writes1
[] = {
4299 "GET http://www.example.org/ HTTP/1.1\r\n"
4300 "Host: www.example.org\r\n"
4301 "Proxy-Connection: keep-alive\r\n\r\n"),
4303 // After calling trans->RestartWithAuth(), this is the request we should
4304 // be issuing -- the final header line contains the credentials.
4306 "GET http://www.example.org/ HTTP/1.1\r\n"
4307 "Host: www.example.org\r\n"
4308 "Proxy-Connection: keep-alive\r\n"
4309 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4312 // The proxy responds to the GET with a 407, using a persistent
4314 MockRead data_reads1
[] = {
4316 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4317 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4318 MockRead("Proxy-Connection: keep-alive\r\n"),
4319 MockRead("Content-Length: 0\r\n\r\n"),
4321 MockRead("HTTP/1.1 200 OK\r\n"),
4322 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4323 MockRead("Content-Length: 100\r\n\r\n"),
4324 MockRead(SYNCHRONOUS
, OK
),
4327 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4328 data_writes1
, arraysize(data_writes1
));
4329 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4330 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4331 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4333 TestCompletionCallback callback1
;
4335 scoped_ptr
<HttpTransaction
> trans(
4336 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4338 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4339 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4341 rv
= callback1
.WaitForResult();
4344 LoadTimingInfo load_timing_info
;
4345 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4346 TestLoadTimingNotReused(load_timing_info
,
4347 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4349 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4350 ASSERT_TRUE(response
!= NULL
);
4351 ASSERT_FALSE(response
->headers
.get() == NULL
);
4352 EXPECT_EQ(407, response
->headers
->response_code());
4353 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4354 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4356 TestCompletionCallback callback2
;
4358 rv
= trans
->RestartWithAuth(
4359 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4360 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4362 rv
= callback2
.WaitForResult();
4365 load_timing_info
= LoadTimingInfo();
4366 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4367 // Retrying with HTTP AUTH is considered to be reusing a socket.
4368 TestLoadTimingReused(load_timing_info
);
4370 response
= trans
->GetResponseInfo();
4371 ASSERT_TRUE(response
!= NULL
);
4373 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4374 EXPECT_EQ(200, response
->headers
->response_code());
4375 EXPECT_EQ(100, response
->headers
->GetContentLength());
4376 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4378 // The password prompt info should not be set.
4379 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4382 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4383 const MockRead
& status
, int expected_status
) {
4384 HttpRequestInfo request
;
4385 request
.method
= "GET";
4386 request
.url
= GURL("https://www.example.org/");
4387 request
.load_flags
= 0;
4389 // Configure against proxy server "myproxy:70".
4390 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
4391 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4393 // Since we have proxy, should try to establish tunnel.
4394 MockWrite data_writes
[] = {
4396 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4397 "Host: www.example.org\r\n"
4398 "Proxy-Connection: keep-alive\r\n\r\n"),
4401 MockRead data_reads
[] = {
4403 MockRead("Content-Length: 10\r\n\r\n"),
4404 // No response body because the test stops reading here.
4405 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4408 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4409 data_writes
, arraysize(data_writes
));
4410 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4412 TestCompletionCallback callback
;
4414 scoped_ptr
<HttpTransaction
> trans(
4415 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4417 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4418 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4420 rv
= callback
.WaitForResult();
4421 EXPECT_EQ(expected_status
, rv
);
4424 void HttpNetworkTransactionTest::ConnectStatusHelper(
4425 const MockRead
& status
) {
4426 ConnectStatusHelperWithExpectedStatus(
4427 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4430 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4431 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4434 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4435 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4438 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4439 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4442 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4443 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4446 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4447 ConnectStatusHelper(
4448 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4451 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4452 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4455 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4456 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4459 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4460 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4463 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4464 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4467 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4468 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4471 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4472 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4475 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4476 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4479 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4480 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4483 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4484 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4487 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4488 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4491 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4492 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4495 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4496 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4499 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4500 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4503 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4504 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4507 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4508 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4511 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4512 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4515 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4516 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4519 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4520 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4523 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4524 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4527 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4528 ConnectStatusHelperWithExpectedStatus(
4529 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4530 ERR_PROXY_AUTH_UNSUPPORTED
);
4533 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4534 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4537 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4538 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4541 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4542 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4545 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4546 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4549 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4550 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4553 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4554 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4557 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4558 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4561 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4562 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4565 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4566 ConnectStatusHelper(
4567 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4570 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4571 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4574 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4575 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4578 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4579 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4582 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4583 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4586 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4587 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4590 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4591 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4594 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4595 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4598 // Test the flow when both the proxy server AND origin server require
4599 // authentication. Again, this uses basic auth for both since that is
4600 // the simplest to mock.
4601 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4602 HttpRequestInfo request
;
4603 request
.method
= "GET";
4604 request
.url
= GURL("http://www.example.org/");
4605 request
.load_flags
= 0;
4607 // Configure against proxy server "myproxy:70".
4608 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
4609 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4611 scoped_ptr
<HttpTransaction
> trans(
4612 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4614 MockWrite data_writes1
[] = {
4616 "GET http://www.example.org/ HTTP/1.1\r\n"
4617 "Host: www.example.org\r\n"
4618 "Proxy-Connection: keep-alive\r\n\r\n"),
4621 MockRead data_reads1
[] = {
4622 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4623 // Give a couple authenticate options (only the middle one is actually
4625 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4626 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4627 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4628 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4629 // Large content-length -- won't matter, as connection will be reset.
4630 MockRead("Content-Length: 10000\r\n\r\n"),
4631 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4634 // After calling trans->RestartWithAuth() the first time, this is the
4635 // request we should be issuing -- the final header line contains the
4636 // proxy's credentials.
4637 MockWrite data_writes2
[] = {
4639 "GET http://www.example.org/ HTTP/1.1\r\n"
4640 "Host: www.example.org\r\n"
4641 "Proxy-Connection: keep-alive\r\n"
4642 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4645 // Now the proxy server lets the request pass through to origin server.
4646 // The origin server responds with a 401.
4647 MockRead data_reads2
[] = {
4648 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4649 // Note: We are using the same realm-name as the proxy server. This is
4650 // completely valid, as realms are unique across hosts.
4651 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4652 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4653 MockRead("Content-Length: 2000\r\n\r\n"),
4654 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4657 // After calling trans->RestartWithAuth() the second time, we should send
4658 // the credentials for both the proxy and origin server.
4659 MockWrite data_writes3
[] = {
4661 "GET http://www.example.org/ HTTP/1.1\r\n"
4662 "Host: www.example.org\r\n"
4663 "Proxy-Connection: keep-alive\r\n"
4664 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4665 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4668 // Lastly we get the desired content.
4669 MockRead data_reads3
[] = {
4670 MockRead("HTTP/1.0 200 OK\r\n"),
4671 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4672 MockRead("Content-Length: 100\r\n\r\n"),
4673 MockRead(SYNCHRONOUS
, OK
),
4676 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4677 data_writes1
, arraysize(data_writes1
));
4678 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4679 data_writes2
, arraysize(data_writes2
));
4680 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4681 data_writes3
, arraysize(data_writes3
));
4682 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4683 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4684 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4686 TestCompletionCallback callback1
;
4688 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4689 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4691 rv
= callback1
.WaitForResult();
4694 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4695 ASSERT_TRUE(response
!= NULL
);
4696 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4698 TestCompletionCallback callback2
;
4700 rv
= trans
->RestartWithAuth(
4701 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4702 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4704 rv
= callback2
.WaitForResult();
4707 response
= trans
->GetResponseInfo();
4708 ASSERT_TRUE(response
!= NULL
);
4709 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4711 TestCompletionCallback callback3
;
4713 rv
= trans
->RestartWithAuth(
4714 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4715 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4717 rv
= callback3
.WaitForResult();
4720 response
= trans
->GetResponseInfo();
4721 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4722 EXPECT_EQ(100, response
->headers
->GetContentLength());
4725 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4726 // can't hook into its internals to cause it to generate predictable NTLM
4727 // authorization headers.
4728 #if defined(NTLM_PORTABLE)
4729 // The NTLM authentication unit tests were generated by capturing the HTTP
4730 // requests and responses using Fiddler 2 and inspecting the generated random
4731 // bytes in the debugger.
4733 // Enter the correct password and authenticate successfully.
4734 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4735 HttpRequestInfo request
;
4736 request
.method
= "GET";
4737 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4739 // Ensure load is not disrupted by flags which suppress behaviour specific
4740 // to other auth schemes.
4741 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4743 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4745 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4747 MockWrite data_writes1
[] = {
4748 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4749 "Host: 172.22.68.17\r\n"
4750 "Connection: keep-alive\r\n\r\n"),
4753 MockRead data_reads1
[] = {
4754 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4755 // Negotiate and NTLM are often requested together. However, we only want
4756 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4757 // the header that requests Negotiate for this test.
4758 MockRead("WWW-Authenticate: NTLM\r\n"),
4759 MockRead("Connection: close\r\n"),
4760 MockRead("Content-Length: 42\r\n"),
4761 MockRead("Content-Type: text/html\r\n\r\n"),
4762 // Missing content -- won't matter, as connection will be reset.
4763 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4766 MockWrite data_writes2
[] = {
4767 // After restarting with a null identity, this is the
4768 // request we should be issuing -- the final header line contains a Type
4770 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4771 "Host: 172.22.68.17\r\n"
4772 "Connection: keep-alive\r\n"
4773 "Authorization: NTLM "
4774 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4776 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4777 // (the credentials for the origin server). The second request continues
4778 // on the same connection.
4779 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4780 "Host: 172.22.68.17\r\n"
4781 "Connection: keep-alive\r\n"
4782 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4783 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4784 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4785 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4786 "ahlhx5I=\r\n\r\n"),
4789 MockRead data_reads2
[] = {
4790 // The origin server responds with a Type 2 message.
4791 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4792 MockRead("WWW-Authenticate: NTLM "
4793 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4794 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4795 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4796 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4797 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4798 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4800 MockRead("Content-Length: 42\r\n"),
4801 MockRead("Content-Type: text/html\r\n\r\n"),
4802 MockRead("You are not authorized to view this page\r\n"),
4804 // Lastly we get the desired content.
4805 MockRead("HTTP/1.1 200 OK\r\n"),
4806 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4807 MockRead("Content-Length: 13\r\n\r\n"),
4808 MockRead("Please Login\r\n"),
4809 MockRead(SYNCHRONOUS
, OK
),
4812 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4813 data_writes1
, arraysize(data_writes1
));
4814 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4815 data_writes2
, arraysize(data_writes2
));
4816 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4817 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4819 TestCompletionCallback callback1
;
4821 scoped_ptr
<HttpTransaction
> trans(
4822 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4824 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4825 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4827 rv
= callback1
.WaitForResult();
4830 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4832 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4833 ASSERT_FALSE(response
== NULL
);
4834 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4836 TestCompletionCallback callback2
;
4838 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4839 callback2
.callback());
4840 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4842 rv
= callback2
.WaitForResult();
4845 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4847 response
= trans
->GetResponseInfo();
4848 ASSERT_TRUE(response
!= NULL
);
4849 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4851 TestCompletionCallback callback3
;
4853 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4854 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4856 rv
= callback3
.WaitForResult();
4859 response
= trans
->GetResponseInfo();
4860 ASSERT_TRUE(response
!= NULL
);
4861 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4862 EXPECT_EQ(13, response
->headers
->GetContentLength());
4865 // Enter a wrong password, and then the correct one.
4866 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4867 HttpRequestInfo request
;
4868 request
.method
= "GET";
4869 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4870 request
.load_flags
= 0;
4872 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4874 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4876 MockWrite data_writes1
[] = {
4877 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4878 "Host: 172.22.68.17\r\n"
4879 "Connection: keep-alive\r\n\r\n"),
4882 MockRead data_reads1
[] = {
4883 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4884 // Negotiate and NTLM are often requested together. However, we only want
4885 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4886 // the header that requests Negotiate for this test.
4887 MockRead("WWW-Authenticate: NTLM\r\n"),
4888 MockRead("Connection: close\r\n"),
4889 MockRead("Content-Length: 42\r\n"),
4890 MockRead("Content-Type: text/html\r\n\r\n"),
4891 // Missing content -- won't matter, as connection will be reset.
4892 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4895 MockWrite data_writes2
[] = {
4896 // After restarting with a null identity, this is the
4897 // request we should be issuing -- the final header line contains a Type
4899 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4900 "Host: 172.22.68.17\r\n"
4901 "Connection: keep-alive\r\n"
4902 "Authorization: NTLM "
4903 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4905 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4906 // (the credentials for the origin server). The second request continues
4907 // on the same connection.
4908 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4909 "Host: 172.22.68.17\r\n"
4910 "Connection: keep-alive\r\n"
4911 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4912 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4913 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4914 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4915 "4Ww7b7E=\r\n\r\n"),
4918 MockRead data_reads2
[] = {
4919 // The origin server responds with a Type 2 message.
4920 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4921 MockRead("WWW-Authenticate: NTLM "
4922 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4923 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4924 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4925 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4926 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4927 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4929 MockRead("Content-Length: 42\r\n"),
4930 MockRead("Content-Type: text/html\r\n\r\n"),
4931 MockRead("You are not authorized to view this page\r\n"),
4934 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4935 MockRead("WWW-Authenticate: NTLM\r\n"),
4936 MockRead("Connection: close\r\n"),
4937 MockRead("Content-Length: 42\r\n"),
4938 MockRead("Content-Type: text/html\r\n\r\n"),
4939 // Missing content -- won't matter, as connection will be reset.
4940 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4943 MockWrite data_writes3
[] = {
4944 // After restarting with a null identity, this is the
4945 // request we should be issuing -- the final header line contains a Type
4947 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4948 "Host: 172.22.68.17\r\n"
4949 "Connection: keep-alive\r\n"
4950 "Authorization: NTLM "
4951 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4953 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4954 // (the credentials for the origin server). The second request continues
4955 // on the same connection.
4956 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4957 "Host: 172.22.68.17\r\n"
4958 "Connection: keep-alive\r\n"
4959 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4960 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4961 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4962 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4963 "+4MUm7c=\r\n\r\n"),
4966 MockRead data_reads3
[] = {
4967 // The origin server responds with a Type 2 message.
4968 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4969 MockRead("WWW-Authenticate: NTLM "
4970 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4971 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4972 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4973 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4974 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4975 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4977 MockRead("Content-Length: 42\r\n"),
4978 MockRead("Content-Type: text/html\r\n\r\n"),
4979 MockRead("You are not authorized to view this page\r\n"),
4981 // Lastly we get the desired content.
4982 MockRead("HTTP/1.1 200 OK\r\n"),
4983 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4984 MockRead("Content-Length: 13\r\n\r\n"),
4985 MockRead("Please Login\r\n"),
4986 MockRead(SYNCHRONOUS
, OK
),
4989 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4990 data_writes1
, arraysize(data_writes1
));
4991 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4992 data_writes2
, arraysize(data_writes2
));
4993 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4994 data_writes3
, arraysize(data_writes3
));
4995 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4996 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4997 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4999 TestCompletionCallback callback1
;
5001 scoped_ptr
<HttpTransaction
> trans(
5002 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5004 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5005 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5007 rv
= callback1
.WaitForResult();
5010 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5012 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5013 ASSERT_TRUE(response
!= NULL
);
5014 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
5016 TestCompletionCallback callback2
;
5018 // Enter the wrong password.
5019 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
5020 callback2
.callback());
5021 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5023 rv
= callback2
.WaitForResult();
5026 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5027 TestCompletionCallback callback3
;
5028 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
5029 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5030 rv
= callback3
.WaitForResult();
5032 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5034 response
= trans
->GetResponseInfo();
5035 ASSERT_FALSE(response
== NULL
);
5036 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
5038 TestCompletionCallback callback4
;
5040 // Now enter the right password.
5041 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
5042 callback4
.callback());
5043 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5045 rv
= callback4
.WaitForResult();
5048 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5050 TestCompletionCallback callback5
;
5052 // One more roundtrip
5053 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
5054 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5056 rv
= callback5
.WaitForResult();
5059 response
= trans
->GetResponseInfo();
5060 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5061 EXPECT_EQ(13, response
->headers
->GetContentLength());
5063 #endif // NTLM_PORTABLE
5065 // Test reading a server response which has only headers, and no body.
5066 // After some maximum number of bytes is consumed, the transaction should
5067 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
5068 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
5069 HttpRequestInfo request
;
5070 request
.method
= "GET";
5071 request
.url
= GURL("http://www.example.org/");
5072 request
.load_flags
= 0;
5074 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5075 scoped_ptr
<HttpTransaction
> trans(
5076 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5078 // Respond with 300 kb of headers (we should fail after 256 kb).
5079 std::string large_headers_string
;
5080 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
5082 MockRead data_reads
[] = {
5083 MockRead("HTTP/1.0 200 OK\r\n"),
5084 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
5085 MockRead("\r\nBODY"),
5086 MockRead(SYNCHRONOUS
, OK
),
5088 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5089 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5091 TestCompletionCallback callback
;
5093 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5094 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5096 rv
= callback
.WaitForResult();
5097 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
5100 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5101 // establish tunnel.
5102 // http://code.google.com/p/chromium/issues/detail?id=3772
5103 TEST_P(HttpNetworkTransactionTest
,
5104 DontRecycleTransportSocketForSSLTunnel
) {
5105 HttpRequestInfo request
;
5106 request
.method
= "GET";
5107 request
.url
= GURL("https://www.example.org/");
5108 request
.load_flags
= 0;
5110 // Configure against proxy server "myproxy:70".
5111 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
5113 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5115 scoped_ptr
<HttpTransaction
> trans(
5116 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5118 // Since we have proxy, should try to establish tunnel.
5119 MockWrite data_writes1
[] = {
5121 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5122 "Host: www.example.org\r\n"
5123 "Proxy-Connection: keep-alive\r\n\r\n"),
5126 // The proxy responds to the connect with a 404, using a persistent
5127 // connection. Usually a proxy would return 501 (not implemented),
5128 // or 200 (tunnel established).
5129 MockRead data_reads1
[] = {
5130 MockRead("HTTP/1.1 404 Not Found\r\n"),
5131 MockRead("Content-Length: 10\r\n\r\n"),
5132 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5135 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5136 data_writes1
, arraysize(data_writes1
));
5137 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5139 TestCompletionCallback callback1
;
5141 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5142 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5144 rv
= callback1
.WaitForResult();
5145 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5147 // Empty the current queue. This is necessary because idle sockets are
5148 // added to the connection pool asynchronously with a PostTask.
5149 base::MessageLoop::current()->RunUntilIdle();
5151 // We now check to make sure the TCPClientSocket was not added back to
5153 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5155 base::MessageLoop::current()->RunUntilIdle();
5156 // Make sure that the socket didn't get recycled after calling the destructor.
5157 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5160 // Make sure that we recycle a socket after reading all of the response body.
5161 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5162 HttpRequestInfo request
;
5163 request
.method
= "GET";
5164 request
.url
= GURL("http://www.example.org/");
5165 request
.load_flags
= 0;
5167 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5169 scoped_ptr
<HttpTransaction
> trans(
5170 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5172 MockRead data_reads
[] = {
5173 // A part of the response body is received with the response headers.
5174 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5175 // The rest of the response body is received in two parts.
5178 MockRead("junk"), // Should not be read!!
5179 MockRead(SYNCHRONOUS
, OK
),
5182 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5183 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5185 TestCompletionCallback callback
;
5187 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5188 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5190 rv
= callback
.WaitForResult();
5193 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5194 ASSERT_TRUE(response
!= NULL
);
5196 EXPECT_TRUE(response
->headers
.get() != NULL
);
5197 std::string status_line
= response
->headers
->GetStatusLine();
5198 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5200 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5202 std::string response_data
;
5203 rv
= ReadTransaction(trans
.get(), &response_data
);
5205 EXPECT_EQ("hello world", response_data
);
5207 // Empty the current queue. This is necessary because idle sockets are
5208 // added to the connection pool asynchronously with a PostTask.
5209 base::MessageLoop::current()->RunUntilIdle();
5211 // We now check to make sure the socket was added back to the pool.
5212 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5215 // Make sure that we recycle a SSL socket after reading all of the response
5217 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5218 HttpRequestInfo request
;
5219 request
.method
= "GET";
5220 request
.url
= GURL("https://www.example.org/");
5221 request
.load_flags
= 0;
5223 MockWrite data_writes
[] = {
5225 "GET / HTTP/1.1\r\n"
5226 "Host: www.example.org\r\n"
5227 "Connection: keep-alive\r\n\r\n"),
5230 MockRead data_reads
[] = {
5231 MockRead("HTTP/1.1 200 OK\r\n"),
5232 MockRead("Content-Length: 11\r\n\r\n"),
5233 MockRead("hello world"),
5234 MockRead(SYNCHRONOUS
, OK
),
5237 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5238 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5240 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5241 data_writes
, arraysize(data_writes
));
5242 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5244 TestCompletionCallback callback
;
5246 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5247 scoped_ptr
<HttpTransaction
> trans(
5248 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5250 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5252 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5253 EXPECT_EQ(OK
, callback
.WaitForResult());
5255 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5256 ASSERT_TRUE(response
!= NULL
);
5257 ASSERT_TRUE(response
->headers
.get() != NULL
);
5258 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5260 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5262 std::string response_data
;
5263 rv
= ReadTransaction(trans
.get(), &response_data
);
5265 EXPECT_EQ("hello world", response_data
);
5267 // Empty the current queue. This is necessary because idle sockets are
5268 // added to the connection pool asynchronously with a PostTask.
5269 base::MessageLoop::current()->RunUntilIdle();
5271 // We now check to make sure the socket was added back to the pool.
5272 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5275 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5276 // from the pool and make sure that we recover okay.
5277 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5278 HttpRequestInfo request
;
5279 request
.method
= "GET";
5280 request
.url
= GURL("https://www.example.org/");
5281 request
.load_flags
= 0;
5283 MockWrite data_writes
[] = {
5285 "GET / HTTP/1.1\r\n"
5286 "Host: www.example.org\r\n"
5287 "Connection: keep-alive\r\n\r\n"),
5289 "GET / HTTP/1.1\r\n"
5290 "Host: www.example.org\r\n"
5291 "Connection: keep-alive\r\n\r\n"),
5294 MockRead data_reads
[] = {
5295 MockRead("HTTP/1.1 200 OK\r\n"),
5296 MockRead("Content-Length: 11\r\n\r\n"),
5297 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5298 MockRead("hello world"),
5299 MockRead(ASYNC
, 0, 0) // EOF
5302 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5303 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5304 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5305 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5307 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5308 data_writes
, arraysize(data_writes
));
5309 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5310 data_writes
, arraysize(data_writes
));
5311 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5312 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5314 TestCompletionCallback callback
;
5316 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5317 scoped_ptr
<HttpTransaction
> trans(
5318 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5320 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5322 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5323 EXPECT_EQ(OK
, callback
.WaitForResult());
5325 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5326 ASSERT_TRUE(response
!= NULL
);
5327 ASSERT_TRUE(response
->headers
.get() != NULL
);
5328 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5330 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5332 std::string response_data
;
5333 rv
= ReadTransaction(trans
.get(), &response_data
);
5335 EXPECT_EQ("hello world", response_data
);
5337 // Empty the current queue. This is necessary because idle sockets are
5338 // added to the connection pool asynchronously with a PostTask.
5339 base::MessageLoop::current()->RunUntilIdle();
5341 // We now check to make sure the socket was added back to the pool.
5342 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5344 // Now start the second transaction, which should reuse the previous socket.
5346 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5348 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5350 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5351 EXPECT_EQ(OK
, callback
.WaitForResult());
5353 response
= trans
->GetResponseInfo();
5354 ASSERT_TRUE(response
!= NULL
);
5355 ASSERT_TRUE(response
->headers
.get() != NULL
);
5356 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5358 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5360 rv
= ReadTransaction(trans
.get(), &response_data
);
5362 EXPECT_EQ("hello world", response_data
);
5364 // Empty the current queue. This is necessary because idle sockets are
5365 // added to the connection pool asynchronously with a PostTask.
5366 base::MessageLoop::current()->RunUntilIdle();
5368 // We now check to make sure the socket was added back to the pool.
5369 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5372 // Make sure that we recycle a socket after a zero-length response.
5373 // http://crbug.com/9880
5374 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5375 HttpRequestInfo request
;
5376 request
.method
= "GET";
5378 "http://www.example.org/csi?v=3&s=web&action=&"
5379 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5380 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5381 "rt=prt.2642,ol.2649,xjs.2951");
5382 request
.load_flags
= 0;
5384 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5386 scoped_ptr
<HttpTransaction
> trans(
5387 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5389 MockRead data_reads
[] = {
5390 MockRead("HTTP/1.1 204 No Content\r\n"
5391 "Content-Length: 0\r\n"
5392 "Content-Type: text/html\r\n\r\n"),
5393 MockRead("junk"), // Should not be read!!
5394 MockRead(SYNCHRONOUS
, OK
),
5397 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5398 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5400 TestCompletionCallback callback
;
5402 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5403 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5405 rv
= callback
.WaitForResult();
5408 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5409 ASSERT_TRUE(response
!= NULL
);
5411 EXPECT_TRUE(response
->headers
.get() != NULL
);
5412 std::string status_line
= response
->headers
->GetStatusLine();
5413 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5415 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5417 std::string response_data
;
5418 rv
= ReadTransaction(trans
.get(), &response_data
);
5420 EXPECT_EQ("", response_data
);
5422 // Empty the current queue. This is necessary because idle sockets are
5423 // added to the connection pool asynchronously with a PostTask.
5424 base::MessageLoop::current()->RunUntilIdle();
5426 // We now check to make sure the socket was added back to the pool.
5427 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5430 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5431 ScopedVector
<UploadElementReader
> element_readers
;
5432 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5433 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5435 HttpRequestInfo request
[2];
5436 // Transaction 1: a GET request that succeeds. The socket is recycled
5438 request
[0].method
= "GET";
5439 request
[0].url
= GURL("http://www.google.com/");
5440 request
[0].load_flags
= 0;
5441 // Transaction 2: a POST request. Reuses the socket kept alive from
5442 // transaction 1. The first attempts fails when writing the POST data.
5443 // This causes the transaction to retry with a new socket. The second
5444 // attempt succeeds.
5445 request
[1].method
= "POST";
5446 request
[1].url
= GURL("http://www.google.com/login.cgi");
5447 request
[1].upload_data_stream
= &upload_data_stream
;
5448 request
[1].load_flags
= 0;
5450 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5452 // The first socket is used for transaction 1 and the first attempt of
5455 // The response of transaction 1.
5456 MockRead data_reads1
[] = {
5457 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5458 MockRead("hello world"),
5459 MockRead(SYNCHRONOUS
, OK
),
5461 // The mock write results of transaction 1 and the first attempt of
5463 MockWrite data_writes1
[] = {
5464 MockWrite(SYNCHRONOUS
, 64), // GET
5465 MockWrite(SYNCHRONOUS
, 93), // POST
5466 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5468 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5469 data_writes1
, arraysize(data_writes1
));
5471 // The second socket is used for the second attempt of transaction 2.
5473 // The response of transaction 2.
5474 MockRead data_reads2
[] = {
5475 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5476 MockRead("welcome"),
5477 MockRead(SYNCHRONOUS
, OK
),
5479 // The mock write results of the second attempt of transaction 2.
5480 MockWrite data_writes2
[] = {
5481 MockWrite(SYNCHRONOUS
, 93), // POST
5482 MockWrite(SYNCHRONOUS
, 3), // POST data
5484 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5485 data_writes2
, arraysize(data_writes2
));
5487 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5488 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5490 const char* const kExpectedResponseData
[] = {
5491 "hello world", "welcome"
5494 for (int i
= 0; i
< 2; ++i
) {
5495 scoped_ptr
<HttpTransaction
> trans(
5496 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5498 TestCompletionCallback callback
;
5500 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5501 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5503 rv
= callback
.WaitForResult();
5506 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5507 ASSERT_TRUE(response
!= NULL
);
5509 EXPECT_TRUE(response
->headers
.get() != NULL
);
5510 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5512 std::string response_data
;
5513 rv
= ReadTransaction(trans
.get(), &response_data
);
5515 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5519 // Test the request-challenge-retry sequence for basic auth when there is
5520 // an identity in the URL. The request should be sent as normal, but when
5521 // it fails the identity from the URL is used to answer the challenge.
5522 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5523 HttpRequestInfo request
;
5524 request
.method
= "GET";
5525 request
.url
= GURL("http://foo:b@r@www.example.org/");
5526 request
.load_flags
= LOAD_NORMAL
;
5528 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5529 scoped_ptr
<HttpTransaction
> trans(
5530 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5532 // The password contains an escaped character -- for this test to pass it
5533 // will need to be unescaped by HttpNetworkTransaction.
5534 EXPECT_EQ("b%40r", request
.url
.password());
5536 MockWrite data_writes1
[] = {
5538 "GET / HTTP/1.1\r\n"
5539 "Host: www.example.org\r\n"
5540 "Connection: keep-alive\r\n\r\n"),
5543 MockRead data_reads1
[] = {
5544 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5545 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5546 MockRead("Content-Length: 10\r\n\r\n"),
5547 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5550 // After the challenge above, the transaction will be restarted using the
5551 // identity from the url (foo, b@r) to answer the challenge.
5552 MockWrite data_writes2
[] = {
5554 "GET / HTTP/1.1\r\n"
5555 "Host: www.example.org\r\n"
5556 "Connection: keep-alive\r\n"
5557 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5560 MockRead data_reads2
[] = {
5561 MockRead("HTTP/1.0 200 OK\r\n"),
5562 MockRead("Content-Length: 100\r\n\r\n"),
5563 MockRead(SYNCHRONOUS
, OK
),
5566 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5567 data_writes1
, arraysize(data_writes1
));
5568 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5569 data_writes2
, arraysize(data_writes2
));
5570 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5571 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5573 TestCompletionCallback callback1
;
5574 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5575 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5576 rv
= callback1
.WaitForResult();
5578 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5580 TestCompletionCallback callback2
;
5581 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5583 rv
= callback2
.WaitForResult();
5585 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5587 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5588 ASSERT_TRUE(response
!= NULL
);
5590 // There is no challenge info, since the identity in URL worked.
5591 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5593 EXPECT_EQ(100, response
->headers
->GetContentLength());
5595 // Empty the current queue.
5596 base::MessageLoop::current()->RunUntilIdle();
5599 // Test the request-challenge-retry sequence for basic auth when there is an
5600 // incorrect identity in the URL. The identity from the URL should be used only
5602 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5603 HttpRequestInfo request
;
5604 request
.method
= "GET";
5605 // Note: the URL has a username:password in it. The password "baz" is
5606 // wrong (should be "bar").
5607 request
.url
= GURL("http://foo:baz@www.example.org/");
5609 request
.load_flags
= LOAD_NORMAL
;
5611 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5612 scoped_ptr
<HttpTransaction
> trans(
5613 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5615 MockWrite data_writes1
[] = {
5617 "GET / HTTP/1.1\r\n"
5618 "Host: www.example.org\r\n"
5619 "Connection: keep-alive\r\n\r\n"),
5622 MockRead data_reads1
[] = {
5623 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5624 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5625 MockRead("Content-Length: 10\r\n\r\n"),
5626 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5629 // After the challenge above, the transaction will be restarted using the
5630 // identity from the url (foo, baz) to answer the challenge.
5631 MockWrite data_writes2
[] = {
5633 "GET / HTTP/1.1\r\n"
5634 "Host: www.example.org\r\n"
5635 "Connection: keep-alive\r\n"
5636 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5639 MockRead data_reads2
[] = {
5640 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5641 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5642 MockRead("Content-Length: 10\r\n\r\n"),
5643 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5646 // After the challenge above, the transaction will be restarted using the
5647 // identity supplied by the user (foo, bar) to answer the challenge.
5648 MockWrite data_writes3
[] = {
5650 "GET / HTTP/1.1\r\n"
5651 "Host: www.example.org\r\n"
5652 "Connection: keep-alive\r\n"
5653 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5656 MockRead data_reads3
[] = {
5657 MockRead("HTTP/1.0 200 OK\r\n"),
5658 MockRead("Content-Length: 100\r\n\r\n"),
5659 MockRead(SYNCHRONOUS
, OK
),
5662 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5663 data_writes1
, arraysize(data_writes1
));
5664 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5665 data_writes2
, arraysize(data_writes2
));
5666 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5667 data_writes3
, arraysize(data_writes3
));
5668 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5669 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5670 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5672 TestCompletionCallback callback1
;
5674 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5675 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5677 rv
= callback1
.WaitForResult();
5680 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5681 TestCompletionCallback callback2
;
5682 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5683 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5684 rv
= callback2
.WaitForResult();
5686 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5688 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5689 ASSERT_TRUE(response
!= NULL
);
5690 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5692 TestCompletionCallback callback3
;
5693 rv
= trans
->RestartWithAuth(
5694 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5695 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5696 rv
= callback3
.WaitForResult();
5698 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5700 response
= trans
->GetResponseInfo();
5701 ASSERT_TRUE(response
!= NULL
);
5703 // There is no challenge info, since the identity worked.
5704 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5706 EXPECT_EQ(100, response
->headers
->GetContentLength());
5708 // Empty the current queue.
5709 base::MessageLoop::current()->RunUntilIdle();
5713 // Test the request-challenge-retry sequence for basic auth when there is a
5714 // correct identity in the URL, but its use is being suppressed. The identity
5715 // from the URL should never be used.
5716 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5717 HttpRequestInfo request
;
5718 request
.method
= "GET";
5719 request
.url
= GURL("http://foo:bar@www.example.org/");
5720 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5722 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5723 scoped_ptr
<HttpTransaction
> trans(
5724 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5726 MockWrite data_writes1
[] = {
5728 "GET / HTTP/1.1\r\n"
5729 "Host: www.example.org\r\n"
5730 "Connection: keep-alive\r\n\r\n"),
5733 MockRead data_reads1
[] = {
5734 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5735 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5736 MockRead("Content-Length: 10\r\n\r\n"),
5737 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5740 // After the challenge above, the transaction will be restarted using the
5741 // identity supplied by the user, not the one in the URL, to answer the
5743 MockWrite data_writes3
[] = {
5745 "GET / HTTP/1.1\r\n"
5746 "Host: www.example.org\r\n"
5747 "Connection: keep-alive\r\n"
5748 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5751 MockRead data_reads3
[] = {
5752 MockRead("HTTP/1.0 200 OK\r\n"),
5753 MockRead("Content-Length: 100\r\n\r\n"),
5754 MockRead(SYNCHRONOUS
, OK
),
5757 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5758 data_writes1
, arraysize(data_writes1
));
5759 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5760 data_writes3
, arraysize(data_writes3
));
5761 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5762 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5764 TestCompletionCallback callback1
;
5765 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5766 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5767 rv
= callback1
.WaitForResult();
5769 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5771 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5772 ASSERT_TRUE(response
!= NULL
);
5773 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5775 TestCompletionCallback callback3
;
5776 rv
= trans
->RestartWithAuth(
5777 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5778 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5779 rv
= callback3
.WaitForResult();
5781 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5783 response
= trans
->GetResponseInfo();
5784 ASSERT_TRUE(response
!= NULL
);
5786 // There is no challenge info, since the identity worked.
5787 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5788 EXPECT_EQ(100, response
->headers
->GetContentLength());
5790 // Empty the current queue.
5791 base::MessageLoop::current()->RunUntilIdle();
5794 // Test that previously tried username/passwords for a realm get re-used.
5795 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5796 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5798 // Transaction 1: authenticate (foo, bar) on MyRealm1
5800 HttpRequestInfo request
;
5801 request
.method
= "GET";
5802 request
.url
= GURL("http://www.example.org/x/y/z");
5803 request
.load_flags
= 0;
5805 scoped_ptr
<HttpTransaction
> trans(
5806 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5808 MockWrite data_writes1
[] = {
5810 "GET /x/y/z HTTP/1.1\r\n"
5811 "Host: www.example.org\r\n"
5812 "Connection: keep-alive\r\n\r\n"),
5815 MockRead data_reads1
[] = {
5816 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5817 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5818 MockRead("Content-Length: 10000\r\n\r\n"),
5819 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5822 // Resend with authorization (username=foo, password=bar)
5823 MockWrite data_writes2
[] = {
5825 "GET /x/y/z HTTP/1.1\r\n"
5826 "Host: www.example.org\r\n"
5827 "Connection: keep-alive\r\n"
5828 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5831 // Sever accepts the authorization.
5832 MockRead data_reads2
[] = {
5833 MockRead("HTTP/1.0 200 OK\r\n"),
5834 MockRead("Content-Length: 100\r\n\r\n"),
5835 MockRead(SYNCHRONOUS
, OK
),
5838 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5839 data_writes1
, arraysize(data_writes1
));
5840 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5841 data_writes2
, arraysize(data_writes2
));
5842 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5843 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5845 TestCompletionCallback callback1
;
5847 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5848 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5850 rv
= callback1
.WaitForResult();
5853 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5854 ASSERT_TRUE(response
!= NULL
);
5855 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5857 TestCompletionCallback callback2
;
5859 rv
= trans
->RestartWithAuth(
5860 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5861 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5863 rv
= callback2
.WaitForResult();
5866 response
= trans
->GetResponseInfo();
5867 ASSERT_TRUE(response
!= NULL
);
5868 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5869 EXPECT_EQ(100, response
->headers
->GetContentLength());
5872 // ------------------------------------------------------------------------
5874 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5876 HttpRequestInfo request
;
5877 request
.method
= "GET";
5878 // Note that Transaction 1 was at /x/y/z, so this is in the same
5879 // protection space as MyRealm1.
5880 request
.url
= GURL("http://www.example.org/x/y/a/b");
5881 request
.load_flags
= 0;
5883 scoped_ptr
<HttpTransaction
> trans(
5884 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5886 MockWrite data_writes1
[] = {
5888 "GET /x/y/a/b HTTP/1.1\r\n"
5889 "Host: www.example.org\r\n"
5890 "Connection: keep-alive\r\n"
5891 // Send preemptive authorization for MyRealm1
5892 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5895 // The server didn't like the preemptive authorization, and
5896 // challenges us for a different realm (MyRealm2).
5897 MockRead data_reads1
[] = {
5898 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5899 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5900 MockRead("Content-Length: 10000\r\n\r\n"),
5901 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5904 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5905 MockWrite data_writes2
[] = {
5907 "GET /x/y/a/b HTTP/1.1\r\n"
5908 "Host: www.example.org\r\n"
5909 "Connection: keep-alive\r\n"
5910 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5913 // Sever accepts the authorization.
5914 MockRead data_reads2
[] = {
5915 MockRead("HTTP/1.0 200 OK\r\n"),
5916 MockRead("Content-Length: 100\r\n\r\n"),
5917 MockRead(SYNCHRONOUS
, OK
),
5920 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5921 data_writes1
, arraysize(data_writes1
));
5922 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5923 data_writes2
, arraysize(data_writes2
));
5924 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5925 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5927 TestCompletionCallback callback1
;
5929 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5930 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5932 rv
= callback1
.WaitForResult();
5935 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5936 ASSERT_TRUE(response
!= NULL
);
5937 ASSERT_TRUE(response
->auth_challenge
.get());
5938 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5939 EXPECT_EQ("www.example.org:80",
5940 response
->auth_challenge
->challenger
.ToString());
5941 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5942 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5944 TestCompletionCallback callback2
;
5946 rv
= trans
->RestartWithAuth(
5947 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5948 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5950 rv
= callback2
.WaitForResult();
5953 response
= trans
->GetResponseInfo();
5954 ASSERT_TRUE(response
!= NULL
);
5955 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5956 EXPECT_EQ(100, response
->headers
->GetContentLength());
5959 // ------------------------------------------------------------------------
5961 // Transaction 3: Resend a request in MyRealm's protection space --
5962 // succeed with preemptive authorization.
5964 HttpRequestInfo request
;
5965 request
.method
= "GET";
5966 request
.url
= GURL("http://www.example.org/x/y/z2");
5967 request
.load_flags
= 0;
5969 scoped_ptr
<HttpTransaction
> trans(
5970 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5972 MockWrite data_writes1
[] = {
5974 "GET /x/y/z2 HTTP/1.1\r\n"
5975 "Host: www.example.org\r\n"
5976 "Connection: keep-alive\r\n"
5977 // The authorization for MyRealm1 gets sent preemptively
5978 // (since the url is in the same protection space)
5979 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5982 // Sever accepts the preemptive authorization
5983 MockRead data_reads1
[] = {
5984 MockRead("HTTP/1.0 200 OK\r\n"),
5985 MockRead("Content-Length: 100\r\n\r\n"),
5986 MockRead(SYNCHRONOUS
, OK
),
5989 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5990 data_writes1
, arraysize(data_writes1
));
5991 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5993 TestCompletionCallback callback1
;
5995 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5996 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5998 rv
= callback1
.WaitForResult();
6001 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6002 ASSERT_TRUE(response
!= NULL
);
6004 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6005 EXPECT_EQ(100, response
->headers
->GetContentLength());
6008 // ------------------------------------------------------------------------
6010 // Transaction 4: request another URL in MyRealm (however the
6011 // url is not known to belong to the protection space, so no pre-auth).
6013 HttpRequestInfo request
;
6014 request
.method
= "GET";
6015 request
.url
= GURL("http://www.example.org/x/1");
6016 request
.load_flags
= 0;
6018 scoped_ptr
<HttpTransaction
> trans(
6019 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6021 MockWrite data_writes1
[] = {
6023 "GET /x/1 HTTP/1.1\r\n"
6024 "Host: www.example.org\r\n"
6025 "Connection: keep-alive\r\n\r\n"),
6028 MockRead data_reads1
[] = {
6029 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6030 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6031 MockRead("Content-Length: 10000\r\n\r\n"),
6032 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6035 // Resend with authorization from MyRealm's cache.
6036 MockWrite data_writes2
[] = {
6038 "GET /x/1 HTTP/1.1\r\n"
6039 "Host: www.example.org\r\n"
6040 "Connection: keep-alive\r\n"
6041 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6044 // Sever accepts the authorization.
6045 MockRead data_reads2
[] = {
6046 MockRead("HTTP/1.0 200 OK\r\n"),
6047 MockRead("Content-Length: 100\r\n\r\n"),
6048 MockRead(SYNCHRONOUS
, OK
),
6051 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6052 data_writes1
, arraysize(data_writes1
));
6053 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6054 data_writes2
, arraysize(data_writes2
));
6055 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6056 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6058 TestCompletionCallback callback1
;
6060 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6061 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6063 rv
= callback1
.WaitForResult();
6066 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6067 TestCompletionCallback callback2
;
6068 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6070 rv
= callback2
.WaitForResult();
6072 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6074 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6075 ASSERT_TRUE(response
!= NULL
);
6076 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6077 EXPECT_EQ(100, response
->headers
->GetContentLength());
6080 // ------------------------------------------------------------------------
6082 // Transaction 5: request a URL in MyRealm, but the server rejects the
6083 // cached identity. Should invalidate and re-prompt.
6085 HttpRequestInfo request
;
6086 request
.method
= "GET";
6087 request
.url
= GURL("http://www.example.org/p/q/t");
6088 request
.load_flags
= 0;
6090 scoped_ptr
<HttpTransaction
> trans(
6091 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6093 MockWrite data_writes1
[] = {
6095 "GET /p/q/t HTTP/1.1\r\n"
6096 "Host: www.example.org\r\n"
6097 "Connection: keep-alive\r\n\r\n"),
6100 MockRead data_reads1
[] = {
6101 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6102 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6103 MockRead("Content-Length: 10000\r\n\r\n"),
6104 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6107 // Resend with authorization from cache for MyRealm.
6108 MockWrite data_writes2
[] = {
6110 "GET /p/q/t HTTP/1.1\r\n"
6111 "Host: www.example.org\r\n"
6112 "Connection: keep-alive\r\n"
6113 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6116 // Sever rejects the authorization.
6117 MockRead data_reads2
[] = {
6118 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6119 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6120 MockRead("Content-Length: 10000\r\n\r\n"),
6121 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6124 // At this point we should prompt for new credentials for MyRealm.
6125 // Restart with username=foo3, password=foo4.
6126 MockWrite data_writes3
[] = {
6128 "GET /p/q/t HTTP/1.1\r\n"
6129 "Host: www.example.org\r\n"
6130 "Connection: keep-alive\r\n"
6131 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6134 // Sever accepts the authorization.
6135 MockRead data_reads3
[] = {
6136 MockRead("HTTP/1.0 200 OK\r\n"),
6137 MockRead("Content-Length: 100\r\n\r\n"),
6138 MockRead(SYNCHRONOUS
, OK
),
6141 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6142 data_writes1
, arraysize(data_writes1
));
6143 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6144 data_writes2
, arraysize(data_writes2
));
6145 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6146 data_writes3
, arraysize(data_writes3
));
6147 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6148 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6149 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6151 TestCompletionCallback callback1
;
6153 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6154 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6156 rv
= callback1
.WaitForResult();
6159 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6160 TestCompletionCallback callback2
;
6161 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6162 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6163 rv
= callback2
.WaitForResult();
6165 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6167 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6168 ASSERT_TRUE(response
!= NULL
);
6169 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6171 TestCompletionCallback callback3
;
6173 rv
= trans
->RestartWithAuth(
6174 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6175 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6177 rv
= callback3
.WaitForResult();
6180 response
= trans
->GetResponseInfo();
6181 ASSERT_TRUE(response
!= NULL
);
6182 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6183 EXPECT_EQ(100, response
->headers
->GetContentLength());
6187 // Tests that nonce count increments when multiple auth attempts
6188 // are started with the same nonce.
6189 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6190 HttpAuthHandlerDigest::Factory
* digest_factory
=
6191 new HttpAuthHandlerDigest::Factory();
6192 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6193 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6194 digest_factory
->set_nonce_generator(nonce_generator
);
6195 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6198 // Transaction 1: authenticate (foo, bar) on MyRealm1
6200 HttpRequestInfo request
;
6201 request
.method
= "GET";
6202 request
.url
= GURL("http://www.example.org/x/y/z");
6203 request
.load_flags
= 0;
6205 scoped_ptr
<HttpTransaction
> trans(
6206 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6208 MockWrite data_writes1
[] = {
6210 "GET /x/y/z HTTP/1.1\r\n"
6211 "Host: www.example.org\r\n"
6212 "Connection: keep-alive\r\n\r\n"),
6215 MockRead data_reads1
[] = {
6216 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6217 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6218 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6219 MockRead(SYNCHRONOUS
, OK
),
6222 // Resend with authorization (username=foo, password=bar)
6223 MockWrite data_writes2
[] = {
6225 "GET /x/y/z HTTP/1.1\r\n"
6226 "Host: www.example.org\r\n"
6227 "Connection: keep-alive\r\n"
6228 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6229 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6230 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6231 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6234 // Sever accepts the authorization.
6235 MockRead data_reads2
[] = {
6236 MockRead("HTTP/1.0 200 OK\r\n"),
6237 MockRead(SYNCHRONOUS
, OK
),
6240 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6241 data_writes1
, arraysize(data_writes1
));
6242 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6243 data_writes2
, arraysize(data_writes2
));
6244 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6245 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6247 TestCompletionCallback callback1
;
6249 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6250 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6252 rv
= callback1
.WaitForResult();
6255 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6256 ASSERT_TRUE(response
!= NULL
);
6257 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6259 TestCompletionCallback callback2
;
6261 rv
= trans
->RestartWithAuth(
6262 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6263 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6265 rv
= callback2
.WaitForResult();
6268 response
= trans
->GetResponseInfo();
6269 ASSERT_TRUE(response
!= NULL
);
6270 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6273 // ------------------------------------------------------------------------
6275 // Transaction 2: Request another resource in digestive's protection space.
6276 // This will preemptively add an Authorization header which should have an
6277 // "nc" value of 2 (as compared to 1 in the first use.
6279 HttpRequestInfo request
;
6280 request
.method
= "GET";
6281 // Note that Transaction 1 was at /x/y/z, so this is in the same
6282 // protection space as digest.
6283 request
.url
= GURL("http://www.example.org/x/y/a/b");
6284 request
.load_flags
= 0;
6286 scoped_ptr
<HttpTransaction
> trans(
6287 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6289 MockWrite data_writes1
[] = {
6291 "GET /x/y/a/b HTTP/1.1\r\n"
6292 "Host: www.example.org\r\n"
6293 "Connection: keep-alive\r\n"
6294 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6295 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6296 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6297 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6300 // Sever accepts the authorization.
6301 MockRead data_reads1
[] = {
6302 MockRead("HTTP/1.0 200 OK\r\n"),
6303 MockRead("Content-Length: 100\r\n\r\n"),
6304 MockRead(SYNCHRONOUS
, OK
),
6307 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6308 data_writes1
, arraysize(data_writes1
));
6309 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6311 TestCompletionCallback callback1
;
6313 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6314 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6316 rv
= callback1
.WaitForResult();
6319 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6320 ASSERT_TRUE(response
!= NULL
);
6321 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6325 // Test the ResetStateForRestart() private method.
6326 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6327 // Create a transaction (the dependencies aren't important).
6328 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6329 scoped_ptr
<HttpNetworkTransaction
> trans(
6330 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6332 // Setup some state (which we expect ResetStateForRestart() will clear).
6333 trans
->read_buf_
= new IOBuffer(15);
6334 trans
->read_buf_len_
= 15;
6335 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6337 // Setup state in response_
6338 HttpResponseInfo
* response
= &trans
->response_
;
6339 response
->auth_challenge
= new AuthChallengeInfo();
6340 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6341 response
->response_time
= base::Time::Now();
6342 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6344 { // Setup state for response_.vary_data
6345 HttpRequestInfo request
;
6346 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6347 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6348 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6349 request
.extra_headers
.SetHeader("Foo", "1");
6350 request
.extra_headers
.SetHeader("bar", "23");
6351 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6354 // Cause the above state to be reset.
6355 trans
->ResetStateForRestart();
6357 // Verify that the state that needed to be reset, has been reset.
6358 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6359 EXPECT_EQ(0, trans
->read_buf_len_
);
6360 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6361 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6362 EXPECT_TRUE(response
->headers
.get() == NULL
);
6363 EXPECT_FALSE(response
->was_cached
);
6364 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6365 EXPECT_FALSE(response
->vary_data
.is_valid());
6368 // Test HTTPS connections to a site with a bad certificate
6369 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6370 HttpRequestInfo request
;
6371 request
.method
= "GET";
6372 request
.url
= GURL("https://www.example.org/");
6373 request
.load_flags
= 0;
6375 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6376 scoped_ptr
<HttpTransaction
> trans(
6377 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6379 MockWrite data_writes
[] = {
6381 "GET / HTTP/1.1\r\n"
6382 "Host: www.example.org\r\n"
6383 "Connection: keep-alive\r\n\r\n"),
6386 MockRead data_reads
[] = {
6387 MockRead("HTTP/1.0 200 OK\r\n"),
6388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6389 MockRead("Content-Length: 100\r\n\r\n"),
6390 MockRead(SYNCHRONOUS
, OK
),
6393 StaticSocketDataProvider ssl_bad_certificate
;
6394 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6395 data_writes
, arraysize(data_writes
));
6396 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6397 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6399 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6400 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6401 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6402 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6404 TestCompletionCallback callback
;
6406 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6407 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6409 rv
= callback
.WaitForResult();
6410 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6412 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6413 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6415 rv
= callback
.WaitForResult();
6418 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6420 ASSERT_TRUE(response
!= NULL
);
6421 EXPECT_EQ(100, response
->headers
->GetContentLength());
6424 // Test HTTPS connections to a site with a bad certificate, going through a
6426 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6427 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
6429 HttpRequestInfo request
;
6430 request
.method
= "GET";
6431 request
.url
= GURL("https://www.example.org/");
6432 request
.load_flags
= 0;
6434 MockWrite proxy_writes
[] = {
6436 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6437 "Host: www.example.org\r\n"
6438 "Proxy-Connection: keep-alive\r\n\r\n"),
6441 MockRead proxy_reads
[] = {
6442 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6443 MockRead(SYNCHRONOUS
, OK
)
6446 MockWrite data_writes
[] = {
6448 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6449 "Host: www.example.org\r\n"
6450 "Proxy-Connection: keep-alive\r\n\r\n"),
6452 "GET / HTTP/1.1\r\n"
6453 "Host: www.example.org\r\n"
6454 "Connection: keep-alive\r\n\r\n"),
6457 MockRead data_reads
[] = {
6458 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6459 MockRead("HTTP/1.0 200 OK\r\n"),
6460 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6461 MockRead("Content-Length: 100\r\n\r\n"),
6462 MockRead(SYNCHRONOUS
, OK
),
6465 StaticSocketDataProvider
ssl_bad_certificate(
6466 proxy_reads
, arraysize(proxy_reads
),
6467 proxy_writes
, arraysize(proxy_writes
));
6468 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6469 data_writes
, arraysize(data_writes
));
6470 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6471 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6473 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6474 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6475 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6476 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6478 TestCompletionCallback callback
;
6480 for (int i
= 0; i
< 2; i
++) {
6481 session_deps_
.socket_factory
->ResetNextMockIndexes();
6483 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6484 scoped_ptr
<HttpTransaction
> trans(
6485 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6487 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6488 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6490 rv
= callback
.WaitForResult();
6491 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6493 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6494 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6496 rv
= callback
.WaitForResult();
6499 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6501 ASSERT_TRUE(response
!= NULL
);
6502 EXPECT_EQ(100, response
->headers
->GetContentLength());
6507 // Test HTTPS connections to a site, going through an HTTPS proxy
6508 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6509 session_deps_
.proxy_service
=
6510 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
6512 session_deps_
.net_log
= &net_log
;
6514 HttpRequestInfo request
;
6515 request
.method
= "GET";
6516 request
.url
= GURL("https://www.example.org/");
6517 request
.load_flags
= 0;
6519 MockWrite data_writes
[] = {
6521 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6522 "Host: www.example.org\r\n"
6523 "Proxy-Connection: keep-alive\r\n\r\n"),
6525 "GET / HTTP/1.1\r\n"
6526 "Host: www.example.org\r\n"
6527 "Connection: keep-alive\r\n\r\n"),
6530 MockRead data_reads
[] = {
6531 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6532 MockRead("HTTP/1.1 200 OK\r\n"),
6533 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6534 MockRead("Content-Length: 100\r\n\r\n"),
6535 MockRead(SYNCHRONOUS
, OK
),
6538 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6539 data_writes
, arraysize(data_writes
));
6540 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6541 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6543 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6544 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6545 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6547 TestCompletionCallback callback
;
6549 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6550 scoped_ptr
<HttpTransaction
> trans(
6551 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6553 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6554 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6556 rv
= callback
.WaitForResult();
6558 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6560 ASSERT_TRUE(response
!= NULL
);
6562 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6563 EXPECT_EQ(200, response
->headers
->response_code());
6564 EXPECT_EQ(100, response
->headers
->GetContentLength());
6565 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6567 LoadTimingInfo load_timing_info
;
6568 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6569 TestLoadTimingNotReusedWithPac(load_timing_info
,
6570 CONNECT_TIMING_HAS_SSL_TIMES
);
6573 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6574 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6575 session_deps_
.proxy_service
=
6576 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
6578 session_deps_
.net_log
= &net_log
;
6580 HttpRequestInfo request
;
6581 request
.method
= "GET";
6582 request
.url
= GURL("https://www.example.org/");
6583 request
.load_flags
= 0;
6585 MockWrite data_writes
[] = {
6587 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6588 "Host: www.example.org\r\n"
6589 "Proxy-Connection: keep-alive\r\n\r\n"),
6592 MockRead data_reads
[] = {
6593 MockRead("HTTP/1.1 302 Redirect\r\n"),
6594 MockRead("Location: http://login.example.com/\r\n"),
6595 MockRead("Content-Length: 0\r\n\r\n"),
6596 MockRead(SYNCHRONOUS
, OK
),
6599 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6600 data_writes
, arraysize(data_writes
));
6601 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6603 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6604 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6606 TestCompletionCallback callback
;
6608 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6609 scoped_ptr
<HttpTransaction
> trans(
6610 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6612 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6613 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6615 rv
= callback
.WaitForResult();
6617 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6619 ASSERT_TRUE(response
!= NULL
);
6621 EXPECT_EQ(302, response
->headers
->response_code());
6623 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6624 EXPECT_EQ("http://login.example.com/", url
);
6626 // In the case of redirects from proxies, HttpNetworkTransaction returns
6627 // timing for the proxy connection instead of the connection to the host,
6628 // and no send / receive times.
6629 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6630 LoadTimingInfo load_timing_info
;
6631 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6633 EXPECT_FALSE(load_timing_info
.socket_reused
);
6634 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6636 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6637 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6638 load_timing_info
.proxy_resolve_end
);
6639 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6640 load_timing_info
.connect_timing
.connect_start
);
6641 ExpectConnectTimingHasTimes(
6642 load_timing_info
.connect_timing
,
6643 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6645 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6646 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6647 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6650 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6651 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6652 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
6654 HttpRequestInfo request
;
6655 request
.method
= "GET";
6656 request
.url
= GURL("https://www.example.org/");
6657 request
.load_flags
= 0;
6659 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6660 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6661 scoped_ptr
<SpdyFrame
> goaway(
6662 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6663 MockWrite data_writes
[] = {
6664 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6665 CreateMockWrite(*goaway
.get(), 2, SYNCHRONOUS
),
6668 static const char* const kExtraHeaders
[] = {
6670 "http://login.example.com/",
6672 scoped_ptr
<SpdyFrame
> resp(
6673 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6674 arraysize(kExtraHeaders
)/2, 1));
6675 MockRead data_reads
[] = {
6676 CreateMockRead(*resp
.get(), 1), MockRead(ASYNC
, 0, 3), // EOF
6679 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6680 arraysize(data_writes
));
6681 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6682 proxy_ssl
.SetNextProto(GetParam());
6684 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6685 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6687 TestCompletionCallback callback
;
6689 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6690 scoped_ptr
<HttpTransaction
> trans(
6691 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6693 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6694 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6696 rv
= callback
.WaitForResult();
6698 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6700 ASSERT_TRUE(response
!= NULL
);
6702 EXPECT_EQ(302, response
->headers
->response_code());
6704 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6705 EXPECT_EQ("http://login.example.com/", url
);
6708 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6709 TEST_P(HttpNetworkTransactionTest
,
6710 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6711 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
6713 HttpRequestInfo request
;
6714 request
.method
= "GET";
6715 request
.url
= GURL("https://www.example.org/");
6716 request
.load_flags
= 0;
6718 MockWrite data_writes
[] = {
6720 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6721 "Host: www.example.org\r\n"
6722 "Proxy-Connection: keep-alive\r\n\r\n"),
6725 MockRead data_reads
[] = {
6726 MockRead("HTTP/1.1 404 Not Found\r\n"),
6727 MockRead("Content-Length: 23\r\n\r\n"),
6728 MockRead("The host does not exist"),
6729 MockRead(SYNCHRONOUS
, OK
),
6732 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6733 data_writes
, arraysize(data_writes
));
6734 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6736 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6737 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6739 TestCompletionCallback callback
;
6741 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6742 scoped_ptr
<HttpTransaction
> trans(
6743 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6745 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6746 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6748 rv
= callback
.WaitForResult();
6749 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6751 // TODO(ttuttle): Anything else to check here?
6754 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6755 TEST_P(HttpNetworkTransactionTest
,
6756 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6757 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
6759 HttpRequestInfo request
;
6760 request
.method
= "GET";
6761 request
.url
= GURL("https://www.example.org/");
6762 request
.load_flags
= 0;
6764 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6765 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6766 scoped_ptr
<SpdyFrame
> rst(
6767 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6768 MockWrite data_writes
[] = {
6769 CreateMockWrite(*conn
.get(), 0), CreateMockWrite(*rst
.get(), 3),
6772 static const char* const kExtraHeaders
[] = {
6774 "http://login.example.com/",
6776 scoped_ptr
<SpdyFrame
> resp(
6777 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6778 arraysize(kExtraHeaders
)/2, 1));
6779 scoped_ptr
<SpdyFrame
> body(
6780 spdy_util_
.ConstructSpdyBodyFrame(
6781 1, "The host does not exist", 23, true));
6782 MockRead data_reads
[] = {
6783 CreateMockRead(*resp
.get(), 1),
6784 CreateMockRead(*body
.get(), 2),
6785 MockRead(ASYNC
, 0, 4), // EOF
6788 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6789 arraysize(data_writes
));
6790 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6791 proxy_ssl
.SetNextProto(GetParam());
6793 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6794 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6796 TestCompletionCallback callback
;
6798 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6799 scoped_ptr
<HttpTransaction
> trans(
6800 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6802 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6803 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6805 rv
= callback
.WaitForResult();
6806 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6808 // TODO(ttuttle): Anything else to check here?
6811 // Test the request-challenge-retry sequence for basic auth, through
6812 // a SPDY proxy over a single SPDY session.
6813 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6814 HttpRequestInfo request
;
6815 request
.method
= "GET";
6816 request
.url
= GURL("https://www.example.org/");
6817 // when the no authentication data flag is set.
6818 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6820 // Configure against https proxy server "myproxy:70".
6821 session_deps_
.proxy_service
=
6822 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
6823 BoundTestNetLog log
;
6824 session_deps_
.net_log
= log
.bound().net_log();
6825 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6827 // Since we have proxy, should try to establish tunnel.
6828 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6829 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6830 scoped_ptr
<SpdyFrame
> rst(
6831 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6833 // After calling trans->RestartWithAuth(), this is the request we should
6834 // be issuing -- the final header line contains the credentials.
6835 const char* const kAuthCredentials
[] = {
6836 "proxy-authorization", "Basic Zm9vOmJhcg==",
6838 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6839 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6840 HostPortPair("www.example.org", 443)));
6841 // fetch https://www.example.org/ via HTTP
6843 "GET / HTTP/1.1\r\n"
6844 "Host: www.example.org\r\n"
6845 "Connection: keep-alive\r\n\r\n";
6846 scoped_ptr
<SpdyFrame
> wrapped_get(
6847 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6849 MockWrite spdy_writes
[] = {
6850 CreateMockWrite(*req
, 0, ASYNC
),
6851 CreateMockWrite(*rst
, 2, ASYNC
),
6852 CreateMockWrite(*connect2
, 3),
6853 CreateMockWrite(*wrapped_get
, 5),
6856 // The proxy responds to the connect with a 407, using a persistent
6858 const char kAuthStatus
[] = "407";
6859 const char* const kAuthChallenge
[] = {
6860 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6862 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6863 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6865 scoped_ptr
<SpdyFrame
> conn_resp(
6866 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6867 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6868 "Content-Length: 5\r\n\r\n";
6870 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6871 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6872 scoped_ptr
<SpdyFrame
> wrapped_body(
6873 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6874 MockRead spdy_reads
[] = {
6875 CreateMockRead(*conn_auth_resp
, 1, ASYNC
),
6876 CreateMockRead(*conn_resp
, 4, ASYNC
),
6877 CreateMockRead(*wrapped_get_resp
, 6, ASYNC
),
6878 CreateMockRead(*wrapped_body
, 7, ASYNC
),
6879 MockRead(ASYNC
, OK
, 8), // EOF. May or may not be read.
6882 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6883 arraysize(spdy_writes
));
6884 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6885 // Negotiate SPDY to the proxy
6886 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6887 proxy
.SetNextProto(GetParam());
6888 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6889 // Vanilla SSL to the server
6890 SSLSocketDataProvider
server(ASYNC
, OK
);
6891 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6893 TestCompletionCallback callback1
;
6895 scoped_ptr
<HttpTransaction
> trans(
6896 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6898 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6899 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6901 rv
= callback1
.WaitForResult();
6903 TestNetLogEntry::List entries
;
6904 log
.GetEntries(&entries
);
6905 size_t pos
= ExpectLogContainsSomewhere(
6906 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6907 NetLog::PHASE_NONE
);
6908 ExpectLogContainsSomewhere(
6910 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6911 NetLog::PHASE_NONE
);
6913 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6914 ASSERT_TRUE(response
!= NULL
);
6915 ASSERT_FALSE(response
->headers
.get() == NULL
);
6916 EXPECT_EQ(407, response
->headers
->response_code());
6917 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6918 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6919 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6921 TestCompletionCallback callback2
;
6923 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6924 callback2
.callback());
6925 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6927 rv
= callback2
.WaitForResult();
6930 response
= trans
->GetResponseInfo();
6931 ASSERT_TRUE(response
!= NULL
);
6933 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6934 EXPECT_EQ(200, response
->headers
->response_code());
6935 EXPECT_EQ(5, response
->headers
->GetContentLength());
6936 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6938 // The password prompt info should not be set.
6939 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6941 LoadTimingInfo load_timing_info
;
6942 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6943 TestLoadTimingNotReusedWithPac(load_timing_info
,
6944 CONNECT_TIMING_HAS_SSL_TIMES
);
6947 session
->CloseAllConnections();
6950 // Test that an explicitly trusted SPDY proxy can push a resource from an
6951 // origin that is different from that of its associated resource.
6952 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6953 HttpRequestInfo request
;
6954 HttpRequestInfo push_request
;
6956 request
.method
= "GET";
6957 request
.url
= GURL("http://www.example.org/");
6958 push_request
.method
= "GET";
6959 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6961 // Configure against https proxy server "myproxy:70".
6962 session_deps_
.proxy_service
=
6963 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
6964 BoundTestNetLog log
;
6965 session_deps_
.net_log
= log
.bound().net_log();
6967 // Enable cross-origin push.
6968 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6970 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6972 scoped_ptr
<SpdyFrame
> stream1_syn(
6973 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6975 MockWrite spdy_writes
[] = {
6976 CreateMockWrite(*stream1_syn
, 0, ASYNC
),
6979 scoped_ptr
<SpdyFrame
>
6980 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6982 scoped_ptr
<SpdyFrame
>
6983 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6985 scoped_ptr
<SpdyFrame
>
6986 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6990 "http://www.another-origin.com/foo.dat"));
6991 const char kPushedData
[] = "pushed";
6992 scoped_ptr
<SpdyFrame
> stream2_body(
6993 spdy_util_
.ConstructSpdyBodyFrame(
6994 2, kPushedData
, strlen(kPushedData
), true));
6996 MockRead spdy_reads
[] = {
6997 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6998 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6999 CreateMockRead(*stream1_body
, 3, ASYNC
),
7000 CreateMockRead(*stream2_body
, 4, ASYNC
),
7001 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7004 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7005 arraysize(spdy_writes
));
7006 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7007 // Negotiate SPDY to the proxy
7008 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7009 proxy
.SetNextProto(GetParam());
7010 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7012 scoped_ptr
<HttpTransaction
> trans(
7013 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7014 TestCompletionCallback callback
;
7015 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7016 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7018 rv
= callback
.WaitForResult();
7020 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7022 scoped_ptr
<HttpTransaction
> push_trans(
7023 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7024 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
7025 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7027 rv
= callback
.WaitForResult();
7029 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
7031 ASSERT_TRUE(response
!= NULL
);
7032 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7034 EXPECT_EQ(200, response
->headers
->response_code());
7035 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7037 std::string response_data
;
7038 rv
= ReadTransaction(trans
.get(), &response_data
);
7040 EXPECT_EQ("hello!", response_data
);
7042 LoadTimingInfo load_timing_info
;
7043 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7044 TestLoadTimingNotReusedWithPac(load_timing_info
,
7045 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7047 // Verify the pushed stream.
7048 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
7049 EXPECT_EQ(200, push_response
->headers
->response_code());
7051 rv
= ReadTransaction(push_trans
.get(), &response_data
);
7053 EXPECT_EQ("pushed", response_data
);
7055 LoadTimingInfo push_load_timing_info
;
7056 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
7057 TestLoadTimingReusedWithPac(push_load_timing_info
);
7058 // The transactions should share a socket ID, despite being for different
7060 EXPECT_EQ(load_timing_info
.socket_log_id
,
7061 push_load_timing_info
.socket_log_id
);
7065 session
->CloseAllConnections();
7068 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
7069 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
7070 HttpRequestInfo request
;
7072 request
.method
= "GET";
7073 request
.url
= GURL("http://www.example.org/");
7075 // Configure against https proxy server "myproxy:70".
7076 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://myproxy:70");
7077 BoundTestNetLog log
;
7078 session_deps_
.net_log
= log
.bound().net_log();
7080 // Enable cross-origin push.
7081 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
7083 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7085 scoped_ptr
<SpdyFrame
> stream1_syn(
7086 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
7088 scoped_ptr
<SpdyFrame
> push_rst(
7089 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
7091 MockWrite spdy_writes
[] = {
7092 CreateMockWrite(*stream1_syn
, 0, ASYNC
), CreateMockWrite(*push_rst
, 3),
7095 scoped_ptr
<SpdyFrame
>
7096 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
7098 scoped_ptr
<SpdyFrame
>
7099 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
7101 scoped_ptr
<SpdyFrame
>
7102 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7106 "https://www.another-origin.com/foo.dat"));
7108 MockRead spdy_reads
[] = {
7109 CreateMockRead(*stream1_reply
, 1, ASYNC
),
7110 CreateMockRead(*stream2_syn
, 2, ASYNC
),
7111 CreateMockRead(*stream1_body
, 4, ASYNC
),
7112 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7115 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7116 arraysize(spdy_writes
));
7117 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7118 // Negotiate SPDY to the proxy
7119 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7120 proxy
.SetNextProto(GetParam());
7121 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7123 scoped_ptr
<HttpTransaction
> trans(
7124 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7125 TestCompletionCallback callback
;
7126 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7127 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7129 rv
= callback
.WaitForResult();
7131 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7133 ASSERT_TRUE(response
!= NULL
);
7134 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7136 EXPECT_EQ(200, response
->headers
->response_code());
7137 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7139 std::string response_data
;
7140 rv
= ReadTransaction(trans
.get(), &response_data
);
7142 EXPECT_EQ("hello!", response_data
);
7145 session
->CloseAllConnections();
7148 // Test HTTPS connections to a site with a bad certificate, going through an
7150 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7151 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
7153 HttpRequestInfo request
;
7154 request
.method
= "GET";
7155 request
.url
= GURL("https://www.example.org/");
7156 request
.load_flags
= 0;
7158 // Attempt to fetch the URL from a server with a bad cert
7159 MockWrite bad_cert_writes
[] = {
7161 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7162 "Host: www.example.org\r\n"
7163 "Proxy-Connection: keep-alive\r\n\r\n"),
7166 MockRead bad_cert_reads
[] = {
7167 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7168 MockRead(SYNCHRONOUS
, OK
)
7171 // Attempt to fetch the URL with a good cert
7172 MockWrite good_data_writes
[] = {
7174 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7175 "Host: www.example.org\r\n"
7176 "Proxy-Connection: keep-alive\r\n\r\n"),
7178 "GET / HTTP/1.1\r\n"
7179 "Host: www.example.org\r\n"
7180 "Connection: keep-alive\r\n\r\n"),
7183 MockRead good_cert_reads
[] = {
7184 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7185 MockRead("HTTP/1.0 200 OK\r\n"),
7186 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7187 MockRead("Content-Length: 100\r\n\r\n"),
7188 MockRead(SYNCHRONOUS
, OK
),
7191 StaticSocketDataProvider
ssl_bad_certificate(
7192 bad_cert_reads
, arraysize(bad_cert_reads
),
7193 bad_cert_writes
, arraysize(bad_cert_writes
));
7194 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7195 good_data_writes
, arraysize(good_data_writes
));
7196 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7197 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7199 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7200 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7201 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7202 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7204 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7205 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7206 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7207 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7209 TestCompletionCallback callback
;
7211 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7212 scoped_ptr
<HttpTransaction
> trans(
7213 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7215 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7216 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7218 rv
= callback
.WaitForResult();
7219 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7221 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7222 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7224 rv
= callback
.WaitForResult();
7227 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7229 ASSERT_TRUE(response
!= NULL
);
7230 EXPECT_EQ(100, response
->headers
->GetContentLength());
7233 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7234 HttpRequestInfo request
;
7235 request
.method
= "GET";
7236 request
.url
= GURL("http://www.example.org/");
7237 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7238 "Chromium Ultra Awesome X Edition");
7240 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7241 scoped_ptr
<HttpTransaction
> trans(
7242 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7244 MockWrite data_writes
[] = {
7246 "GET / HTTP/1.1\r\n"
7247 "Host: www.example.org\r\n"
7248 "Connection: keep-alive\r\n"
7249 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7252 // Lastly, the server responds with the actual content.
7253 MockRead data_reads
[] = {
7254 MockRead("HTTP/1.0 200 OK\r\n"),
7255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7256 MockRead("Content-Length: 100\r\n\r\n"),
7257 MockRead(SYNCHRONOUS
, OK
),
7260 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7261 data_writes
, arraysize(data_writes
));
7262 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7264 TestCompletionCallback callback
;
7266 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7267 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7269 rv
= callback
.WaitForResult();
7273 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7274 HttpRequestInfo request
;
7275 request
.method
= "GET";
7276 request
.url
= GURL("https://www.example.org/");
7277 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7278 "Chromium Ultra Awesome X Edition");
7280 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
7281 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7282 scoped_ptr
<HttpTransaction
> trans(
7283 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7285 MockWrite data_writes
[] = {
7287 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7288 "Host: www.example.org\r\n"
7289 "Proxy-Connection: keep-alive\r\n"
7290 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7292 MockRead data_reads
[] = {
7293 // Return an error, so the transaction stops here (this test isn't
7294 // interested in the rest).
7295 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7296 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7297 MockRead("Proxy-Connection: close\r\n\r\n"),
7300 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7301 data_writes
, arraysize(data_writes
));
7302 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7304 TestCompletionCallback callback
;
7306 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7307 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7309 rv
= callback
.WaitForResult();
7313 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7314 HttpRequestInfo request
;
7315 request
.method
= "GET";
7316 request
.url
= GURL("http://www.example.org/");
7317 request
.load_flags
= 0;
7318 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7319 "http://the.previous.site.com/");
7321 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7322 scoped_ptr
<HttpTransaction
> trans(
7323 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7325 MockWrite data_writes
[] = {
7327 "GET / HTTP/1.1\r\n"
7328 "Host: www.example.org\r\n"
7329 "Connection: keep-alive\r\n"
7330 "Referer: http://the.previous.site.com/\r\n\r\n"),
7333 // Lastly, the server responds with the actual content.
7334 MockRead data_reads
[] = {
7335 MockRead("HTTP/1.0 200 OK\r\n"),
7336 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7337 MockRead("Content-Length: 100\r\n\r\n"),
7338 MockRead(SYNCHRONOUS
, OK
),
7341 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7342 data_writes
, arraysize(data_writes
));
7343 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7345 TestCompletionCallback callback
;
7347 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7348 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7350 rv
= callback
.WaitForResult();
7354 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7355 HttpRequestInfo request
;
7356 request
.method
= "POST";
7357 request
.url
= GURL("http://www.example.org/");
7359 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7360 scoped_ptr
<HttpTransaction
> trans(
7361 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7363 MockWrite data_writes
[] = {
7365 "POST / HTTP/1.1\r\n"
7366 "Host: www.example.org\r\n"
7367 "Connection: keep-alive\r\n"
7368 "Content-Length: 0\r\n\r\n"),
7371 // Lastly, the server responds with the actual content.
7372 MockRead data_reads
[] = {
7373 MockRead("HTTP/1.0 200 OK\r\n"),
7374 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7375 MockRead("Content-Length: 100\r\n\r\n"),
7376 MockRead(SYNCHRONOUS
, OK
),
7379 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7380 data_writes
, arraysize(data_writes
));
7381 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7383 TestCompletionCallback callback
;
7385 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7386 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7388 rv
= callback
.WaitForResult();
7392 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7393 HttpRequestInfo request
;
7394 request
.method
= "PUT";
7395 request
.url
= GURL("http://www.example.org/");
7397 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7398 scoped_ptr
<HttpTransaction
> trans(
7399 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7401 MockWrite data_writes
[] = {
7403 "PUT / HTTP/1.1\r\n"
7404 "Host: www.example.org\r\n"
7405 "Connection: keep-alive\r\n"
7406 "Content-Length: 0\r\n\r\n"),
7409 // Lastly, the server responds with the actual content.
7410 MockRead data_reads
[] = {
7411 MockRead("HTTP/1.0 200 OK\r\n"),
7412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7413 MockRead("Content-Length: 100\r\n\r\n"),
7414 MockRead(SYNCHRONOUS
, OK
),
7417 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7418 data_writes
, arraysize(data_writes
));
7419 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7421 TestCompletionCallback callback
;
7423 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7424 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7426 rv
= callback
.WaitForResult();
7430 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7431 HttpRequestInfo request
;
7432 request
.method
= "HEAD";
7433 request
.url
= GURL("http://www.example.org/");
7435 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7436 scoped_ptr
<HttpTransaction
> trans(
7437 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7439 MockWrite data_writes
[] = {
7440 MockWrite("HEAD / HTTP/1.1\r\n"
7441 "Host: www.example.org\r\n"
7442 "Connection: keep-alive\r\n\r\n"),
7445 // Lastly, the server responds with the actual content.
7446 MockRead data_reads
[] = {
7447 MockRead("HTTP/1.0 200 OK\r\n"),
7448 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7449 MockRead("Content-Length: 100\r\n\r\n"),
7450 MockRead(SYNCHRONOUS
, OK
),
7453 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7454 data_writes
, arraysize(data_writes
));
7455 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7457 TestCompletionCallback callback
;
7459 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7460 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7462 rv
= callback
.WaitForResult();
7466 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7467 HttpRequestInfo request
;
7468 request
.method
= "GET";
7469 request
.url
= GURL("http://www.example.org/");
7470 request
.load_flags
= LOAD_BYPASS_CACHE
;
7472 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7473 scoped_ptr
<HttpTransaction
> trans(
7474 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7476 MockWrite data_writes
[] = {
7478 "GET / HTTP/1.1\r\n"
7479 "Host: www.example.org\r\n"
7480 "Connection: keep-alive\r\n"
7481 "Pragma: no-cache\r\n"
7482 "Cache-Control: no-cache\r\n\r\n"),
7485 // Lastly, the server responds with the actual content.
7486 MockRead data_reads
[] = {
7487 MockRead("HTTP/1.0 200 OK\r\n"),
7488 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7489 MockRead("Content-Length: 100\r\n\r\n"),
7490 MockRead(SYNCHRONOUS
, OK
),
7493 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7494 data_writes
, arraysize(data_writes
));
7495 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7497 TestCompletionCallback callback
;
7499 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7500 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7502 rv
= callback
.WaitForResult();
7506 TEST_P(HttpNetworkTransactionTest
,
7507 BuildRequest_CacheControlValidateCache
) {
7508 HttpRequestInfo request
;
7509 request
.method
= "GET";
7510 request
.url
= GURL("http://www.example.org/");
7511 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7513 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7514 scoped_ptr
<HttpTransaction
> trans(
7515 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7517 MockWrite data_writes
[] = {
7519 "GET / HTTP/1.1\r\n"
7520 "Host: www.example.org\r\n"
7521 "Connection: keep-alive\r\n"
7522 "Cache-Control: max-age=0\r\n\r\n"),
7525 // Lastly, the server responds with the actual content.
7526 MockRead data_reads
[] = {
7527 MockRead("HTTP/1.0 200 OK\r\n"),
7528 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7529 MockRead("Content-Length: 100\r\n\r\n"),
7530 MockRead(SYNCHRONOUS
, OK
),
7533 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7534 data_writes
, arraysize(data_writes
));
7535 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7537 TestCompletionCallback callback
;
7539 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7540 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7542 rv
= callback
.WaitForResult();
7546 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7547 HttpRequestInfo request
;
7548 request
.method
= "GET";
7549 request
.url
= GURL("http://www.example.org/");
7550 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7552 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7553 scoped_ptr
<HttpTransaction
> trans(
7554 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7556 MockWrite data_writes
[] = {
7558 "GET / HTTP/1.1\r\n"
7559 "Host: www.example.org\r\n"
7560 "Connection: keep-alive\r\n"
7561 "FooHeader: Bar\r\n\r\n"),
7564 // Lastly, the server responds with the actual content.
7565 MockRead data_reads
[] = {
7566 MockRead("HTTP/1.0 200 OK\r\n"),
7567 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7568 MockRead("Content-Length: 100\r\n\r\n"),
7569 MockRead(SYNCHRONOUS
, OK
),
7572 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7573 data_writes
, arraysize(data_writes
));
7574 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7576 TestCompletionCallback callback
;
7578 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7579 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7581 rv
= callback
.WaitForResult();
7585 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7586 HttpRequestInfo request
;
7587 request
.method
= "GET";
7588 request
.url
= GURL("http://www.example.org/");
7589 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7590 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7591 request
.extra_headers
.SetHeader("FoO", "bar");
7593 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7594 scoped_ptr
<HttpTransaction
> trans(
7595 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7597 MockWrite data_writes
[] = {
7599 "GET / HTTP/1.1\r\n"
7600 "Host: www.example.org\r\n"
7601 "Connection: keep-alive\r\n"
7602 "referer: www.foo.com\r\n"
7604 "FoO: bar\r\n\r\n"),
7607 // Lastly, the server responds with the actual content.
7608 MockRead data_reads
[] = {
7609 MockRead("HTTP/1.0 200 OK\r\n"),
7610 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7611 MockRead("Content-Length: 100\r\n\r\n"),
7612 MockRead(SYNCHRONOUS
, OK
),
7615 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7616 data_writes
, arraysize(data_writes
));
7617 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7619 TestCompletionCallback callback
;
7621 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7622 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7624 rv
= callback
.WaitForResult();
7628 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7629 HttpRequestInfo request
;
7630 request
.method
= "GET";
7631 request
.url
= GURL("http://www.example.org/");
7632 request
.load_flags
= 0;
7634 session_deps_
.proxy_service
=
7635 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
7637 session_deps_
.net_log
= &net_log
;
7639 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7640 scoped_ptr
<HttpTransaction
> trans(
7641 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7643 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7644 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7646 MockWrite data_writes
[] = {
7647 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7649 "GET / HTTP/1.1\r\n"
7650 "Host: www.example.org\r\n"
7651 "Connection: keep-alive\r\n\r\n")};
7653 MockRead data_reads
[] = {
7654 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7655 MockRead("HTTP/1.0 200 OK\r\n"),
7656 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7657 MockRead("Payload"),
7658 MockRead(SYNCHRONOUS
, OK
)
7661 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7662 data_writes
, arraysize(data_writes
));
7663 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7665 TestCompletionCallback callback
;
7667 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7668 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7670 rv
= callback
.WaitForResult();
7673 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7674 ASSERT_TRUE(response
!= NULL
);
7676 LoadTimingInfo load_timing_info
;
7677 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7678 TestLoadTimingNotReusedWithPac(load_timing_info
,
7679 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7681 std::string response_text
;
7682 rv
= ReadTransaction(trans
.get(), &response_text
);
7684 EXPECT_EQ("Payload", response_text
);
7687 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7688 HttpRequestInfo request
;
7689 request
.method
= "GET";
7690 request
.url
= GURL("https://www.example.org/");
7691 request
.load_flags
= 0;
7693 session_deps_
.proxy_service
=
7694 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
7696 session_deps_
.net_log
= &net_log
;
7698 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7699 scoped_ptr
<HttpTransaction
> trans(
7700 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7702 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7703 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7705 MockWrite data_writes
[] = {
7706 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7707 arraysize(write_buffer
)),
7709 "GET / HTTP/1.1\r\n"
7710 "Host: www.example.org\r\n"
7711 "Connection: keep-alive\r\n\r\n")};
7713 MockRead data_reads
[] = {
7714 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7715 arraysize(read_buffer
)),
7716 MockRead("HTTP/1.0 200 OK\r\n"),
7717 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7718 MockRead("Payload"),
7719 MockRead(SYNCHRONOUS
, OK
)
7722 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7723 data_writes
, arraysize(data_writes
));
7724 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7726 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7727 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7729 TestCompletionCallback callback
;
7731 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7732 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7734 rv
= callback
.WaitForResult();
7737 LoadTimingInfo load_timing_info
;
7738 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7739 TestLoadTimingNotReusedWithPac(load_timing_info
,
7740 CONNECT_TIMING_HAS_SSL_TIMES
);
7742 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7743 ASSERT_TRUE(response
!= NULL
);
7745 std::string response_text
;
7746 rv
= ReadTransaction(trans
.get(), &response_text
);
7748 EXPECT_EQ("Payload", response_text
);
7751 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7752 HttpRequestInfo request
;
7753 request
.method
= "GET";
7754 request
.url
= GURL("http://www.example.org/");
7755 request
.load_flags
= 0;
7757 session_deps_
.proxy_service
=
7758 ProxyService::CreateFixed("socks4://myproxy:1080");
7760 session_deps_
.net_log
= &net_log
;
7762 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7763 scoped_ptr
<HttpTransaction
> trans(
7764 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7766 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7767 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7769 MockWrite data_writes
[] = {
7770 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7772 "GET / HTTP/1.1\r\n"
7773 "Host: www.example.org\r\n"
7774 "Connection: keep-alive\r\n\r\n")};
7776 MockRead data_reads
[] = {
7777 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7778 MockRead("HTTP/1.0 200 OK\r\n"),
7779 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7780 MockRead("Payload"),
7781 MockRead(SYNCHRONOUS
, OK
)
7784 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7785 data_writes
, arraysize(data_writes
));
7786 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7788 TestCompletionCallback callback
;
7790 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7791 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7793 rv
= callback
.WaitForResult();
7796 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7797 ASSERT_TRUE(response
!= NULL
);
7799 LoadTimingInfo load_timing_info
;
7800 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7801 TestLoadTimingNotReused(load_timing_info
,
7802 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7804 std::string response_text
;
7805 rv
= ReadTransaction(trans
.get(), &response_text
);
7807 EXPECT_EQ("Payload", response_text
);
7810 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7811 HttpRequestInfo request
;
7812 request
.method
= "GET";
7813 request
.url
= GURL("http://www.example.org/");
7814 request
.load_flags
= 0;
7816 session_deps_
.proxy_service
=
7817 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
7819 session_deps_
.net_log
= &net_log
;
7821 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7822 scoped_ptr
<HttpTransaction
> trans(
7823 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7825 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7826 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7827 const char kSOCKS5OkRequest
[] = {
7829 0x01, // Command (CONNECT)
7831 0x03, // Address type (DOMAINNAME).
7832 0x0F, // Length of domain (15)
7833 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7834 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7836 const char kSOCKS5OkResponse
[] =
7837 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7839 MockWrite data_writes
[] = {
7840 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7841 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7843 "GET / HTTP/1.1\r\n"
7844 "Host: www.example.org\r\n"
7845 "Connection: keep-alive\r\n\r\n")};
7847 MockRead data_reads
[] = {
7848 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7849 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7850 MockRead("HTTP/1.0 200 OK\r\n"),
7851 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7852 MockRead("Payload"),
7853 MockRead(SYNCHRONOUS
, OK
)
7856 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7857 data_writes
, arraysize(data_writes
));
7858 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7860 TestCompletionCallback callback
;
7862 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7863 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7865 rv
= callback
.WaitForResult();
7868 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7869 ASSERT_TRUE(response
!= NULL
);
7871 LoadTimingInfo load_timing_info
;
7872 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7873 TestLoadTimingNotReusedWithPac(load_timing_info
,
7874 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7876 std::string response_text
;
7877 rv
= ReadTransaction(trans
.get(), &response_text
);
7879 EXPECT_EQ("Payload", response_text
);
7882 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7883 HttpRequestInfo request
;
7884 request
.method
= "GET";
7885 request
.url
= GURL("https://www.example.org/");
7886 request
.load_flags
= 0;
7888 session_deps_
.proxy_service
=
7889 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
7891 session_deps_
.net_log
= &net_log
;
7893 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7894 scoped_ptr
<HttpTransaction
> trans(
7895 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7897 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7898 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7899 const unsigned char kSOCKS5OkRequest
[] = {
7901 0x01, // Command (CONNECT)
7903 0x03, // Address type (DOMAINNAME).
7904 0x0F, // Length of domain (15)
7905 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7906 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7909 const char kSOCKS5OkResponse
[] =
7910 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7912 MockWrite data_writes
[] = {
7913 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7914 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7915 arraysize(kSOCKS5OkRequest
)),
7917 "GET / HTTP/1.1\r\n"
7918 "Host: www.example.org\r\n"
7919 "Connection: keep-alive\r\n\r\n")};
7921 MockRead data_reads
[] = {
7922 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7923 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7924 MockRead("HTTP/1.0 200 OK\r\n"),
7925 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7926 MockRead("Payload"),
7927 MockRead(SYNCHRONOUS
, OK
)
7930 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7931 data_writes
, arraysize(data_writes
));
7932 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7934 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7935 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7937 TestCompletionCallback callback
;
7939 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7940 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7942 rv
= callback
.WaitForResult();
7945 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7946 ASSERT_TRUE(response
!= NULL
);
7948 LoadTimingInfo load_timing_info
;
7949 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7950 TestLoadTimingNotReusedWithPac(load_timing_info
,
7951 CONNECT_TIMING_HAS_SSL_TIMES
);
7953 std::string response_text
;
7954 rv
= ReadTransaction(trans
.get(), &response_text
);
7956 EXPECT_EQ("Payload", response_text
);
7961 // Tests that for connection endpoints the group names are correctly set.
7963 struct GroupNameTest
{
7964 std::string proxy_server
;
7966 std::string expected_group_name
;
7970 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7971 NextProto next_proto
,
7972 SpdySessionDependencies
* session_deps_
) {
7973 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7975 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7976 session
->http_server_properties();
7977 AlternativeService
alternative_service(
7978 AlternateProtocolFromNextProto(next_proto
), "", 443);
7979 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
7980 http_server_properties
->SetAlternativeService(
7981 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0,
7987 int GroupNameTransactionHelper(
7988 const std::string
& url
,
7989 const scoped_refptr
<HttpNetworkSession
>& session
) {
7990 HttpRequestInfo request
;
7991 request
.method
= "GET";
7992 request
.url
= GURL(url
);
7993 request
.load_flags
= 0;
7995 scoped_ptr
<HttpTransaction
> trans(
7996 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7998 TestCompletionCallback callback
;
8000 // We do not complete this request, the dtor will clean the transaction up.
8001 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
8006 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
8007 const GroupNameTest tests
[] = {
8010 "http://www.example.org/direct",
8011 "www.example.org:80",
8016 "http://[2001:1418:13:1::25]/direct",
8017 "[2001:1418:13:1::25]:80",
8024 "https://www.example.org/direct_ssl",
8025 "ssl/www.example.org:443",
8030 "https://[2001:1418:13:1::25]/direct",
8031 "ssl/[2001:1418:13:1::25]:443",
8036 "http://host.with.alternate/direct",
8037 "ssl/host.with.alternate:443",
8042 session_deps_
.use_alternative_services
= true;
8044 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8045 session_deps_
.proxy_service
=
8046 ProxyService::CreateFixed(tests
[i
].proxy_server
);
8047 scoped_refptr
<HttpNetworkSession
> session(
8048 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8050 HttpNetworkSessionPeer
peer(session
);
8051 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
8052 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
8053 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8054 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8055 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8056 new MockClientSocketPoolManager
);
8057 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
8058 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
8059 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8061 EXPECT_EQ(ERR_IO_PENDING
,
8062 GroupNameTransactionHelper(tests
[i
].url
, session
));
8064 EXPECT_EQ(tests
[i
].expected_group_name
,
8065 ssl_conn_pool
->last_group_name_received());
8067 EXPECT_EQ(tests
[i
].expected_group_name
,
8068 transport_conn_pool
->last_group_name_received());
8072 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
8073 const GroupNameTest tests
[] = {
8076 "http://www.example.org/http_proxy_normal",
8077 "www.example.org:80",
8084 "https://www.example.org/http_connect_ssl",
8085 "ssl/www.example.org:443",
8091 "http://host.with.alternate/direct",
8092 "ssl/host.with.alternate:443",
8098 "ftp://ftp.google.com/http_proxy_normal",
8099 "ftp/ftp.google.com:21",
8104 session_deps_
.use_alternative_services
= true;
8106 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8107 session_deps_
.proxy_service
=
8108 ProxyService::CreateFixed(tests
[i
].proxy_server
);
8109 scoped_refptr
<HttpNetworkSession
> session(
8110 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8112 HttpNetworkSessionPeer
peer(session
);
8114 HostPortPair
proxy_host("http_proxy", 80);
8115 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8116 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8117 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8118 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8120 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8121 new MockClientSocketPoolManager
);
8122 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8123 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8124 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8126 EXPECT_EQ(ERR_IO_PENDING
,
8127 GroupNameTransactionHelper(tests
[i
].url
, session
));
8129 EXPECT_EQ(tests
[i
].expected_group_name
,
8130 ssl_conn_pool
->last_group_name_received());
8132 EXPECT_EQ(tests
[i
].expected_group_name
,
8133 http_proxy_pool
->last_group_name_received());
8137 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8138 const GroupNameTest tests
[] = {
8140 "socks4://socks_proxy:1080",
8141 "http://www.example.org/socks4_direct",
8142 "socks4/www.example.org:80",
8146 "socks5://socks_proxy:1080",
8147 "http://www.example.org/socks5_direct",
8148 "socks5/www.example.org:80",
8154 "socks4://socks_proxy:1080",
8155 "https://www.example.org/socks4_ssl",
8156 "socks4/ssl/www.example.org:443",
8160 "socks5://socks_proxy:1080",
8161 "https://www.example.org/socks5_ssl",
8162 "socks5/ssl/www.example.org:443",
8167 "socks4://socks_proxy:1080",
8168 "http://host.with.alternate/direct",
8169 "socks4/ssl/host.with.alternate:443",
8174 session_deps_
.use_alternative_services
= true;
8176 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8177 session_deps_
.proxy_service
=
8178 ProxyService::CreateFixed(tests
[i
].proxy_server
);
8179 scoped_refptr
<HttpNetworkSession
> session(
8180 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8182 HttpNetworkSessionPeer
peer(session
);
8184 HostPortPair
proxy_host("socks_proxy", 1080);
8185 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8186 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8187 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8188 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8190 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8191 new MockClientSocketPoolManager
);
8192 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8193 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8194 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8196 scoped_ptr
<HttpTransaction
> trans(
8197 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8199 EXPECT_EQ(ERR_IO_PENDING
,
8200 GroupNameTransactionHelper(tests
[i
].url
, session
));
8202 EXPECT_EQ(tests
[i
].expected_group_name
,
8203 ssl_conn_pool
->last_group_name_received());
8205 EXPECT_EQ(tests
[i
].expected_group_name
,
8206 socks_conn_pool
->last_group_name_received());
8210 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8211 HttpRequestInfo request
;
8212 request
.method
= "GET";
8213 request
.url
= GURL("http://www.example.org/");
8215 session_deps_
.proxy_service
=
8216 ProxyService::CreateFixed("myproxy:70;foobar:80");
8218 // This simulates failure resolving all hostnames; that means we will fail
8219 // connecting to both proxies (myproxy:70 and foobar:80).
8220 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8222 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8223 scoped_ptr
<HttpTransaction
> trans(
8224 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8226 TestCompletionCallback callback
;
8228 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8229 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8231 rv
= callback
.WaitForResult();
8232 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8235 // Base test to make sure that when the load flags for a request specify to
8236 // bypass the cache, the DNS cache is not used.
8237 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8239 // Issue a request, asking to bypass the cache(s).
8240 HttpRequestInfo request
;
8241 request
.method
= "GET";
8242 request
.load_flags
= load_flags
;
8243 request
.url
= GURL("http://www.example.org/");
8245 // Select a host resolver that does caching.
8246 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8248 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8249 scoped_ptr
<HttpTransaction
> trans(
8250 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8252 // Warm up the host cache so it has an entry for "www.example.org".
8253 AddressList addrlist
;
8254 TestCompletionCallback callback
;
8255 int rv
= session_deps_
.host_resolver
->Resolve(
8256 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8257 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8258 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8259 rv
= callback
.WaitForResult();
8262 // Verify that it was added to host cache, by doing a subsequent async lookup
8263 // and confirming it completes synchronously.
8264 rv
= session_deps_
.host_resolver
->Resolve(
8265 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8266 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8269 // Inject a failure the next time that "www.example.org" is resolved. This way
8270 // we can tell if the next lookup hit the cache, or the "network".
8271 // (cache --> success, "network" --> failure).
8272 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8274 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8275 // first read -- this won't be reached as the host resolution will fail first.
8276 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8277 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8278 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8281 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8282 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8283 rv
= callback
.WaitForResult();
8285 // If we bypassed the cache, we would have gotten a failure while resolving
8286 // "www.example.org".
8287 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8290 // There are multiple load flags that should trigger the host cache bypass.
8291 // Test each in isolation:
8292 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8293 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8296 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8297 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8300 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8301 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8304 // Make sure we can handle an error when writing the request.
8305 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8306 HttpRequestInfo request
;
8307 request
.method
= "GET";
8308 request
.url
= GURL("http://www.foo.com/");
8309 request
.load_flags
= 0;
8311 MockWrite write_failure
[] = {
8312 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8314 StaticSocketDataProvider
data(NULL
, 0,
8315 write_failure
, arraysize(write_failure
));
8316 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8317 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8319 TestCompletionCallback callback
;
8321 scoped_ptr
<HttpTransaction
> trans(
8322 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8324 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8325 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8327 rv
= callback
.WaitForResult();
8328 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8331 // Check that a connection closed after the start of the headers finishes ok.
8332 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8333 HttpRequestInfo request
;
8334 request
.method
= "GET";
8335 request
.url
= GURL("http://www.foo.com/");
8336 request
.load_flags
= 0;
8338 MockRead data_reads
[] = {
8339 MockRead("HTTP/1."),
8340 MockRead(SYNCHRONOUS
, OK
),
8343 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8344 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8345 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8347 TestCompletionCallback callback
;
8349 scoped_ptr
<HttpTransaction
> trans(
8350 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8352 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8353 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8355 rv
= callback
.WaitForResult();
8358 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8359 ASSERT_TRUE(response
!= NULL
);
8361 EXPECT_TRUE(response
->headers
.get() != NULL
);
8362 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8364 std::string response_data
;
8365 rv
= ReadTransaction(trans
.get(), &response_data
);
8367 EXPECT_EQ("", response_data
);
8370 // Make sure that a dropped connection while draining the body for auth
8371 // restart does the right thing.
8372 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8373 HttpRequestInfo request
;
8374 request
.method
= "GET";
8375 request
.url
= GURL("http://www.example.org/");
8376 request
.load_flags
= 0;
8378 MockWrite data_writes1
[] = {
8380 "GET / HTTP/1.1\r\n"
8381 "Host: www.example.org\r\n"
8382 "Connection: keep-alive\r\n\r\n"),
8385 MockRead data_reads1
[] = {
8386 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8387 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8389 MockRead("Content-Length: 14\r\n\r\n"),
8391 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8394 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8395 data_writes1
, arraysize(data_writes1
));
8396 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8398 // After calling trans->RestartWithAuth(), this is the request we should
8399 // be issuing -- the final header line contains the credentials.
8400 MockWrite data_writes2
[] = {
8402 "GET / HTTP/1.1\r\n"
8403 "Host: www.example.org\r\n"
8404 "Connection: keep-alive\r\n"
8405 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8408 // Lastly, the server responds with the actual content.
8409 MockRead data_reads2
[] = {
8410 MockRead("HTTP/1.1 200 OK\r\n"),
8411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8412 MockRead("Content-Length: 100\r\n\r\n"),
8413 MockRead(SYNCHRONOUS
, OK
),
8416 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8417 data_writes2
, arraysize(data_writes2
));
8418 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8419 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8421 TestCompletionCallback callback1
;
8423 scoped_ptr
<HttpTransaction
> trans(
8424 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8426 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8427 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8429 rv
= callback1
.WaitForResult();
8432 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8433 ASSERT_TRUE(response
!= NULL
);
8434 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8436 TestCompletionCallback callback2
;
8438 rv
= trans
->RestartWithAuth(
8439 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8440 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8442 rv
= callback2
.WaitForResult();
8445 response
= trans
->GetResponseInfo();
8446 ASSERT_TRUE(response
!= NULL
);
8447 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8448 EXPECT_EQ(100, response
->headers
->GetContentLength());
8451 // Test HTTPS connections going through a proxy that sends extra data.
8452 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8453 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
8455 HttpRequestInfo request
;
8456 request
.method
= "GET";
8457 request
.url
= GURL("https://www.example.org/");
8458 request
.load_flags
= 0;
8460 MockRead proxy_reads
[] = {
8461 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8462 MockRead(SYNCHRONOUS
, OK
)
8465 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8466 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8468 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8469 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8471 TestCompletionCallback callback
;
8473 session_deps_
.socket_factory
->ResetNextMockIndexes();
8475 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8476 scoped_ptr
<HttpTransaction
> trans(
8477 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8479 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8480 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8482 rv
= callback
.WaitForResult();
8483 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8486 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8487 HttpRequestInfo request
;
8488 request
.method
= "GET";
8489 request
.url
= GURL("http://www.example.org/");
8490 request
.load_flags
= 0;
8492 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8493 scoped_ptr
<HttpTransaction
> trans(
8494 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8496 MockRead data_reads
[] = {
8497 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8498 MockRead(SYNCHRONOUS
, OK
),
8501 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8502 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8504 TestCompletionCallback callback
;
8506 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8507 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8509 EXPECT_EQ(OK
, callback
.WaitForResult());
8511 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8512 ASSERT_TRUE(response
!= NULL
);
8514 EXPECT_TRUE(response
->headers
.get() != NULL
);
8515 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8517 std::string response_data
;
8518 rv
= ReadTransaction(trans
.get(), &response_data
);
8519 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8522 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8523 base::FilePath temp_file_path
;
8524 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8525 const uint64 kFakeSize
= 100000; // file is actually blank
8526 UploadFileElementReader::ScopedOverridingContentLengthForTests
8527 overriding_content_length(kFakeSize
);
8529 ScopedVector
<UploadElementReader
> element_readers
;
8530 element_readers
.push_back(
8531 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8532 temp_file_path
, 0, kuint64max
, base::Time()));
8533 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8535 HttpRequestInfo request
;
8536 request
.method
= "POST";
8537 request
.url
= GURL("http://www.example.org/upload");
8538 request
.upload_data_stream
= &upload_data_stream
;
8539 request
.load_flags
= 0;
8541 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8542 scoped_ptr
<HttpTransaction
> trans(
8543 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8545 MockRead data_reads
[] = {
8546 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8547 MockRead("hello world"),
8548 MockRead(SYNCHRONOUS
, OK
),
8550 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8551 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8553 TestCompletionCallback callback
;
8555 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8556 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8558 rv
= callback
.WaitForResult();
8561 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8562 ASSERT_TRUE(response
!= NULL
);
8564 EXPECT_TRUE(response
->headers
.get() != NULL
);
8565 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8567 std::string response_data
;
8568 rv
= ReadTransaction(trans
.get(), &response_data
);
8570 EXPECT_EQ("hello world", response_data
);
8572 base::DeleteFile(temp_file_path
, false);
8575 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8576 base::FilePath temp_file
;
8577 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8578 std::string
temp_file_content("Unreadable file.");
8579 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8580 temp_file_content
.length()));
8581 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8583 ScopedVector
<UploadElementReader
> element_readers
;
8584 element_readers
.push_back(
8585 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8586 temp_file
, 0, kuint64max
, base::Time()));
8587 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8589 HttpRequestInfo request
;
8590 request
.method
= "POST";
8591 request
.url
= GURL("http://www.example.org/upload");
8592 request
.upload_data_stream
= &upload_data_stream
;
8593 request
.load_flags
= 0;
8595 // If we try to upload an unreadable file, the transaction should fail.
8596 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8597 scoped_ptr
<HttpTransaction
> trans(
8598 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8600 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8601 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8603 TestCompletionCallback callback
;
8605 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8606 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8608 rv
= callback
.WaitForResult();
8609 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8611 base::DeleteFile(temp_file
, false);
8614 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8615 class FakeUploadElementReader
: public UploadElementReader
{
8617 FakeUploadElementReader() {}
8618 ~FakeUploadElementReader() override
{}
8620 const CompletionCallback
& callback() const { return callback_
; }
8622 // UploadElementReader overrides:
8623 int Init(const CompletionCallback
& callback
) override
{
8624 callback_
= callback
;
8625 return ERR_IO_PENDING
;
8627 uint64
GetContentLength() const override
{ return 0; }
8628 uint64
BytesRemaining() const override
{ return 0; }
8629 int Read(IOBuffer
* buf
,
8631 const CompletionCallback
& callback
) override
{
8636 CompletionCallback callback_
;
8639 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8640 ScopedVector
<UploadElementReader
> element_readers
;
8641 element_readers
.push_back(fake_reader
);
8642 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8644 HttpRequestInfo request
;
8645 request
.method
= "POST";
8646 request
.url
= GURL("http://www.example.org/upload");
8647 request
.upload_data_stream
= &upload_data_stream
;
8648 request
.load_flags
= 0;
8650 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8651 scoped_ptr
<HttpTransaction
> trans(
8652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8654 StaticSocketDataProvider data
;
8655 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8657 TestCompletionCallback callback
;
8658 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8659 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8660 base::MessageLoop::current()->RunUntilIdle();
8662 // Transaction is pending on request body initialization.
8663 ASSERT_FALSE(fake_reader
->callback().is_null());
8665 // Return Init()'s result after the transaction gets destroyed.
8667 fake_reader
->callback().Run(OK
); // Should not crash.
8670 // Tests that changes to Auth realms are treated like auth rejections.
8671 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8672 HttpRequestInfo request
;
8673 request
.method
= "GET";
8674 request
.url
= GURL("http://www.example.org/");
8675 request
.load_flags
= 0;
8677 // First transaction will request a resource and receive a Basic challenge
8678 // with realm="first_realm".
8679 MockWrite data_writes1
[] = {
8681 "GET / HTTP/1.1\r\n"
8682 "Host: www.example.org\r\n"
8683 "Connection: keep-alive\r\n"
8686 MockRead data_reads1
[] = {
8687 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8688 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8692 // After calling trans->RestartWithAuth(), provide an Authentication header
8693 // for first_realm. The server will reject and provide a challenge with
8695 MockWrite data_writes2
[] = {
8697 "GET / HTTP/1.1\r\n"
8698 "Host: www.example.org\r\n"
8699 "Connection: keep-alive\r\n"
8700 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8703 MockRead data_reads2
[] = {
8704 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8705 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8709 // This again fails, and goes back to first_realm. Make sure that the
8710 // entry is removed from cache.
8711 MockWrite data_writes3
[] = {
8713 "GET / HTTP/1.1\r\n"
8714 "Host: www.example.org\r\n"
8715 "Connection: keep-alive\r\n"
8716 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8719 MockRead data_reads3
[] = {
8720 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8721 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8725 // Try one last time (with the correct password) and get the resource.
8726 MockWrite data_writes4
[] = {
8728 "GET / HTTP/1.1\r\n"
8729 "Host: www.example.org\r\n"
8730 "Connection: keep-alive\r\n"
8731 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8734 MockRead data_reads4
[] = {
8735 MockRead("HTTP/1.1 200 OK\r\n"
8736 "Content-Type: text/html; charset=iso-8859-1\r\n"
8737 "Content-Length: 5\r\n"
8742 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8743 data_writes1
, arraysize(data_writes1
));
8744 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8745 data_writes2
, arraysize(data_writes2
));
8746 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8747 data_writes3
, arraysize(data_writes3
));
8748 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8749 data_writes4
, arraysize(data_writes4
));
8750 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8751 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8752 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8753 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8755 TestCompletionCallback callback1
;
8757 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8758 scoped_ptr
<HttpTransaction
> trans(
8759 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8761 // Issue the first request with Authorize headers. There should be a
8762 // password prompt for first_realm waiting to be filled in after the
8763 // transaction completes.
8764 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8765 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8766 rv
= callback1
.WaitForResult();
8768 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8769 ASSERT_TRUE(response
!= NULL
);
8770 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8771 ASSERT_FALSE(challenge
== NULL
);
8772 EXPECT_FALSE(challenge
->is_proxy
);
8773 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8774 EXPECT_EQ("first_realm", challenge
->realm
);
8775 EXPECT_EQ("basic", challenge
->scheme
);
8777 // Issue the second request with an incorrect password. There should be a
8778 // password prompt for second_realm waiting to be filled in after the
8779 // transaction completes.
8780 TestCompletionCallback callback2
;
8781 rv
= trans
->RestartWithAuth(
8782 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8783 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8784 rv
= callback2
.WaitForResult();
8786 response
= trans
->GetResponseInfo();
8787 ASSERT_TRUE(response
!= NULL
);
8788 challenge
= response
->auth_challenge
.get();
8789 ASSERT_FALSE(challenge
== NULL
);
8790 EXPECT_FALSE(challenge
->is_proxy
);
8791 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8792 EXPECT_EQ("second_realm", challenge
->realm
);
8793 EXPECT_EQ("basic", challenge
->scheme
);
8795 // Issue the third request with another incorrect password. There should be
8796 // a password prompt for first_realm waiting to be filled in. If the password
8797 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8798 // first_realm was not correctly removed.
8799 TestCompletionCallback callback3
;
8800 rv
= trans
->RestartWithAuth(
8801 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8802 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8803 rv
= callback3
.WaitForResult();
8805 response
= trans
->GetResponseInfo();
8806 ASSERT_TRUE(response
!= NULL
);
8807 challenge
= response
->auth_challenge
.get();
8808 ASSERT_FALSE(challenge
== NULL
);
8809 EXPECT_FALSE(challenge
->is_proxy
);
8810 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8811 EXPECT_EQ("first_realm", challenge
->realm
);
8812 EXPECT_EQ("basic", challenge
->scheme
);
8814 // Issue the fourth request with the correct password and username.
8815 TestCompletionCallback callback4
;
8816 rv
= trans
->RestartWithAuth(
8817 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8818 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8819 rv
= callback4
.WaitForResult();
8821 response
= trans
->GetResponseInfo();
8822 ASSERT_TRUE(response
!= NULL
);
8823 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8826 TEST_P(HttpNetworkTransactionTest
, HonorAlternativeServiceHeader
) {
8827 session_deps_
.next_protos
= SpdyNextProtos();
8828 session_deps_
.use_alternative_services
= true;
8830 std::string alternative_service_http_header
=
8831 GetAlternativeServiceHttpHeader();
8833 MockRead data_reads
[] = {
8834 MockRead("HTTP/1.1 200 OK\r\n"),
8835 MockRead(alternative_service_http_header
.c_str()),
8837 MockRead("hello world"),
8838 MockRead(SYNCHRONOUS
, OK
),
8841 HttpRequestInfo request
;
8842 request
.method
= "GET";
8843 request
.url
= GURL("http://www.example.org/");
8844 request
.load_flags
= 0;
8846 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8848 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8850 TestCompletionCallback callback
;
8852 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8853 scoped_ptr
<HttpTransaction
> trans(
8854 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8856 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8857 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8859 HostPortPair
http_host_port_pair("www.example.org", 80);
8860 HttpServerProperties
& http_server_properties
=
8861 *session
->http_server_properties();
8862 AlternativeServiceVector alternative_service_vector
=
8863 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8864 EXPECT_TRUE(alternative_service_vector
.empty());
8866 EXPECT_EQ(OK
, callback
.WaitForResult());
8868 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8869 ASSERT_TRUE(response
!= NULL
);
8870 ASSERT_TRUE(response
->headers
.get() != NULL
);
8871 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8872 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8873 EXPECT_FALSE(response
->was_npn_negotiated
);
8875 std::string response_data
;
8876 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8877 EXPECT_EQ("hello world", response_data
);
8879 alternative_service_vector
=
8880 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8881 ASSERT_EQ(1u, alternative_service_vector
.size());
8882 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8883 alternative_service_vector
[0].protocol
);
8884 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
8885 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8888 // Alternative Service headers must be ignored when |use_alternative_services|
8890 TEST_P(HttpNetworkTransactionTest
, DoNotHonorAlternativeServiceHeader
) {
8891 session_deps_
.next_protos
= SpdyNextProtos();
8892 session_deps_
.use_alternative_services
= false;
8894 std::string alternative_service_http_header
=
8895 GetAlternativeServiceHttpHeader();
8897 MockRead data_reads
[] = {
8898 MockRead("HTTP/1.1 200 OK\r\n"),
8899 MockRead(alternative_service_http_header
.c_str()),
8901 MockRead("hello world"),
8902 MockRead(SYNCHRONOUS
, OK
),
8905 HttpRequestInfo request
;
8906 request
.method
= "GET";
8907 request
.url
= GURL("http://www.example.org/");
8908 request
.load_flags
= 0;
8910 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), nullptr, 0);
8912 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8914 TestCompletionCallback callback
;
8916 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8917 scoped_ptr
<HttpTransaction
> trans(
8918 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8920 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8923 HostPortPair
http_host_port_pair("www.example.org", 80);
8924 HttpServerProperties
& http_server_properties
=
8925 *session
->http_server_properties();
8926 AlternativeServiceVector alternative_service_vector
=
8927 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8928 EXPECT_TRUE(alternative_service_vector
.empty());
8930 EXPECT_EQ(OK
, callback
.WaitForResult());
8932 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8933 ASSERT_TRUE(response
!= nullptr);
8934 ASSERT_TRUE(response
->headers
.get() != nullptr);
8935 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8936 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8937 EXPECT_FALSE(response
->was_npn_negotiated
);
8939 std::string response_data
;
8940 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8941 EXPECT_EQ("hello world", response_data
);
8943 alternative_service_vector
=
8944 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8945 EXPECT_TRUE(alternative_service_vector
.empty());
8948 TEST_P(HttpNetworkTransactionTest
, HonorMultipleAlternativeServiceHeader
) {
8949 session_deps_
.next_protos
= SpdyNextProtos();
8950 session_deps_
.use_alternative_services
= true;
8952 MockRead data_reads
[] = {
8953 MockRead("HTTP/1.1 200 OK\r\n"),
8954 MockRead("Alt-Svc: "),
8955 MockRead(GetAlternateProtocolFromParam()),
8956 MockRead("=\"www.example.com:443\";p=1.0,"),
8957 MockRead("quic=\":1234\"\r\n\r\n"),
8958 MockRead("hello world"),
8959 MockRead(SYNCHRONOUS
, OK
),
8962 HttpRequestInfo request
;
8963 request
.method
= "GET";
8964 request
.url
= GURL("http://www.example.org/");
8965 request
.load_flags
= 0;
8967 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8969 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8971 TestCompletionCallback callback
;
8973 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8974 scoped_ptr
<HttpTransaction
> trans(
8975 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8977 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8978 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8980 HostPortPair
http_host_port_pair("www.example.org", 80);
8981 HttpServerProperties
& http_server_properties
=
8982 *session
->http_server_properties();
8983 AlternativeServiceVector alternative_service_vector
=
8984 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8985 EXPECT_TRUE(alternative_service_vector
.empty());
8987 EXPECT_EQ(OK
, callback
.WaitForResult());
8989 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8990 ASSERT_TRUE(response
!= NULL
);
8991 ASSERT_TRUE(response
->headers
.get() != NULL
);
8992 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8993 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8994 EXPECT_FALSE(response
->was_npn_negotiated
);
8996 std::string response_data
;
8997 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8998 EXPECT_EQ("hello world", response_data
);
9000 alternative_service_vector
=
9001 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9002 ASSERT_EQ(2u, alternative_service_vector
.size());
9003 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9004 alternative_service_vector
[0].protocol
);
9005 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
9006 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9007 EXPECT_EQ(QUIC
, alternative_service_vector
[1].protocol
);
9008 EXPECT_EQ("www.example.org", alternative_service_vector
[1].host
);
9009 EXPECT_EQ(1234, alternative_service_vector
[1].port
);
9012 // Alternate Protocol headers must be honored even if |use_alternative_services|
9014 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
9015 session_deps_
.next_protos
= SpdyNextProtos();
9016 session_deps_
.use_alternative_services
= false;
9018 std::string alternate_protocol_http_header
=
9019 GetAlternateProtocolHttpHeader();
9021 MockRead data_reads
[] = {
9022 MockRead("HTTP/1.1 200 OK\r\n"),
9023 MockRead(alternate_protocol_http_header
.c_str()),
9025 MockRead("hello world"),
9026 MockRead(SYNCHRONOUS
, OK
),
9029 HttpRequestInfo request
;
9030 request
.method
= "GET";
9031 request
.url
= GURL("http://www.example.org/");
9032 request
.load_flags
= 0;
9034 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9036 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9038 TestCompletionCallback callback
;
9040 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9041 scoped_ptr
<HttpTransaction
> trans(
9042 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9044 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9047 HostPortPair
http_host_port_pair("www.example.org", 80);
9048 HttpServerProperties
& http_server_properties
=
9049 *session
->http_server_properties();
9050 AlternativeServiceVector alternative_service_vector
=
9051 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9052 EXPECT_TRUE(alternative_service_vector
.empty());
9054 EXPECT_EQ(OK
, callback
.WaitForResult());
9056 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9057 ASSERT_TRUE(response
!= NULL
);
9058 ASSERT_TRUE(response
->headers
.get() != NULL
);
9059 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9060 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9061 EXPECT_FALSE(response
->was_npn_negotiated
);
9063 std::string response_data
;
9064 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9065 EXPECT_EQ("hello world", response_data
);
9067 alternative_service_vector
=
9068 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9069 ASSERT_EQ(1u, alternative_service_vector
.size());
9070 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9071 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9072 alternative_service_vector
[0].protocol
);
9075 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
9076 session_deps_
.next_protos
= SpdyNextProtos();
9077 session_deps_
.use_alternative_services
= true;
9079 MockRead data_reads
[] = {
9080 MockRead("HTTP/1.1 200 OK\r\n"),
9081 MockRead("Alternate-Protocol: \r\n\r\n"),
9082 MockRead("hello world"),
9083 MockRead(SYNCHRONOUS
, OK
),
9086 HttpRequestInfo request
;
9087 request
.method
= "GET";
9088 request
.url
= GURL("http://www.example.org/");
9089 request
.load_flags
= 0;
9091 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9093 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9095 TestCompletionCallback callback
;
9097 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9099 HostPortPair
http_host_port_pair("www.example.org", 80);
9100 HttpServerProperties
& http_server_properties
=
9101 *session
->http_server_properties();
9102 AlternativeService
alternative_service(QUIC
, "", 80);
9103 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9104 http_server_properties
.SetAlternativeService(
9105 http_host_port_pair
, alternative_service
, 1.0, expiration
);
9107 AlternativeServiceVector alternative_service_vector
=
9108 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9109 ASSERT_EQ(1u, alternative_service_vector
.size());
9110 EXPECT_EQ(QUIC
, alternative_service_vector
[0].protocol
);
9112 scoped_ptr
<HttpTransaction
> trans(
9113 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9115 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9116 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9118 EXPECT_EQ(OK
, callback
.WaitForResult());
9120 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9121 ASSERT_TRUE(response
!= NULL
);
9122 ASSERT_TRUE(response
->headers
.get() != NULL
);
9123 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9124 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9125 EXPECT_FALSE(response
->was_npn_negotiated
);
9127 std::string response_data
;
9128 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9129 EXPECT_EQ("hello world", response_data
);
9131 alternative_service_vector
=
9132 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9133 EXPECT_TRUE(alternative_service_vector
.empty());
9136 TEST_P(HttpNetworkTransactionTest
, AltSvcOverwritesAlternateProtocol
) {
9137 session_deps_
.next_protos
= SpdyNextProtos();
9138 session_deps_
.use_alternative_services
= true;
9140 std::string alternative_service_http_header
=
9141 GetAlternativeServiceHttpHeader();
9142 std::string alternate_protocol_http_header
= GetAlternateProtocolHttpHeader();
9144 MockRead data_reads
[] = {
9145 MockRead("HTTP/1.1 200 OK\r\n"),
9146 MockRead(alternative_service_http_header
.c_str()),
9147 MockRead(alternate_protocol_http_header
.c_str()),
9149 MockRead("hello world"),
9150 MockRead(SYNCHRONOUS
, OK
),
9153 HttpRequestInfo request
;
9154 request
.method
= "GET";
9155 request
.url
= GURL("http://www.example.org/");
9156 request
.load_flags
= 0;
9158 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9160 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9162 TestCompletionCallback callback
;
9164 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9165 scoped_ptr
<HttpTransaction
> trans(
9166 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9168 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9169 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9171 HostPortPair
http_host_port_pair("www.example.org", 80);
9172 HttpServerProperties
& http_server_properties
=
9173 *session
->http_server_properties();
9174 AlternativeServiceVector alternative_service_vector
=
9175 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9176 EXPECT_TRUE(alternative_service_vector
.empty());
9178 EXPECT_EQ(OK
, callback
.WaitForResult());
9180 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9181 ASSERT_TRUE(response
!= NULL
);
9182 ASSERT_TRUE(response
->headers
.get() != NULL
);
9183 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9184 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9185 EXPECT_FALSE(response
->was_npn_negotiated
);
9187 std::string response_data
;
9188 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9189 EXPECT_EQ("hello world", response_data
);
9191 alternative_service_vector
=
9192 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9193 ASSERT_EQ(1u, alternative_service_vector
.size());
9194 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9195 alternative_service_vector
[0].protocol
);
9196 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
9197 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9200 // When |use_alternative_services| is false, do not observe alternative service
9201 // entries that point to a different host.
9202 TEST_P(HttpNetworkTransactionTest
, DisableAlternativeServiceToDifferentHost
) {
9203 session_deps_
.use_alternative_services
= false;
9205 HttpRequestInfo request
;
9206 request
.method
= "GET";
9207 request
.url
= GURL("http://www.example.org/");
9208 request
.load_flags
= 0;
9210 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9211 StaticSocketDataProvider first_data
;
9212 first_data
.set_connect_data(mock_connect
);
9213 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9215 MockRead data_reads
[] = {
9216 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
9217 MockRead(ASYNC
, OK
),
9219 StaticSocketDataProvider
second_data(data_reads
, arraysize(data_reads
),
9221 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9223 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9225 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9226 session
->http_server_properties();
9227 AlternativeService
alternative_service(
9228 AlternateProtocolFromNextProto(GetParam()), "different.example.org", 80);
9229 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9230 http_server_properties
->SetAlternativeService(
9231 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0, expiration
);
9233 scoped_ptr
<HttpTransaction
> trans(
9234 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9235 TestCompletionCallback callback
;
9237 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9238 // The connetion to origin was refused, and the alternative service should not
9239 // be used (even though mock data are there), therefore the request should
9241 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.GetResult(rv
));
9244 TEST_P(HttpNetworkTransactionTest
,
9245 MarkBrokenAlternateProtocolAndFallback
) {
9246 session_deps_
.use_alternative_services
= true;
9248 HttpRequestInfo request
;
9249 request
.method
= "GET";
9250 request
.url
= GURL("http://www.example.org/");
9251 request
.load_flags
= 0;
9253 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9254 StaticSocketDataProvider first_data
;
9255 first_data
.set_connect_data(mock_connect
);
9256 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9258 MockRead data_reads
[] = {
9259 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9260 MockRead("hello world"),
9261 MockRead(ASYNC
, OK
),
9263 StaticSocketDataProvider
second_data(
9264 data_reads
, arraysize(data_reads
), NULL
, 0);
9265 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9267 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9269 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9270 session
->http_server_properties();
9271 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
9272 // Port must be < 1024, or the header will be ignored (since initial port was
9273 // port 80 (another restricted port).
9274 const AlternativeService
alternative_service(
9275 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9276 666); // Port is ignored by MockConnect anyway.
9277 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9278 http_server_properties
->SetAlternativeService(
9279 host_port_pair
, alternative_service
, 1.0, expiration
);
9281 scoped_ptr
<HttpTransaction
> trans(
9282 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9283 TestCompletionCallback callback
;
9285 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9286 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9287 EXPECT_EQ(OK
, callback
.WaitForResult());
9289 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9290 ASSERT_TRUE(response
!= NULL
);
9291 ASSERT_TRUE(response
->headers
.get() != NULL
);
9292 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9294 std::string response_data
;
9295 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9296 EXPECT_EQ("hello world", response_data
);
9298 const AlternativeServiceVector alternative_service_vector
=
9299 http_server_properties
->GetAlternativeServices(host_port_pair
);
9300 ASSERT_EQ(1u, alternative_service_vector
.size());
9301 EXPECT_EQ(alternative_service
, alternative_service_vector
[0]);
9302 EXPECT_TRUE(http_server_properties
->IsAlternativeServiceBroken(
9303 alternative_service_vector
[0]));
9306 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9307 // to an unrestricted (port >= 1024) when the original traffic was on a
9308 // restricted port (port < 1024). Ensure that we can redirect in all other
9310 TEST_P(HttpNetworkTransactionTest
,
9311 AlternateProtocolPortRestrictedBlocked
) {
9312 session_deps_
.use_alternative_services
= true;
9314 HttpRequestInfo restricted_port_request
;
9315 restricted_port_request
.method
= "GET";
9316 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9317 restricted_port_request
.load_flags
= 0;
9319 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9320 StaticSocketDataProvider first_data
;
9321 first_data
.set_connect_data(mock_connect
);
9322 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9324 MockRead data_reads
[] = {
9325 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9326 MockRead("hello world"),
9327 MockRead(ASYNC
, OK
),
9329 StaticSocketDataProvider
second_data(
9330 data_reads
, arraysize(data_reads
), NULL
, 0);
9331 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9333 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9335 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9336 session
->http_server_properties();
9337 const int kUnrestrictedAlternatePort
= 1024;
9338 AlternativeService
alternative_service(
9339 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9340 kUnrestrictedAlternatePort
);
9341 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9342 http_server_properties
->SetAlternativeService(
9343 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9346 scoped_ptr
<HttpTransaction
> trans(
9347 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9348 TestCompletionCallback callback
;
9350 int rv
= trans
->Start(
9351 &restricted_port_request
,
9352 callback
.callback(), BoundNetLog());
9353 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9354 // Invalid change to unrestricted port should fail.
9355 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
9358 // Ensure that we are allowed to redirect traffic via an alternate protocol to
9359 // an unrestricted (port >= 1024) when the original traffic was on a restricted
9360 // port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
9361 TEST_P(HttpNetworkTransactionTest
,
9362 AlternateProtocolPortRestrictedPermitted
) {
9363 session_deps_
.use_alternative_services
= true;
9364 session_deps_
.enable_user_alternate_protocol_ports
= true;
9366 HttpRequestInfo restricted_port_request
;
9367 restricted_port_request
.method
= "GET";
9368 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9369 restricted_port_request
.load_flags
= 0;
9371 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9372 StaticSocketDataProvider first_data
;
9373 first_data
.set_connect_data(mock_connect
);
9374 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9376 MockRead data_reads
[] = {
9377 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9378 MockRead("hello world"),
9379 MockRead(ASYNC
, OK
),
9381 StaticSocketDataProvider
second_data(
9382 data_reads
, arraysize(data_reads
), NULL
, 0);
9383 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9385 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9387 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9388 session
->http_server_properties();
9389 const int kUnrestrictedAlternatePort
= 1024;
9390 AlternativeService
alternative_service(
9391 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9392 kUnrestrictedAlternatePort
);
9393 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9394 http_server_properties
->SetAlternativeService(
9395 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9398 scoped_ptr
<HttpTransaction
> trans(
9399 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9400 TestCompletionCallback callback
;
9402 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9403 &restricted_port_request
,
9404 callback
.callback(), BoundNetLog()));
9405 // Change to unrestricted port should succeed.
9406 EXPECT_EQ(OK
, callback
.WaitForResult());
9409 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9410 // to an unrestricted (port >= 1024) when the original traffic was on a
9411 // restricted port (port < 1024). Ensure that we can redirect in all other
9413 TEST_P(HttpNetworkTransactionTest
,
9414 AlternateProtocolPortRestrictedAllowed
) {
9415 session_deps_
.use_alternative_services
= true;
9417 HttpRequestInfo restricted_port_request
;
9418 restricted_port_request
.method
= "GET";
9419 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9420 restricted_port_request
.load_flags
= 0;
9422 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9423 StaticSocketDataProvider first_data
;
9424 first_data
.set_connect_data(mock_connect
);
9425 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9427 MockRead data_reads
[] = {
9428 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9429 MockRead("hello world"),
9430 MockRead(ASYNC
, OK
),
9432 StaticSocketDataProvider
second_data(
9433 data_reads
, arraysize(data_reads
), NULL
, 0);
9434 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9436 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9438 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9439 session
->http_server_properties();
9440 const int kRestrictedAlternatePort
= 80;
9441 AlternativeService
alternative_service(
9442 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9443 kRestrictedAlternatePort
);
9444 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9445 http_server_properties
->SetAlternativeService(
9446 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9449 scoped_ptr
<HttpTransaction
> trans(
9450 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9451 TestCompletionCallback callback
;
9453 int rv
= trans
->Start(
9454 &restricted_port_request
,
9455 callback
.callback(), BoundNetLog());
9456 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9457 // Valid change to restricted port should pass.
9458 EXPECT_EQ(OK
, callback
.WaitForResult());
9461 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9462 // to an unrestricted (port >= 1024) when the original traffic was on a
9463 // restricted port (port < 1024). Ensure that we can redirect in all other
9465 TEST_P(HttpNetworkTransactionTest
,
9466 AlternateProtocolPortUnrestrictedAllowed1
) {
9467 session_deps_
.use_alternative_services
= true;
9469 HttpRequestInfo unrestricted_port_request
;
9470 unrestricted_port_request
.method
= "GET";
9471 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9472 unrestricted_port_request
.load_flags
= 0;
9474 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9475 StaticSocketDataProvider first_data
;
9476 first_data
.set_connect_data(mock_connect
);
9477 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9479 MockRead data_reads
[] = {
9480 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9481 MockRead("hello world"),
9482 MockRead(ASYNC
, OK
),
9484 StaticSocketDataProvider
second_data(
9485 data_reads
, arraysize(data_reads
), NULL
, 0);
9486 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9488 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9490 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9491 session
->http_server_properties();
9492 const int kRestrictedAlternatePort
= 80;
9493 AlternativeService
alternative_service(
9494 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9495 kRestrictedAlternatePort
);
9496 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9497 http_server_properties
->SetAlternativeService(
9498 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9501 scoped_ptr
<HttpTransaction
> trans(
9502 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9503 TestCompletionCallback callback
;
9505 int rv
= trans
->Start(
9506 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9507 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9508 // Valid change to restricted port should pass.
9509 EXPECT_EQ(OK
, callback
.WaitForResult());
9512 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9513 // to an unrestricted (port >= 1024) when the original traffic was on a
9514 // restricted port (port < 1024). Ensure that we can redirect in all other
9516 TEST_P(HttpNetworkTransactionTest
,
9517 AlternateProtocolPortUnrestrictedAllowed2
) {
9518 session_deps_
.use_alternative_services
= true;
9520 HttpRequestInfo unrestricted_port_request
;
9521 unrestricted_port_request
.method
= "GET";
9522 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9523 unrestricted_port_request
.load_flags
= 0;
9525 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9526 StaticSocketDataProvider first_data
;
9527 first_data
.set_connect_data(mock_connect
);
9528 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9530 MockRead data_reads
[] = {
9531 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9532 MockRead("hello world"),
9533 MockRead(ASYNC
, OK
),
9535 StaticSocketDataProvider
second_data(
9536 data_reads
, arraysize(data_reads
), NULL
, 0);
9537 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9539 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9541 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9542 session
->http_server_properties();
9543 const int kUnrestrictedAlternatePort
= 1025;
9544 AlternativeService
alternative_service(
9545 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9546 kUnrestrictedAlternatePort
);
9547 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9548 http_server_properties
->SetAlternativeService(
9549 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9552 scoped_ptr
<HttpTransaction
> trans(
9553 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9554 TestCompletionCallback callback
;
9556 int rv
= trans
->Start(
9557 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9558 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9559 // Valid change to an unrestricted port should pass.
9560 EXPECT_EQ(OK
, callback
.WaitForResult());
9563 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9564 // to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
9565 // once the alternate protocol request fails.
9566 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9567 session_deps_
.use_alternative_services
= true;
9569 HttpRequestInfo request
;
9570 request
.method
= "GET";
9571 request
.url
= GURL("http://www.example.org/");
9572 request
.load_flags
= 0;
9574 // The alternate protocol request will error out before we attempt to connect,
9575 // so only the standard HTTP request will try to connect.
9576 MockRead data_reads
[] = {
9577 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9578 MockRead("hello world"),
9579 MockRead(ASYNC
, OK
),
9581 StaticSocketDataProvider
data(
9582 data_reads
, arraysize(data_reads
), NULL
, 0);
9583 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9585 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9587 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9588 session
->http_server_properties();
9589 const int kUnsafePort
= 7;
9590 AlternativeService
alternative_service(
9591 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9593 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9594 http_server_properties
->SetAlternativeService(
9595 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0, expiration
);
9597 scoped_ptr
<HttpTransaction
> trans(
9598 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9599 TestCompletionCallback callback
;
9601 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9602 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9603 // The HTTP request should succeed.
9604 EXPECT_EQ(OK
, callback
.WaitForResult());
9606 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9607 ASSERT_TRUE(response
!= NULL
);
9608 ASSERT_TRUE(response
->headers
.get() != NULL
);
9609 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9611 std::string response_data
;
9612 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9613 EXPECT_EQ("hello world", response_data
);
9616 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9617 session_deps_
.use_alternative_services
= true;
9618 session_deps_
.next_protos
= SpdyNextProtos();
9620 HttpRequestInfo request
;
9621 request
.method
= "GET";
9622 request
.url
= GURL("http://www.example.org/");
9623 request
.load_flags
= 0;
9625 std::string alternate_protocol_http_header
=
9626 GetAlternateProtocolHttpHeader();
9628 MockRead data_reads
[] = {
9629 MockRead("HTTP/1.1 200 OK\r\n"),
9630 MockRead(alternate_protocol_http_header
.c_str()),
9632 MockRead("hello world"),
9633 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9634 MockRead(ASYNC
, OK
)};
9636 StaticSocketDataProvider
first_transaction(
9637 data_reads
, arraysize(data_reads
), NULL
, 0);
9638 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9640 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9641 ssl
.SetNextProto(GetParam());
9642 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9643 ASSERT_TRUE(ssl
.cert
.get());
9644 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9646 scoped_ptr
<SpdyFrame
> req(
9647 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9648 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9650 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9651 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9652 MockRead spdy_reads
[] = {
9653 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9656 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9657 arraysize(spdy_writes
));
9658 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9660 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9661 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9663 hanging_non_alternate_protocol_socket
.set_connect_data(
9664 never_finishing_connect
);
9665 session_deps_
.socket_factory
->AddSocketDataProvider(
9666 &hanging_non_alternate_protocol_socket
);
9668 TestCompletionCallback callback
;
9670 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9671 scoped_ptr
<HttpTransaction
> trans(
9672 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9674 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9675 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9676 EXPECT_EQ(OK
, callback
.WaitForResult());
9678 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9679 ASSERT_TRUE(response
!= NULL
);
9680 ASSERT_TRUE(response
->headers
.get() != NULL
);
9681 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9683 std::string response_data
;
9684 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9685 EXPECT_EQ("hello world", response_data
);
9687 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9689 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9690 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9691 EXPECT_EQ(OK
, callback
.WaitForResult());
9693 response
= trans
->GetResponseInfo();
9694 ASSERT_TRUE(response
!= NULL
);
9695 ASSERT_TRUE(response
->headers
.get() != NULL
);
9696 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9697 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9698 EXPECT_TRUE(response
->was_npn_negotiated
);
9700 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9701 EXPECT_EQ("hello!", response_data
);
9704 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9705 session_deps_
.use_alternative_services
= true;
9706 session_deps_
.next_protos
= SpdyNextProtos();
9708 HttpRequestInfo request
;
9709 request
.method
= "GET";
9710 request
.url
= GURL("http://www.example.org/");
9711 request
.load_flags
= 0;
9713 std::string alternate_protocol_http_header
=
9714 GetAlternateProtocolHttpHeader();
9716 MockRead data_reads
[] = {
9717 MockRead("HTTP/1.1 200 OK\r\n"),
9718 MockRead(alternate_protocol_http_header
.c_str()),
9720 MockRead("hello world"),
9721 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9722 MockRead(ASYNC
, OK
),
9725 StaticSocketDataProvider
first_transaction(
9726 data_reads
, arraysize(data_reads
), NULL
, 0);
9727 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9728 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9730 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9731 StaticSocketDataProvider
hanging_socket(
9733 hanging_socket
.set_connect_data(never_finishing_connect
);
9734 // Socket 2 and 3 are the hanging Alternate-Protocol and
9735 // non-Alternate-Protocol jobs from the 2nd transaction.
9736 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9737 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9739 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9740 ssl
.SetNextProto(GetParam());
9741 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9742 ASSERT_TRUE(ssl
.cert
.get());
9743 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9745 scoped_ptr
<SpdyFrame
> req1(
9746 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9747 scoped_ptr
<SpdyFrame
> req2(
9748 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9749 MockWrite spdy_writes
[] = {
9750 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
9752 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9753 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9754 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9755 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9756 MockRead spdy_reads
[] = {
9757 CreateMockRead(*resp1
, 2),
9758 CreateMockRead(*data1
, 3),
9759 CreateMockRead(*resp2
, 4),
9760 CreateMockRead(*data2
, 5),
9761 MockRead(ASYNC
, 0, 6),
9764 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9765 arraysize(spdy_writes
));
9766 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9767 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9769 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9770 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9772 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9773 TestCompletionCallback callback1
;
9774 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9776 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9777 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9778 EXPECT_EQ(OK
, callback1
.WaitForResult());
9780 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9781 ASSERT_TRUE(response
!= NULL
);
9782 ASSERT_TRUE(response
->headers
.get() != NULL
);
9783 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9785 std::string response_data
;
9786 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9787 EXPECT_EQ("hello world", response_data
);
9789 TestCompletionCallback callback2
;
9790 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9791 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9792 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9794 TestCompletionCallback callback3
;
9795 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9796 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9797 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9799 EXPECT_EQ(OK
, callback2
.WaitForResult());
9800 EXPECT_EQ(OK
, callback3
.WaitForResult());
9802 response
= trans2
.GetResponseInfo();
9803 ASSERT_TRUE(response
!= NULL
);
9804 ASSERT_TRUE(response
->headers
.get() != NULL
);
9805 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9806 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9807 EXPECT_TRUE(response
->was_npn_negotiated
);
9808 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9809 EXPECT_EQ("hello!", response_data
);
9811 response
= trans3
.GetResponseInfo();
9812 ASSERT_TRUE(response
!= NULL
);
9813 ASSERT_TRUE(response
->headers
.get() != NULL
);
9814 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9815 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9816 EXPECT_TRUE(response
->was_npn_negotiated
);
9817 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9818 EXPECT_EQ("hello!", response_data
);
9821 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9822 session_deps_
.use_alternative_services
= true;
9823 session_deps_
.next_protos
= SpdyNextProtos();
9825 HttpRequestInfo request
;
9826 request
.method
= "GET";
9827 request
.url
= GURL("http://www.example.org/");
9828 request
.load_flags
= 0;
9830 std::string alternate_protocol_http_header
=
9831 GetAlternateProtocolHttpHeader();
9833 MockRead data_reads
[] = {
9834 MockRead("HTTP/1.1 200 OK\r\n"),
9835 MockRead(alternate_protocol_http_header
.c_str()),
9837 MockRead("hello world"),
9838 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9839 MockRead(ASYNC
, OK
),
9842 StaticSocketDataProvider
first_transaction(
9843 data_reads
, arraysize(data_reads
), NULL
, 0);
9844 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9846 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9847 ssl
.SetNextProto(GetParam());
9848 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9850 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9851 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9853 hanging_alternate_protocol_socket
.set_connect_data(
9854 never_finishing_connect
);
9855 session_deps_
.socket_factory
->AddSocketDataProvider(
9856 &hanging_alternate_protocol_socket
);
9858 // 2nd request is just a copy of the first one, over HTTP again.
9859 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9861 TestCompletionCallback callback
;
9863 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9864 scoped_ptr
<HttpTransaction
> trans(
9865 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9867 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9868 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9869 EXPECT_EQ(OK
, callback
.WaitForResult());
9871 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9872 ASSERT_TRUE(response
!= NULL
);
9873 ASSERT_TRUE(response
->headers
.get() != NULL
);
9874 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9876 std::string response_data
;
9877 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9878 EXPECT_EQ("hello world", response_data
);
9880 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9882 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9883 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9884 EXPECT_EQ(OK
, callback
.WaitForResult());
9886 response
= trans
->GetResponseInfo();
9887 ASSERT_TRUE(response
!= NULL
);
9888 ASSERT_TRUE(response
->headers
.get() != NULL
);
9889 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9890 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9891 EXPECT_FALSE(response
->was_npn_negotiated
);
9893 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9894 EXPECT_EQ("hello world", response_data
);
9897 class CapturingProxyResolver
: public ProxyResolver
{
9899 CapturingProxyResolver() {}
9900 ~CapturingProxyResolver() override
{}
9902 int GetProxyForURL(const GURL
& url
,
9904 const CompletionCallback
& callback
,
9905 RequestHandle
* request
,
9906 const BoundNetLog
& net_log
) override
{
9907 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9908 HostPortPair("myproxy", 80));
9909 results
->UseProxyServer(proxy_server
);
9910 resolved_
.push_back(url
);
9914 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9916 LoadState
GetLoadState(RequestHandle request
) const override
{
9918 return LOAD_STATE_IDLE
;
9921 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9924 std::vector
<GURL
> resolved_
;
9926 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9929 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9931 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9932 : ProxyResolverFactory(false), resolver_(resolver
) {}
9934 int CreateProxyResolver(
9935 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9936 scoped_ptr
<ProxyResolver
>* resolver
,
9937 const net::CompletionCallback
& callback
,
9938 scoped_ptr
<Request
>* request
) override
{
9939 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9944 ProxyResolver
* resolver_
;
9947 TEST_P(HttpNetworkTransactionTest
,
9948 UseAlternateProtocolForTunneledNpnSpdy
) {
9949 session_deps_
.use_alternative_services
= true;
9950 session_deps_
.next_protos
= SpdyNextProtos();
9952 ProxyConfig proxy_config
;
9953 proxy_config
.set_auto_detect(true);
9954 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9956 CapturingProxyResolver capturing_proxy_resolver
;
9957 session_deps_
.proxy_service
.reset(new ProxyService(
9958 new ProxyConfigServiceFixed(proxy_config
),
9960 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9963 session_deps_
.net_log
= &net_log
;
9965 HttpRequestInfo request
;
9966 request
.method
= "GET";
9967 request
.url
= GURL("http://www.example.org/");
9968 request
.load_flags
= 0;
9970 std::string alternate_protocol_http_header
=
9971 GetAlternateProtocolHttpHeader();
9973 MockRead data_reads
[] = {
9974 MockRead("HTTP/1.1 200 OK\r\n"),
9975 MockRead(alternate_protocol_http_header
.c_str()),
9977 MockRead("hello world"),
9978 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9979 MockRead(ASYNC
, OK
),
9982 StaticSocketDataProvider
first_transaction(
9983 data_reads
, arraysize(data_reads
), NULL
, 0);
9984 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9986 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9987 ssl
.SetNextProto(GetParam());
9988 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9989 ASSERT_TRUE(ssl
.cert
.get());
9990 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9992 scoped_ptr
<SpdyFrame
> req(
9993 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9994 MockWrite spdy_writes
[] = {
9996 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9997 "Host: www.example.org\r\n"
9998 "Proxy-Connection: keep-alive\r\n\r\n"),
9999 CreateMockWrite(*req
, 2),
10002 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10004 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10005 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10006 MockRead spdy_reads
[] = {
10007 MockRead(ASYNC
, 1, kCONNECTResponse
),
10008 CreateMockRead(*resp
.get(), 3),
10009 CreateMockRead(*data
.get(), 4),
10010 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
10013 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10014 arraysize(spdy_writes
));
10015 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10017 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10018 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10020 hanging_non_alternate_protocol_socket
.set_connect_data(
10021 never_finishing_connect
);
10022 session_deps_
.socket_factory
->AddSocketDataProvider(
10023 &hanging_non_alternate_protocol_socket
);
10025 TestCompletionCallback callback
;
10027 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10028 scoped_ptr
<HttpTransaction
> trans(
10029 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10031 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10033 EXPECT_EQ(OK
, callback
.WaitForResult());
10035 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10036 ASSERT_TRUE(response
!= NULL
);
10037 ASSERT_TRUE(response
->headers
.get() != NULL
);
10038 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10039 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10040 EXPECT_FALSE(response
->was_npn_negotiated
);
10042 std::string response_data
;
10043 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10044 EXPECT_EQ("hello world", response_data
);
10046 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10048 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10049 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10050 EXPECT_EQ(OK
, callback
.WaitForResult());
10052 response
= trans
->GetResponseInfo();
10053 ASSERT_TRUE(response
!= NULL
);
10054 ASSERT_TRUE(response
->headers
.get() != NULL
);
10055 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10056 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10057 EXPECT_TRUE(response
->was_npn_negotiated
);
10059 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10060 EXPECT_EQ("hello!", response_data
);
10061 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
10062 EXPECT_EQ("http://www.example.org/",
10063 capturing_proxy_resolver
.resolved()[0].spec());
10064 EXPECT_EQ("https://www.example.org/",
10065 capturing_proxy_resolver
.resolved()[1].spec());
10067 LoadTimingInfo load_timing_info
;
10068 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10069 TestLoadTimingNotReusedWithPac(load_timing_info
,
10070 CONNECT_TIMING_HAS_SSL_TIMES
);
10073 TEST_P(HttpNetworkTransactionTest
,
10074 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
10075 session_deps_
.use_alternative_services
= true;
10076 session_deps_
.next_protos
= SpdyNextProtos();
10078 HttpRequestInfo request
;
10079 request
.method
= "GET";
10080 request
.url
= GURL("http://www.example.org/");
10081 request
.load_flags
= 0;
10083 std::string alternate_protocol_http_header
=
10084 GetAlternateProtocolHttpHeader();
10086 MockRead data_reads
[] = {
10087 MockRead("HTTP/1.1 200 OK\r\n"),
10088 MockRead(alternate_protocol_http_header
.c_str()),
10090 MockRead("hello world"),
10091 MockRead(ASYNC
, OK
),
10094 StaticSocketDataProvider
first_transaction(
10095 data_reads
, arraysize(data_reads
), NULL
, 0);
10096 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
10098 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10099 ssl
.SetNextProto(GetParam());
10100 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10101 ASSERT_TRUE(ssl
.cert
.get());
10102 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10104 scoped_ptr
<SpdyFrame
> req(
10105 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10106 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
10108 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10109 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10110 MockRead spdy_reads
[] = {
10111 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
10114 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10115 arraysize(spdy_writes
));
10116 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10118 TestCompletionCallback callback
;
10120 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10122 scoped_ptr
<HttpTransaction
> trans(
10123 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10125 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10126 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10127 EXPECT_EQ(OK
, callback
.WaitForResult());
10129 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10130 ASSERT_TRUE(response
!= NULL
);
10131 ASSERT_TRUE(response
->headers
.get() != NULL
);
10132 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10134 std::string response_data
;
10135 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10136 EXPECT_EQ("hello world", response_data
);
10138 // Set up an initial SpdySession in the pool to reuse.
10139 HostPortPair
host_port_pair("www.example.org", 443);
10140 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10141 PRIVACY_MODE_DISABLED
);
10142 base::WeakPtr
<SpdySession
> spdy_session
=
10143 CreateSecureSpdySession(session
, key
, BoundNetLog());
10145 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10147 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10148 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10149 EXPECT_EQ(OK
, callback
.WaitForResult());
10151 response
= trans
->GetResponseInfo();
10152 ASSERT_TRUE(response
!= NULL
);
10153 ASSERT_TRUE(response
->headers
.get() != NULL
);
10154 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10155 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10156 EXPECT_TRUE(response
->was_npn_negotiated
);
10158 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10159 EXPECT_EQ("hello!", response_data
);
10162 // GenerateAuthToken is a mighty big test.
10163 // It tests all permutation of GenerateAuthToken behavior:
10164 // - Synchronous and Asynchronous completion.
10165 // - OK or error on completion.
10166 // - Direct connection, non-authenticating proxy, and authenticating proxy.
10167 // - HTTP or HTTPS backend (to include proxy tunneling).
10168 // - Non-authenticating and authenticating backend.
10170 // In all, there are 44 reasonable permuations (for example, if there are
10171 // problems generating an auth token for an authenticating proxy, we don't
10172 // need to test all permutations of the backend server).
10174 // The test proceeds by going over each of the configuration cases, and
10175 // potentially running up to three rounds in each of the tests. The TestConfig
10176 // specifies both the configuration for the test as well as the expectations
10177 // for the results.
10178 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
10179 static const char kServer
[] = "http://www.example.com";
10180 static const char kSecureServer
[] = "https://www.example.com";
10181 static const char kProxy
[] = "myproxy:70";
10182 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
10190 const MockWrite
kGet(
10191 "GET / HTTP/1.1\r\n"
10192 "Host: www.example.com\r\n"
10193 "Connection: keep-alive\r\n\r\n");
10194 const MockWrite
kGetProxy(
10195 "GET http://www.example.com/ HTTP/1.1\r\n"
10196 "Host: www.example.com\r\n"
10197 "Proxy-Connection: keep-alive\r\n\r\n");
10198 const MockWrite
kGetAuth(
10199 "GET / HTTP/1.1\r\n"
10200 "Host: www.example.com\r\n"
10201 "Connection: keep-alive\r\n"
10202 "Authorization: auth_token\r\n\r\n");
10203 const MockWrite
kGetProxyAuth(
10204 "GET http://www.example.com/ HTTP/1.1\r\n"
10205 "Host: www.example.com\r\n"
10206 "Proxy-Connection: keep-alive\r\n"
10207 "Proxy-Authorization: auth_token\r\n\r\n");
10208 const MockWrite
kGetAuthThroughProxy(
10209 "GET http://www.example.com/ HTTP/1.1\r\n"
10210 "Host: www.example.com\r\n"
10211 "Proxy-Connection: keep-alive\r\n"
10212 "Authorization: auth_token\r\n\r\n");
10213 const MockWrite
kGetAuthWithProxyAuth(
10214 "GET http://www.example.com/ HTTP/1.1\r\n"
10215 "Host: www.example.com\r\n"
10216 "Proxy-Connection: keep-alive\r\n"
10217 "Proxy-Authorization: auth_token\r\n"
10218 "Authorization: auth_token\r\n\r\n");
10219 const MockWrite
kConnect(
10220 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10221 "Host: www.example.com\r\n"
10222 "Proxy-Connection: keep-alive\r\n\r\n");
10223 const MockWrite
kConnectProxyAuth(
10224 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10225 "Host: www.example.com\r\n"
10226 "Proxy-Connection: keep-alive\r\n"
10227 "Proxy-Authorization: auth_token\r\n\r\n");
10229 const MockRead
kSuccess(
10230 "HTTP/1.1 200 OK\r\n"
10231 "Content-Type: text/html; charset=iso-8859-1\r\n"
10232 "Content-Length: 3\r\n\r\n"
10234 const MockRead
kFailure(
10235 "Should not be called.");
10236 const MockRead
kServerChallenge(
10237 "HTTP/1.1 401 Unauthorized\r\n"
10238 "WWW-Authenticate: Mock realm=server\r\n"
10239 "Content-Type: text/html; charset=iso-8859-1\r\n"
10240 "Content-Length: 14\r\n\r\n"
10241 "Unauthorized\r\n");
10242 const MockRead
kProxyChallenge(
10243 "HTTP/1.1 407 Unauthorized\r\n"
10244 "Proxy-Authenticate: Mock realm=proxy\r\n"
10245 "Proxy-Connection: close\r\n"
10246 "Content-Type: text/html; charset=iso-8859-1\r\n"
10247 "Content-Length: 14\r\n\r\n"
10248 "Unauthorized\r\n");
10249 const MockRead
kProxyConnected(
10250 "HTTP/1.1 200 Connection Established\r\n\r\n");
10252 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10253 // no constructors, but the C++ compiler on Windows warns about
10254 // unspecified data in compound literals. So, moved to using constructors,
10255 // and TestRound's created with the default constructor should not be used.
10258 : expected_rv(ERR_UNEXPECTED
),
10262 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10263 int expected_rv_arg
)
10264 : write(write_arg
),
10266 expected_rv(expected_rv_arg
),
10270 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10271 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
10272 const MockRead
* extra_read_arg
)
10273 : write(write_arg
),
10275 expected_rv(expected_rv_arg
),
10276 extra_write(extra_write_arg
),
10277 extra_read(extra_read_arg
) {
10282 const MockWrite
* extra_write
;
10283 const MockRead
* extra_read
;
10286 static const int kNoSSL
= 500;
10288 struct TestConfig
{
10289 const char* const proxy_url
;
10290 AuthTiming proxy_auth_timing
;
10292 const char* const server_url
;
10293 AuthTiming server_auth_timing
;
10294 int server_auth_rv
;
10295 int num_auth_rounds
;
10296 int first_ssl_round
;
10297 TestRound rounds
[3];
10298 } test_configs
[] = {
10299 // Non-authenticating HTTP server with a direct connection.
10300 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10301 { TestRound(kGet
, kSuccess
, OK
)}},
10302 // Authenticating HTTP server with a direct connection.
10303 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10304 { TestRound(kGet
, kServerChallenge
, OK
),
10305 TestRound(kGetAuth
, kSuccess
, OK
)}},
10306 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10307 { TestRound(kGet
, kServerChallenge
, OK
),
10308 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10309 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10310 { TestRound(kGet
, kServerChallenge
, OK
),
10311 TestRound(kGetAuth
, kSuccess
, OK
)}},
10312 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10313 { TestRound(kGet
, kServerChallenge
, OK
),
10314 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10315 // Non-authenticating HTTP server through a non-authenticating proxy.
10316 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10317 { TestRound(kGetProxy
, kSuccess
, OK
)}},
10318 // Authenticating HTTP server through a non-authenticating proxy.
10319 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10320 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10321 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10322 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10323 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10324 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10325 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10326 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10327 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10328 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10329 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10330 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10331 // Non-authenticating HTTP server through an authenticating proxy.
10332 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10333 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10334 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10335 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10336 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10337 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10338 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10339 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10340 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10341 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10342 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10343 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10344 // Authenticating HTTP server through an authenticating proxy.
10345 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10346 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10347 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10348 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10349 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10350 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10351 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10352 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10353 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10354 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10355 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10356 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10357 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10358 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10359 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10360 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10361 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10362 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10363 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10364 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10365 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10366 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10367 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10368 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10369 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10370 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10371 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10372 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10373 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10374 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10375 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10376 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10377 // Non-authenticating HTTPS server with a direct connection.
10378 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10379 { TestRound(kGet
, kSuccess
, OK
)}},
10380 // Authenticating HTTPS server with a direct connection.
10381 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10382 { TestRound(kGet
, kServerChallenge
, OK
),
10383 TestRound(kGetAuth
, kSuccess
, OK
)}},
10384 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10385 { TestRound(kGet
, kServerChallenge
, OK
),
10386 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10387 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10388 { TestRound(kGet
, kServerChallenge
, OK
),
10389 TestRound(kGetAuth
, kSuccess
, OK
)}},
10390 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10391 { TestRound(kGet
, kServerChallenge
, OK
),
10392 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10393 // Non-authenticating HTTPS server with a non-authenticating proxy.
10394 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10395 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10396 // Authenticating HTTPS server through a non-authenticating proxy.
10397 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10398 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10399 TestRound(kGetAuth
, kSuccess
, OK
)}},
10400 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10401 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10402 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10403 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10404 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10405 TestRound(kGetAuth
, kSuccess
, OK
)}},
10406 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10407 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10408 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10409 // Non-Authenticating HTTPS server through an authenticating proxy.
10410 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10411 { TestRound(kConnect
, kProxyChallenge
, OK
),
10412 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10413 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10414 { TestRound(kConnect
, kProxyChallenge
, OK
),
10415 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10416 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10417 { TestRound(kConnect
, kProxyChallenge
, OK
),
10418 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10419 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10420 { TestRound(kConnect
, kProxyChallenge
, OK
),
10421 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10422 // Authenticating HTTPS server through an authenticating proxy.
10423 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10424 { TestRound(kConnect
, kProxyChallenge
, OK
),
10425 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10426 &kGet
, &kServerChallenge
),
10427 TestRound(kGetAuth
, kSuccess
, OK
)}},
10428 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10429 { TestRound(kConnect
, kProxyChallenge
, OK
),
10430 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10431 &kGet
, &kServerChallenge
),
10432 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10433 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10434 { TestRound(kConnect
, kProxyChallenge
, OK
),
10435 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10436 &kGet
, &kServerChallenge
),
10437 TestRound(kGetAuth
, kSuccess
, OK
)}},
10438 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10439 { TestRound(kConnect
, kProxyChallenge
, OK
),
10440 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10441 &kGet
, &kServerChallenge
),
10442 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10443 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10444 { TestRound(kConnect
, kProxyChallenge
, OK
),
10445 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10446 &kGet
, &kServerChallenge
),
10447 TestRound(kGetAuth
, kSuccess
, OK
)}},
10448 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10449 { TestRound(kConnect
, kProxyChallenge
, OK
),
10450 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10451 &kGet
, &kServerChallenge
),
10452 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10453 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10454 { TestRound(kConnect
, kProxyChallenge
, OK
),
10455 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10456 &kGet
, &kServerChallenge
),
10457 TestRound(kGetAuth
, kSuccess
, OK
)}},
10458 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10459 { TestRound(kConnect
, kProxyChallenge
, OK
),
10460 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10461 &kGet
, &kServerChallenge
),
10462 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10465 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10466 HttpAuthHandlerMock::Factory
* auth_factory(
10467 new HttpAuthHandlerMock::Factory());
10468 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10469 const TestConfig
& test_config
= test_configs
[i
];
10471 // Set up authentication handlers as necessary.
10472 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10473 for (int n
= 0; n
< 2; n
++) {
10474 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10475 std::string auth_challenge
= "Mock realm=proxy";
10476 GURL
origin(test_config
.proxy_url
);
10477 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10478 auth_challenge
.end());
10479 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10480 origin
, BoundNetLog());
10481 auth_handler
->SetGenerateExpectation(
10482 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10483 test_config
.proxy_auth_rv
);
10484 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10487 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10488 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10489 std::string auth_challenge
= "Mock realm=server";
10490 GURL
origin(test_config
.server_url
);
10491 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10492 auth_challenge
.end());
10493 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10494 origin
, BoundNetLog());
10495 auth_handler
->SetGenerateExpectation(
10496 test_config
.server_auth_timing
== AUTH_ASYNC
,
10497 test_config
.server_auth_rv
);
10498 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10500 if (test_config
.proxy_url
) {
10501 session_deps_
.proxy_service
=
10502 ProxyService::CreateFixed(test_config
.proxy_url
);
10504 session_deps_
.proxy_service
= ProxyService::CreateDirect();
10507 HttpRequestInfo request
;
10508 request
.method
= "GET";
10509 request
.url
= GURL(test_config
.server_url
);
10510 request
.load_flags
= 0;
10512 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10513 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10515 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10517 std::vector
<std::vector
<MockRead
>> mock_reads(1);
10518 std::vector
<std::vector
<MockWrite
>> mock_writes(1);
10519 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10520 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10522 // Set up expected reads and writes.
10523 mock_reads
.back().push_back(read_write_round
.read
);
10524 mock_writes
.back().push_back(read_write_round
.write
);
10526 // kProxyChallenge uses Proxy-Connection: close which means that the
10527 // socket is closed and a new one will be created for the next request.
10528 if (read_write_round
.read
.data
== kProxyChallenge
.data
) {
10529 mock_reads
.push_back(std::vector
<MockRead
>());
10530 mock_writes
.push_back(std::vector
<MockWrite
>());
10533 if (read_write_round
.extra_read
) {
10534 mock_reads
.back().push_back(*read_write_round
.extra_read
);
10536 if (read_write_round
.extra_write
) {
10537 mock_writes
.back().push_back(*read_write_round
.extra_write
);
10540 // Add an SSL sequence if necessary.
10541 if (round
>= test_config
.first_ssl_round
)
10542 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10543 &ssl_socket_data_provider
);
10546 ScopedVector
<StaticSocketDataProvider
> data_providers
;
10547 for (size_t i
= 0; i
< mock_reads
.size(); ++i
) {
10548 data_providers
.push_back(new StaticSocketDataProvider(
10549 vector_as_array(&mock_reads
[i
]), mock_reads
[i
].size(),
10550 vector_as_array(&mock_writes
[i
]), mock_writes
[i
].size()));
10551 session_deps_
.socket_factory
->AddSocketDataProvider(
10552 data_providers
.back());
10555 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10556 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10557 // Start or restart the transaction.
10558 TestCompletionCallback callback
;
10561 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10563 rv
= trans
.RestartWithAuth(
10564 AuthCredentials(kFoo
, kBar
), callback
.callback());
10566 if (rv
== ERR_IO_PENDING
)
10567 rv
= callback
.WaitForResult();
10569 // Compare results with expected data.
10570 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10571 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10572 if (read_write_round
.expected_rv
!= OK
) {
10573 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10576 if (round
+ 1 < test_config
.num_auth_rounds
) {
10577 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10579 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10585 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10586 // Do multi-round authentication and make sure it works correctly.
10587 HttpAuthHandlerMock::Factory
* auth_factory(
10588 new HttpAuthHandlerMock::Factory());
10589 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10590 session_deps_
.proxy_service
= ProxyService::CreateDirect();
10591 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10592 session_deps_
.host_resolver
->set_synchronous_mode(true);
10594 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10595 auth_handler
->set_connection_based(true);
10596 std::string auth_challenge
= "Mock realm=server";
10597 GURL
origin("http://www.example.com");
10598 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10599 auth_challenge
.end());
10600 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10601 origin
, BoundNetLog());
10602 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10605 const HttpResponseInfo
* response
= NULL
;
10606 HttpRequestInfo request
;
10607 request
.method
= "GET";
10608 request
.url
= origin
;
10609 request
.load_flags
= 0;
10611 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10613 // Use a TCP Socket Pool with only one connection per group. This is used
10614 // to validate that the TCP socket is not released to the pool between
10615 // each round of multi-round authentication.
10616 HttpNetworkSessionPeer
session_peer(session
);
10617 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10618 50, // Max sockets for pool
10619 1, // Max sockets per group
10620 session_deps_
.host_resolver
.get(),
10621 session_deps_
.socket_factory
.get(),
10622 session_deps_
.net_log
);
10623 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10624 new MockClientSocketPoolManager
);
10625 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10626 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10628 scoped_ptr
<HttpTransaction
> trans(
10629 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10630 TestCompletionCallback callback
;
10632 const MockWrite
kGet(
10633 "GET / HTTP/1.1\r\n"
10634 "Host: www.example.com\r\n"
10635 "Connection: keep-alive\r\n\r\n");
10636 const MockWrite
kGetAuth(
10637 "GET / HTTP/1.1\r\n"
10638 "Host: www.example.com\r\n"
10639 "Connection: keep-alive\r\n"
10640 "Authorization: auth_token\r\n\r\n");
10642 const MockRead
kServerChallenge(
10643 "HTTP/1.1 401 Unauthorized\r\n"
10644 "WWW-Authenticate: Mock realm=server\r\n"
10645 "Content-Type: text/html; charset=iso-8859-1\r\n"
10646 "Content-Length: 14\r\n\r\n"
10647 "Unauthorized\r\n");
10648 const MockRead
kSuccess(
10649 "HTTP/1.1 200 OK\r\n"
10650 "Content-Type: text/html; charset=iso-8859-1\r\n"
10651 "Content-Length: 3\r\n\r\n"
10654 MockWrite writes
[] = {
10663 // Competing request
10666 MockRead reads
[] = {
10675 // Competing response
10678 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10679 writes
, arraysize(writes
));
10680 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10682 const char kSocketGroup
[] = "www.example.com:80";
10684 // First round of authentication.
10685 auth_handler
->SetGenerateExpectation(false, OK
);
10686 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10687 if (rv
== ERR_IO_PENDING
)
10688 rv
= callback
.WaitForResult();
10690 response
= trans
->GetResponseInfo();
10691 ASSERT_TRUE(response
!= NULL
);
10692 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10693 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10695 // In between rounds, another request comes in for the same domain.
10696 // It should not be able to grab the TCP socket that trans has already
10698 scoped_ptr
<HttpTransaction
> trans_compete(
10699 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10700 TestCompletionCallback callback_compete
;
10701 rv
= trans_compete
->Start(
10702 &request
, callback_compete
.callback(), BoundNetLog());
10703 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10704 // callback_compete.WaitForResult at this point would stall forever,
10705 // since the HttpNetworkTransaction does not release the request back to
10706 // the pool until after authentication completes.
10708 // Second round of authentication.
10709 auth_handler
->SetGenerateExpectation(false, OK
);
10710 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10711 if (rv
== ERR_IO_PENDING
)
10712 rv
= callback
.WaitForResult();
10714 response
= trans
->GetResponseInfo();
10715 ASSERT_TRUE(response
!= NULL
);
10716 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10717 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10719 // Third round of authentication.
10720 auth_handler
->SetGenerateExpectation(false, OK
);
10721 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10722 if (rv
== ERR_IO_PENDING
)
10723 rv
= callback
.WaitForResult();
10725 response
= trans
->GetResponseInfo();
10726 ASSERT_TRUE(response
!= NULL
);
10727 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10728 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10730 // Fourth round of authentication, which completes successfully.
10731 auth_handler
->SetGenerateExpectation(false, OK
);
10732 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10733 if (rv
== ERR_IO_PENDING
)
10734 rv
= callback
.WaitForResult();
10736 response
= trans
->GetResponseInfo();
10737 ASSERT_TRUE(response
!= NULL
);
10738 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10739 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10741 // Read the body since the fourth round was successful. This will also
10742 // release the socket back to the pool.
10743 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10744 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10745 if (rv
== ERR_IO_PENDING
)
10746 rv
= callback
.WaitForResult();
10748 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10750 // There are still 0 idle sockets, since the trans_compete transaction
10751 // will be handed it immediately after trans releases it to the group.
10752 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10754 // The competing request can now finish. Wait for the headers and then
10756 rv
= callback_compete
.WaitForResult();
10758 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10759 if (rv
== ERR_IO_PENDING
)
10760 rv
= callback
.WaitForResult();
10762 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10765 // Finally, the socket is released to the group.
10766 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10769 // This tests the case that a request is issued via http instead of spdy after
10770 // npn is negotiated.
10771 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10772 session_deps_
.use_alternative_services
= true;
10773 NextProtoVector next_protos
;
10774 next_protos
.push_back(kProtoHTTP11
);
10775 session_deps_
.next_protos
= next_protos
;
10777 HttpRequestInfo request
;
10778 request
.method
= "GET";
10779 request
.url
= GURL("https://www.example.org/");
10780 request
.load_flags
= 0;
10782 MockWrite data_writes
[] = {
10784 "GET / HTTP/1.1\r\n"
10785 "Host: www.example.org\r\n"
10786 "Connection: keep-alive\r\n\r\n"),
10789 std::string alternate_protocol_http_header
=
10790 GetAlternateProtocolHttpHeader();
10792 MockRead data_reads
[] = {
10793 MockRead("HTTP/1.1 200 OK\r\n"),
10794 MockRead(alternate_protocol_http_header
.c_str()),
10796 MockRead("hello world"),
10797 MockRead(SYNCHRONOUS
, OK
),
10800 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10801 ssl
.SetNextProto(kProtoHTTP11
);
10803 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10805 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10806 data_writes
, arraysize(data_writes
));
10807 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10809 TestCompletionCallback callback
;
10811 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10812 scoped_ptr
<HttpTransaction
> trans(
10813 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10815 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10817 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10818 EXPECT_EQ(OK
, callback
.WaitForResult());
10820 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10821 ASSERT_TRUE(response
!= NULL
);
10822 ASSERT_TRUE(response
->headers
.get() != NULL
);
10823 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10825 std::string response_data
;
10826 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10827 EXPECT_EQ("hello world", response_data
);
10829 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10830 EXPECT_TRUE(response
->was_npn_negotiated
);
10833 // Simulate the SSL handshake completing with an NPN negotiation followed by an
10834 // immediate server closing of the socket.
10835 // Regression test for https://crbug.com/46369.
10836 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10837 session_deps_
.use_alternative_services
= true;
10838 session_deps_
.next_protos
= SpdyNextProtos();
10840 HttpRequestInfo request
;
10841 request
.method
= "GET";
10842 request
.url
= GURL("https://www.example.org/");
10843 request
.load_flags
= 0;
10845 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10846 ssl
.SetNextProto(GetParam());
10847 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10849 scoped_ptr
<SpdyFrame
> req(
10850 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10851 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 1)};
10853 MockRead spdy_reads
[] = {
10854 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10857 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10858 arraysize(spdy_writes
));
10859 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10861 TestCompletionCallback callback
;
10863 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10864 scoped_ptr
<HttpTransaction
> trans(
10865 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10867 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10868 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10869 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10872 // A subclass of HttpAuthHandlerMock that records the request URL when
10873 // it gets it. This is needed since the auth handler may get destroyed
10874 // before we get a chance to query it.
10875 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10877 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10879 ~UrlRecordingHttpAuthHandlerMock() override
{}
10882 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10883 const HttpRequestInfo
* request
,
10884 const CompletionCallback
& callback
,
10885 std::string
* auth_token
) override
{
10886 *url_
= request
->url
;
10887 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10888 credentials
, request
, callback
, auth_token
);
10895 // This test ensures that the URL passed into the proxy is upgraded to https
10896 // when doing an Alternate Protocol upgrade.
10897 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10898 session_deps_
.use_alternative_services
= true;
10899 session_deps_
.next_protos
= SpdyNextProtos();
10901 session_deps_
.proxy_service
=
10902 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
10903 TestNetLog net_log
;
10904 session_deps_
.net_log
= &net_log
;
10907 HttpAuthHandlerMock::Factory
* auth_factory
=
10908 new HttpAuthHandlerMock::Factory();
10909 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10910 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10911 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10912 auth_factory
->set_do_init_from_challenge(true);
10913 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10916 HttpRequestInfo request
;
10917 request
.method
= "GET";
10918 request
.url
= GURL("http://www.example.org");
10919 request
.load_flags
= 0;
10921 // First round goes unauthenticated through the proxy.
10922 MockWrite data_writes_1
[] = {
10924 "GET http://www.example.org/ HTTP/1.1\r\n"
10925 "Host: www.example.org\r\n"
10926 "Proxy-Connection: keep-alive\r\n"
10929 MockRead data_reads_1
[] = {
10930 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10931 MockRead("HTTP/1.1 200 OK\r\n"),
10932 MockRead("Alternate-Protocol: 443:"),
10933 MockRead(GetAlternateProtocolFromParam()),
10935 MockRead("Proxy-Connection: close\r\n"),
10938 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10939 data_writes_1
, arraysize(data_writes_1
));
10941 // Second round tries to tunnel to www.example.org due to the
10942 // Alternate-Protocol announcement in the first round. It fails due
10943 // to a proxy authentication challenge.
10944 // After the failure, a tunnel is established to www.example.org using
10945 // Proxy-Authorization headers. There is then a SPDY request round.
10947 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10948 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10949 // does a Disconnect and Connect on the same socket, rather than trying
10950 // to obtain a new one.
10952 // NOTE: Originally, the proxy response to the second CONNECT request
10953 // simply returned another 407 so the unit test could skip the SSL connection
10954 // establishment and SPDY framing issues. Alas, the
10955 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10956 // complicated to set up expectations for than the SPDY session.
10958 scoped_ptr
<SpdyFrame
> req(
10959 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10960 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10961 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10963 MockWrite data_writes_2
[] = {
10964 // First connection attempt without Proxy-Authorization.
10965 MockWrite(ASYNC
, 0,
10966 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10967 "Host: www.example.org\r\n"
10968 "Proxy-Connection: keep-alive\r\n"
10971 // Second connection attempt with Proxy-Authorization.
10972 MockWrite(ASYNC
, 2,
10973 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10974 "Host: www.example.org\r\n"
10975 "Proxy-Connection: keep-alive\r\n"
10976 "Proxy-Authorization: auth_token\r\n"
10980 CreateMockWrite(*req
, 4),
10982 MockRead data_reads_2
[] = {
10983 // First connection attempt fails
10985 "HTTP/1.1 407 Unauthorized\r\n"
10986 "Proxy-Authenticate: Mock\r\n"
10987 "Content-Length: 0\r\n"
10988 "Proxy-Connection: keep-alive\r\n"
10991 // Second connection attempt passes
10992 MockRead(ASYNC
, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
10995 CreateMockRead(*resp
.get(), 5), CreateMockRead(*data
.get(), 6),
10996 MockRead(ASYNC
, 0, 0, 7),
10998 SequencedSocketData
data_2(data_reads_2
, arraysize(data_reads_2
),
10999 data_writes_2
, arraysize(data_writes_2
));
11001 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11002 ssl
.SetNextProto(GetParam());
11003 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11004 ASSERT_TRUE(ssl
.cert
.get());
11006 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
11007 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
11009 hanging_non_alternate_protocol_socket
.set_connect_data(
11010 never_finishing_connect
);
11012 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
11013 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
11014 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11015 session_deps_
.socket_factory
->AddSocketDataProvider(
11016 &hanging_non_alternate_protocol_socket
);
11017 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11019 // First round should work and provide the Alternate-Protocol state.
11020 TestCompletionCallback callback_1
;
11021 scoped_ptr
<HttpTransaction
> trans_1(
11022 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11023 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
11024 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11025 EXPECT_EQ(OK
, callback_1
.WaitForResult());
11027 // Second round should attempt a tunnel connect and get an auth challenge.
11028 TestCompletionCallback callback_2
;
11029 scoped_ptr
<HttpTransaction
> trans_2(
11030 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11031 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
11032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11033 EXPECT_EQ(OK
, callback_2
.WaitForResult());
11034 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
11035 ASSERT_TRUE(response
!= NULL
);
11036 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
11038 // Restart with auth. Tunnel should work and response received.
11039 TestCompletionCallback callback_3
;
11040 rv
= trans_2
->RestartWithAuth(
11041 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
11042 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11043 EXPECT_EQ(OK
, callback_3
.WaitForResult());
11045 // After all that work, these two lines (or actually, just the scheme) are
11046 // what this test is all about. Make sure it happens correctly.
11047 EXPECT_EQ("https", request_url
.scheme());
11048 EXPECT_EQ("www.example.org", request_url
.host());
11050 LoadTimingInfo load_timing_info
;
11051 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
11052 TestLoadTimingNotReusedWithPac(load_timing_info
,
11053 CONNECT_TIMING_HAS_SSL_TIMES
);
11056 // Test that if we cancel the transaction as the connection is completing, that
11057 // everything tears down correctly.
11058 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
11059 // Setup everything about the connection to complete synchronously, so that
11060 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
11061 // for is the callback from the HttpStreamRequest.
11062 // Then cancel the transaction.
11063 // Verify that we don't crash.
11064 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
11065 MockRead data_reads
[] = {
11066 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
11067 MockRead(SYNCHRONOUS
, "hello world"),
11068 MockRead(SYNCHRONOUS
, OK
),
11071 HttpRequestInfo request
;
11072 request
.method
= "GET";
11073 request
.url
= GURL("http://www.example.org/");
11074 request
.load_flags
= 0;
11076 session_deps_
.host_resolver
->set_synchronous_mode(true);
11077 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11078 scoped_ptr
<HttpTransaction
> trans(
11079 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11081 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
11082 data
.set_connect_data(mock_connect
);
11083 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11085 TestCompletionCallback callback
;
11087 BoundTestNetLog log
;
11088 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
11089 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11090 trans
.reset(); // Cancel the transaction here.
11092 base::MessageLoop::current()->RunUntilIdle();
11095 // Test that if a transaction is cancelled after receiving the headers, the
11096 // stream is drained properly and added back to the socket pool. The main
11097 // purpose of this test is to make sure that an HttpStreamParser can be read
11098 // from after the HttpNetworkTransaction and the objects it owns have been
11100 // See http://crbug.com/368418
11101 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
11102 MockRead data_reads
[] = {
11103 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
11104 MockRead(ASYNC
, "Content-Length: 2\r\n"),
11105 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
11106 MockRead(ASYNC
, "1"),
11107 // 2 async reads are necessary to trigger a ReadResponseBody call after the
11108 // HttpNetworkTransaction has been deleted.
11109 MockRead(ASYNC
, "2"),
11110 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
11112 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
11113 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11115 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11118 HttpRequestInfo request
;
11119 request
.method
= "GET";
11120 request
.url
= GURL("http://www.example.org/");
11121 request
.load_flags
= 0;
11123 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
11124 TestCompletionCallback callback
;
11126 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
11127 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11128 callback
.WaitForResult();
11130 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
11131 ASSERT_TRUE(response
!= NULL
);
11132 EXPECT_TRUE(response
->headers
.get() != NULL
);
11133 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11135 // The transaction and HttpRequestInfo are deleted.
11138 // Let the HttpResponseBodyDrainer drain the socket.
11139 base::MessageLoop::current()->RunUntilIdle();
11141 // Socket should now be idle, waiting to be reused.
11142 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
11145 // Test a basic GET request through a proxy.
11146 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
11147 session_deps_
.proxy_service
=
11148 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
11149 BoundTestNetLog log
;
11150 session_deps_
.net_log
= log
.bound().net_log();
11151 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11153 HttpRequestInfo request
;
11154 request
.method
= "GET";
11155 request
.url
= GURL("http://www.example.org/");
11157 MockWrite data_writes1
[] = {
11159 "GET http://www.example.org/ HTTP/1.1\r\n"
11160 "Host: www.example.org\r\n"
11161 "Proxy-Connection: keep-alive\r\n\r\n"),
11164 MockRead data_reads1
[] = {
11165 MockRead("HTTP/1.1 200 OK\r\n"),
11166 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11167 MockRead("Content-Length: 100\r\n\r\n"),
11168 MockRead(SYNCHRONOUS
, OK
),
11171 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11172 data_writes1
, arraysize(data_writes1
));
11173 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11175 TestCompletionCallback callback1
;
11177 scoped_ptr
<HttpTransaction
> trans(
11178 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11179 BeforeProxyHeadersSentHandler proxy_headers_handler
;
11180 trans
->SetBeforeProxyHeadersSentCallback(
11181 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
11182 base::Unretained(&proxy_headers_handler
)));
11184 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11185 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11187 rv
= callback1
.WaitForResult();
11190 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11191 ASSERT_TRUE(response
!= NULL
);
11193 EXPECT_TRUE(response
->headers
->IsKeepAlive());
11194 EXPECT_EQ(200, response
->headers
->response_code());
11195 EXPECT_EQ(100, response
->headers
->GetContentLength());
11196 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11198 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11199 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
11200 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
11201 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11203 LoadTimingInfo load_timing_info
;
11204 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11205 TestLoadTimingNotReusedWithPac(load_timing_info
,
11206 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
11209 // Test a basic HTTPS GET request through a proxy.
11210 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
11211 session_deps_
.proxy_service
=
11212 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
11213 BoundTestNetLog log
;
11214 session_deps_
.net_log
= log
.bound().net_log();
11215 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11217 HttpRequestInfo request
;
11218 request
.method
= "GET";
11219 request
.url
= GURL("https://www.example.org/");
11221 // Since we have proxy, should try to establish tunnel.
11222 MockWrite data_writes1
[] = {
11224 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11225 "Host: www.example.org\r\n"
11226 "Proxy-Connection: keep-alive\r\n\r\n"),
11229 "GET / HTTP/1.1\r\n"
11230 "Host: www.example.org\r\n"
11231 "Connection: keep-alive\r\n\r\n"),
11234 MockRead data_reads1
[] = {
11235 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11237 MockRead("HTTP/1.1 200 OK\r\n"),
11238 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11239 MockRead("Content-Length: 100\r\n\r\n"),
11240 MockRead(SYNCHRONOUS
, OK
),
11243 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11244 data_writes1
, arraysize(data_writes1
));
11245 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11246 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11247 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11249 TestCompletionCallback callback1
;
11251 scoped_ptr
<HttpTransaction
> trans(
11252 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11254 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11255 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11257 rv
= callback1
.WaitForResult();
11259 TestNetLogEntry::List entries
;
11260 log
.GetEntries(&entries
);
11261 size_t pos
= ExpectLogContainsSomewhere(
11262 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11263 NetLog::PHASE_NONE
);
11264 ExpectLogContainsSomewhere(
11266 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11267 NetLog::PHASE_NONE
);
11269 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11270 ASSERT_TRUE(response
!= NULL
);
11272 EXPECT_TRUE(response
->headers
->IsKeepAlive());
11273 EXPECT_EQ(200, response
->headers
->response_code());
11274 EXPECT_EQ(100, response
->headers
->GetContentLength());
11275 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11276 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11278 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11280 LoadTimingInfo load_timing_info
;
11281 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11282 TestLoadTimingNotReusedWithPac(load_timing_info
,
11283 CONNECT_TIMING_HAS_SSL_TIMES
);
11286 // Test a basic HTTPS GET request through a proxy, but the server hangs up
11287 // while establishing the tunnel.
11288 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
11289 session_deps_
.proxy_service
= ProxyService::CreateFixed("myproxy:70");
11290 BoundTestNetLog log
;
11291 session_deps_
.net_log
= log
.bound().net_log();
11292 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11294 HttpRequestInfo request
;
11295 request
.method
= "GET";
11296 request
.url
= GURL("https://www.example.org/");
11298 // Since we have proxy, should try to establish tunnel.
11299 MockWrite data_writes1
[] = {
11301 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11302 "Host: www.example.org\r\n"
11303 "Proxy-Connection: keep-alive\r\n\r\n"),
11306 "GET / HTTP/1.1\r\n"
11307 "Host: www.example.org\r\n"
11308 "Connection: keep-alive\r\n\r\n"),
11311 MockRead data_reads1
[] = {
11312 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
11313 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11314 MockRead(ASYNC
, 0, 0), // EOF
11317 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11318 data_writes1
, arraysize(data_writes1
));
11319 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11320 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11321 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11323 TestCompletionCallback callback1
;
11325 scoped_ptr
<HttpTransaction
> trans(
11326 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11328 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11329 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11331 rv
= callback1
.WaitForResult();
11332 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
11333 TestNetLogEntry::List entries
;
11334 log
.GetEntries(&entries
);
11335 size_t pos
= ExpectLogContainsSomewhere(
11336 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11337 NetLog::PHASE_NONE
);
11338 ExpectLogContainsSomewhere(
11340 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11341 NetLog::PHASE_NONE
);
11344 // Test for crbug.com/55424.
11345 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
11346 scoped_ptr
<SpdyFrame
> req(
11347 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11348 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
11350 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11351 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11352 MockRead spdy_reads
[] = {
11353 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
11356 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
11357 arraysize(spdy_writes
));
11358 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11360 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11361 ssl
.SetNextProto(GetParam());
11362 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11364 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11366 // Set up an initial SpdySession in the pool to reuse.
11367 HostPortPair
host_port_pair("www.example.org", 443);
11368 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
11369 PRIVACY_MODE_DISABLED
);
11370 base::WeakPtr
<SpdySession
> spdy_session
=
11371 CreateInsecureSpdySession(session
, key
, BoundNetLog());
11373 HttpRequestInfo request
;
11374 request
.method
= "GET";
11375 request
.url
= GURL("https://www.example.org/");
11376 request
.load_flags
= 0;
11378 // This is the important line that marks this as a preconnect.
11379 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11381 scoped_ptr
<HttpTransaction
> trans(
11382 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11384 TestCompletionCallback callback
;
11385 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11386 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11387 EXPECT_EQ(OK
, callback
.WaitForResult());
11390 // Given a net error, cause that error to be returned from the first Write()
11391 // call and verify that the HttpTransaction fails with that error.
11392 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11393 int error
, IoMode mode
) {
11394 HttpRequestInfo request_info
;
11395 request_info
.url
= GURL("https://www.example.com/");
11396 request_info
.method
= "GET";
11397 request_info
.load_flags
= LOAD_NORMAL
;
11399 SSLSocketDataProvider
ssl_data(mode
, OK
);
11400 MockWrite data_writes
[] = {
11401 MockWrite(mode
, error
),
11403 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11404 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11405 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11407 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11408 scoped_ptr
<HttpTransaction
> trans(
11409 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11411 TestCompletionCallback callback
;
11412 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11413 if (rv
== ERR_IO_PENDING
)
11414 rv
= callback
.WaitForResult();
11415 ASSERT_EQ(error
, rv
);
11418 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11419 // Just check a grab bag of cert errors.
11420 static const int kErrors
[] = {
11421 ERR_CERT_COMMON_NAME_INVALID
,
11422 ERR_CERT_AUTHORITY_INVALID
,
11423 ERR_CERT_DATE_INVALID
,
11425 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11426 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11427 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11431 // Ensure that a client certificate is removed from the SSL client auth
11433 // 1) No proxy is involved.
11434 // 2) TLS False Start is disabled.
11435 // 3) The initial TLS handshake requests a client certificate.
11436 // 4) The client supplies an invalid/unacceptable certificate.
11437 TEST_P(HttpNetworkTransactionTest
,
11438 ClientAuthCertCache_Direct_NoFalseStart
) {
11439 HttpRequestInfo request_info
;
11440 request_info
.url
= GURL("https://www.example.com/");
11441 request_info
.method
= "GET";
11442 request_info
.load_flags
= LOAD_NORMAL
;
11444 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11445 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11447 // [ssl_]data1 contains the data for the first SSL handshake. When a
11448 // CertificateRequest is received for the first time, the handshake will
11449 // be aborted to allow the caller to provide a certificate.
11450 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11451 ssl_data1
.cert_request_info
= cert_request
.get();
11452 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11453 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11454 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11456 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11457 // False Start is not being used, the result of the SSL handshake will be
11458 // returned as part of the SSLClientSocket::Connect() call. This test
11459 // matches the result of a server sending a handshake_failure alert,
11460 // rather than a Finished message, because it requires a client
11461 // certificate and none was supplied.
11462 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11463 ssl_data2
.cert_request_info
= cert_request
.get();
11464 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11465 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11466 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11468 // [ssl_]data3 contains the data for the third SSL handshake. When a
11469 // connection to a server fails during an SSL handshake,
11470 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11471 // connection was attempted with TLSv1.2. This is transparent to the caller
11472 // of the HttpNetworkTransaction. Because this test failure is due to
11473 // requiring a client certificate, this fallback handshake should also
11475 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11476 ssl_data3
.cert_request_info
= cert_request
.get();
11477 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11478 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11479 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11481 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11482 // connection to a server fails during an SSL handshake,
11483 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11484 // connection was attempted with TLSv1.1. This is transparent to the caller
11485 // of the HttpNetworkTransaction. Because this test failure is due to
11486 // requiring a client certificate, this fallback handshake should also
11488 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11489 ssl_data4
.cert_request_info
= cert_request
.get();
11490 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11491 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11492 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11494 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11495 scoped_ptr
<HttpTransaction
> trans(
11496 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11498 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11499 TestCompletionCallback callback
;
11500 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11501 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11503 // Complete the SSL handshake, which should abort due to requiring a
11504 // client certificate.
11505 rv
= callback
.WaitForResult();
11506 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11508 // Indicate that no certificate should be supplied. From the perspective
11509 // of SSLClientCertCache, NULL is just as meaningful as a real
11510 // certificate, so this is the same as supply a
11511 // legitimate-but-unacceptable certificate.
11512 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11513 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11515 // Ensure the certificate was added to the client auth cache before
11516 // allowing the connection to continue restarting.
11517 scoped_refptr
<X509Certificate
> client_cert
;
11518 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11519 HostPortPair("www.example.com", 443), &client_cert
));
11520 ASSERT_EQ(NULL
, client_cert
.get());
11522 // Restart the handshake. This will consume ssl_data2, which fails, and
11523 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11524 // The result code is checked against what ssl_data4 should return.
11525 rv
= callback
.WaitForResult();
11526 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11528 // Ensure that the client certificate is removed from the cache on a
11529 // handshake failure.
11530 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11531 HostPortPair("www.example.com", 443), &client_cert
));
11534 // Ensure that a client certificate is removed from the SSL client auth
11536 // 1) No proxy is involved.
11537 // 2) TLS False Start is enabled.
11538 // 3) The initial TLS handshake requests a client certificate.
11539 // 4) The client supplies an invalid/unacceptable certificate.
11540 TEST_P(HttpNetworkTransactionTest
,
11541 ClientAuthCertCache_Direct_FalseStart
) {
11542 HttpRequestInfo request_info
;
11543 request_info
.url
= GURL("https://www.example.com/");
11544 request_info
.method
= "GET";
11545 request_info
.load_flags
= LOAD_NORMAL
;
11547 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11548 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11550 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11551 // return successfully after reading up to the peer's Certificate message.
11552 // This is to allow the caller to call SSLClientSocket::Write(), which can
11553 // enqueue application data to be sent in the same packet as the
11554 // ChangeCipherSpec and Finished messages.
11555 // The actual handshake will be finished when SSLClientSocket::Read() is
11556 // called, which expects to process the peer's ChangeCipherSpec and
11557 // Finished messages. If there was an error negotiating with the peer,
11558 // such as due to the peer requiring a client certificate when none was
11559 // supplied, the alert sent by the peer won't be processed until Read() is
11562 // Like the non-False Start case, when a client certificate is requested by
11563 // the peer, the handshake is aborted during the Connect() call.
11564 // [ssl_]data1 represents the initial SSL handshake with the peer.
11565 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11566 ssl_data1
.cert_request_info
= cert_request
.get();
11567 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11568 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11569 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11571 // When a client certificate is supplied, Connect() will not be aborted
11572 // when the peer requests the certificate. Instead, the handshake will
11573 // artificially succeed, allowing the caller to write the HTTP request to
11574 // the socket. The handshake messages are not processed until Read() is
11575 // called, which then detects that the handshake was aborted, due to the
11576 // peer sending a handshake_failure because it requires a client
11578 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11579 ssl_data2
.cert_request_info
= cert_request
.get();
11580 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11581 MockRead data2_reads
[] = {
11582 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11584 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11585 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11587 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11588 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11589 // TLSv1. It has the same behaviour as [ssl_]data2.
11590 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11591 ssl_data3
.cert_request_info
= cert_request
.get();
11592 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11593 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11594 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11596 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11597 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11598 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11599 ssl_data4
.cert_request_info
= cert_request
.get();
11600 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11601 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11602 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11604 // Need one more if TLSv1.2 is enabled.
11605 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11606 ssl_data5
.cert_request_info
= cert_request
.get();
11607 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11608 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11609 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11611 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11612 scoped_ptr
<HttpTransaction
> trans(
11613 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11615 // Begin the initial SSL handshake.
11616 TestCompletionCallback callback
;
11617 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11618 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11620 // Complete the SSL handshake, which should abort due to requiring a
11621 // client certificate.
11622 rv
= callback
.WaitForResult();
11623 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11625 // Indicate that no certificate should be supplied. From the perspective
11626 // of SSLClientCertCache, NULL is just as meaningful as a real
11627 // certificate, so this is the same as supply a
11628 // legitimate-but-unacceptable certificate.
11629 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11630 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11632 // Ensure the certificate was added to the client auth cache before
11633 // allowing the connection to continue restarting.
11634 scoped_refptr
<X509Certificate
> client_cert
;
11635 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11636 HostPortPair("www.example.com", 443), &client_cert
));
11637 ASSERT_EQ(NULL
, client_cert
.get());
11639 // Restart the handshake. This will consume ssl_data2, which fails, and
11640 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11641 // The result code is checked against what ssl_data4 should return.
11642 rv
= callback
.WaitForResult();
11643 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11645 // Ensure that the client certificate is removed from the cache on a
11646 // handshake failure.
11647 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11648 HostPortPair("www.example.com", 443), &client_cert
));
11651 // Ensure that a client certificate is removed from the SSL client auth
11653 // 1) An HTTPS proxy is involved.
11654 // 3) The HTTPS proxy requests a client certificate.
11655 // 4) The client supplies an invalid/unacceptable certificate for the
11657 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11658 // then for connecting to an HTTP endpoint.
11659 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11660 session_deps_
.proxy_service
= ProxyService::CreateFixed("https://proxy:70");
11661 BoundTestNetLog log
;
11662 session_deps_
.net_log
= log
.bound().net_log();
11664 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11665 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11667 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11668 // [ssl_]data[1-3]. Rather than represending the endpoint
11669 // (www.example.com:443), they represent failures with the HTTPS proxy
11671 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11672 ssl_data1
.cert_request_info
= cert_request
.get();
11673 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11674 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11675 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11677 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11678 ssl_data2
.cert_request_info
= cert_request
.get();
11679 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11680 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11681 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11683 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11685 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11686 ssl_data3
.cert_request_info
= cert_request
.get();
11687 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11688 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11689 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11692 HttpRequestInfo requests
[2];
11693 requests
[0].url
= GURL("https://www.example.com/");
11694 requests
[0].method
= "GET";
11695 requests
[0].load_flags
= LOAD_NORMAL
;
11697 requests
[1].url
= GURL("http://www.example.com/");
11698 requests
[1].method
= "GET";
11699 requests
[1].load_flags
= LOAD_NORMAL
;
11701 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11702 session_deps_
.socket_factory
->ResetNextMockIndexes();
11703 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11704 scoped_ptr
<HttpNetworkTransaction
> trans(
11705 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11707 // Begin the SSL handshake with the proxy.
11708 TestCompletionCallback callback
;
11709 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11710 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11712 // Complete the SSL handshake, which should abort due to requiring a
11713 // client certificate.
11714 rv
= callback
.WaitForResult();
11715 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11717 // Indicate that no certificate should be supplied. From the perspective
11718 // of SSLClientCertCache, NULL is just as meaningful as a real
11719 // certificate, so this is the same as supply a
11720 // legitimate-but-unacceptable certificate.
11721 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11722 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11724 // Ensure the certificate was added to the client auth cache before
11725 // allowing the connection to continue restarting.
11726 scoped_refptr
<X509Certificate
> client_cert
;
11727 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11728 HostPortPair("proxy", 70), &client_cert
));
11729 ASSERT_EQ(NULL
, client_cert
.get());
11730 // Ensure the certificate was NOT cached for the endpoint. This only
11731 // applies to HTTPS requests, but is fine to check for HTTP requests.
11732 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11733 HostPortPair("www.example.com", 443), &client_cert
));
11735 // Restart the handshake. This will consume ssl_data2, which fails, and
11736 // then consume ssl_data3, which should also fail. The result code is
11737 // checked against what ssl_data3 should return.
11738 rv
= callback
.WaitForResult();
11739 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11741 // Now that the new handshake has failed, ensure that the client
11742 // certificate was removed from the client auth cache.
11743 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11744 HostPortPair("proxy", 70), &client_cert
));
11745 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11746 HostPortPair("www.example.com", 443), &client_cert
));
11750 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPooling
) {
11751 session_deps_
.use_alternative_services
= true;
11752 session_deps_
.next_protos
= SpdyNextProtos();
11754 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11755 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11756 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11757 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11758 pool_peer
.DisableDomainAuthenticationVerification();
11760 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11761 ssl
.SetNextProto(GetParam());
11762 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11764 scoped_ptr
<SpdyFrame
> host1_req(
11765 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11766 scoped_ptr
<SpdyFrame
> host2_req(
11767 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11768 MockWrite spdy_writes
[] = {
11769 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11771 scoped_ptr
<SpdyFrame
> host1_resp(
11772 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11773 scoped_ptr
<SpdyFrame
> host1_resp_body(
11774 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11775 scoped_ptr
<SpdyFrame
> host2_resp(
11776 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11777 scoped_ptr
<SpdyFrame
> host2_resp_body(
11778 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11779 MockRead spdy_reads
[] = {
11780 CreateMockRead(*host1_resp
, 1),
11781 CreateMockRead(*host1_resp_body
, 2),
11782 CreateMockRead(*host2_resp
, 4),
11783 CreateMockRead(*host2_resp_body
, 5),
11784 MockRead(ASYNC
, 0, 6),
11787 IPAddressNumber ip
;
11788 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11789 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11790 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11791 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11792 spdy_writes
, arraysize(spdy_writes
));
11793 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11795 TestCompletionCallback callback
;
11796 HttpRequestInfo request1
;
11797 request1
.method
= "GET";
11798 request1
.url
= GURL("https://www.example.org/");
11799 request1
.load_flags
= 0;
11800 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11802 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11803 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11804 EXPECT_EQ(OK
, callback
.WaitForResult());
11806 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11807 ASSERT_TRUE(response
!= NULL
);
11808 ASSERT_TRUE(response
->headers
.get() != NULL
);
11809 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11811 std::string response_data
;
11812 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11813 EXPECT_EQ("hello!", response_data
);
11815 // Preload www.gmail.com into HostCache.
11816 HostPortPair
host_port("www.gmail.com", 443);
11817 HostResolver::RequestInfo
resolve_info(host_port
);
11818 AddressList ignored
;
11819 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11822 callback
.callback(),
11825 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11826 rv
= callback
.WaitForResult();
11829 HttpRequestInfo request2
;
11830 request2
.method
= "GET";
11831 request2
.url
= GURL("https://www.gmail.com/");
11832 request2
.load_flags
= 0;
11833 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11835 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11836 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11837 EXPECT_EQ(OK
, callback
.WaitForResult());
11839 response
= trans2
.GetResponseInfo();
11840 ASSERT_TRUE(response
!= NULL
);
11841 ASSERT_TRUE(response
->headers
.get() != NULL
);
11842 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11843 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11844 EXPECT_TRUE(response
->was_npn_negotiated
);
11845 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11846 EXPECT_EQ("hello!", response_data
);
11849 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11850 session_deps_
.use_alternative_services
= true;
11851 session_deps_
.next_protos
= SpdyNextProtos();
11853 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11854 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11855 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11856 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11857 pool_peer
.DisableDomainAuthenticationVerification();
11859 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11860 ssl
.SetNextProto(GetParam());
11861 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11863 scoped_ptr
<SpdyFrame
> host1_req(
11864 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11865 scoped_ptr
<SpdyFrame
> host2_req(
11866 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11867 MockWrite spdy_writes
[] = {
11868 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11870 scoped_ptr
<SpdyFrame
> host1_resp(
11871 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11872 scoped_ptr
<SpdyFrame
> host1_resp_body(
11873 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11874 scoped_ptr
<SpdyFrame
> host2_resp(
11875 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11876 scoped_ptr
<SpdyFrame
> host2_resp_body(
11877 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11878 MockRead spdy_reads
[] = {
11879 CreateMockRead(*host1_resp
, 1),
11880 CreateMockRead(*host1_resp_body
, 2),
11881 CreateMockRead(*host2_resp
, 4),
11882 CreateMockRead(*host2_resp_body
, 5),
11883 MockRead(ASYNC
, 0, 6),
11886 IPAddressNumber ip
;
11887 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11888 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11889 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11890 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11891 spdy_writes
, arraysize(spdy_writes
));
11892 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11894 TestCompletionCallback callback
;
11895 HttpRequestInfo request1
;
11896 request1
.method
= "GET";
11897 request1
.url
= GURL("https://www.example.org/");
11898 request1
.load_flags
= 0;
11899 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11901 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11902 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11903 EXPECT_EQ(OK
, callback
.WaitForResult());
11905 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11906 ASSERT_TRUE(response
!= NULL
);
11907 ASSERT_TRUE(response
->headers
.get() != NULL
);
11908 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11910 std::string response_data
;
11911 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11912 EXPECT_EQ("hello!", response_data
);
11914 HttpRequestInfo request2
;
11915 request2
.method
= "GET";
11916 request2
.url
= GURL("https://www.gmail.com/");
11917 request2
.load_flags
= 0;
11918 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11920 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11922 EXPECT_EQ(OK
, callback
.WaitForResult());
11924 response
= trans2
.GetResponseInfo();
11925 ASSERT_TRUE(response
!= NULL
);
11926 ASSERT_TRUE(response
->headers
.get() != NULL
);
11927 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11928 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11929 EXPECT_TRUE(response
->was_npn_negotiated
);
11930 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11931 EXPECT_EQ("hello!", response_data
);
11934 class OneTimeCachingHostResolver
: public HostResolver
{
11936 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11937 : host_port_(host_port
) {}
11938 ~OneTimeCachingHostResolver() override
{}
11940 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11942 // HostResolver methods:
11943 int Resolve(const RequestInfo
& info
,
11944 RequestPriority priority
,
11945 AddressList
* addresses
,
11946 const CompletionCallback
& callback
,
11947 RequestHandle
* out_req
,
11948 const BoundNetLog
& net_log
) override
{
11949 return host_resolver_
.Resolve(
11950 info
, priority
, addresses
, callback
, out_req
, net_log
);
11953 int ResolveFromCache(const RequestInfo
& info
,
11954 AddressList
* addresses
,
11955 const BoundNetLog
& net_log
) override
{
11956 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11957 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11958 host_resolver_
.GetHostCache()->clear();
11962 void CancelRequest(RequestHandle req
) override
{
11963 host_resolver_
.CancelRequest(req
);
11966 MockCachingHostResolver
* GetMockHostResolver() {
11967 return &host_resolver_
;
11971 MockCachingHostResolver host_resolver_
;
11972 const HostPortPair host_port_
;
11975 TEST_P(HttpNetworkTransactionTest
,
11976 UseIPConnectionPoolingWithHostCacheExpiration
) {
11977 session_deps_
.use_alternative_services
= true;
11978 session_deps_
.next_protos
= SpdyNextProtos();
11980 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11981 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11982 HttpNetworkSession::Params params
=
11983 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11984 params
.host_resolver
= &host_resolver
;
11985 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11986 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11987 pool_peer
.DisableDomainAuthenticationVerification();
11989 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11990 ssl
.SetNextProto(GetParam());
11991 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11993 scoped_ptr
<SpdyFrame
> host1_req(
11994 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11995 scoped_ptr
<SpdyFrame
> host2_req(
11996 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11997 MockWrite spdy_writes
[] = {
11998 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
12000 scoped_ptr
<SpdyFrame
> host1_resp(
12001 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12002 scoped_ptr
<SpdyFrame
> host1_resp_body(
12003 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12004 scoped_ptr
<SpdyFrame
> host2_resp(
12005 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12006 scoped_ptr
<SpdyFrame
> host2_resp_body(
12007 spdy_util_
.ConstructSpdyBodyFrame(3, true));
12008 MockRead spdy_reads
[] = {
12009 CreateMockRead(*host1_resp
, 1),
12010 CreateMockRead(*host1_resp_body
, 2),
12011 CreateMockRead(*host2_resp
, 4),
12012 CreateMockRead(*host2_resp_body
, 5),
12013 MockRead(ASYNC
, 0, 6),
12016 IPAddressNumber ip
;
12017 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
12018 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12019 MockConnect
connect(ASYNC
, OK
, peer_addr
);
12020 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
12021 spdy_writes
, arraysize(spdy_writes
));
12022 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
12024 TestCompletionCallback callback
;
12025 HttpRequestInfo request1
;
12026 request1
.method
= "GET";
12027 request1
.url
= GURL("https://www.example.org/");
12028 request1
.load_flags
= 0;
12029 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12031 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
12032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12033 EXPECT_EQ(OK
, callback
.WaitForResult());
12035 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
12036 ASSERT_TRUE(response
!= NULL
);
12037 ASSERT_TRUE(response
->headers
.get() != NULL
);
12038 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12040 std::string response_data
;
12041 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
12042 EXPECT_EQ("hello!", response_data
);
12044 // Preload cache entries into HostCache.
12045 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
12046 AddressList ignored
;
12047 rv
= host_resolver
.Resolve(resolve_info
,
12050 callback
.callback(),
12053 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12054 rv
= callback
.WaitForResult();
12057 HttpRequestInfo request2
;
12058 request2
.method
= "GET";
12059 request2
.url
= GURL("https://www.gmail.com/");
12060 request2
.load_flags
= 0;
12061 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12063 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
12064 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12065 EXPECT_EQ(OK
, callback
.WaitForResult());
12067 response
= trans2
.GetResponseInfo();
12068 ASSERT_TRUE(response
!= NULL
);
12069 ASSERT_TRUE(response
->headers
.get() != NULL
);
12070 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12071 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12072 EXPECT_TRUE(response
->was_npn_negotiated
);
12073 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
12074 EXPECT_EQ("hello!", response_data
);
12077 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
12078 const std::string https_url
= "https://www.example.org:8080/";
12079 const std::string http_url
= "http://www.example.org:8080/";
12081 // SPDY GET for HTTPS URL
12082 scoped_ptr
<SpdyFrame
> req1(
12083 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12085 MockWrite writes1
[] = {
12086 CreateMockWrite(*req1
, 0),
12089 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12090 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12091 MockRead reads1
[] = {
12092 CreateMockRead(*resp1
, 1),
12093 CreateMockRead(*body1
, 2),
12094 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
12097 SequencedSocketData
data1(reads1
, arraysize(reads1
), writes1
,
12098 arraysize(writes1
));
12099 MockConnect
connect_data1(ASYNC
, OK
);
12100 data1
.set_connect_data(connect_data1
);
12102 // HTTP GET for the HTTP URL
12103 MockWrite writes2
[] = {
12104 MockWrite(ASYNC
, 0,
12105 "GET / HTTP/1.1\r\n"
12106 "Host: www.example.org:8080\r\n"
12107 "Connection: keep-alive\r\n\r\n"),
12110 MockRead reads2
[] = {
12111 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
12112 MockRead(ASYNC
, 2, "hello"),
12113 MockRead(ASYNC
, OK
, 3),
12116 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12117 arraysize(writes2
));
12119 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12120 ssl
.SetNextProto(GetParam());
12121 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12122 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12123 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12125 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12127 // Start the first transaction to set up the SpdySession
12128 HttpRequestInfo request1
;
12129 request1
.method
= "GET";
12130 request1
.url
= GURL(https_url
);
12131 request1
.load_flags
= 0;
12132 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12133 TestCompletionCallback callback1
;
12134 EXPECT_EQ(ERR_IO_PENDING
,
12135 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12136 base::MessageLoop::current()->RunUntilIdle();
12138 EXPECT_EQ(OK
, callback1
.WaitForResult());
12139 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12141 // Now, start the HTTP request
12142 HttpRequestInfo request2
;
12143 request2
.method
= "GET";
12144 request2
.url
= GURL(http_url
);
12145 request2
.load_flags
= 0;
12146 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12147 TestCompletionCallback callback2
;
12148 EXPECT_EQ(ERR_IO_PENDING
,
12149 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12150 base::MessageLoop::current()->RunUntilIdle();
12152 EXPECT_EQ(OK
, callback2
.WaitForResult());
12153 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12156 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
12158 void Run(bool pooling
, bool valid
) {
12159 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
12161 HostPortPair
alternative("www.example.org", 443);
12163 base::FilePath certs_dir
= GetTestCertsDirectory();
12164 scoped_refptr
<X509Certificate
> cert(
12165 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
12166 ASSERT_TRUE(cert
.get());
12167 bool common_name_fallback_used
;
12169 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
12171 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
12172 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12173 ssl
.SetNextProto(GetParam());
12175 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12177 // If pooling, then start a request to alternative first to create a
12179 std::string url0
= "https://www.example.org:443";
12180 // Second request to origin, which has an alternative service, and could
12181 // open a connection to the alternative host or pool to the existing one.
12182 std::string
url1("https://");
12183 url1
.append(origin
.host());
12184 url1
.append(":443");
12186 scoped_ptr
<SpdyFrame
> req0
;
12187 scoped_ptr
<SpdyFrame
> req1
;
12188 scoped_ptr
<SpdyFrame
> resp0
;
12189 scoped_ptr
<SpdyFrame
> body0
;
12190 scoped_ptr
<SpdyFrame
> resp1
;
12191 scoped_ptr
<SpdyFrame
> body1
;
12192 std::vector
<MockWrite
> writes
;
12193 std::vector
<MockRead
> reads
;
12196 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
12197 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
12199 writes
.push_back(CreateMockWrite(*req0
, 0));
12200 writes
.push_back(CreateMockWrite(*req1
, 3));
12202 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12203 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12204 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12205 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12207 reads
.push_back(CreateMockRead(*resp0
, 1));
12208 reads
.push_back(CreateMockRead(*body0
, 2));
12209 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
12210 reads
.push_back(CreateMockRead(*resp1
, 5));
12211 reads
.push_back(CreateMockRead(*body1
, 6));
12212 reads
.push_back(MockRead(ASYNC
, OK
, 7));
12214 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
12216 writes
.push_back(CreateMockWrite(*req1
, 0));
12218 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12219 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12221 reads
.push_back(CreateMockRead(*resp1
, 1));
12222 reads
.push_back(CreateMockRead(*body1
, 2));
12223 reads
.push_back(MockRead(ASYNC
, OK
, 3));
12226 SequencedSocketData
data(vector_as_array(&reads
), reads
.size(),
12227 vector_as_array(&writes
), writes
.size());
12228 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12230 // Connection to the origin fails.
12231 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12232 StaticSocketDataProvider data_refused
;
12233 data_refused
.set_connect_data(mock_connect
);
12234 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12236 session_deps_
.use_alternative_services
= true;
12237 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12238 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12239 session
->http_server_properties();
12240 AlternativeService
alternative_service(
12241 AlternateProtocolFromNextProto(GetParam()), alternative
);
12242 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12243 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12246 // First request to alternative.
12248 scoped_ptr
<HttpTransaction
> trans0(
12249 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12250 HttpRequestInfo request0
;
12251 request0
.method
= "GET";
12252 request0
.url
= GURL(url0
);
12253 request0
.load_flags
= 0;
12254 TestCompletionCallback callback0
;
12256 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
12257 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12258 rv
= callback0
.WaitForResult();
12262 // Second request to origin.
12263 scoped_ptr
<HttpTransaction
> trans1(
12264 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12265 HttpRequestInfo request1
;
12266 request1
.method
= "GET";
12267 request1
.url
= GURL(url1
);
12268 request1
.load_flags
= 0;
12269 TestCompletionCallback callback1
;
12271 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12273 base::MessageLoop::current()->RunUntilIdle();
12274 if (data
.IsReadPaused()) {
12275 data
.CompleteRead();
12277 rv
= callback1
.WaitForResult();
12282 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12284 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
12290 INSTANTIATE_TEST_CASE_P(NextProto
,
12291 AltSvcCertificateVerificationTest
,
12292 testing::Values(kProtoSPDY31
,
12295 // The alternative service host must exhibit a certificate that is valid for the
12296 // origin host. Test that this is enforced when pooling to an existing
12298 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
12302 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
12306 // The alternative service host must exhibit a certificate that is valid for the
12307 // origin host. Test that this is enforced when opening a new connection.
12308 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
12312 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
12316 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12317 // with the alternative server. That connection should not be used.
12318 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceNotOnHttp11
) {
12319 HostPortPair
origin("origin.example.org", 443);
12320 HostPortPair
alternative("alternative.example.org", 443);
12322 // Negotiate HTTP/1.1 with alternative.example.org.
12323 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12324 ssl
.SetNextProto(kProtoHTTP11
);
12325 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12327 // No data should be read from the alternative, because HTTP/1.1 is
12329 StaticSocketDataProvider data
;
12330 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12332 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12333 // negotiated. In order to test this, a failed connection to the origin is
12334 // mocked. This way the request relies on the alternate Job.
12335 StaticSocketDataProvider data_refused
;
12336 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12337 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12339 // Set up alternative service for origin.
12340 session_deps_
.use_alternative_services
= true;
12341 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12342 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12343 session
->http_server_properties();
12344 AlternativeService
alternative_service(
12345 AlternateProtocolFromNextProto(GetParam()), alternative
);
12346 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12347 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12350 scoped_ptr
<HttpTransaction
> trans(
12351 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12352 HttpRequestInfo request
;
12353 request
.method
= "GET";
12354 request
.url
= GURL("https://origin.example.org:443");
12355 request
.load_flags
= 0;
12356 TestCompletionCallback callback
;
12358 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12359 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12360 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12361 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED
, callback
.GetResult(rv
));
12364 // A request to a server with an alternative service fires two Jobs: one to the
12365 // origin, and an alternate one to the alternative server. If the former
12366 // succeeds, the request should succeed, even if the latter fails because
12367 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12368 TEST_P(HttpNetworkTransactionTest
, FailedAlternativeServiceIsNotUserVisible
) {
12369 HostPortPair
origin("origin.example.org", 443);
12370 HostPortPair
alternative("alternative.example.org", 443);
12372 // Negotiate HTTP/1.1 with alternative.
12373 SSLSocketDataProvider
alternative_ssl(ASYNC
, OK
);
12374 alternative_ssl
.SetNextProto(kProtoHTTP11
);
12375 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&alternative_ssl
);
12377 // No data should be read from the alternative, because HTTP/1.1 is
12379 StaticSocketDataProvider data
;
12380 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12382 // Negotiate HTTP/1.1 with origin.
12383 SSLSocketDataProvider
origin_ssl(ASYNC
, OK
);
12384 origin_ssl
.SetNextProto(kProtoHTTP11
);
12385 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&origin_ssl
);
12387 MockWrite http_writes
[] = {
12389 "GET / HTTP/1.1\r\n"
12390 "Host: origin.example.org\r\n"
12391 "Connection: keep-alive\r\n\r\n"),
12393 "GET /second HTTP/1.1\r\n"
12394 "Host: origin.example.org\r\n"
12395 "Connection: keep-alive\r\n\r\n"),
12398 MockRead http_reads
[] = {
12399 MockRead("HTTP/1.1 200 OK\r\n"),
12400 MockRead("Content-Type: text/html\r\n"),
12401 MockRead("Content-Length: 6\r\n\r\n"),
12402 MockRead("foobar"),
12403 MockRead("HTTP/1.1 200 OK\r\n"),
12404 MockRead("Content-Type: text/html\r\n"),
12405 MockRead("Content-Length: 7\r\n\r\n"),
12406 MockRead("another"),
12408 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12409 http_writes
, arraysize(http_writes
));
12410 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12412 // Set up alternative service for origin.
12413 session_deps_
.use_alternative_services
= true;
12414 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12415 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12416 session
->http_server_properties();
12417 AlternativeService
alternative_service(
12418 AlternateProtocolFromNextProto(GetParam()), alternative
);
12419 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12420 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12423 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12424 HttpRequestInfo request1
;
12425 request1
.method
= "GET";
12426 request1
.url
= GURL("https://origin.example.org:443");
12427 request1
.load_flags
= 0;
12428 TestCompletionCallback callback1
;
12430 int rv
= trans1
.Start(&request1
, callback1
.callback(), BoundNetLog());
12431 rv
= callback1
.GetResult(rv
);
12434 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
12435 ASSERT_TRUE(response1
!= nullptr);
12436 ASSERT_TRUE(response1
->headers
.get() != nullptr);
12437 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12439 std::string response_data1
;
12440 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data1
));
12441 EXPECT_EQ("foobar", response_data1
);
12443 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12444 // for alternative service.
12446 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
12448 // Since |alternative_service| is broken, a second transaction to origin
12449 // should not start an alternate Job. It should pool to existing connection
12451 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12452 HttpRequestInfo request2
;
12453 request2
.method
= "GET";
12454 request2
.url
= GURL("https://origin.example.org:443/second");
12455 request2
.load_flags
= 0;
12456 TestCompletionCallback callback2
;
12458 rv
= trans2
.Start(&request2
, callback2
.callback(), BoundNetLog());
12459 rv
= callback2
.GetResult(rv
);
12462 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
12463 ASSERT_TRUE(response2
!= nullptr);
12464 ASSERT_TRUE(response2
->headers
.get() != nullptr);
12465 EXPECT_EQ("HTTP/1.1 200 OK", response2
->headers
->GetStatusLine());
12467 std::string response_data2
;
12468 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data2
));
12469 EXPECT_EQ("another", response_data2
);
12472 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12473 // HTTP/1.1 socket open to the alternative server. That socket should not be
12475 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceShouldNotPoolToHttp11
) {
12476 HostPortPair
origin("origin.example.org", 443);
12477 HostPortPair
alternative("alternative.example.org", 443);
12478 std::string origin_url
= "https://origin.example.org:443";
12479 std::string alternative_url
= "https://alternative.example.org:443";
12481 // Negotiate HTTP/1.1 with alternative.example.org.
12482 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12483 ssl
.SetNextProto(kProtoHTTP11
);
12484 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12486 // HTTP/1.1 data for |request1| and |request2|.
12487 MockWrite http_writes
[] = {
12489 "GET / HTTP/1.1\r\n"
12490 "Host: alternative.example.org\r\n"
12491 "Connection: keep-alive\r\n\r\n"),
12493 "GET / HTTP/1.1\r\n"
12494 "Host: alternative.example.org\r\n"
12495 "Connection: keep-alive\r\n\r\n"),
12498 MockRead http_reads
[] = {
12500 "HTTP/1.1 200 OK\r\n"
12501 "Content-Type: text/html; charset=iso-8859-1\r\n"
12502 "Content-Length: 40\r\n\r\n"
12503 "first HTTP/1.1 response from alternative"),
12505 "HTTP/1.1 200 OK\r\n"
12506 "Content-Type: text/html; charset=iso-8859-1\r\n"
12507 "Content-Length: 41\r\n\r\n"
12508 "second HTTP/1.1 response from alternative"),
12510 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12511 http_writes
, arraysize(http_writes
));
12512 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12514 // This test documents that an alternate Job should not pool to an already
12515 // existing HTTP/1.1 connection. In order to test this, a failed connection
12516 // to the origin is mocked. This way |request2| relies on the alternate Job.
12517 StaticSocketDataProvider data_refused
;
12518 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12519 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12521 // Set up alternative service for origin.
12522 session_deps_
.use_alternative_services
= true;
12523 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12524 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12525 session
->http_server_properties();
12526 AlternativeService
alternative_service(
12527 AlternateProtocolFromNextProto(GetParam()), alternative
);
12528 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12529 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12532 // First transaction to alternative to open an HTTP/1.1 socket.
12533 scoped_ptr
<HttpTransaction
> trans1(
12534 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12535 HttpRequestInfo request1
;
12536 request1
.method
= "GET";
12537 request1
.url
= GURL(alternative_url
);
12538 request1
.load_flags
= 0;
12539 TestCompletionCallback callback1
;
12541 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12542 EXPECT_EQ(OK
, callback1
.GetResult(rv
));
12543 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12544 ASSERT_TRUE(response1
);
12545 ASSERT_TRUE(response1
->headers
.get());
12546 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12547 EXPECT_TRUE(response1
->was_npn_negotiated
);
12548 EXPECT_FALSE(response1
->was_fetched_via_spdy
);
12549 std::string response_data1
;
12550 ASSERT_EQ(OK
, ReadTransaction(trans1
.get(), &response_data1
));
12551 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1
);
12553 // Request for origin.example.org, which has an alternative service. This
12554 // will start two Jobs: the alternative looks for connections to pool to,
12555 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12556 // open other connections to alternative server. The Job to origin fails, so
12557 // this request fails.
12558 scoped_ptr
<HttpTransaction
> trans2(
12559 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12560 HttpRequestInfo request2
;
12561 request2
.method
= "GET";
12562 request2
.url
= GURL(origin_url
);
12563 request2
.load_flags
= 0;
12564 TestCompletionCallback callback2
;
12566 rv
= trans2
->Start(&request2
, callback2
.callback(), BoundNetLog());
12567 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback2
.GetResult(rv
));
12569 // Another transaction to alternative. This is to test that the HTTP/1.1
12570 // socket is still open and in the pool.
12571 scoped_ptr
<HttpTransaction
> trans3(
12572 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12573 HttpRequestInfo request3
;
12574 request3
.method
= "GET";
12575 request3
.url
= GURL(alternative_url
);
12576 request3
.load_flags
= 0;
12577 TestCompletionCallback callback3
;
12579 rv
= trans3
->Start(&request3
, callback3
.callback(), BoundNetLog());
12580 EXPECT_EQ(OK
, callback3
.GetResult(rv
));
12581 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
12582 ASSERT_TRUE(response3
);
12583 ASSERT_TRUE(response3
->headers
.get());
12584 EXPECT_EQ("HTTP/1.1 200 OK", response3
->headers
->GetStatusLine());
12585 EXPECT_TRUE(response3
->was_npn_negotiated
);
12586 EXPECT_FALSE(response3
->was_fetched_via_spdy
);
12587 std::string response_data3
;
12588 ASSERT_EQ(OK
, ReadTransaction(trans3
.get(), &response_data3
));
12589 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3
);
12592 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
12593 const std::string https_url
= "https://www.example.org:8080/";
12594 const std::string http_url
= "http://www.example.org:8080/";
12596 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12597 const HostPortPair
host_port_pair("www.example.org", 8080);
12598 scoped_ptr
<SpdyFrame
> connect(
12599 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
12600 scoped_ptr
<SpdyFrame
> req1(
12601 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12602 scoped_ptr
<SpdyFrame
> wrapped_req1(
12603 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
12605 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12606 SpdyHeaderBlock req2_block
;
12607 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
12608 req2_block
[spdy_util_
.GetPathKey()] = "/";
12609 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
12610 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
12611 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
12612 scoped_ptr
<SpdyFrame
> req2(
12613 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
12615 MockWrite writes1
[] = {
12616 CreateMockWrite(*connect
, 0),
12617 CreateMockWrite(*wrapped_req1
, 2),
12618 CreateMockWrite(*req2
, 5),
12621 scoped_ptr
<SpdyFrame
> conn_resp(
12622 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12623 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12624 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12625 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12626 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12627 scoped_ptr
<SpdyFrame
> wrapped_body1(
12628 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12629 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12630 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12631 MockRead reads1
[] = {
12632 CreateMockRead(*conn_resp
, 1),
12633 CreateMockRead(*wrapped_resp1
, 3),
12634 CreateMockRead(*wrapped_body1
, 4),
12635 CreateMockRead(*resp2
, 6),
12636 CreateMockRead(*body2
, 7),
12637 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12640 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12641 writes1
, arraysize(writes1
));
12642 MockConnect
connect_data1(ASYNC
, OK
);
12643 data1
.set_connect_data(connect_data1
);
12645 session_deps_
.proxy_service
=
12646 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
12648 session_deps_
.net_log
= &log
;
12649 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12650 ssl1
.SetNextProto(GetParam());
12651 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12652 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12653 ssl2
.SetNextProto(GetParam());
12654 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12655 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12657 scoped_refptr
<HttpNetworkSession
> session(
12658 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12660 // Start the first transaction to set up the SpdySession
12661 HttpRequestInfo request1
;
12662 request1
.method
= "GET";
12663 request1
.url
= GURL(https_url
);
12664 request1
.load_flags
= 0;
12665 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12666 TestCompletionCallback callback1
;
12667 EXPECT_EQ(ERR_IO_PENDING
,
12668 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12669 base::MessageLoop::current()->RunUntilIdle();
12672 EXPECT_EQ(OK
, callback1
.WaitForResult());
12673 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12675 LoadTimingInfo load_timing_info1
;
12676 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12677 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12678 CONNECT_TIMING_HAS_SSL_TIMES
);
12680 // Now, start the HTTP request
12681 HttpRequestInfo request2
;
12682 request2
.method
= "GET";
12683 request2
.url
= GURL(http_url
);
12684 request2
.load_flags
= 0;
12685 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12686 TestCompletionCallback callback2
;
12687 EXPECT_EQ(ERR_IO_PENDING
,
12688 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12689 base::MessageLoop::current()->RunUntilIdle();
12692 EXPECT_EQ(OK
, callback2
.WaitForResult());
12693 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12695 LoadTimingInfo load_timing_info2
;
12696 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12697 // The established SPDY sessions is considered reused by the HTTP request.
12698 TestLoadTimingReusedWithPac(load_timing_info2
);
12699 // HTTP requests over a SPDY session should have a different connection
12700 // socket_log_id than requests over a tunnel.
12701 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12704 // Test that in the case where we have a SPDY session to a SPDY proxy
12705 // that we do not pool other origins that resolve to the same IP when
12706 // the certificate does not match the new origin.
12707 // http://crbug.com/134690
12708 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12709 const std::string url1
= "http://www.example.org/";
12710 const std::string url2
= "https://news.example.org/";
12711 const std::string ip_addr
= "1.2.3.4";
12713 // SPDY GET for HTTP URL (through SPDY proxy)
12714 scoped_ptr
<SpdyHeaderBlock
> headers(
12715 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12716 scoped_ptr
<SpdyFrame
> req1(
12717 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12719 MockWrite writes1
[] = {
12720 CreateMockWrite(*req1
, 0),
12723 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12724 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12725 MockRead reads1
[] = {
12726 CreateMockRead(*resp1
, 1),
12727 CreateMockRead(*body1
, 2),
12728 MockRead(ASYNC
, OK
, 3) // EOF
12731 scoped_ptr
<DeterministicSocketData
> data1(
12732 new DeterministicSocketData(reads1
, arraysize(reads1
),
12733 writes1
, arraysize(writes1
)));
12734 IPAddressNumber ip
;
12735 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12736 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12737 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12738 data1
->set_connect_data(connect_data1
);
12740 // SPDY GET for HTTPS URL (direct)
12741 scoped_ptr
<SpdyFrame
> req2(
12742 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12744 MockWrite writes2
[] = {
12745 CreateMockWrite(*req2
, 0),
12748 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12749 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12750 MockRead reads2
[] = {
12751 CreateMockRead(*resp2
, 1),
12752 CreateMockRead(*body2
, 2),
12753 MockRead(ASYNC
, OK
, 3) // EOF
12756 scoped_ptr
<DeterministicSocketData
> data2(
12757 new DeterministicSocketData(reads2
, arraysize(reads2
),
12758 writes2
, arraysize(writes2
)));
12759 MockConnect
connect_data2(ASYNC
, OK
);
12760 data2
->set_connect_data(connect_data2
);
12762 // Set up a proxy config that sends HTTP requests to a proxy, and
12763 // all others direct.
12764 ProxyConfig proxy_config
;
12765 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12766 session_deps_
.proxy_service
.reset(new ProxyService(
12767 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12769 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12770 ssl1
.SetNextProto(GetParam());
12771 // Load a valid cert. Note, that this does not need to
12772 // be valid for proxy because the MockSSLClientSocket does
12773 // not actually verify it. But SpdySession will use this
12774 // to see if it is valid for the new origin
12775 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12776 ASSERT_TRUE(ssl1
.cert
.get());
12777 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12778 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12781 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12782 ssl2
.SetNextProto(GetParam());
12783 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12784 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12787 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12788 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12789 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12791 scoped_refptr
<HttpNetworkSession
> session(
12792 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12794 // Start the first transaction to set up the SpdySession
12795 HttpRequestInfo request1
;
12796 request1
.method
= "GET";
12797 request1
.url
= GURL(url1
);
12798 request1
.load_flags
= 0;
12799 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12800 TestCompletionCallback callback1
;
12801 ASSERT_EQ(ERR_IO_PENDING
,
12802 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12805 ASSERT_TRUE(callback1
.have_result());
12806 EXPECT_EQ(OK
, callback1
.WaitForResult());
12807 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12809 // Now, start the HTTP request
12810 HttpRequestInfo request2
;
12811 request2
.method
= "GET";
12812 request2
.url
= GURL(url2
);
12813 request2
.load_flags
= 0;
12814 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12815 TestCompletionCallback callback2
;
12816 EXPECT_EQ(ERR_IO_PENDING
,
12817 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12818 base::MessageLoop::current()->RunUntilIdle();
12821 ASSERT_TRUE(callback2
.have_result());
12822 EXPECT_EQ(OK
, callback2
.WaitForResult());
12823 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12826 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12827 // error) in SPDY session, removes the socket from pool and closes the SPDY
12828 // session. Verify that new url's from the same HttpNetworkSession (and a new
12829 // SpdySession) do work. http://crbug.com/224701
12830 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12831 const std::string https_url
= "https://www.example.org/";
12833 MockRead reads1
[] = {
12834 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12837 SequencedSocketData
data1(reads1
, arraysize(reads1
), NULL
, 0);
12839 scoped_ptr
<SpdyFrame
> req2(
12840 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12841 MockWrite writes2
[] = {
12842 CreateMockWrite(*req2
, 0),
12845 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12846 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12847 MockRead reads2
[] = {
12848 CreateMockRead(*resp2
, 1),
12849 CreateMockRead(*body2
, 2),
12850 MockRead(ASYNC
, OK
, 3) // EOF
12853 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12854 arraysize(writes2
));
12856 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12857 ssl1
.SetNextProto(GetParam());
12858 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12859 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12861 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12862 ssl2
.SetNextProto(GetParam());
12863 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12864 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12866 scoped_refptr
<HttpNetworkSession
> session(
12867 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
12869 // Start the first transaction to set up the SpdySession and verify that
12870 // connection was closed.
12871 HttpRequestInfo request1
;
12872 request1
.method
= "GET";
12873 request1
.url
= GURL(https_url
);
12874 request1
.load_flags
= 0;
12875 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12876 TestCompletionCallback callback1
;
12877 EXPECT_EQ(ERR_IO_PENDING
,
12878 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12879 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12881 // Now, start the second request and make sure it succeeds.
12882 HttpRequestInfo request2
;
12883 request2
.method
= "GET";
12884 request2
.url
= GURL(https_url
);
12885 request2
.load_flags
= 0;
12886 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12887 TestCompletionCallback callback2
;
12888 EXPECT_EQ(ERR_IO_PENDING
,
12889 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12891 ASSERT_EQ(OK
, callback2
.WaitForResult());
12892 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12895 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12896 session_deps_
.next_protos
= SpdyNextProtos();
12897 ClientSocketPoolManager::set_max_sockets_per_group(
12898 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12899 ClientSocketPoolManager::set_max_sockets_per_pool(
12900 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12902 // Use two different hosts with different IPs so they don't get pooled.
12903 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12904 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12905 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12907 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12908 ssl1
.SetNextProto(GetParam());
12909 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12910 ssl2
.SetNextProto(GetParam());
12911 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12912 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12914 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12915 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12916 MockWrite spdy1_writes
[] = {
12917 CreateMockWrite(*host1_req
, 0),
12919 scoped_ptr
<SpdyFrame
> host1_resp(
12920 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12921 scoped_ptr
<SpdyFrame
> host1_resp_body(
12922 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12923 MockRead spdy1_reads
[] = {
12924 CreateMockRead(*host1_resp
, 1),
12925 CreateMockRead(*host1_resp_body
, 2),
12926 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12929 scoped_ptr
<SequencedSocketData
> spdy1_data(
12930 new SequencedSocketData(spdy1_reads
, arraysize(spdy1_reads
), spdy1_writes
,
12931 arraysize(spdy1_writes
)));
12932 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12934 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12935 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12936 MockWrite spdy2_writes
[] = {
12937 CreateMockWrite(*host2_req
, 0),
12939 scoped_ptr
<SpdyFrame
> host2_resp(
12940 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12941 scoped_ptr
<SpdyFrame
> host2_resp_body(
12942 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12943 MockRead spdy2_reads
[] = {
12944 CreateMockRead(*host2_resp
, 1),
12945 CreateMockRead(*host2_resp_body
, 2),
12946 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12949 scoped_ptr
<SequencedSocketData
> spdy2_data(
12950 new SequencedSocketData(spdy2_reads
, arraysize(spdy2_reads
), spdy2_writes
,
12951 arraysize(spdy2_writes
)));
12952 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12954 MockWrite http_write
[] = {
12955 MockWrite("GET / HTTP/1.1\r\n"
12956 "Host: www.a.com\r\n"
12957 "Connection: keep-alive\r\n\r\n"),
12960 MockRead http_read
[] = {
12961 MockRead("HTTP/1.1 200 OK\r\n"),
12962 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12963 MockRead("Content-Length: 6\r\n\r\n"),
12964 MockRead("hello!"),
12966 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12967 http_write
, arraysize(http_write
));
12968 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12970 HostPortPair
host_port_pair_a("www.a.com", 443);
12971 SpdySessionKey
spdy_session_key_a(
12972 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12974 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12976 TestCompletionCallback callback
;
12977 HttpRequestInfo request1
;
12978 request1
.method
= "GET";
12979 request1
.url
= GURL("https://www.a.com/");
12980 request1
.load_flags
= 0;
12981 scoped_ptr
<HttpNetworkTransaction
> trans(
12982 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12984 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12985 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12986 EXPECT_EQ(OK
, callback
.WaitForResult());
12988 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12989 ASSERT_TRUE(response
!= NULL
);
12990 ASSERT_TRUE(response
->headers
.get() != NULL
);
12991 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12992 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12993 EXPECT_TRUE(response
->was_npn_negotiated
);
12995 std::string response_data
;
12996 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12997 EXPECT_EQ("hello!", response_data
);
13000 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
13002 HostPortPair
host_port_pair_b("www.b.com", 443);
13003 SpdySessionKey
spdy_session_key_b(
13004 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
13006 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13007 HttpRequestInfo request2
;
13008 request2
.method
= "GET";
13009 request2
.url
= GURL("https://www.b.com/");
13010 request2
.load_flags
= 0;
13011 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13013 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
13014 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13015 EXPECT_EQ(OK
, callback
.WaitForResult());
13017 response
= trans
->GetResponseInfo();
13018 ASSERT_TRUE(response
!= NULL
);
13019 ASSERT_TRUE(response
->headers
.get() != NULL
);
13020 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
13021 EXPECT_TRUE(response
->was_fetched_via_spdy
);
13022 EXPECT_TRUE(response
->was_npn_negotiated
);
13023 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
13024 EXPECT_EQ("hello!", response_data
);
13026 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
13028 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13030 HostPortPair
host_port_pair_a1("www.a.com", 80);
13031 SpdySessionKey
spdy_session_key_a1(
13032 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
13034 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
13035 HttpRequestInfo request3
;
13036 request3
.method
= "GET";
13037 request3
.url
= GURL("http://www.a.com/");
13038 request3
.load_flags
= 0;
13039 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13041 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
13042 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13043 EXPECT_EQ(OK
, callback
.WaitForResult());
13045 response
= trans
->GetResponseInfo();
13046 ASSERT_TRUE(response
!= NULL
);
13047 ASSERT_TRUE(response
->headers
.get() != NULL
);
13048 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
13049 EXPECT_FALSE(response
->was_fetched_via_spdy
);
13050 EXPECT_FALSE(response
->was_npn_negotiated
);
13051 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
13052 EXPECT_EQ("hello!", response_data
);
13054 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
13056 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13059 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
13060 HttpRequestInfo request
;
13061 request
.method
= "GET";
13062 request
.url
= GURL("http://www.example.org/");
13063 request
.load_flags
= 0;
13065 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13066 scoped_ptr
<HttpTransaction
> trans(
13067 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13069 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
13070 StaticSocketDataProvider data
;
13071 data
.set_connect_data(mock_connect
);
13072 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13074 TestCompletionCallback callback
;
13076 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13077 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13079 rv
= callback
.WaitForResult();
13080 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
13082 // We don't care whether this succeeds or fails, but it shouldn't crash.
13083 HttpRequestHeaders request_headers
;
13084 trans
->GetFullRequestHeaders(&request_headers
);
13086 ConnectionAttempts attempts
;
13087 trans
->GetConnectionAttempts(&attempts
);
13088 ASSERT_EQ(1u, attempts
.size());
13089 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
13092 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
13093 HttpRequestInfo request
;
13094 request
.method
= "GET";
13095 request
.url
= GURL("http://www.example.org/");
13096 request
.load_flags
= 0;
13098 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13099 scoped_ptr
<HttpTransaction
> trans(
13100 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13102 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
13103 StaticSocketDataProvider data
;
13104 data
.set_connect_data(mock_connect
);
13105 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13107 TestCompletionCallback callback
;
13109 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13110 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13112 rv
= callback
.WaitForResult();
13113 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
13115 // We don't care whether this succeeds or fails, but it shouldn't crash.
13116 HttpRequestHeaders request_headers
;
13117 trans
->GetFullRequestHeaders(&request_headers
);
13119 ConnectionAttempts attempts
;
13120 trans
->GetConnectionAttempts(&attempts
);
13121 ASSERT_EQ(1u, attempts
.size());
13122 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
13125 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
13126 HttpRequestInfo request
;
13127 request
.method
= "GET";
13128 request
.url
= GURL("http://www.example.org/");
13129 request
.load_flags
= 0;
13131 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13132 scoped_ptr
<HttpTransaction
> trans(
13133 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13135 MockWrite data_writes
[] = {
13136 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13138 MockRead data_reads
[] = {
13139 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
13142 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13143 data_writes
, arraysize(data_writes
));
13144 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13146 TestCompletionCallback callback
;
13148 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13149 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13151 rv
= callback
.WaitForResult();
13152 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13154 HttpRequestHeaders request_headers
;
13155 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13156 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13159 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
13160 HttpRequestInfo request
;
13161 request
.method
= "GET";
13162 request
.url
= GURL("http://www.example.org/");
13163 request
.load_flags
= 0;
13165 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13166 scoped_ptr
<HttpTransaction
> trans(
13167 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13169 MockWrite data_writes
[] = {
13170 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
13172 MockRead data_reads
[] = {
13173 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
13176 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13177 data_writes
, arraysize(data_writes
));
13178 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13180 TestCompletionCallback callback
;
13182 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13183 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13185 rv
= callback
.WaitForResult();
13186 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13188 HttpRequestHeaders request_headers
;
13189 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13190 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13193 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
13194 HttpRequestInfo request
;
13195 request
.method
= "GET";
13196 request
.url
= GURL("http://www.example.org/");
13197 request
.load_flags
= 0;
13199 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13200 scoped_ptr
<HttpTransaction
> trans(
13201 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13203 MockWrite data_writes
[] = {
13205 "GET / HTTP/1.1\r\n"
13206 "Host: www.example.org\r\n"
13207 "Connection: keep-alive\r\n\r\n"),
13209 MockRead data_reads
[] = {
13210 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13213 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13214 data_writes
, arraysize(data_writes
));
13215 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13217 TestCompletionCallback callback
;
13219 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13220 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13222 rv
= callback
.WaitForResult();
13223 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13225 HttpRequestHeaders request_headers
;
13226 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13227 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13230 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
13231 HttpRequestInfo request
;
13232 request
.method
= "GET";
13233 request
.url
= GURL("http://www.example.org/");
13234 request
.load_flags
= 0;
13236 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13237 scoped_ptr
<HttpTransaction
> trans(
13238 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13240 MockWrite data_writes
[] = {
13242 "GET / HTTP/1.1\r\n"
13243 "Host: www.example.org\r\n"
13244 "Connection: keep-alive\r\n\r\n"),
13246 MockRead data_reads
[] = {
13247 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
13250 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13251 data_writes
, arraysize(data_writes
));
13252 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13254 TestCompletionCallback callback
;
13256 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13257 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13259 rv
= callback
.WaitForResult();
13260 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13262 HttpRequestHeaders request_headers
;
13263 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13264 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13267 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
13268 HttpRequestInfo request
;
13269 request
.method
= "GET";
13270 request
.url
= GURL("http://www.example.org/");
13271 request
.load_flags
= 0;
13272 request
.extra_headers
.SetHeader("X-Foo", "bar");
13274 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13275 scoped_ptr
<HttpTransaction
> trans(
13276 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13278 MockWrite data_writes
[] = {
13280 "GET / HTTP/1.1\r\n"
13281 "Host: www.example.org\r\n"
13282 "Connection: keep-alive\r\n"
13283 "X-Foo: bar\r\n\r\n"),
13285 MockRead data_reads
[] = {
13286 MockRead("HTTP/1.1 200 OK\r\n"
13287 "Content-Length: 5\r\n\r\n"
13289 MockRead(ASYNC
, ERR_UNEXPECTED
),
13292 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13293 data_writes
, arraysize(data_writes
));
13294 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13296 TestCompletionCallback callback
;
13298 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13299 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13301 rv
= callback
.WaitForResult();
13304 HttpRequestHeaders request_headers
;
13305 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13307 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
13308 EXPECT_EQ("bar", foo
);
13313 // Fake HttpStream that simply records calls to SetPriority().
13314 class FakeStream
: public HttpStream
,
13315 public base::SupportsWeakPtr
<FakeStream
> {
13317 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
13318 ~FakeStream() override
{}
13320 RequestPriority
priority() const { return priority_
; }
13322 int InitializeStream(const HttpRequestInfo
* request_info
,
13323 RequestPriority priority
,
13324 const BoundNetLog
& net_log
,
13325 const CompletionCallback
& callback
) override
{
13326 return ERR_IO_PENDING
;
13329 int SendRequest(const HttpRequestHeaders
& request_headers
,
13330 HttpResponseInfo
* response
,
13331 const CompletionCallback
& callback
) override
{
13333 return ERR_UNEXPECTED
;
13336 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13338 return ERR_UNEXPECTED
;
13341 int ReadResponseBody(IOBuffer
* buf
,
13343 const CompletionCallback
& callback
) override
{
13345 return ERR_UNEXPECTED
;
13348 void Close(bool not_reusable
) override
{}
13350 bool IsResponseBodyComplete() const override
{
13355 bool IsConnectionReused() const override
{
13360 void SetConnectionReused() override
{ ADD_FAILURE(); }
13362 bool CanReuseConnection() const override
{ return false; }
13364 int64
GetTotalReceivedBytes() const override
{
13369 int64_t GetTotalSentBytes() const override
{
13374 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13379 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
13381 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13385 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
13387 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13389 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
13391 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
13394 RequestPriority priority_
;
13396 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
13399 // Fake HttpStreamRequest that simply records calls to SetPriority()
13400 // and vends FakeStreams with its current priority.
13401 class FakeStreamRequest
: public HttpStreamRequest
,
13402 public base::SupportsWeakPtr
<FakeStreamRequest
> {
13404 FakeStreamRequest(RequestPriority priority
,
13405 HttpStreamRequest::Delegate
* delegate
)
13406 : priority_(priority
),
13407 delegate_(delegate
),
13408 websocket_stream_create_helper_(NULL
) {}
13410 FakeStreamRequest(RequestPriority priority
,
13411 HttpStreamRequest::Delegate
* delegate
,
13412 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
13413 : priority_(priority
),
13414 delegate_(delegate
),
13415 websocket_stream_create_helper_(create_helper
) {}
13417 ~FakeStreamRequest() override
{}
13419 RequestPriority
priority() const { return priority_
; }
13421 const WebSocketHandshakeStreamBase::CreateHelper
*
13422 websocket_stream_create_helper() const {
13423 return websocket_stream_create_helper_
;
13426 // Create a new FakeStream and pass it to the request's
13427 // delegate. Returns a weak pointer to the FakeStream.
13428 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
13429 FakeStream
* fake_stream
= new FakeStream(priority_
);
13430 // Do this before calling OnStreamReady() as OnStreamReady() may
13431 // immediately delete |fake_stream|.
13432 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
13433 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
13434 return weak_stream
;
13437 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
13439 return ERR_UNEXPECTED
;
13442 LoadState
GetLoadState() const override
{
13444 return LoadState();
13447 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13449 bool was_npn_negotiated() const override
{ return false; }
13451 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
13453 bool using_spdy() const override
{ return false; }
13455 const ConnectionAttempts
& connection_attempts() const override
{
13456 static ConnectionAttempts no_attempts
;
13457 return no_attempts
;
13461 RequestPriority priority_
;
13462 HttpStreamRequest::Delegate
* const delegate_
;
13463 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
13465 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
13468 // Fake HttpStreamFactory that vends FakeStreamRequests.
13469 class FakeStreamFactory
: public HttpStreamFactory
{
13471 FakeStreamFactory() {}
13472 ~FakeStreamFactory() override
{}
13474 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13475 // RequestStream() (which may be NULL if it was destroyed already).
13476 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
13477 return last_stream_request_
;
13480 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
13481 RequestPriority priority
,
13482 const SSLConfig
& server_ssl_config
,
13483 const SSLConfig
& proxy_ssl_config
,
13484 HttpStreamRequest::Delegate
* delegate
,
13485 const BoundNetLog
& net_log
) override
{
13486 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
13487 last_stream_request_
= fake_request
->AsWeakPtr();
13488 return fake_request
;
13491 HttpStreamRequest
* RequestWebSocketHandshakeStream(
13492 const HttpRequestInfo
& info
,
13493 RequestPriority priority
,
13494 const SSLConfig
& server_ssl_config
,
13495 const SSLConfig
& proxy_ssl_config
,
13496 HttpStreamRequest::Delegate
* delegate
,
13497 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
13498 const BoundNetLog
& net_log
) override
{
13499 FakeStreamRequest
* fake_request
=
13500 new FakeStreamRequest(priority
, delegate
, create_helper
);
13501 last_stream_request_
= fake_request
->AsWeakPtr();
13502 return fake_request
;
13505 void PreconnectStreams(int num_streams
,
13506 const HttpRequestInfo
& info
,
13507 const SSLConfig
& server_ssl_config
,
13508 const SSLConfig
& proxy_ssl_config
) override
{
13512 const HostMappingRules
* GetHostMappingRules() const override
{
13518 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
13520 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
13523 // TODO(ricea): Maybe unify this with the one in
13524 // url_request_http_job_unittest.cc ?
13525 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
13527 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
13529 : state_(connection
.release(), using_proxy
) {}
13531 // Fake implementation of HttpStreamBase methods.
13532 // This ends up being quite "real" because this object has to really send data
13533 // on the mock socket. It might be easier to use the real implementation, but
13534 // the fact that the WebSocket code is not compiled on iOS makes that
13536 int InitializeStream(const HttpRequestInfo
* request_info
,
13537 RequestPriority priority
,
13538 const BoundNetLog
& net_log
,
13539 const CompletionCallback
& callback
) override
{
13540 state_
.Initialize(request_info
, priority
, net_log
, callback
);
13544 int SendRequest(const HttpRequestHeaders
& request_headers
,
13545 HttpResponseInfo
* response
,
13546 const CompletionCallback
& callback
) override
{
13547 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
13548 response
, callback
);
13551 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13552 return parser()->ReadResponseHeaders(callback
);
13555 int ReadResponseBody(IOBuffer
* buf
,
13557 const CompletionCallback
& callback
) override
{
13559 return ERR_IO_PENDING
;
13562 void Close(bool not_reusable
) override
{
13564 parser()->Close(true);
13567 bool IsResponseBodyComplete() const override
{
13572 bool IsConnectionReused() const override
{
13576 void SetConnectionReused() override
{ NOTREACHED(); }
13578 bool CanReuseConnection() const override
{ return false; }
13580 int64
GetTotalReceivedBytes() const override
{
13585 int64_t GetTotalSentBytes() const override
{
13590 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13595 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13597 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13601 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13603 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13605 UploadProgress
GetUploadProgress() const override
{
13607 return UploadProgress();
13610 HttpStream
* RenewStreamForAuth() override
{
13615 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13616 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13618 return scoped_ptr
<WebSocketStream
>();
13622 HttpStreamParser
* parser() const { return state_
.parser(); }
13623 HttpBasicState state_
;
13625 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13628 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13630 class FakeWebSocketStreamCreateHelper
:
13631 public WebSocketHandshakeStreamBase::CreateHelper
{
13633 WebSocketHandshakeStreamBase
* CreateBasicStream(
13634 scoped_ptr
<ClientSocketHandle
> connection
,
13635 bool using_proxy
) override
{
13636 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13640 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13641 const base::WeakPtr
<SpdySession
>& session
,
13642 bool use_relative_url
) override
{
13647 ~FakeWebSocketStreamCreateHelper() override
{}
13649 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13651 return scoped_ptr
<WebSocketStream
>();
13657 // Make sure that HttpNetworkTransaction passes on its priority to its
13658 // stream request on start.
13659 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13660 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13661 HttpNetworkSessionPeer
peer(session
);
13662 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13663 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13665 HttpNetworkTransaction
trans(LOW
, session
.get());
13667 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13669 HttpRequestInfo request
;
13670 TestCompletionCallback callback
;
13671 EXPECT_EQ(ERR_IO_PENDING
,
13672 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13674 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13675 fake_factory
->last_stream_request();
13676 ASSERT_TRUE(fake_request
!= NULL
);
13677 EXPECT_EQ(LOW
, fake_request
->priority());
13680 // Make sure that HttpNetworkTransaction passes on its priority
13681 // updates to its stream request.
13682 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13683 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13684 HttpNetworkSessionPeer
peer(session
);
13685 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13686 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13688 HttpNetworkTransaction
trans(LOW
, session
.get());
13690 HttpRequestInfo request
;
13691 TestCompletionCallback callback
;
13692 EXPECT_EQ(ERR_IO_PENDING
,
13693 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13695 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13696 fake_factory
->last_stream_request();
13697 ASSERT_TRUE(fake_request
!= NULL
);
13698 EXPECT_EQ(LOW
, fake_request
->priority());
13700 trans
.SetPriority(LOWEST
);
13701 ASSERT_TRUE(fake_request
!= NULL
);
13702 EXPECT_EQ(LOWEST
, fake_request
->priority());
13705 // Make sure that HttpNetworkTransaction passes on its priority
13706 // updates to its stream.
13707 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13708 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13709 HttpNetworkSessionPeer
peer(session
);
13710 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13711 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13713 HttpNetworkTransaction
trans(LOW
, session
.get());
13715 HttpRequestInfo request
;
13716 TestCompletionCallback callback
;
13717 EXPECT_EQ(ERR_IO_PENDING
,
13718 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13720 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13721 fake_factory
->last_stream_request();
13722 ASSERT_TRUE(fake_request
!= NULL
);
13723 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13724 ASSERT_TRUE(fake_stream
!= NULL
);
13725 EXPECT_EQ(LOW
, fake_stream
->priority());
13727 trans
.SetPriority(LOWEST
);
13728 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13731 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13732 // The same logic needs to be tested for both ws: and wss: schemes, but this
13733 // test is already parameterised on NextProto, so it uses a loop to verify
13734 // that the different schemes work.
13735 std::string test_cases
[] = {"ws://www.example.org/",
13736 "wss://www.example.org/"};
13737 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13738 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13739 HttpNetworkSessionPeer
peer(session
);
13740 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13741 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13742 peer
.SetHttpStreamFactoryForWebSocket(
13743 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13745 HttpNetworkTransaction
trans(LOW
, session
.get());
13746 trans
.SetWebSocketHandshakeStreamCreateHelper(
13747 &websocket_stream_create_helper
);
13749 HttpRequestInfo request
;
13750 TestCompletionCallback callback
;
13751 request
.method
= "GET";
13752 request
.url
= GURL(test_cases
[i
]);
13754 EXPECT_EQ(ERR_IO_PENDING
,
13755 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13757 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13758 fake_factory
->last_stream_request();
13759 ASSERT_TRUE(fake_request
!= NULL
);
13760 EXPECT_EQ(&websocket_stream_create_helper
,
13761 fake_request
->websocket_stream_create_helper());
13765 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13766 // if the transport socket pool is stalled on the global socket limit.
13767 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13768 ClientSocketPoolManager::set_max_sockets_per_group(
13769 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13770 ClientSocketPoolManager::set_max_sockets_per_pool(
13771 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13773 // Set up SSL request.
13775 HttpRequestInfo ssl_request
;
13776 ssl_request
.method
= "GET";
13777 ssl_request
.url
= GURL("https://www.example.org/");
13779 MockWrite ssl_writes
[] = {
13781 "GET / HTTP/1.1\r\n"
13782 "Host: www.example.org\r\n"
13783 "Connection: keep-alive\r\n\r\n"),
13785 MockRead ssl_reads
[] = {
13786 MockRead("HTTP/1.1 200 OK\r\n"),
13787 MockRead("Content-Length: 11\r\n\r\n"),
13788 MockRead("hello world"),
13789 MockRead(SYNCHRONOUS
, OK
),
13791 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13792 ssl_writes
, arraysize(ssl_writes
));
13793 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13795 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13796 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13798 // Set up HTTP request.
13800 HttpRequestInfo http_request
;
13801 http_request
.method
= "GET";
13802 http_request
.url
= GURL("http://www.example.org/");
13804 MockWrite http_writes
[] = {
13806 "GET / HTTP/1.1\r\n"
13807 "Host: www.example.org\r\n"
13808 "Connection: keep-alive\r\n\r\n"),
13810 MockRead http_reads
[] = {
13811 MockRead("HTTP/1.1 200 OK\r\n"),
13812 MockRead("Content-Length: 7\r\n\r\n"),
13813 MockRead("falafel"),
13814 MockRead(SYNCHRONOUS
, OK
),
13816 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13817 http_writes
, arraysize(http_writes
));
13818 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13820 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13822 // Start the SSL request.
13823 TestCompletionCallback ssl_callback
;
13824 scoped_ptr
<HttpTransaction
> ssl_trans(
13825 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13826 ASSERT_EQ(ERR_IO_PENDING
,
13827 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13830 // Start the HTTP request. Pool should stall.
13831 TestCompletionCallback http_callback
;
13832 scoped_ptr
<HttpTransaction
> http_trans(
13833 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13834 ASSERT_EQ(ERR_IO_PENDING
,
13835 http_trans
->Start(&http_request
, http_callback
.callback(),
13837 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13839 // Wait for response from SSL request.
13840 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13841 std::string response_data
;
13842 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13843 EXPECT_EQ("hello world", response_data
);
13845 // The SSL socket should automatically be closed, so the HTTP request can
13847 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13848 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13850 // The HTTP request can now complete.
13851 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13852 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13853 EXPECT_EQ("falafel", response_data
);
13855 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13858 // Tests that when a SSL connection is established but there's no corresponding
13859 // request that needs it, the new socket is closed if the transport socket pool
13860 // is stalled on the global socket limit.
13861 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13862 ClientSocketPoolManager::set_max_sockets_per_group(
13863 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13864 ClientSocketPoolManager::set_max_sockets_per_pool(
13865 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13867 // Set up an ssl request.
13869 HttpRequestInfo ssl_request
;
13870 ssl_request
.method
= "GET";
13871 ssl_request
.url
= GURL("https://www.foopy.com/");
13873 // No data will be sent on the SSL socket.
13874 StaticSocketDataProvider ssl_data
;
13875 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13877 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13878 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13880 // Set up HTTP request.
13882 HttpRequestInfo http_request
;
13883 http_request
.method
= "GET";
13884 http_request
.url
= GURL("http://www.example.org/");
13886 MockWrite http_writes
[] = {
13888 "GET / HTTP/1.1\r\n"
13889 "Host: www.example.org\r\n"
13890 "Connection: keep-alive\r\n\r\n"),
13892 MockRead http_reads
[] = {
13893 MockRead("HTTP/1.1 200 OK\r\n"),
13894 MockRead("Content-Length: 7\r\n\r\n"),
13895 MockRead("falafel"),
13896 MockRead(SYNCHRONOUS
, OK
),
13898 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13899 http_writes
, arraysize(http_writes
));
13900 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13902 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13904 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13905 // cancelled when a normal transaction is cancelled.
13906 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13907 SSLConfig ssl_config
;
13908 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13909 http_stream_factory
->PreconnectStreams(1, ssl_request
, ssl_config
,
13911 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13913 // Start the HTTP request. Pool should stall.
13914 TestCompletionCallback http_callback
;
13915 scoped_ptr
<HttpTransaction
> http_trans(
13916 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13917 ASSERT_EQ(ERR_IO_PENDING
,
13918 http_trans
->Start(&http_request
, http_callback
.callback(),
13920 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13922 // The SSL connection will automatically be closed once the connection is
13923 // established, to let the HTTP request start.
13924 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13925 std::string response_data
;
13926 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13927 EXPECT_EQ("falafel", response_data
);
13929 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13932 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13933 ScopedVector
<UploadElementReader
> element_readers
;
13934 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13935 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13937 HttpRequestInfo request
;
13938 request
.method
= "POST";
13939 request
.url
= GURL("http://www.foo.com/");
13940 request
.upload_data_stream
= &upload_data_stream
;
13941 request
.load_flags
= 0;
13943 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13944 scoped_ptr
<HttpTransaction
> trans(
13945 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13946 // Send headers successfully, but get an error while sending the body.
13947 MockWrite data_writes
[] = {
13948 MockWrite("POST / HTTP/1.1\r\n"
13949 "Host: www.foo.com\r\n"
13950 "Connection: keep-alive\r\n"
13951 "Content-Length: 3\r\n\r\n"),
13952 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13955 MockRead data_reads
[] = {
13956 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13957 MockRead("hello world"),
13958 MockRead(SYNCHRONOUS
, OK
),
13960 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13961 arraysize(data_writes
));
13962 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13964 TestCompletionCallback callback
;
13966 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13967 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13969 rv
= callback
.WaitForResult();
13972 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13973 ASSERT_TRUE(response
!= NULL
);
13975 EXPECT_TRUE(response
->headers
.get() != NULL
);
13976 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13978 std::string response_data
;
13979 rv
= ReadTransaction(trans
.get(), &response_data
);
13981 EXPECT_EQ("hello world", response_data
);
13984 // This test makes sure the retry logic doesn't trigger when reading an error
13985 // response from a server that rejected a POST with a CONNECTION_RESET.
13986 TEST_P(HttpNetworkTransactionTest
,
13987 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13988 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13989 MockWrite data_writes
[] = {
13990 MockWrite("GET / HTTP/1.1\r\n"
13991 "Host: www.foo.com\r\n"
13992 "Connection: keep-alive\r\n\r\n"),
13993 MockWrite("POST / HTTP/1.1\r\n"
13994 "Host: www.foo.com\r\n"
13995 "Connection: keep-alive\r\n"
13996 "Content-Length: 3\r\n\r\n"),
13997 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14000 MockRead data_reads
[] = {
14001 MockRead("HTTP/1.1 200 Peachy\r\n"
14002 "Content-Length: 14\r\n\r\n"),
14003 MockRead("first response"),
14004 MockRead("HTTP/1.1 400 Not OK\r\n"
14005 "Content-Length: 15\r\n\r\n"),
14006 MockRead("second response"),
14007 MockRead(SYNCHRONOUS
, OK
),
14009 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14010 arraysize(data_writes
));
14011 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14013 TestCompletionCallback callback
;
14014 HttpRequestInfo request1
;
14015 request1
.method
= "GET";
14016 request1
.url
= GURL("http://www.foo.com/");
14017 request1
.load_flags
= 0;
14019 scoped_ptr
<HttpTransaction
> trans1(
14020 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14021 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
14022 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14024 rv
= callback
.WaitForResult();
14027 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
14028 ASSERT_TRUE(response1
!= NULL
);
14030 EXPECT_TRUE(response1
->headers
.get() != NULL
);
14031 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
14033 std::string response_data1
;
14034 rv
= ReadTransaction(trans1
.get(), &response_data1
);
14036 EXPECT_EQ("first response", response_data1
);
14037 // Delete the transaction to release the socket back into the socket pool.
14040 ScopedVector
<UploadElementReader
> element_readers
;
14041 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14042 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14044 HttpRequestInfo request2
;
14045 request2
.method
= "POST";
14046 request2
.url
= GURL("http://www.foo.com/");
14047 request2
.upload_data_stream
= &upload_data_stream
;
14048 request2
.load_flags
= 0;
14050 scoped_ptr
<HttpTransaction
> trans2(
14051 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14052 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
14053 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14055 rv
= callback
.WaitForResult();
14058 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
14059 ASSERT_TRUE(response2
!= NULL
);
14061 EXPECT_TRUE(response2
->headers
.get() != NULL
);
14062 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
14064 std::string response_data2
;
14065 rv
= ReadTransaction(trans2
.get(), &response_data2
);
14067 EXPECT_EQ("second response", response_data2
);
14070 TEST_P(HttpNetworkTransactionTest
,
14071 PostReadsErrorResponseAfterResetPartialBodySent
) {
14072 ScopedVector
<UploadElementReader
> element_readers
;
14073 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14074 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14076 HttpRequestInfo request
;
14077 request
.method
= "POST";
14078 request
.url
= GURL("http://www.foo.com/");
14079 request
.upload_data_stream
= &upload_data_stream
;
14080 request
.load_flags
= 0;
14082 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14083 scoped_ptr
<HttpTransaction
> trans(
14084 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14085 // Send headers successfully, but get an error while sending the body.
14086 MockWrite data_writes
[] = {
14087 MockWrite("POST / HTTP/1.1\r\n"
14088 "Host: www.foo.com\r\n"
14089 "Connection: keep-alive\r\n"
14090 "Content-Length: 3\r\n\r\n"
14092 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14095 MockRead data_reads
[] = {
14096 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14097 MockRead("hello world"),
14098 MockRead(SYNCHRONOUS
, OK
),
14100 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14101 arraysize(data_writes
));
14102 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14104 TestCompletionCallback callback
;
14106 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14107 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14109 rv
= callback
.WaitForResult();
14112 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14113 ASSERT_TRUE(response
!= NULL
);
14115 EXPECT_TRUE(response
->headers
.get() != NULL
);
14116 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14118 std::string response_data
;
14119 rv
= ReadTransaction(trans
.get(), &response_data
);
14121 EXPECT_EQ("hello world", response_data
);
14124 // This tests the more common case than the previous test, where headers and
14125 // body are not merged into a single request.
14126 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
14127 ScopedVector
<UploadElementReader
> element_readers
;
14128 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14129 ChunkedUploadDataStream
upload_data_stream(0);
14131 HttpRequestInfo request
;
14132 request
.method
= "POST";
14133 request
.url
= GURL("http://www.foo.com/");
14134 request
.upload_data_stream
= &upload_data_stream
;
14135 request
.load_flags
= 0;
14137 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14138 scoped_ptr
<HttpTransaction
> trans(
14139 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14140 // Send headers successfully, but get an error while sending the body.
14141 MockWrite data_writes
[] = {
14142 MockWrite("POST / HTTP/1.1\r\n"
14143 "Host: www.foo.com\r\n"
14144 "Connection: keep-alive\r\n"
14145 "Transfer-Encoding: chunked\r\n\r\n"),
14146 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14149 MockRead data_reads
[] = {
14150 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14151 MockRead("hello world"),
14152 MockRead(SYNCHRONOUS
, OK
),
14154 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14155 arraysize(data_writes
));
14156 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14158 TestCompletionCallback callback
;
14160 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14161 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14162 // Make sure the headers are sent before adding a chunk. This ensures that
14163 // they can't be merged with the body in a single send. Not currently
14164 // necessary since a chunked body is never merged with headers, but this makes
14165 // the test more future proof.
14166 base::RunLoop().RunUntilIdle();
14168 upload_data_stream
.AppendData("last chunk", 10, true);
14170 rv
= callback
.WaitForResult();
14173 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14174 ASSERT_TRUE(response
!= NULL
);
14176 EXPECT_TRUE(response
->headers
.get() != NULL
);
14177 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14179 std::string response_data
;
14180 rv
= ReadTransaction(trans
.get(), &response_data
);
14182 EXPECT_EQ("hello world", response_data
);
14185 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
14186 ScopedVector
<UploadElementReader
> element_readers
;
14187 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14188 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14190 HttpRequestInfo request
;
14191 request
.method
= "POST";
14192 request
.url
= GURL("http://www.foo.com/");
14193 request
.upload_data_stream
= &upload_data_stream
;
14194 request
.load_flags
= 0;
14196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14197 scoped_ptr
<HttpTransaction
> trans(
14198 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14200 MockWrite data_writes
[] = {
14201 MockWrite("POST / HTTP/1.1\r\n"
14202 "Host: www.foo.com\r\n"
14203 "Connection: keep-alive\r\n"
14204 "Content-Length: 3\r\n\r\n"),
14205 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14208 MockRead data_reads
[] = {
14209 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14210 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14211 MockRead("hello world"),
14212 MockRead(SYNCHRONOUS
, OK
),
14214 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14215 arraysize(data_writes
));
14216 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14218 TestCompletionCallback callback
;
14220 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14221 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14223 rv
= callback
.WaitForResult();
14226 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14227 ASSERT_TRUE(response
!= NULL
);
14229 EXPECT_TRUE(response
->headers
.get() != NULL
);
14230 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14232 std::string response_data
;
14233 rv
= ReadTransaction(trans
.get(), &response_data
);
14235 EXPECT_EQ("hello world", response_data
);
14238 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
14239 ScopedVector
<UploadElementReader
> element_readers
;
14240 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14241 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14243 HttpRequestInfo request
;
14244 request
.method
= "POST";
14245 request
.url
= GURL("http://www.foo.com/");
14246 request
.upload_data_stream
= &upload_data_stream
;
14247 request
.load_flags
= 0;
14249 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14250 scoped_ptr
<HttpTransaction
> trans(
14251 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14252 // Send headers successfully, but get an error while sending the body.
14253 MockWrite data_writes
[] = {
14254 MockWrite("POST / HTTP/1.1\r\n"
14255 "Host: www.foo.com\r\n"
14256 "Connection: keep-alive\r\n"
14257 "Content-Length: 3\r\n\r\n"),
14258 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14261 MockRead data_reads
[] = {
14262 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14263 MockRead("hello world"),
14264 MockRead(SYNCHRONOUS
, OK
),
14266 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14267 arraysize(data_writes
));
14268 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14270 TestCompletionCallback callback
;
14272 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14273 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14275 rv
= callback
.WaitForResult();
14276 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14279 TEST_P(HttpNetworkTransactionTest
,
14280 PostIgnoresNonErrorResponseAfterResetAnd100
) {
14281 ScopedVector
<UploadElementReader
> element_readers
;
14282 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14283 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14285 HttpRequestInfo request
;
14286 request
.method
= "POST";
14287 request
.url
= GURL("http://www.foo.com/");
14288 request
.upload_data_stream
= &upload_data_stream
;
14289 request
.load_flags
= 0;
14291 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14292 scoped_ptr
<HttpTransaction
> trans(
14293 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14294 // Send headers successfully, but get an error while sending the body.
14295 MockWrite data_writes
[] = {
14296 MockWrite("POST / HTTP/1.1\r\n"
14297 "Host: www.foo.com\r\n"
14298 "Connection: keep-alive\r\n"
14299 "Content-Length: 3\r\n\r\n"),
14300 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14303 MockRead data_reads
[] = {
14304 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14305 MockRead("HTTP/1.0 302 Redirect\r\n"),
14306 MockRead("Location: http://somewhere-else.com/\r\n"),
14307 MockRead("Content-Length: 0\r\n\r\n"),
14308 MockRead(SYNCHRONOUS
, OK
),
14310 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14311 arraysize(data_writes
));
14312 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14314 TestCompletionCallback callback
;
14316 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14317 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14319 rv
= callback
.WaitForResult();
14320 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14323 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
14324 ScopedVector
<UploadElementReader
> element_readers
;
14325 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14326 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14328 HttpRequestInfo request
;
14329 request
.method
= "POST";
14330 request
.url
= GURL("http://www.foo.com/");
14331 request
.upload_data_stream
= &upload_data_stream
;
14332 request
.load_flags
= 0;
14334 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14335 scoped_ptr
<HttpTransaction
> trans(
14336 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14337 // Send headers successfully, but get an error while sending the body.
14338 MockWrite data_writes
[] = {
14339 MockWrite("POST / HTTP/1.1\r\n"
14340 "Host: www.foo.com\r\n"
14341 "Connection: keep-alive\r\n"
14342 "Content-Length: 3\r\n\r\n"),
14343 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14346 MockRead data_reads
[] = {
14347 MockRead("HTTP 0.9 rocks!"),
14348 MockRead(SYNCHRONOUS
, OK
),
14350 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14351 arraysize(data_writes
));
14352 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14354 TestCompletionCallback callback
;
14356 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14357 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14359 rv
= callback
.WaitForResult();
14360 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14363 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
14364 ScopedVector
<UploadElementReader
> element_readers
;
14365 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14366 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14368 HttpRequestInfo request
;
14369 request
.method
= "POST";
14370 request
.url
= GURL("http://www.foo.com/");
14371 request
.upload_data_stream
= &upload_data_stream
;
14372 request
.load_flags
= 0;
14374 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14375 scoped_ptr
<HttpTransaction
> trans(
14376 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14377 // Send headers successfully, but get an error while sending the body.
14378 MockWrite data_writes
[] = {
14379 MockWrite("POST / HTTP/1.1\r\n"
14380 "Host: www.foo.com\r\n"
14381 "Connection: keep-alive\r\n"
14382 "Content-Length: 3\r\n\r\n"),
14383 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14386 MockRead data_reads
[] = {
14387 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14388 MockRead(SYNCHRONOUS
, OK
),
14390 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14391 arraysize(data_writes
));
14392 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14394 TestCompletionCallback callback
;
14396 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14397 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14399 rv
= callback
.WaitForResult();
14400 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14403 // Verify that proxy headers are not sent to the destination server when
14404 // establishing a tunnel for a secure WebSocket connection.
14405 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
14406 HttpRequestInfo request
;
14407 request
.method
= "GET";
14408 request
.url
= GURL("wss://www.example.org/");
14409 AddWebSocketHeaders(&request
.extra_headers
);
14411 // Configure against proxy server "myproxy:70".
14412 session_deps_
.proxy_service
=
14413 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
14415 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14417 // Since a proxy is configured, try to establish a tunnel.
14418 MockWrite data_writes
[] = {
14420 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14421 "Host: www.example.org\r\n"
14422 "Proxy-Connection: keep-alive\r\n\r\n"),
14424 // After calling trans->RestartWithAuth(), this is the request we should
14425 // be issuing -- the final header line contains the credentials.
14427 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14428 "Host: www.example.org\r\n"
14429 "Proxy-Connection: keep-alive\r\n"
14430 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14433 "GET / HTTP/1.1\r\n"
14434 "Host: www.example.org\r\n"
14435 "Connection: Upgrade\r\n"
14436 "Upgrade: websocket\r\n"
14437 "Origin: http://www.example.org\r\n"
14438 "Sec-WebSocket-Version: 13\r\n"
14439 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14442 // The proxy responds to the connect with a 407, using a persistent
14444 MockRead data_reads
[] = {
14446 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14447 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14448 MockRead("Content-Length: 0\r\n"),
14449 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
14451 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14453 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14454 MockRead("Upgrade: websocket\r\n"),
14455 MockRead("Connection: Upgrade\r\n"),
14456 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14459 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14460 arraysize(data_writes
));
14461 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14462 SSLSocketDataProvider
ssl(ASYNC
, OK
);
14463 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
14465 scoped_ptr
<HttpTransaction
> trans(
14466 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14467 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14468 trans
->SetWebSocketHandshakeStreamCreateHelper(
14469 &websocket_stream_create_helper
);
14472 TestCompletionCallback callback
;
14474 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14475 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14477 rv
= callback
.WaitForResult();
14481 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14482 ASSERT_TRUE(response
);
14483 ASSERT_TRUE(response
->headers
.get());
14484 EXPECT_EQ(407, response
->headers
->response_code());
14487 TestCompletionCallback callback
;
14489 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
14490 callback
.callback());
14491 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14493 rv
= callback
.WaitForResult();
14497 response
= trans
->GetResponseInfo();
14498 ASSERT_TRUE(response
);
14499 ASSERT_TRUE(response
->headers
.get());
14501 EXPECT_EQ(101, response
->headers
->response_code());
14504 session
->CloseAllConnections();
14507 // Verify that proxy headers are not sent to the destination server when
14508 // establishing a tunnel for an insecure WebSocket connection.
14509 // This requires the authentication info to be injected into the auth cache
14510 // due to crbug.com/395064
14511 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14512 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
14513 HttpRequestInfo request
;
14514 request
.method
= "GET";
14515 request
.url
= GURL("ws://www.example.org/");
14516 AddWebSocketHeaders(&request
.extra_headers
);
14518 // Configure against proxy server "myproxy:70".
14519 session_deps_
.proxy_service
=
14520 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
14522 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14524 MockWrite data_writes
[] = {
14525 // Try to establish a tunnel for the WebSocket connection, with
14526 // credentials. Because WebSockets have a separate set of socket pools,
14527 // they cannot and will not use the same TCP/IP connection as the
14528 // preflight HTTP request.
14530 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14531 "Host: www.example.org:80\r\n"
14532 "Proxy-Connection: keep-alive\r\n"
14533 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14536 "GET / HTTP/1.1\r\n"
14537 "Host: www.example.org\r\n"
14538 "Connection: Upgrade\r\n"
14539 "Upgrade: websocket\r\n"
14540 "Origin: http://www.example.org\r\n"
14541 "Sec-WebSocket-Version: 13\r\n"
14542 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14545 MockRead data_reads
[] = {
14546 // HTTP CONNECT with credentials.
14547 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14549 // WebSocket connection established inside tunnel.
14550 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14551 MockRead("Upgrade: websocket\r\n"),
14552 MockRead("Connection: Upgrade\r\n"),
14553 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14556 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14557 arraysize(data_writes
));
14558 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14560 session
->http_auth_cache()->Add(
14561 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
14562 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
14564 scoped_ptr
<HttpTransaction
> trans(
14565 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14566 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14567 trans
->SetWebSocketHandshakeStreamCreateHelper(
14568 &websocket_stream_create_helper
);
14570 TestCompletionCallback callback
;
14572 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14573 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14575 rv
= callback
.WaitForResult();
14578 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14579 ASSERT_TRUE(response
);
14580 ASSERT_TRUE(response
->headers
.get());
14582 EXPECT_EQ(101, response
->headers
->response_code());
14585 session
->CloseAllConnections();
14588 TEST_P(HttpNetworkTransactionTest
, TotalNetworkBytesPost
) {
14589 ScopedVector
<UploadElementReader
> element_readers
;
14590 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14591 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14593 HttpRequestInfo request
;
14594 request
.method
= "POST";
14595 request
.url
= GURL("http://www.foo.com/");
14596 request
.upload_data_stream
= &upload_data_stream
;
14598 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14599 scoped_ptr
<HttpTransaction
> trans(
14600 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14601 MockWrite data_writes
[] = {
14602 MockWrite("POST / HTTP/1.1\r\n"
14603 "Host: www.foo.com\r\n"
14604 "Connection: keep-alive\r\n"
14605 "Content-Length: 3\r\n\r\n"),
14609 MockRead data_reads
[] = {
14610 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
14611 MockRead(SYNCHRONOUS
, OK
),
14613 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14614 arraysize(data_writes
));
14615 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14617 TestCompletionCallback callback
;
14619 EXPECT_EQ(ERR_IO_PENDING
,
14620 trans
->Start(&request
, callback
.callback(), BoundNetLog()));
14621 EXPECT_EQ(OK
, callback
.WaitForResult());
14623 std::string response_data
;
14624 EXPECT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
14626 EXPECT_EQ(CountWriteBytes(data_writes
, arraysize(data_writes
)),
14627 trans
->GetTotalSentBytes());
14628 EXPECT_EQ(CountReadBytes(data_reads
, arraysize(data_reads
)),
14629 trans
->GetTotalReceivedBytes());
14632 TEST_P(HttpNetworkTransactionTest
, TotalNetworkBytesPost100Continue
) {
14633 ScopedVector
<UploadElementReader
> element_readers
;
14634 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14635 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14637 HttpRequestInfo request
;
14638 request
.method
= "POST";
14639 request
.url
= GURL("http://www.foo.com/");
14640 request
.upload_data_stream
= &upload_data_stream
;
14642 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14643 scoped_ptr
<HttpTransaction
> trans(
14644 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14645 MockWrite data_writes
[] = {
14646 MockWrite("POST / HTTP/1.1\r\n"
14647 "Host: www.foo.com\r\n"
14648 "Connection: keep-alive\r\n"
14649 "Content-Length: 3\r\n\r\n"),
14653 MockRead data_reads
[] = {
14654 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
14655 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
14656 MockRead(SYNCHRONOUS
, OK
),
14658 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14659 arraysize(data_writes
));
14660 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14662 TestCompletionCallback callback
;
14664 EXPECT_EQ(ERR_IO_PENDING
,
14665 trans
->Start(&request
, callback
.callback(), BoundNetLog()));
14666 EXPECT_EQ(OK
, callback
.WaitForResult());
14668 std::string response_data
;
14669 EXPECT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
14671 EXPECT_EQ(CountWriteBytes(data_writes
, arraysize(data_writes
)),
14672 trans
->GetTotalSentBytes());
14673 EXPECT_EQ(CountReadBytes(data_reads
, arraysize(data_reads
)),
14674 trans
->GetTotalReceivedBytes());
14677 TEST_P(HttpNetworkTransactionTest
, TotalNetworkBytesChunkedPost
) {
14678 ScopedVector
<UploadElementReader
> element_readers
;
14679 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14680 ChunkedUploadDataStream
upload_data_stream(0);
14682 HttpRequestInfo request
;
14683 request
.method
= "POST";
14684 request
.url
= GURL("http://www.foo.com/");
14685 request
.upload_data_stream
= &upload_data_stream
;
14687 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14688 scoped_ptr
<HttpTransaction
> trans(
14689 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14690 // Send headers successfully, but get an error while sending the body.
14691 MockWrite data_writes
[] = {
14692 MockWrite("POST / HTTP/1.1\r\n"
14693 "Host: www.foo.com\r\n"
14694 "Connection: keep-alive\r\n"
14695 "Transfer-Encoding: chunked\r\n\r\n"),
14696 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
14699 MockRead data_reads
[] = {
14700 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
14701 MockRead(SYNCHRONOUS
, OK
),
14703 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14704 arraysize(data_writes
));
14705 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14707 TestCompletionCallback callback
;
14709 EXPECT_EQ(ERR_IO_PENDING
,
14710 trans
->Start(&request
, callback
.callback(), BoundNetLog()));
14712 base::RunLoop().RunUntilIdle();
14713 upload_data_stream
.AppendData("f", 1, false);
14715 base::RunLoop().RunUntilIdle();
14716 upload_data_stream
.AppendData("oo", 2, true);
14718 EXPECT_EQ(OK
, callback
.WaitForResult());
14720 std::string response_data
;
14721 EXPECT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
14723 EXPECT_EQ(CountWriteBytes(data_writes
, arraysize(data_writes
)),
14724 trans
->GetTotalSentBytes());
14725 EXPECT_EQ(CountReadBytes(data_reads
, arraysize(data_reads
)),
14726 trans
->GetTotalReceivedBytes());