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 totalReceivedBytes
;
269 LoadTimingInfo load_timing_info
;
270 ConnectionAttempts connection_attempts
;
273 void SetUp() override
{
274 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
275 base::MessageLoop::current()->RunUntilIdle();
278 void TearDown() override
{
279 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
280 base::MessageLoop::current()->RunUntilIdle();
281 // Empty the current queue.
282 base::MessageLoop::current()->RunUntilIdle();
283 PlatformTest::TearDown();
284 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
285 base::MessageLoop::current()->RunUntilIdle();
288 const char* GetAlternateProtocolFromParam() {
290 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
293 std::string
GetAlternativeServiceHttpHeader() {
294 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
295 "=\"www.example.com:443\"\r\n";
298 std::string
GetAlternateProtocolHttpHeader() {
299 return std::string("Alternate-Protocol: 443:") +
300 GetAlternateProtocolFromParam() + "\r\n";
303 // Either |write_failure| specifies a write failure or |read_failure|
304 // specifies a read failure when using a reused socket. In either case, the
305 // failure should cause the network transaction to resend the request, and the
306 // other argument should be NULL.
307 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
308 const MockRead
* read_failure
);
310 // Either |write_failure| specifies a write failure or |read_failure|
311 // specifies a read failure when using a reused socket. In either case, the
312 // failure should cause the network transaction to resend the request, and the
313 // other argument should be NULL.
314 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
315 const MockRead
* read_failure
,
318 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
320 SimpleGetHelperResult out
;
322 HttpRequestInfo request
;
323 request
.method
= "GET";
324 request
.url
= GURL("http://www.example.org/");
325 request
.load_flags
= 0;
328 session_deps_
.net_log
= log
.bound().net_log();
329 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
330 scoped_ptr
<HttpTransaction
> trans(
331 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
333 for (size_t i
= 0; i
< data_count
; ++i
) {
334 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
337 TestCompletionCallback callback
;
339 EXPECT_TRUE(log
.bound().IsCapturing());
340 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
341 EXPECT_EQ(ERR_IO_PENDING
, rv
);
343 out
.rv
= callback
.WaitForResult();
345 // Even in the failure cases that use this function, connections are always
346 // successfully established before the error.
347 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
348 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
353 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
354 // Can't use ASSERT_* inside helper functions like this, so
356 if (response
== NULL
|| response
->headers
.get() == NULL
) {
357 out
.rv
= ERR_UNEXPECTED
;
360 out
.status_line
= response
->headers
->GetStatusLine();
362 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
363 EXPECT_EQ(80, response
->socket_address
.port());
365 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
368 TestNetLogEntry::List entries
;
369 log
.GetEntries(&entries
);
370 size_t pos
= ExpectLogContainsSomewhere(
371 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
373 ExpectLogContainsSomewhere(
375 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
379 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
380 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
382 HttpRequestHeaders request_headers
;
383 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
385 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
386 EXPECT_EQ("www.example.org", value
);
387 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
388 EXPECT_EQ("keep-alive", value
);
390 std::string response_headers
;
391 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
392 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
395 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
396 trans
->GetConnectionAttempts(&out
.connection_attempts
);
400 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
401 size_t reads_count
) {
402 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
403 StaticSocketDataProvider
* data
[] = { &reads
};
404 return SimpleGetHelperForData(data
, 1);
407 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
409 for (size_t i
= 0; i
< reads_count
; ++i
)
410 size
+= data_reads
[i
].data_len
;
414 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
415 int expected_status
);
417 void ConnectStatusHelper(const MockRead
& status
);
419 void BypassHostCacheOnRefreshHelper(int load_flags
);
421 void CheckErrorIsPassedBack(int error
, IoMode mode
);
423 SpdyTestUtil spdy_util_
;
424 SpdySessionDependencies session_deps_
;
426 // Original socket limits. Some tests set these. Safest to always restore
427 // them once each test has been run.
428 int old_max_group_sockets_
;
429 int old_max_pool_sockets_
;
432 INSTANTIATE_TEST_CASE_P(NextProto
,
433 HttpNetworkTransactionTest
,
434 testing::Values(kProtoSPDY31
,
439 class BeforeNetworkStartHandler
{
441 explicit BeforeNetworkStartHandler(bool defer
)
442 : defer_on_before_network_start_(defer
),
443 observed_before_network_start_(false) {}
445 void OnBeforeNetworkStart(bool* defer
) {
446 *defer
= defer_on_before_network_start_
;
447 observed_before_network_start_
= true;
450 bool observed_before_network_start() const {
451 return observed_before_network_start_
;
455 const bool defer_on_before_network_start_
;
456 bool observed_before_network_start_
;
458 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
461 class BeforeProxyHeadersSentHandler
{
463 BeforeProxyHeadersSentHandler()
464 : observed_before_proxy_headers_sent_(false) {}
466 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
467 HttpRequestHeaders
* request_headers
) {
468 observed_before_proxy_headers_sent_
= true;
469 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
472 bool observed_before_proxy_headers_sent() const {
473 return observed_before_proxy_headers_sent_
;
476 std::string
observed_proxy_server_uri() const {
477 return observed_proxy_server_uri_
;
481 bool observed_before_proxy_headers_sent_
;
482 std::string observed_proxy_server_uri_
;
484 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
487 // Fill |str| with a long header list that consumes >= |size| bytes.
488 void FillLargeHeadersString(std::string
* str
, int size
) {
490 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
491 const int sizeof_row
= strlen(row
);
492 const int num_rows
= static_cast<int>(
493 ceil(static_cast<float>(size
) / sizeof_row
));
494 const int sizeof_data
= num_rows
* sizeof_row
;
495 DCHECK(sizeof_data
>= size
);
496 str
->reserve(sizeof_data
);
498 for (int i
= 0; i
< num_rows
; ++i
)
499 str
->append(row
, sizeof_row
);
502 #if defined(NTLM_PORTABLE)
503 // Alternative functions that eliminate randomness and dependency on the local
504 // host name so that the generated NTLM messages are reproducible.
505 void MockGenerateRandom1(uint8
* output
, size_t n
) {
506 static const uint8 bytes
[] = {
507 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
509 static size_t current_byte
= 0;
510 for (size_t i
= 0; i
< n
; ++i
) {
511 output
[i
] = bytes
[current_byte
++];
512 current_byte
%= arraysize(bytes
);
516 void MockGenerateRandom2(uint8
* output
, size_t n
) {
517 static const uint8 bytes
[] = {
518 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
519 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
521 static size_t current_byte
= 0;
522 for (size_t i
= 0; i
< n
; ++i
) {
523 output
[i
] = bytes
[current_byte
++];
524 current_byte
%= arraysize(bytes
);
528 std::string
MockGetHostName() {
531 #endif // defined(NTLM_PORTABLE)
533 template<typename ParentPool
>
534 class CaptureGroupNameSocketPool
: public ParentPool
{
536 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
537 CertVerifier
* cert_verifier
);
539 const std::string
last_group_name_received() const {
540 return last_group_name_
;
543 int RequestSocket(const std::string
& group_name
,
544 const void* socket_params
,
545 RequestPriority priority
,
546 ClientSocketHandle
* handle
,
547 const CompletionCallback
& callback
,
548 const BoundNetLog
& net_log
) override
{
549 last_group_name_
= group_name
;
550 return ERR_IO_PENDING
;
552 void CancelRequest(const std::string
& group_name
,
553 ClientSocketHandle
* handle
) override
{}
554 void ReleaseSocket(const std::string
& group_name
,
555 scoped_ptr
<StreamSocket
> socket
,
557 void CloseIdleSockets() override
{}
558 int IdleSocketCount() const override
{ return 0; }
559 int IdleSocketCountInGroup(const std::string
& group_name
) const override
{
562 LoadState
GetLoadState(const std::string
& group_name
,
563 const ClientSocketHandle
* handle
) const override
{
564 return LOAD_STATE_IDLE
;
566 base::TimeDelta
ConnectionTimeout() const override
{
567 return base::TimeDelta();
571 std::string last_group_name_
;
574 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
575 CaptureGroupNameTransportSocketPool
;
576 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
577 CaptureGroupNameHttpProxySocketPool
;
578 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
579 CaptureGroupNameSOCKSSocketPool
;
580 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
581 CaptureGroupNameSSLSocketPool
;
583 template <typename ParentPool
>
584 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
585 HostResolver
* host_resolver
,
586 CertVerifier
* /* cert_verifier */)
587 : ParentPool(0, 0, host_resolver
, NULL
, NULL
) {
591 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
592 HostResolver
* /* host_resolver */,
593 CertVerifier
* /* cert_verifier */)
594 : HttpProxyClientSocketPool(0, 0, NULL
, NULL
, NULL
) {
598 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
599 HostResolver
* /* host_resolver */,
600 CertVerifier
* cert_verifier
)
601 : SSLClientSocketPool(0,
617 //-----------------------------------------------------------------------------
619 // Helper functions for validating that AuthChallengeInfo's are correctly
620 // configured for common cases.
621 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
624 EXPECT_FALSE(auth_challenge
->is_proxy
);
625 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
626 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
627 EXPECT_EQ("basic", auth_challenge
->scheme
);
631 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
634 EXPECT_TRUE(auth_challenge
->is_proxy
);
635 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
636 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
637 EXPECT_EQ("basic", auth_challenge
->scheme
);
641 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
644 EXPECT_FALSE(auth_challenge
->is_proxy
);
645 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
646 EXPECT_EQ("digestive", auth_challenge
->realm
);
647 EXPECT_EQ("digest", auth_challenge
->scheme
);
651 #if defined(NTLM_PORTABLE)
652 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
655 EXPECT_FALSE(auth_challenge
->is_proxy
);
656 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
657 EXPECT_EQ(std::string(), auth_challenge
->realm
);
658 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
661 #endif // defined(NTLM_PORTABLE)
665 TEST_P(HttpNetworkTransactionTest
, Basic
) {
666 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
667 scoped_ptr
<HttpTransaction
> trans(
668 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
671 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
672 MockRead data_reads
[] = {
673 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
674 MockRead("hello world"),
675 MockRead(SYNCHRONOUS
, OK
),
677 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
678 arraysize(data_reads
));
679 EXPECT_EQ(OK
, out
.rv
);
680 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
681 EXPECT_EQ("hello world", out
.response_data
);
682 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
683 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
684 EXPECT_EQ(0u, out
.connection_attempts
.size());
687 // Response with no status line.
688 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
689 MockRead data_reads
[] = {
690 MockRead("hello world"),
691 MockRead(SYNCHRONOUS
, OK
),
693 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
694 arraysize(data_reads
));
695 EXPECT_EQ(OK
, out
.rv
);
696 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
697 EXPECT_EQ("hello world", out
.response_data
);
698 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
699 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
702 // Allow up to 4 bytes of junk to precede status line.
703 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
704 MockRead data_reads
[] = {
705 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
706 MockRead(SYNCHRONOUS
, OK
),
708 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
709 arraysize(data_reads
));
710 EXPECT_EQ(OK
, out
.rv
);
711 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
712 EXPECT_EQ("DATA", out
.response_data
);
713 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
714 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
717 // Allow up to 4 bytes of junk to precede status line.
718 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
719 MockRead data_reads
[] = {
720 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
721 MockRead(SYNCHRONOUS
, OK
),
723 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
724 arraysize(data_reads
));
725 EXPECT_EQ(OK
, out
.rv
);
726 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
727 EXPECT_EQ("DATA", out
.response_data
);
728 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
729 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
732 // Beyond 4 bytes of slop and it should fail to find a status line.
733 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
734 MockRead data_reads
[] = {
735 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
736 MockRead(SYNCHRONOUS
, OK
),
738 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
739 arraysize(data_reads
));
740 EXPECT_EQ(OK
, out
.rv
);
741 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
742 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
743 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
744 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
747 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
748 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
749 MockRead data_reads
[] = {
754 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
755 MockRead(SYNCHRONOUS
, OK
),
757 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
758 arraysize(data_reads
));
759 EXPECT_EQ(OK
, out
.rv
);
760 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
761 EXPECT_EQ("DATA", out
.response_data
);
762 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
763 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
766 // Close the connection before enough bytes to have a status line.
767 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
768 MockRead data_reads
[] = {
770 MockRead(SYNCHRONOUS
, OK
),
772 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
773 arraysize(data_reads
));
774 EXPECT_EQ(OK
, out
.rv
);
775 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
776 EXPECT_EQ("HTT", out
.response_data
);
777 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
778 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
781 // Simulate a 204 response, lacking a Content-Length header, sent over a
782 // persistent connection. The response should still terminate since a 204
783 // cannot have a response body.
784 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
785 char junk
[] = "junk";
786 MockRead data_reads
[] = {
787 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
788 MockRead(junk
), // Should not be read!!
789 MockRead(SYNCHRONOUS
, OK
),
791 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
792 arraysize(data_reads
));
793 EXPECT_EQ(OK
, out
.rv
);
794 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
795 EXPECT_EQ("", out
.response_data
);
796 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
797 int64 response_size
= reads_size
- strlen(junk
);
798 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
801 // A simple request using chunked encoding with some extra data after.
802 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
803 std::string final_chunk
= "0\r\n\r\n";
804 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
805 std::string last_read
= final_chunk
+ extra_data
;
806 MockRead data_reads
[] = {
807 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
808 MockRead("5\r\nHello\r\n"),
811 MockRead("5\r\nworld\r\n"),
812 MockRead(last_read
.data()),
813 MockRead(SYNCHRONOUS
, OK
),
815 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
816 arraysize(data_reads
));
817 EXPECT_EQ(OK
, out
.rv
);
818 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
819 EXPECT_EQ("Hello world", out
.response_data
);
820 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
821 int64 response_size
= reads_size
- extra_data
.size();
822 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
825 // Next tests deal with http://crbug.com/56344.
827 TEST_P(HttpNetworkTransactionTest
,
828 MultipleContentLengthHeadersNoTransferEncoding
) {
829 MockRead data_reads
[] = {
830 MockRead("HTTP/1.1 200 OK\r\n"),
831 MockRead("Content-Length: 10\r\n"),
832 MockRead("Content-Length: 5\r\n\r\n"),
834 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
835 arraysize(data_reads
));
836 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
839 TEST_P(HttpNetworkTransactionTest
,
840 DuplicateContentLengthHeadersNoTransferEncoding
) {
841 MockRead data_reads
[] = {
842 MockRead("HTTP/1.1 200 OK\r\n"),
843 MockRead("Content-Length: 5\r\n"),
844 MockRead("Content-Length: 5\r\n\r\n"),
847 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
848 arraysize(data_reads
));
849 EXPECT_EQ(OK
, out
.rv
);
850 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
851 EXPECT_EQ("Hello", out
.response_data
);
854 TEST_P(HttpNetworkTransactionTest
,
855 ComplexContentLengthHeadersNoTransferEncoding
) {
856 // More than 2 dupes.
858 MockRead data_reads
[] = {
859 MockRead("HTTP/1.1 200 OK\r\n"),
860 MockRead("Content-Length: 5\r\n"),
861 MockRead("Content-Length: 5\r\n"),
862 MockRead("Content-Length: 5\r\n\r\n"),
865 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
866 arraysize(data_reads
));
867 EXPECT_EQ(OK
, out
.rv
);
868 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
869 EXPECT_EQ("Hello", out
.response_data
);
873 MockRead data_reads
[] = {
874 MockRead("HTTP/1.0 200 OK\r\n"),
875 MockRead("Content-Length: 5\r\n"),
876 MockRead("Content-Length: 5\r\n"),
877 MockRead("Content-Length: 5\r\n\r\n"),
880 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
881 arraysize(data_reads
));
882 EXPECT_EQ(OK
, out
.rv
);
883 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
884 EXPECT_EQ("Hello", out
.response_data
);
886 // 2 dupes and one mismatched.
888 MockRead data_reads
[] = {
889 MockRead("HTTP/1.1 200 OK\r\n"),
890 MockRead("Content-Length: 10\r\n"),
891 MockRead("Content-Length: 10\r\n"),
892 MockRead("Content-Length: 5\r\n\r\n"),
894 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
895 arraysize(data_reads
));
896 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
900 TEST_P(HttpNetworkTransactionTest
,
901 MultipleContentLengthHeadersTransferEncoding
) {
902 MockRead data_reads
[] = {
903 MockRead("HTTP/1.1 200 OK\r\n"),
904 MockRead("Content-Length: 666\r\n"),
905 MockRead("Content-Length: 1337\r\n"),
906 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
907 MockRead("5\r\nHello\r\n"),
910 MockRead("5\r\nworld\r\n"),
911 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
912 MockRead(SYNCHRONOUS
, OK
),
914 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
915 arraysize(data_reads
));
916 EXPECT_EQ(OK
, out
.rv
);
917 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
918 EXPECT_EQ("Hello world", out
.response_data
);
921 // Next tests deal with http://crbug.com/98895.
923 // Checks that a single Content-Disposition header results in no error.
924 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
925 MockRead data_reads
[] = {
926 MockRead("HTTP/1.1 200 OK\r\n"),
927 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
928 MockRead("Content-Length: 5\r\n\r\n"),
931 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
932 arraysize(data_reads
));
933 EXPECT_EQ(OK
, out
.rv
);
934 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
935 EXPECT_EQ("Hello", out
.response_data
);
938 // Checks that two identical Content-Disposition headers result in no error.
939 TEST_P(HttpNetworkTransactionTest
,
940 TwoIdenticalContentDispositionHeaders
) {
941 MockRead data_reads
[] = {
942 MockRead("HTTP/1.1 200 OK\r\n"),
943 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
944 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
945 MockRead("Content-Length: 5\r\n\r\n"),
948 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
949 arraysize(data_reads
));
950 EXPECT_EQ(OK
, out
.rv
);
951 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
952 EXPECT_EQ("Hello", out
.response_data
);
955 // Checks that two distinct Content-Disposition headers result in an error.
956 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
957 MockRead data_reads
[] = {
958 MockRead("HTTP/1.1 200 OK\r\n"),
959 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
960 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
961 MockRead("Content-Length: 5\r\n\r\n"),
964 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
965 arraysize(data_reads
));
966 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
969 // Checks that two identical Location headers result in no error.
970 // Also tests Location header behavior.
971 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
972 MockRead data_reads
[] = {
973 MockRead("HTTP/1.1 302 Redirect\r\n"),
974 MockRead("Location: http://good.com/\r\n"),
975 MockRead("Location: http://good.com/\r\n"),
976 MockRead("Content-Length: 0\r\n\r\n"),
977 MockRead(SYNCHRONOUS
, OK
),
980 HttpRequestInfo request
;
981 request
.method
= "GET";
982 request
.url
= GURL("http://redirect.com/");
983 request
.load_flags
= 0;
985 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
986 scoped_ptr
<HttpTransaction
> trans(
987 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
989 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
990 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
992 TestCompletionCallback callback
;
994 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
995 EXPECT_EQ(ERR_IO_PENDING
, rv
);
997 EXPECT_EQ(OK
, callback
.WaitForResult());
999 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1000 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
1001 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
1003 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
1004 EXPECT_EQ("http://good.com/", url
);
1005 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1008 // Checks that two distinct Location headers result in an error.
1009 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
1010 MockRead data_reads
[] = {
1011 MockRead("HTTP/1.1 302 Redirect\r\n"),
1012 MockRead("Location: http://good.com/\r\n"),
1013 MockRead("Location: http://evil.com/\r\n"),
1014 MockRead("Content-Length: 0\r\n\r\n"),
1015 MockRead(SYNCHRONOUS
, OK
),
1017 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1018 arraysize(data_reads
));
1019 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
1022 // Do a request using the HEAD method. Verify that we don't try to read the
1023 // message body (since HEAD has none).
1024 TEST_P(HttpNetworkTransactionTest
, Head
) {
1025 HttpRequestInfo request
;
1026 request
.method
= "HEAD";
1027 request
.url
= GURL("http://www.example.org/");
1028 request
.load_flags
= 0;
1030 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1031 scoped_ptr
<HttpTransaction
> trans(
1032 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1033 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1034 trans
->SetBeforeProxyHeadersSentCallback(
1035 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1036 base::Unretained(&proxy_headers_handler
)));
1038 MockWrite data_writes1
[] = {
1039 MockWrite("HEAD / HTTP/1.1\r\n"
1040 "Host: www.example.org\r\n"
1041 "Connection: keep-alive\r\n\r\n"),
1043 MockRead data_reads1
[] = {
1044 MockRead("HTTP/1.1 404 Not Found\r\n"),
1045 MockRead("Server: Blah\r\n"),
1046 MockRead("Content-Length: 1234\r\n\r\n"),
1048 // No response body because the test stops reading here.
1049 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1052 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1053 data_writes1
, arraysize(data_writes1
));
1054 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1056 TestCompletionCallback callback1
;
1058 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1059 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1061 rv
= callback1
.WaitForResult();
1064 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1065 ASSERT_TRUE(response
!= NULL
);
1067 // Check that the headers got parsed.
1068 EXPECT_TRUE(response
->headers
.get() != NULL
);
1069 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1070 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1071 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1072 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1074 std::string server_header
;
1076 bool has_server_header
= response
->headers
->EnumerateHeader(
1077 &iter
, "Server", &server_header
);
1078 EXPECT_TRUE(has_server_header
);
1079 EXPECT_EQ("Blah", server_header
);
1081 // Reading should give EOF right away, since there is no message body
1082 // (despite non-zero content-length).
1083 std::string response_data
;
1084 rv
= ReadTransaction(trans
.get(), &response_data
);
1086 EXPECT_EQ("", response_data
);
1089 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1090 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1092 MockRead data_reads
[] = {
1093 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1095 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1097 MockRead(SYNCHRONOUS
, OK
),
1099 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1100 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1102 const char* const kExpectedResponseData
[] = {
1106 for (int i
= 0; i
< 2; ++i
) {
1107 HttpRequestInfo request
;
1108 request
.method
= "GET";
1109 request
.url
= GURL("http://www.example.org/");
1110 request
.load_flags
= 0;
1112 scoped_ptr
<HttpTransaction
> trans(
1113 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1115 TestCompletionCallback callback
;
1117 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1118 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1120 rv
= callback
.WaitForResult();
1123 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1124 ASSERT_TRUE(response
!= NULL
);
1126 EXPECT_TRUE(response
->headers
.get() != NULL
);
1127 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1128 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1130 std::string response_data
;
1131 rv
= ReadTransaction(trans
.get(), &response_data
);
1133 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1137 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1138 ScopedVector
<UploadElementReader
> element_readers
;
1139 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1140 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1142 HttpRequestInfo request
;
1143 request
.method
= "POST";
1144 request
.url
= GURL("http://www.foo.com/");
1145 request
.upload_data_stream
= &upload_data_stream
;
1146 request
.load_flags
= 0;
1148 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1149 scoped_ptr
<HttpTransaction
> trans(
1150 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1152 MockRead data_reads
[] = {
1153 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1154 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1155 MockRead("hello world"),
1156 MockRead(SYNCHRONOUS
, OK
),
1158 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1159 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1161 TestCompletionCallback callback
;
1163 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1164 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1166 rv
= callback
.WaitForResult();
1169 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1170 ASSERT_TRUE(response
!= NULL
);
1172 EXPECT_TRUE(response
->headers
.get() != NULL
);
1173 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1175 std::string response_data
;
1176 rv
= ReadTransaction(trans
.get(), &response_data
);
1178 EXPECT_EQ("hello world", response_data
);
1181 // This test is almost the same as Ignores100 above, but the response contains
1182 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1183 // HTTP/1.1 and the two status headers are read in one read.
1184 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1185 HttpRequestInfo request
;
1186 request
.method
= "GET";
1187 request
.url
= GURL("http://www.foo.com/");
1188 request
.load_flags
= 0;
1190 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1191 scoped_ptr
<HttpTransaction
> trans(
1192 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1194 MockRead data_reads
[] = {
1195 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1196 "HTTP/1.1 200 OK\r\n\r\n"),
1197 MockRead("hello world"),
1198 MockRead(SYNCHRONOUS
, OK
),
1200 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1201 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1203 TestCompletionCallback callback
;
1205 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1206 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1208 rv
= callback
.WaitForResult();
1211 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1212 ASSERT_TRUE(response
!= NULL
);
1214 EXPECT_TRUE(response
->headers
.get() != NULL
);
1215 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1217 std::string response_data
;
1218 rv
= ReadTransaction(trans
.get(), &response_data
);
1220 EXPECT_EQ("hello world", response_data
);
1223 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1224 HttpRequestInfo request
;
1225 request
.method
= "POST";
1226 request
.url
= GURL("http://www.foo.com/");
1227 request
.load_flags
= 0;
1229 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1230 scoped_ptr
<HttpTransaction
> trans(
1231 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1233 MockRead data_reads
[] = {
1234 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1237 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1238 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1240 TestCompletionCallback callback
;
1242 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1243 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1245 rv
= callback
.WaitForResult();
1248 std::string response_data
;
1249 rv
= ReadTransaction(trans
.get(), &response_data
);
1251 EXPECT_EQ("", response_data
);
1254 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1255 HttpRequestInfo request
;
1256 request
.method
= "POST";
1257 request
.url
= GURL("http://www.foo.com/");
1258 request
.load_flags
= 0;
1260 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1261 scoped_ptr
<HttpTransaction
> trans(
1262 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1264 MockRead data_reads
[] = {
1267 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1268 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1270 TestCompletionCallback callback
;
1272 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1273 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1275 rv
= callback
.WaitForResult();
1276 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1279 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1280 const MockWrite
* write_failure
,
1281 const MockRead
* read_failure
) {
1282 HttpRequestInfo request
;
1283 request
.method
= "GET";
1284 request
.url
= GURL("http://www.foo.com/");
1285 request
.load_flags
= 0;
1288 session_deps_
.net_log
= &net_log
;
1289 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1291 // Written data for successfully sending both requests.
1292 MockWrite data1_writes
[] = {
1293 MockWrite("GET / HTTP/1.1\r\n"
1294 "Host: www.foo.com\r\n"
1295 "Connection: keep-alive\r\n\r\n"),
1296 MockWrite("GET / HTTP/1.1\r\n"
1297 "Host: www.foo.com\r\n"
1298 "Connection: keep-alive\r\n\r\n")
1301 // Read results for the first request.
1302 MockRead data1_reads
[] = {
1303 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1305 MockRead(ASYNC
, OK
),
1308 if (write_failure
) {
1309 ASSERT_FALSE(read_failure
);
1310 data1_writes
[1] = *write_failure
;
1312 ASSERT_TRUE(read_failure
);
1313 data1_reads
[2] = *read_failure
;
1316 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1317 data1_writes
, arraysize(data1_writes
));
1318 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1320 MockRead data2_reads
[] = {
1321 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1323 MockRead(ASYNC
, OK
),
1325 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1326 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1328 const char* const kExpectedResponseData
[] = {
1332 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1333 for (int i
= 0; i
< 2; ++i
) {
1334 TestCompletionCallback callback
;
1336 scoped_ptr
<HttpTransaction
> trans(
1337 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1339 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1340 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1342 rv
= callback
.WaitForResult();
1345 LoadTimingInfo load_timing_info
;
1346 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1347 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1349 first_socket_log_id
= load_timing_info
.socket_log_id
;
1351 // The second request should be using a new socket.
1352 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1355 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1356 ASSERT_TRUE(response
!= NULL
);
1358 EXPECT_TRUE(response
->headers
.get() != NULL
);
1359 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1361 std::string response_data
;
1362 rv
= ReadTransaction(trans
.get(), &response_data
);
1364 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1368 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1369 const MockWrite
* write_failure
,
1370 const MockRead
* read_failure
,
1372 HttpRequestInfo request
;
1373 request
.method
= "GET";
1374 request
.url
= GURL("https://www.foo.com/");
1375 request
.load_flags
= 0;
1378 session_deps_
.net_log
= &net_log
;
1379 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1381 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1382 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1384 ssl1
.SetNextProto(GetParam());
1385 ssl2
.SetNextProto(GetParam());
1387 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1388 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1390 // SPDY versions of the request and response.
1391 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1392 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1393 scoped_ptr
<SpdyFrame
> spdy_response(
1394 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1395 scoped_ptr
<SpdyFrame
> spdy_data(
1396 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1398 // HTTP/1.1 versions of the request and response.
1399 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1400 "Host: www.foo.com\r\n"
1401 "Connection: keep-alive\r\n\r\n";
1402 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1403 const char kHttpData
[] = "hello";
1405 std::vector
<MockRead
> data1_reads
;
1406 std::vector
<MockWrite
> data1_writes
;
1407 if (write_failure
) {
1408 ASSERT_FALSE(read_failure
);
1409 data1_writes
.push_back(*write_failure
);
1410 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1412 ASSERT_TRUE(read_failure
);
1414 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1416 data1_writes
.push_back(MockWrite(kHttpRequest
));
1418 data1_reads
.push_back(*read_failure
);
1421 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1422 &data1_writes
[0], data1_writes
.size());
1423 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1425 std::vector
<MockRead
> data2_reads
;
1426 std::vector
<MockWrite
> data2_writes
;
1429 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1431 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1432 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1433 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1435 data2_writes
.push_back(
1436 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1438 data2_reads
.push_back(
1439 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1440 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1441 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1443 SequencedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1444 &data2_writes
[0], data2_writes
.size());
1445 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1447 // Preconnect a socket.
1448 SSLConfig ssl_config
;
1449 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1450 session
->GetNextProtos(&ssl_config
.next_protos
);
1451 session
->http_stream_factory()->PreconnectStreams(1, request
, ssl_config
,
1453 // Wait for the preconnect to complete.
1454 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1455 base::RunLoop().RunUntilIdle();
1456 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1458 // Make the request.
1459 TestCompletionCallback callback
;
1461 scoped_ptr
<HttpTransaction
> trans(
1462 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1464 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1465 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1467 rv
= callback
.WaitForResult();
1470 LoadTimingInfo load_timing_info
;
1471 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1472 TestLoadTimingNotReused(
1474 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1476 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1477 ASSERT_TRUE(response
!= NULL
);
1479 EXPECT_TRUE(response
->headers
.get() != NULL
);
1480 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1482 std::string response_data
;
1483 rv
= ReadTransaction(trans
.get(), &response_data
);
1485 EXPECT_EQ(kHttpData
, response_data
);
1488 TEST_P(HttpNetworkTransactionTest
,
1489 KeepAliveConnectionNotConnectedOnWrite
) {
1490 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1491 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1494 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1495 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1496 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1499 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1500 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1501 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1504 // Make sure that on a 408 response (Request Timeout), the request is retried,
1505 // if the socket was a reused keep alive socket.
1506 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1507 MockRead
read_failure(SYNCHRONOUS
,
1508 "HTTP/1.1 408 Request Timeout\r\n"
1509 "Connection: Keep-Alive\r\n"
1510 "Content-Length: 6\r\n\r\n"
1512 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1515 TEST_P(HttpNetworkTransactionTest
,
1516 PreconnectErrorNotConnectedOnWrite
) {
1517 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1518 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1521 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1522 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1523 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1526 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1527 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1528 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1531 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1532 MockRead
read_failure(ASYNC
, OK
); // EOF
1533 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1536 // Make sure that on a 408 response (Request Timeout), the request is retried,
1537 // if the socket was a preconnected (UNUSED_IDLE) socket.
1538 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1539 MockRead
read_failure(SYNCHRONOUS
,
1540 "HTTP/1.1 408 Request Timeout\r\n"
1541 "Connection: Keep-Alive\r\n"
1542 "Content-Length: 6\r\n\r\n"
1544 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1545 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1548 TEST_P(HttpNetworkTransactionTest
,
1549 SpdyPreconnectErrorNotConnectedOnWrite
) {
1550 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1551 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1554 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1555 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1556 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1559 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1560 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1561 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1564 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1565 MockRead
read_failure(ASYNC
, OK
); // EOF
1566 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1569 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1570 HttpRequestInfo request
;
1571 request
.method
= "GET";
1572 request
.url
= GURL("http://www.example.org/");
1573 request
.load_flags
= 0;
1575 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1576 scoped_ptr
<HttpTransaction
> trans(
1577 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1579 MockRead data_reads
[] = {
1580 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1581 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1582 MockRead("hello world"),
1583 MockRead(SYNCHRONOUS
, OK
),
1585 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1586 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1588 TestCompletionCallback callback
;
1590 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1591 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1593 rv
= callback
.WaitForResult();
1594 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1597 // What do various browsers do when the server closes a non-keepalive
1598 // connection without sending any response header or body?
1601 // Safari 3.1.2 (Windows): error page
1602 // Firefox 3.0.1: blank page
1603 // Opera 9.52: after five attempts, blank page
1604 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1605 // Us: error page (EMPTY_RESPONSE)
1606 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1607 MockRead data_reads
[] = {
1608 MockRead(SYNCHRONOUS
, OK
), // EOF
1609 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1610 MockRead("hello world"),
1611 MockRead(SYNCHRONOUS
, OK
),
1613 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1614 arraysize(data_reads
));
1615 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1618 // Test that network access can be deferred and resumed.
1619 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1620 HttpRequestInfo request
;
1621 request
.method
= "GET";
1622 request
.url
= GURL("http://www.example.org/");
1623 request
.load_flags
= 0;
1625 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1626 scoped_ptr
<HttpTransaction
> trans(
1627 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1629 // Defer on OnBeforeNetworkStart.
1630 BeforeNetworkStartHandler
net_start_handler(true); // defer
1631 trans
->SetBeforeNetworkStartCallback(
1632 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1633 base::Unretained(&net_start_handler
)));
1635 MockRead data_reads
[] = {
1636 MockRead("HTTP/1.0 200 OK\r\n"),
1637 MockRead("Content-Length: 5\r\n\r\n"),
1639 MockRead(SYNCHRONOUS
, 0),
1641 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1642 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1644 TestCompletionCallback callback
;
1646 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1647 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1648 base::MessageLoop::current()->RunUntilIdle();
1650 // Should have deferred for network start.
1651 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1652 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1654 trans
->ResumeNetworkStart();
1655 rv
= callback
.WaitForResult();
1657 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1659 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1660 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1661 if (rv
== ERR_IO_PENDING
)
1662 rv
= callback
.WaitForResult();
1667 // Test that network use can be deferred and canceled.
1668 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1669 HttpRequestInfo request
;
1670 request
.method
= "GET";
1671 request
.url
= GURL("http://www.example.org/");
1672 request
.load_flags
= 0;
1674 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1675 scoped_ptr
<HttpTransaction
> trans(
1676 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1678 // Defer on OnBeforeNetworkStart.
1679 BeforeNetworkStartHandler
net_start_handler(true); // defer
1680 trans
->SetBeforeNetworkStartCallback(
1681 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1682 base::Unretained(&net_start_handler
)));
1684 TestCompletionCallback callback
;
1686 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1687 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1688 base::MessageLoop::current()->RunUntilIdle();
1690 // Should have deferred for network start.
1691 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1692 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1695 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1696 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1697 // destructor in such situations.
1698 // See http://crbug.com/154712 and http://crbug.com/156609.
1699 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1700 HttpRequestInfo request
;
1701 request
.method
= "GET";
1702 request
.url
= GURL("http://www.example.org/");
1703 request
.load_flags
= 0;
1705 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1706 scoped_ptr
<HttpTransaction
> trans(
1707 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1709 MockRead data_reads
[] = {
1710 MockRead("HTTP/1.0 200 OK\r\n"),
1711 MockRead("Connection: keep-alive\r\n"),
1712 MockRead("Content-Length: 100\r\n\r\n"),
1714 MockRead(SYNCHRONOUS
, 0),
1716 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1717 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1719 TestCompletionCallback callback
;
1721 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1722 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1724 rv
= callback
.WaitForResult();
1727 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1728 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1729 if (rv
== ERR_IO_PENDING
)
1730 rv
= callback
.WaitForResult();
1732 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1733 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1736 base::MessageLoop::current()->RunUntilIdle();
1737 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1740 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1741 HttpRequestInfo request
;
1742 request
.method
= "GET";
1743 request
.url
= GURL("http://www.example.org/");
1744 request
.load_flags
= 0;
1746 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1747 scoped_ptr
<HttpTransaction
> trans(
1748 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1750 MockRead data_reads
[] = {
1751 MockRead("HTTP/1.0 200 OK\r\n"),
1752 MockRead("Connection: keep-alive\r\n"),
1753 MockRead("Content-Length: 100\r\n\r\n"),
1754 MockRead(SYNCHRONOUS
, 0),
1756 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1757 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1759 TestCompletionCallback callback
;
1761 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1762 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1764 rv
= callback
.WaitForResult();
1767 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1768 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1769 if (rv
== ERR_IO_PENDING
)
1770 rv
= callback
.WaitForResult();
1771 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1774 base::MessageLoop::current()->RunUntilIdle();
1775 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1778 // Test that we correctly reuse a keep-alive connection after not explicitly
1779 // reading the body.
1780 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1781 HttpRequestInfo request
;
1782 request
.method
= "GET";
1783 request
.url
= GURL("http://www.foo.com/");
1784 request
.load_flags
= 0;
1787 session_deps_
.net_log
= &net_log
;
1788 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1790 // Note that because all these reads happen in the same
1791 // StaticSocketDataProvider, it shows that the same socket is being reused for
1792 // all transactions.
1793 MockRead data1_reads
[] = {
1794 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1795 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1796 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1797 MockRead("HTTP/1.1 302 Found\r\n"
1798 "Content-Length: 0\r\n\r\n"),
1799 MockRead("HTTP/1.1 302 Found\r\n"
1800 "Content-Length: 5\r\n\r\n"
1802 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1803 "Content-Length: 0\r\n\r\n"),
1804 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1805 "Content-Length: 5\r\n\r\n"
1807 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1810 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1811 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1813 MockRead data2_reads
[] = {
1814 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1816 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1817 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1819 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1820 std::string response_lines
[kNumUnreadBodies
];
1822 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1823 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1824 TestCompletionCallback callback
;
1826 scoped_ptr
<HttpTransaction
> trans(
1827 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1829 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1830 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1832 rv
= callback
.WaitForResult();
1835 LoadTimingInfo load_timing_info
;
1836 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1838 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1839 first_socket_log_id
= load_timing_info
.socket_log_id
;
1841 TestLoadTimingReused(load_timing_info
);
1842 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1845 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1846 ASSERT_TRUE(response
!= NULL
);
1848 ASSERT_TRUE(response
->headers
.get() != NULL
);
1849 response_lines
[i
] = response
->headers
->GetStatusLine();
1851 // We intentionally don't read the response bodies.
1854 const char* const kStatusLines
[] = {
1855 "HTTP/1.1 204 No Content",
1856 "HTTP/1.1 205 Reset Content",
1857 "HTTP/1.1 304 Not Modified",
1858 "HTTP/1.1 302 Found",
1859 "HTTP/1.1 302 Found",
1860 "HTTP/1.1 301 Moved Permanently",
1861 "HTTP/1.1 301 Moved Permanently",
1864 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1865 "forgot to update kStatusLines");
1867 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1868 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1870 TestCompletionCallback callback
;
1871 scoped_ptr
<HttpTransaction
> trans(
1872 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1873 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1874 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1875 rv
= callback
.WaitForResult();
1877 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1878 ASSERT_TRUE(response
!= NULL
);
1879 ASSERT_TRUE(response
->headers
.get() != NULL
);
1880 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1881 std::string response_data
;
1882 rv
= ReadTransaction(trans
.get(), &response_data
);
1884 EXPECT_EQ("hello", response_data
);
1887 // Test the request-challenge-retry sequence for basic auth.
1888 // (basic auth is the easiest to mock, because it has no randomness).
1889 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1890 HttpRequestInfo request
;
1891 request
.method
= "GET";
1892 request
.url
= GURL("http://www.example.org/");
1893 request
.load_flags
= 0;
1896 session_deps_
.net_log
= &log
;
1897 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1898 scoped_ptr
<HttpTransaction
> trans(
1899 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1901 MockWrite data_writes1
[] = {
1903 "GET / HTTP/1.1\r\n"
1904 "Host: www.example.org\r\n"
1905 "Connection: keep-alive\r\n\r\n"),
1908 MockRead data_reads1
[] = {
1909 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1910 // Give a couple authenticate options (only the middle one is actually
1912 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1913 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1914 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1915 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1916 // Large content-length -- won't matter, as connection will be reset.
1917 MockRead("Content-Length: 10000\r\n\r\n"),
1918 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1921 // After calling trans->RestartWithAuth(), this is the request we should
1922 // be issuing -- the final header line contains the credentials.
1923 MockWrite data_writes2
[] = {
1925 "GET / HTTP/1.1\r\n"
1926 "Host: www.example.org\r\n"
1927 "Connection: keep-alive\r\n"
1928 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1931 // Lastly, the server responds with the actual content.
1932 MockRead data_reads2
[] = {
1933 MockRead("HTTP/1.0 200 OK\r\n"),
1934 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1935 MockRead("Content-Length: 100\r\n\r\n"),
1936 MockRead(SYNCHRONOUS
, OK
),
1939 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1940 data_writes1
, arraysize(data_writes1
));
1941 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1942 data_writes2
, arraysize(data_writes2
));
1943 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1944 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1946 TestCompletionCallback callback1
;
1948 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1949 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1951 rv
= callback1
.WaitForResult();
1954 LoadTimingInfo load_timing_info1
;
1955 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1956 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1958 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1959 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1961 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1962 ASSERT_TRUE(response
!= NULL
);
1963 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1965 TestCompletionCallback callback2
;
1967 rv
= trans
->RestartWithAuth(
1968 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1969 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1971 rv
= callback2
.WaitForResult();
1974 LoadTimingInfo load_timing_info2
;
1975 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1976 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1977 // The load timing after restart should have a new socket ID, and times after
1978 // those of the first load timing.
1979 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1980 load_timing_info2
.connect_timing
.connect_start
);
1981 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1983 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1984 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1986 response
= trans
->GetResponseInfo();
1987 ASSERT_TRUE(response
!= NULL
);
1988 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1989 EXPECT_EQ(100, response
->headers
->GetContentLength());
1992 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1993 HttpRequestInfo request
;
1994 request
.method
= "GET";
1995 request
.url
= GURL("http://www.example.org/");
1996 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
1998 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1999 scoped_ptr
<HttpTransaction
> trans(
2000 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2002 MockWrite data_writes
[] = {
2004 "GET / HTTP/1.1\r\n"
2005 "Host: www.example.org\r\n"
2006 "Connection: keep-alive\r\n\r\n"),
2009 MockRead data_reads
[] = {
2010 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2011 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2012 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2013 // Large content-length -- won't matter, as connection will be reset.
2014 MockRead("Content-Length: 10000\r\n\r\n"),
2015 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2018 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2019 data_writes
, arraysize(data_writes
));
2020 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2021 TestCompletionCallback callback
;
2023 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2024 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2026 rv
= callback
.WaitForResult();
2029 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2030 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2032 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2033 ASSERT_TRUE(response
!= NULL
);
2034 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2037 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2039 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2040 HttpRequestInfo request
;
2041 request
.method
= "GET";
2042 request
.url
= GURL("http://www.example.org/");
2043 request
.load_flags
= 0;
2046 session_deps_
.net_log
= &log
;
2047 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2049 MockWrite data_writes1
[] = {
2051 "GET / HTTP/1.1\r\n"
2052 "Host: www.example.org\r\n"
2053 "Connection: keep-alive\r\n\r\n"),
2055 // After calling trans->RestartWithAuth(), this is the request we should
2056 // be issuing -- the final header line contains the credentials.
2058 "GET / HTTP/1.1\r\n"
2059 "Host: www.example.org\r\n"
2060 "Connection: keep-alive\r\n"
2061 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2064 MockRead data_reads1
[] = {
2065 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2066 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2067 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2068 MockRead("Content-Length: 14\r\n\r\n"),
2069 MockRead("Unauthorized\r\n"),
2071 // Lastly, the server responds with the actual content.
2072 MockRead("HTTP/1.1 200 OK\r\n"),
2073 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2074 MockRead("Content-Length: 5\r\n\r\n"),
2078 // If there is a regression where we disconnect a Keep-Alive
2079 // connection during an auth roundtrip, we'll end up reading this.
2080 MockRead data_reads2
[] = {
2081 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2084 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2085 data_writes1
, arraysize(data_writes1
));
2086 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2088 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2089 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2091 TestCompletionCallback callback1
;
2093 scoped_ptr
<HttpTransaction
> trans(
2094 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2095 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2096 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2098 rv
= callback1
.WaitForResult();
2101 LoadTimingInfo load_timing_info1
;
2102 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2103 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2105 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2106 ASSERT_TRUE(response
!= NULL
);
2107 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2109 TestCompletionCallback callback2
;
2111 rv
= trans
->RestartWithAuth(
2112 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2113 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2115 rv
= callback2
.WaitForResult();
2118 LoadTimingInfo load_timing_info2
;
2119 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2120 TestLoadTimingReused(load_timing_info2
);
2121 // The load timing after restart should have the same socket ID, and times
2122 // those of the first load timing.
2123 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2124 load_timing_info2
.send_start
);
2125 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2127 response
= trans
->GetResponseInfo();
2128 ASSERT_TRUE(response
!= NULL
);
2129 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2130 EXPECT_EQ(5, response
->headers
->GetContentLength());
2132 std::string response_data
;
2133 rv
= ReadTransaction(trans
.get(), &response_data
);
2135 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2136 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2139 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2140 // connection and with no response body to drain.
2141 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2142 HttpRequestInfo request
;
2143 request
.method
= "GET";
2144 request
.url
= GURL("http://www.example.org/");
2145 request
.load_flags
= 0;
2147 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2149 MockWrite data_writes1
[] = {
2151 "GET / HTTP/1.1\r\n"
2152 "Host: www.example.org\r\n"
2153 "Connection: keep-alive\r\n\r\n"),
2155 // After calling trans->RestartWithAuth(), this is the request we should
2156 // be issuing -- the final header line contains the credentials.
2158 "GET / HTTP/1.1\r\n"
2159 "Host: www.example.org\r\n"
2160 "Connection: keep-alive\r\n"
2161 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2164 MockRead data_reads1
[] = {
2165 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2166 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2167 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2169 // Lastly, the server responds with the actual content.
2170 MockRead("HTTP/1.1 200 OK\r\n"),
2171 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2172 MockRead("Content-Length: 5\r\n\r\n"),
2176 // An incorrect reconnect would cause this to be read.
2177 MockRead data_reads2
[] = {
2178 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2181 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2182 data_writes1
, arraysize(data_writes1
));
2183 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2185 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2186 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2188 TestCompletionCallback callback1
;
2190 scoped_ptr
<HttpTransaction
> trans(
2191 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2192 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2193 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2195 rv
= callback1
.WaitForResult();
2198 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2199 ASSERT_TRUE(response
!= NULL
);
2200 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2202 TestCompletionCallback callback2
;
2204 rv
= trans
->RestartWithAuth(
2205 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2206 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2208 rv
= callback2
.WaitForResult();
2211 response
= trans
->GetResponseInfo();
2212 ASSERT_TRUE(response
!= NULL
);
2213 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2214 EXPECT_EQ(5, response
->headers
->GetContentLength());
2217 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2218 // connection and with a large response body to drain.
2219 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2220 HttpRequestInfo request
;
2221 request
.method
= "GET";
2222 request
.url
= GURL("http://www.example.org/");
2223 request
.load_flags
= 0;
2225 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2227 MockWrite data_writes1
[] = {
2229 "GET / HTTP/1.1\r\n"
2230 "Host: www.example.org\r\n"
2231 "Connection: keep-alive\r\n\r\n"),
2233 // After calling trans->RestartWithAuth(), this is the request we should
2234 // be issuing -- the final header line contains the credentials.
2236 "GET / HTTP/1.1\r\n"
2237 "Host: www.example.org\r\n"
2238 "Connection: keep-alive\r\n"
2239 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2242 // Respond with 5 kb of response body.
2243 std::string
large_body_string("Unauthorized");
2244 large_body_string
.append(5 * 1024, ' ');
2245 large_body_string
.append("\r\n");
2247 MockRead data_reads1
[] = {
2248 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2249 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2251 // 5134 = 12 + 5 * 1024 + 2
2252 MockRead("Content-Length: 5134\r\n\r\n"),
2253 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2255 // Lastly, the server responds with the actual content.
2256 MockRead("HTTP/1.1 200 OK\r\n"),
2257 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2258 MockRead("Content-Length: 5\r\n\r\n"),
2262 // An incorrect reconnect would cause this to be read.
2263 MockRead data_reads2
[] = {
2264 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2267 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2268 data_writes1
, arraysize(data_writes1
));
2269 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2271 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2272 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2274 TestCompletionCallback callback1
;
2276 scoped_ptr
<HttpTransaction
> trans(
2277 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2278 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2279 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2281 rv
= callback1
.WaitForResult();
2284 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2285 ASSERT_TRUE(response
!= NULL
);
2286 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2288 TestCompletionCallback callback2
;
2290 rv
= trans
->RestartWithAuth(
2291 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2292 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2294 rv
= callback2
.WaitForResult();
2297 response
= trans
->GetResponseInfo();
2298 ASSERT_TRUE(response
!= NULL
);
2299 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2300 EXPECT_EQ(5, response
->headers
->GetContentLength());
2303 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2304 // connection, but the server gets impatient and closes the connection.
2305 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2306 HttpRequestInfo request
;
2307 request
.method
= "GET";
2308 request
.url
= GURL("http://www.example.org/");
2309 request
.load_flags
= 0;
2311 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2313 MockWrite data_writes1
[] = {
2315 "GET / HTTP/1.1\r\n"
2316 "Host: www.example.org\r\n"
2317 "Connection: keep-alive\r\n\r\n"),
2318 // This simulates the seemingly successful write to a closed connection
2319 // if the bug is not fixed.
2321 "GET / HTTP/1.1\r\n"
2322 "Host: www.example.org\r\n"
2323 "Connection: keep-alive\r\n"
2324 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2327 MockRead data_reads1
[] = {
2328 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2329 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2330 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2331 MockRead("Content-Length: 14\r\n\r\n"),
2332 // Tell MockTCPClientSocket to simulate the server closing the connection.
2333 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2334 MockRead("Unauthorized\r\n"),
2335 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2338 // After calling trans->RestartWithAuth(), this is the request we should
2339 // be issuing -- the final header line contains the credentials.
2340 MockWrite data_writes2
[] = {
2342 "GET / HTTP/1.1\r\n"
2343 "Host: www.example.org\r\n"
2344 "Connection: keep-alive\r\n"
2345 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2348 // Lastly, the server responds with the actual content.
2349 MockRead data_reads2
[] = {
2350 MockRead("HTTP/1.1 200 OK\r\n"),
2351 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2352 MockRead("Content-Length: 5\r\n\r\n"),
2356 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2357 data_writes1
, arraysize(data_writes1
));
2358 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2359 data_writes2
, arraysize(data_writes2
));
2360 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2361 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2363 TestCompletionCallback callback1
;
2365 scoped_ptr
<HttpTransaction
> trans(
2366 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2367 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2368 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2370 rv
= callback1
.WaitForResult();
2373 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2374 ASSERT_TRUE(response
!= NULL
);
2375 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2377 TestCompletionCallback callback2
;
2379 rv
= trans
->RestartWithAuth(
2380 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2381 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2383 rv
= callback2
.WaitForResult();
2386 response
= trans
->GetResponseInfo();
2387 ASSERT_TRUE(response
!= NULL
);
2388 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2389 EXPECT_EQ(5, response
->headers
->GetContentLength());
2392 // Test the request-challenge-retry sequence for basic auth, over a connection
2393 // that requires a restart when setting up an SSL tunnel.
2394 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2395 HttpRequestInfo request
;
2396 request
.method
= "GET";
2397 request
.url
= GURL("https://www.example.org/");
2398 // when the no authentication data flag is set.
2399 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2401 // Configure against proxy server "myproxy:70".
2402 session_deps_
.proxy_service
.reset(
2403 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2404 BoundTestNetLog log
;
2405 session_deps_
.net_log
= log
.bound().net_log();
2406 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2408 // Since we have proxy, should try to establish tunnel.
2409 MockWrite data_writes1
[] = {
2410 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2411 "Host: www.example.org\r\n"
2412 "Proxy-Connection: keep-alive\r\n\r\n"),
2415 // The proxy responds to the connect with a 407, using a non-persistent
2417 MockRead data_reads1
[] = {
2419 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2420 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2423 // Since the first connection couldn't be reused, need to establish another
2424 // once given credentials.
2425 MockWrite data_writes2
[] = {
2426 // After calling trans->RestartWithAuth(), this is the request we should
2427 // be issuing -- the final header line contains the credentials.
2428 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2429 "Host: www.example.org\r\n"
2430 "Proxy-Connection: keep-alive\r\n"
2431 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2433 MockWrite("GET / HTTP/1.1\r\n"
2434 "Host: www.example.org\r\n"
2435 "Connection: keep-alive\r\n\r\n"),
2438 MockRead data_reads2
[] = {
2439 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2441 MockRead("HTTP/1.1 200 OK\r\n"),
2442 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2443 MockRead("Content-Length: 5\r\n\r\n"),
2444 MockRead(SYNCHRONOUS
, "hello"),
2447 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2448 data_writes1
, arraysize(data_writes1
));
2449 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2450 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2451 data_writes2
, arraysize(data_writes2
));
2452 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2453 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2454 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2456 TestCompletionCallback callback1
;
2458 scoped_ptr
<HttpTransaction
> trans(
2459 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2461 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2462 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2464 rv
= callback1
.WaitForResult();
2466 TestNetLogEntry::List entries
;
2467 log
.GetEntries(&entries
);
2468 size_t pos
= ExpectLogContainsSomewhere(
2469 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2470 NetLog::PHASE_NONE
);
2471 ExpectLogContainsSomewhere(
2472 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2473 NetLog::PHASE_NONE
);
2475 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2476 ASSERT_TRUE(response
!= NULL
);
2477 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2478 ASSERT_FALSE(response
->headers
.get() == NULL
);
2479 EXPECT_EQ(407, response
->headers
->response_code());
2480 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2481 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2483 LoadTimingInfo load_timing_info
;
2484 // CONNECT requests and responses are handled at the connect job level, so
2485 // the transaction does not yet have a connection.
2486 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2488 TestCompletionCallback callback2
;
2491 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2492 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2494 rv
= callback2
.WaitForResult();
2497 response
= trans
->GetResponseInfo();
2498 ASSERT_TRUE(response
!= NULL
);
2500 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2501 EXPECT_EQ(200, response
->headers
->response_code());
2502 EXPECT_EQ(5, response
->headers
->GetContentLength());
2503 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2505 // The password prompt info should not be set.
2506 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2508 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2509 TestLoadTimingNotReusedWithPac(load_timing_info
,
2510 CONNECT_TIMING_HAS_SSL_TIMES
);
2513 session
->CloseAllConnections();
2516 // Test the request-challenge-retry sequence for basic auth, over a connection
2517 // that requires a restart when setting up an SSL tunnel.
2518 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2519 HttpRequestInfo request
;
2520 request
.method
= "GET";
2521 request
.url
= GURL("https://www.example.org/");
2522 // when the no authentication data flag is set.
2523 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2525 // Configure against proxy server "myproxy:70".
2526 session_deps_
.proxy_service
.reset(
2527 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2528 BoundTestNetLog log
;
2529 session_deps_
.net_log
= log
.bound().net_log();
2530 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2532 // Since we have proxy, should try to establish tunnel.
2533 MockWrite data_writes1
[] = {
2534 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2535 "Host: www.example.org\r\n"
2536 "Proxy-Connection: keep-alive\r\n\r\n"),
2539 // The proxy responds to the connect with a 407, using a non-persistent
2541 MockRead data_reads1
[] = {
2543 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2544 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2545 MockRead("Proxy-Connection: close\r\n\r\n"),
2548 MockWrite data_writes2
[] = {
2549 // After calling trans->RestartWithAuth(), this is the request we should
2550 // be issuing -- the final header line contains the credentials.
2551 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2552 "Host: www.example.org\r\n"
2553 "Proxy-Connection: keep-alive\r\n"
2554 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2556 MockWrite("GET / HTTP/1.1\r\n"
2557 "Host: www.example.org\r\n"
2558 "Connection: keep-alive\r\n\r\n"),
2561 MockRead data_reads2
[] = {
2562 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2564 MockRead("HTTP/1.1 200 OK\r\n"),
2565 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2566 MockRead("Content-Length: 5\r\n\r\n"),
2567 MockRead(SYNCHRONOUS
, "hello"),
2570 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2571 data_writes1
, arraysize(data_writes1
));
2572 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2573 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2574 data_writes2
, arraysize(data_writes2
));
2575 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2576 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2577 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2579 TestCompletionCallback callback1
;
2581 scoped_ptr
<HttpTransaction
> trans(
2582 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2584 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2585 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2587 rv
= callback1
.WaitForResult();
2589 TestNetLogEntry::List entries
;
2590 log
.GetEntries(&entries
);
2591 size_t pos
= ExpectLogContainsSomewhere(
2592 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2593 NetLog::PHASE_NONE
);
2594 ExpectLogContainsSomewhere(
2596 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2597 NetLog::PHASE_NONE
);
2599 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2600 ASSERT_TRUE(response
!= NULL
);
2601 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2602 ASSERT_FALSE(response
->headers
.get() == NULL
);
2603 EXPECT_EQ(407, response
->headers
->response_code());
2604 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2605 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2607 LoadTimingInfo load_timing_info
;
2608 // CONNECT requests and responses are handled at the connect job level, so
2609 // the transaction does not yet have a connection.
2610 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2612 TestCompletionCallback callback2
;
2614 rv
= trans
->RestartWithAuth(
2615 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2616 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2618 rv
= callback2
.WaitForResult();
2621 response
= trans
->GetResponseInfo();
2622 ASSERT_TRUE(response
!= NULL
);
2624 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2625 EXPECT_EQ(200, response
->headers
->response_code());
2626 EXPECT_EQ(5, response
->headers
->GetContentLength());
2627 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2629 // The password prompt info should not be set.
2630 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2632 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2633 TestLoadTimingNotReusedWithPac(load_timing_info
,
2634 CONNECT_TIMING_HAS_SSL_TIMES
);
2637 session
->CloseAllConnections();
2640 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2641 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2642 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2643 HttpRequestInfo request
;
2644 request
.method
= "GET";
2645 request
.url
= GURL("https://www.example.org/");
2646 // Ensure that proxy authentication is attempted even
2647 // when the no authentication data flag is set.
2648 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2650 // Configure against proxy server "myproxy:70".
2651 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2652 BoundTestNetLog log
;
2653 session_deps_
.net_log
= log
.bound().net_log();
2654 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2656 scoped_ptr
<HttpTransaction
> trans(
2657 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2659 // Since we have proxy, should try to establish tunnel.
2660 MockWrite data_writes1
[] = {
2662 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2663 "Host: www.example.org\r\n"
2664 "Proxy-Connection: keep-alive\r\n\r\n"),
2666 // After calling trans->RestartWithAuth(), this is the request we should
2667 // be issuing -- the final header line contains the credentials.
2669 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2670 "Host: www.example.org\r\n"
2671 "Proxy-Connection: keep-alive\r\n"
2672 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2675 // The proxy responds to the connect with a 407, using a persistent
2676 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2677 MockRead data_reads1
[] = {
2679 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2680 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2681 MockRead("Proxy-Connection: keep-alive\r\n"),
2682 MockRead("Content-Length: 10\r\n\r\n"),
2683 MockRead("0123456789"),
2685 // Wrong credentials (wrong password).
2686 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2687 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2688 MockRead("Proxy-Connection: keep-alive\r\n"),
2689 MockRead("Content-Length: 10\r\n\r\n"),
2690 // No response body because the test stops reading here.
2691 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2694 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2695 data_writes1
, arraysize(data_writes1
));
2696 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2698 TestCompletionCallback callback1
;
2700 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2701 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2703 rv
= callback1
.WaitForResult();
2705 TestNetLogEntry::List entries
;
2706 log
.GetEntries(&entries
);
2707 size_t pos
= ExpectLogContainsSomewhere(
2708 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2709 NetLog::PHASE_NONE
);
2710 ExpectLogContainsSomewhere(
2711 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2712 NetLog::PHASE_NONE
);
2714 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2715 ASSERT_TRUE(response
);
2716 ASSERT_TRUE(response
->headers
);
2717 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2718 EXPECT_EQ(407, response
->headers
->response_code());
2719 EXPECT_EQ(10, response
->headers
->GetContentLength());
2720 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2721 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2723 TestCompletionCallback callback2
;
2725 // Wrong password (should be "bar").
2727 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2728 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2730 rv
= callback2
.WaitForResult();
2733 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 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2744 session
->CloseAllConnections();
2747 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2748 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2749 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2750 HttpRequestInfo request
;
2751 request
.method
= "GET";
2752 request
.url
= GURL("https://www.example.org/");
2753 // Ensure that proxy authentication is attempted even
2754 // when the no authentication data flag is set.
2755 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2757 // Configure against proxy server "myproxy:70".
2758 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2759 BoundTestNetLog log
;
2760 session_deps_
.net_log
= log
.bound().net_log();
2761 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2763 scoped_ptr
<HttpTransaction
> trans(
2764 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2766 // Since we have proxy, should try to establish tunnel.
2767 MockWrite data_writes1
[] = {
2769 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2770 "Host: www.example.org\r\n"
2771 "Proxy-Connection: keep-alive\r\n\r\n"),
2773 // After calling trans->RestartWithAuth(), this is the request we should
2774 // be issuing -- the final header line contains the credentials.
2776 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2777 "Host: www.example.org\r\n"
2778 "Proxy-Connection: keep-alive\r\n"
2779 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2782 // The proxy responds to the connect with a 407, using a persistent
2784 MockRead data_reads1
[] = {
2786 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2787 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2788 MockRead("Content-Length: 10\r\n\r\n"),
2789 MockRead("0123456789"),
2791 // Wrong credentials (wrong password).
2792 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2793 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2794 MockRead("Content-Length: 10\r\n\r\n"),
2795 // No response body because the test stops reading here.
2796 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2799 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2800 data_writes1
, arraysize(data_writes1
));
2801 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2803 TestCompletionCallback callback1
;
2805 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2806 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2808 rv
= callback1
.WaitForResult();
2810 TestNetLogEntry::List entries
;
2811 log
.GetEntries(&entries
);
2812 size_t pos
= ExpectLogContainsSomewhere(
2813 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2814 NetLog::PHASE_NONE
);
2815 ExpectLogContainsSomewhere(
2817 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2818 NetLog::PHASE_NONE
);
2820 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2821 ASSERT_TRUE(response
);
2822 ASSERT_TRUE(response
->headers
);
2823 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2824 EXPECT_EQ(407, response
->headers
->response_code());
2825 EXPECT_EQ(10, response
->headers
->GetContentLength());
2826 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2827 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2829 TestCompletionCallback callback2
;
2831 // Wrong password (should be "bar").
2832 rv
= trans
->RestartWithAuth(
2833 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2834 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2836 rv
= callback2
.WaitForResult();
2839 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 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2850 session
->CloseAllConnections();
2853 // Test the case a proxy closes a socket while the challenge body is being
2855 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHangupDuringBody
) {
2856 HttpRequestInfo request
;
2857 request
.method
= "GET";
2858 request
.url
= GURL("https://www.example.org/");
2859 // Ensure that proxy authentication is attempted even
2860 // when the no authentication data flag is set.
2861 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2863 // Configure against proxy server "myproxy:70".
2864 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2865 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2867 scoped_ptr
<HttpTransaction
> trans(
2868 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2870 // Since we have proxy, should try to establish tunnel.
2871 MockWrite data_writes1
[] = {
2872 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2873 "Host: www.example.org\r\n"
2874 "Proxy-Connection: keep-alive\r\n\r\n"),
2877 // The proxy responds to the connect with a 407, using a persistent
2879 MockRead data_reads1
[] = {
2881 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2882 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2883 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
2884 // Server hands up in the middle of the body.
2885 MockRead(ASYNC
, ERR_CONNECTION_CLOSED
),
2888 MockWrite data_writes2
[] = {
2889 // After calling trans->RestartWithAuth(), this is the request we should
2890 // be issuing -- the final header line contains the credentials.
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"
2894 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2896 MockWrite("GET / HTTP/1.1\r\n"
2897 "Host: www.example.org\r\n"
2898 "Connection: keep-alive\r\n\r\n"),
2901 MockRead data_reads2
[] = {
2902 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2904 MockRead("HTTP/1.1 200 OK\r\n"),
2905 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2906 MockRead("Content-Length: 5\r\n\r\n"),
2907 MockRead(SYNCHRONOUS
, "hello"),
2910 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2911 data_writes1
, arraysize(data_writes1
));
2912 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2913 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2914 data_writes2
, arraysize(data_writes2
));
2915 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2916 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2917 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2919 TestCompletionCallback callback
;
2921 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2922 EXPECT_EQ(OK
, callback
.GetResult(rv
));
2924 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2925 ASSERT_TRUE(response
);
2926 ASSERT_TRUE(response
->headers
);
2927 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2928 EXPECT_EQ(407, response
->headers
->response_code());
2929 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2931 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
2932 EXPECT_EQ(OK
, callback
.GetResult(rv
));
2934 response
= trans
->GetResponseInfo();
2935 ASSERT_TRUE(response
);
2936 ASSERT_TRUE(response
->headers
);
2937 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2938 EXPECT_EQ(200, response
->headers
->response_code());
2940 EXPECT_EQ(OK
, ReadTransaction(trans
.get(), &body
));
2941 EXPECT_EQ("hello", body
);
2944 // Test that we don't read the response body when we fail to establish a tunnel,
2945 // even if the user cancels the proxy's auth attempt.
2946 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2947 HttpRequestInfo request
;
2948 request
.method
= "GET";
2949 request
.url
= GURL("https://www.example.org/");
2950 request
.load_flags
= 0;
2952 // Configure against proxy server "myproxy:70".
2953 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2955 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2957 scoped_ptr
<HttpTransaction
> trans(
2958 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2960 // Since we have proxy, should try to establish tunnel.
2961 MockWrite data_writes
[] = {
2963 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2964 "Host: www.example.org\r\n"
2965 "Proxy-Connection: keep-alive\r\n\r\n"),
2968 // The proxy responds to the connect with a 407.
2969 MockRead data_reads
[] = {
2970 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2971 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2972 MockRead("Content-Length: 10\r\n\r\n"),
2973 MockRead("0123456789"), // Should not be reached.
2974 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2977 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2978 data_writes
, arraysize(data_writes
));
2979 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2981 TestCompletionCallback callback
;
2983 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2984 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2986 rv
= callback
.WaitForResult();
2989 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2990 ASSERT_TRUE(response
);
2991 ASSERT_TRUE(response
->headers
);
2992 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2993 EXPECT_EQ(407, response
->headers
->response_code());
2994 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2996 std::string response_data
;
2997 rv
= ReadTransaction(trans
.get(), &response_data
);
2998 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3000 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3001 session
->CloseAllConnections();
3004 // Test that we don't pass extraneous headers from the proxy's response to the
3005 // caller when the proxy responds to CONNECT with 407.
3006 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
3007 HttpRequestInfo request
;
3008 request
.method
= "GET";
3009 request
.url
= GURL("https://www.example.org/");
3010 request
.load_flags
= 0;
3012 // Configure against proxy server "myproxy:70".
3013 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3015 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3017 scoped_ptr
<HttpTransaction
> trans(
3018 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3020 // Since we have proxy, should try to establish tunnel.
3021 MockWrite data_writes
[] = {
3023 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3024 "Host: www.example.org\r\n"
3025 "Proxy-Connection: keep-alive\r\n\r\n"),
3028 // The proxy responds to the connect with a 407.
3029 MockRead data_reads
[] = {
3030 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3031 MockRead("X-Foo: bar\r\n"),
3032 MockRead("Set-Cookie: foo=bar\r\n"),
3033 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3034 MockRead("Content-Length: 10\r\n\r\n"),
3035 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3038 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
3039 arraysize(data_writes
));
3040 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3042 TestCompletionCallback callback
;
3044 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3047 rv
= callback
.WaitForResult();
3050 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3051 ASSERT_TRUE(response
);
3052 ASSERT_TRUE(response
->headers
);
3053 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3054 EXPECT_EQ(407, response
->headers
->response_code());
3055 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3056 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
3057 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
3059 std::string response_data
;
3060 rv
= ReadTransaction(trans
.get(), &response_data
);
3061 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3063 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3064 session
->CloseAllConnections();
3067 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3068 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
3069 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
3070 HttpRequestInfo request
;
3071 request
.method
= "GET";
3072 request
.url
= GURL("http://www.example.org/");
3073 request
.load_flags
= 0;
3075 // We are using a DIRECT connection (i.e. no proxy) for this session.
3076 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3077 scoped_ptr
<HttpTransaction
> trans(
3078 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3080 MockWrite data_writes1
[] = {
3082 "GET / HTTP/1.1\r\n"
3083 "Host: www.example.org\r\n"
3084 "Connection: keep-alive\r\n\r\n"),
3087 MockRead data_reads1
[] = {
3088 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3089 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3090 // Large content-length -- won't matter, as connection will be reset.
3091 MockRead("Content-Length: 10000\r\n\r\n"),
3092 MockRead(SYNCHRONOUS
, ERR_FAILED
),
3095 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3096 data_writes1
, arraysize(data_writes1
));
3097 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3099 TestCompletionCallback callback
;
3101 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3102 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3104 rv
= callback
.WaitForResult();
3105 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3108 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3109 // through a non-authenticating proxy. The request should fail with
3110 // ERR_UNEXPECTED_PROXY_AUTH.
3111 // Note that it is impossible to detect if an HTTP server returns a 407 through
3112 // a non-authenticating proxy - there is nothing to indicate whether the
3113 // response came from the proxy or the server, so it is treated as if the proxy
3114 // issued the challenge.
3115 TEST_P(HttpNetworkTransactionTest
,
3116 HttpsServerRequestsProxyAuthThroughProxy
) {
3117 HttpRequestInfo request
;
3118 request
.method
= "GET";
3119 request
.url
= GURL("https://www.example.org/");
3121 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3122 BoundTestNetLog log
;
3123 session_deps_
.net_log
= log
.bound().net_log();
3124 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3126 // Since we have proxy, should try to establish tunnel.
3127 MockWrite data_writes1
[] = {
3129 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3130 "Host: www.example.org\r\n"
3131 "Proxy-Connection: keep-alive\r\n\r\n"),
3134 "GET / HTTP/1.1\r\n"
3135 "Host: www.example.org\r\n"
3136 "Connection: keep-alive\r\n\r\n"),
3139 MockRead data_reads1
[] = {
3140 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3142 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3143 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3145 MockRead(SYNCHRONOUS
, OK
),
3148 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3149 data_writes1
, arraysize(data_writes1
));
3150 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3151 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3152 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3154 TestCompletionCallback callback1
;
3156 scoped_ptr
<HttpTransaction
> trans(
3157 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3159 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3160 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3162 rv
= callback1
.WaitForResult();
3163 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3164 TestNetLogEntry::List entries
;
3165 log
.GetEntries(&entries
);
3166 size_t pos
= ExpectLogContainsSomewhere(
3167 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3168 NetLog::PHASE_NONE
);
3169 ExpectLogContainsSomewhere(
3171 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3172 NetLog::PHASE_NONE
);
3175 // Test the load timing for HTTPS requests with an HTTP proxy.
3176 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3177 HttpRequestInfo request1
;
3178 request1
.method
= "GET";
3179 request1
.url
= GURL("https://www.example.org/1");
3181 HttpRequestInfo request2
;
3182 request2
.method
= "GET";
3183 request2
.url
= GURL("https://www.example.org/2");
3185 // Configure against proxy server "myproxy:70".
3186 session_deps_
.proxy_service
.reset(
3187 ProxyService::CreateFixed("PROXY myproxy:70"));
3188 BoundTestNetLog log
;
3189 session_deps_
.net_log
= log
.bound().net_log();
3190 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3192 // Since we have proxy, should try to establish tunnel.
3193 MockWrite data_writes1
[] = {
3195 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3196 "Host: www.example.org\r\n"
3197 "Proxy-Connection: keep-alive\r\n\r\n"),
3200 "GET /1 HTTP/1.1\r\n"
3201 "Host: www.example.org\r\n"
3202 "Connection: keep-alive\r\n\r\n"),
3205 "GET /2 HTTP/1.1\r\n"
3206 "Host: www.example.org\r\n"
3207 "Connection: keep-alive\r\n\r\n"),
3210 // The proxy responds to the connect with a 407, using a persistent
3212 MockRead data_reads1
[] = {
3213 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3215 MockRead("HTTP/1.1 200 OK\r\n"),
3216 MockRead("Content-Length: 1\r\n\r\n"),
3217 MockRead(SYNCHRONOUS
, "1"),
3219 MockRead("HTTP/1.1 200 OK\r\n"),
3220 MockRead("Content-Length: 2\r\n\r\n"),
3221 MockRead(SYNCHRONOUS
, "22"),
3224 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3225 data_writes1
, arraysize(data_writes1
));
3226 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3227 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3228 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3230 TestCompletionCallback callback1
;
3231 scoped_ptr
<HttpTransaction
> trans1(
3232 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3234 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3235 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3237 rv
= callback1
.WaitForResult();
3240 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3241 ASSERT_TRUE(response1
!= NULL
);
3242 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3243 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3245 LoadTimingInfo load_timing_info1
;
3246 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3247 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3251 TestCompletionCallback callback2
;
3252 scoped_ptr
<HttpTransaction
> trans2(
3253 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3255 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3258 rv
= callback2
.WaitForResult();
3261 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3262 ASSERT_TRUE(response2
!= NULL
);
3263 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3264 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3266 LoadTimingInfo load_timing_info2
;
3267 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3268 TestLoadTimingReused(load_timing_info2
);
3270 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3273 session
->CloseAllConnections();
3276 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3277 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3278 HttpRequestInfo request1
;
3279 request1
.method
= "GET";
3280 request1
.url
= GURL("https://www.example.org/1");
3282 HttpRequestInfo request2
;
3283 request2
.method
= "GET";
3284 request2
.url
= GURL("https://www.example.org/2");
3286 // Configure against proxy server "myproxy:70".
3287 session_deps_
.proxy_service
.reset(
3288 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3289 BoundTestNetLog log
;
3290 session_deps_
.net_log
= log
.bound().net_log();
3291 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3293 // Since we have proxy, should try to establish tunnel.
3294 MockWrite data_writes1
[] = {
3296 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3297 "Host: www.example.org\r\n"
3298 "Proxy-Connection: keep-alive\r\n\r\n"),
3301 "GET /1 HTTP/1.1\r\n"
3302 "Host: www.example.org\r\n"
3303 "Connection: keep-alive\r\n\r\n"),
3306 "GET /2 HTTP/1.1\r\n"
3307 "Host: www.example.org\r\n"
3308 "Connection: keep-alive\r\n\r\n"),
3311 // The proxy responds to the connect with a 407, using a persistent
3313 MockRead data_reads1
[] = {
3314 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3316 MockRead("HTTP/1.1 200 OK\r\n"),
3317 MockRead("Content-Length: 1\r\n\r\n"),
3318 MockRead(SYNCHRONOUS
, "1"),
3320 MockRead("HTTP/1.1 200 OK\r\n"),
3321 MockRead("Content-Length: 2\r\n\r\n"),
3322 MockRead(SYNCHRONOUS
, "22"),
3325 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3326 data_writes1
, arraysize(data_writes1
));
3327 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3328 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3329 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3331 TestCompletionCallback callback1
;
3332 scoped_ptr
<HttpTransaction
> trans1(
3333 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3335 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3336 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3338 rv
= callback1
.WaitForResult();
3341 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3342 ASSERT_TRUE(response1
!= NULL
);
3343 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3344 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3346 LoadTimingInfo load_timing_info1
;
3347 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3348 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3349 CONNECT_TIMING_HAS_SSL_TIMES
);
3353 TestCompletionCallback callback2
;
3354 scoped_ptr
<HttpTransaction
> trans2(
3355 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3357 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3358 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3360 rv
= callback2
.WaitForResult();
3363 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3364 ASSERT_TRUE(response2
!= NULL
);
3365 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3366 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3368 LoadTimingInfo load_timing_info2
;
3369 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3370 TestLoadTimingReusedWithPac(load_timing_info2
);
3372 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3375 session
->CloseAllConnections();
3378 // Test a simple get through an HTTPS Proxy.
3379 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3380 HttpRequestInfo request
;
3381 request
.method
= "GET";
3382 request
.url
= GURL("http://www.example.org/");
3384 // Configure against https proxy server "proxy:70".
3385 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3386 "https://proxy:70"));
3387 BoundTestNetLog log
;
3388 session_deps_
.net_log
= log
.bound().net_log();
3389 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3391 // Since we have proxy, should use full url
3392 MockWrite data_writes1
[] = {
3394 "GET http://www.example.org/ HTTP/1.1\r\n"
3395 "Host: www.example.org\r\n"
3396 "Proxy-Connection: keep-alive\r\n\r\n"),
3399 MockRead data_reads1
[] = {
3400 MockRead("HTTP/1.1 200 OK\r\n"),
3401 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3402 MockRead("Content-Length: 100\r\n\r\n"),
3403 MockRead(SYNCHRONOUS
, OK
),
3406 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3407 data_writes1
, arraysize(data_writes1
));
3408 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3409 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3410 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3412 TestCompletionCallback callback1
;
3414 scoped_ptr
<HttpTransaction
> trans(
3415 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3417 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3418 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3420 rv
= callback1
.WaitForResult();
3423 LoadTimingInfo load_timing_info
;
3424 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3425 TestLoadTimingNotReused(load_timing_info
,
3426 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3428 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3429 ASSERT_TRUE(response
!= NULL
);
3431 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3432 EXPECT_EQ(200, response
->headers
->response_code());
3433 EXPECT_EQ(100, response
->headers
->GetContentLength());
3434 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3436 // The password prompt info should not be set.
3437 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3440 // Test a SPDY get through an HTTPS Proxy.
3441 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3442 HttpRequestInfo request
;
3443 request
.method
= "GET";
3444 request
.url
= GURL("http://www.example.org/");
3445 request
.load_flags
= 0;
3447 // Configure against https proxy server "proxy:70".
3448 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3449 "https://proxy:70"));
3450 BoundTestNetLog log
;
3451 session_deps_
.net_log
= log
.bound().net_log();
3452 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3454 // fetch http://www.example.org/ via SPDY
3455 scoped_ptr
<SpdyFrame
> req(
3456 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3457 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3459 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3460 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3461 MockRead spdy_reads
[] = {
3462 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3465 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3466 arraysize(spdy_writes
));
3467 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3469 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3470 ssl
.SetNextProto(GetParam());
3471 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3473 TestCompletionCallback callback1
;
3475 scoped_ptr
<HttpTransaction
> trans(
3476 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3478 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3479 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3481 rv
= callback1
.WaitForResult();
3484 LoadTimingInfo load_timing_info
;
3485 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3486 TestLoadTimingNotReused(load_timing_info
,
3487 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3489 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3490 ASSERT_TRUE(response
!= NULL
);
3491 ASSERT_TRUE(response
->headers
.get() != NULL
);
3492 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3494 std::string response_data
;
3495 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3496 EXPECT_EQ(kUploadData
, response_data
);
3499 // Verifies that a session which races and wins against the owning transaction
3500 // (completing prior to host resolution), doesn't fail the transaction.
3501 // Regression test for crbug.com/334413.
3502 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3503 HttpRequestInfo request
;
3504 request
.method
= "GET";
3505 request
.url
= GURL("http://www.example.org/");
3506 request
.load_flags
= 0;
3508 // Configure SPDY proxy server "proxy:70".
3509 session_deps_
.proxy_service
.reset(
3510 ProxyService::CreateFixed("https://proxy:70"));
3511 BoundTestNetLog log
;
3512 session_deps_
.net_log
= log
.bound().net_log();
3513 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3515 // Fetch http://www.example.org/ through the SPDY proxy.
3516 scoped_ptr
<SpdyFrame
> req(
3517 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3518 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3520 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3521 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3522 MockRead spdy_reads
[] = {
3523 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3526 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3527 arraysize(spdy_writes
));
3528 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3530 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3531 ssl
.SetNextProto(GetParam());
3532 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3534 TestCompletionCallback callback1
;
3536 scoped_ptr
<HttpTransaction
> trans(
3537 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3539 // Stall the hostname resolution begun by the transaction.
3540 session_deps_
.host_resolver
->set_synchronous_mode(false);
3541 session_deps_
.host_resolver
->set_ondemand_mode(true);
3543 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3544 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3546 // Race a session to the proxy, which completes first.
3547 session_deps_
.host_resolver
->set_ondemand_mode(false);
3549 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3550 base::WeakPtr
<SpdySession
> spdy_session
=
3551 CreateSecureSpdySession(session
, key
, log
.bound());
3553 // Unstall the resolution begun by the transaction.
3554 session_deps_
.host_resolver
->set_ondemand_mode(true);
3555 session_deps_
.host_resolver
->ResolveAllPending();
3557 EXPECT_FALSE(callback1
.have_result());
3558 rv
= callback1
.WaitForResult();
3561 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3562 ASSERT_TRUE(response
!= NULL
);
3563 ASSERT_TRUE(response
->headers
.get() != NULL
);
3564 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3566 std::string response_data
;
3567 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3568 EXPECT_EQ(kUploadData
, response_data
);
3571 // Test a SPDY get through an HTTPS Proxy.
3572 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3573 HttpRequestInfo request
;
3574 request
.method
= "GET";
3575 request
.url
= GURL("http://www.example.org/");
3576 request
.load_flags
= 0;
3578 // Configure against https proxy server "myproxy:70".
3579 session_deps_
.proxy_service
.reset(
3580 ProxyService::CreateFixed("https://myproxy:70"));
3581 BoundTestNetLog log
;
3582 session_deps_
.net_log
= log
.bound().net_log();
3583 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3585 // The first request will be a bare GET, the second request will be a
3586 // GET with a Proxy-Authorization header.
3587 scoped_ptr
<SpdyFrame
> req_get(
3588 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3589 const char* const kExtraAuthorizationHeaders
[] = {
3590 "proxy-authorization", "Basic Zm9vOmJhcg=="
3592 scoped_ptr
<SpdyFrame
> req_get_authorization(
3593 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3594 arraysize(kExtraAuthorizationHeaders
) / 2,
3599 MockWrite spdy_writes
[] = {
3600 CreateMockWrite(*req_get
, 0), CreateMockWrite(*req_get_authorization
, 3),
3603 // The first response is a 407 proxy authentication challenge, and the second
3604 // response will be a 200 response since the second request includes a valid
3605 // Authorization header.
3606 const char* const kExtraAuthenticationHeaders
[] = {
3607 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3609 scoped_ptr
<SpdyFrame
> resp_authentication(
3610 spdy_util_
.ConstructSpdySynReplyError(
3611 "407 Proxy Authentication Required",
3612 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3614 scoped_ptr
<SpdyFrame
> body_authentication(
3615 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3616 scoped_ptr
<SpdyFrame
> resp_data(
3617 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3618 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3619 MockRead spdy_reads
[] = {
3620 CreateMockRead(*resp_authentication
, 1),
3621 CreateMockRead(*body_authentication
, 2),
3622 CreateMockRead(*resp_data
, 4),
3623 CreateMockRead(*body_data
, 5),
3624 MockRead(ASYNC
, 0, 6),
3627 SequencedSocketData
data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3628 arraysize(spdy_writes
));
3629 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3631 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3632 ssl
.SetNextProto(GetParam());
3633 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3635 TestCompletionCallback callback1
;
3637 scoped_ptr
<HttpTransaction
> trans(
3638 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3640 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3641 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3643 rv
= callback1
.WaitForResult();
3646 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3648 ASSERT_TRUE(response
!= NULL
);
3649 ASSERT_TRUE(response
->headers
.get() != NULL
);
3650 EXPECT_EQ(407, response
->headers
->response_code());
3651 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3652 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3654 TestCompletionCallback callback2
;
3656 rv
= trans
->RestartWithAuth(
3657 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3658 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3660 rv
= callback2
.WaitForResult();
3663 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3665 ASSERT_TRUE(response_restart
!= NULL
);
3666 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3667 EXPECT_EQ(200, response_restart
->headers
->response_code());
3668 // The password prompt info should not be set.
3669 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3672 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3673 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3674 HttpRequestInfo request
;
3675 request
.method
= "GET";
3676 request
.url
= GURL("https://www.example.org/");
3677 request
.load_flags
= 0;
3679 // Configure against https proxy server "proxy:70".
3680 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3681 "https://proxy:70"));
3682 BoundTestNetLog log
;
3683 session_deps_
.net_log
= log
.bound().net_log();
3684 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3686 scoped_ptr
<HttpTransaction
> trans(
3687 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3689 // CONNECT to www.example.org:443 via SPDY
3690 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3691 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3692 // fetch https://www.example.org/ via HTTP
3695 "GET / HTTP/1.1\r\n"
3696 "Host: www.example.org\r\n"
3697 "Connection: keep-alive\r\n\r\n";
3698 scoped_ptr
<SpdyFrame
> wrapped_get(
3699 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3700 scoped_ptr
<SpdyFrame
> conn_resp(
3701 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3702 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3703 "Content-Length: 10\r\n\r\n";
3704 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3705 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3706 scoped_ptr
<SpdyFrame
> wrapped_body(
3707 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3708 scoped_ptr
<SpdyFrame
> window_update(
3709 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3711 MockWrite spdy_writes
[] = {
3712 CreateMockWrite(*connect
, 0),
3713 CreateMockWrite(*wrapped_get
, 2),
3714 CreateMockWrite(*window_update
, 6),
3717 MockRead spdy_reads
[] = {
3718 CreateMockRead(*conn_resp
, 1, ASYNC
),
3719 CreateMockRead(*wrapped_get_resp
, 3, ASYNC
),
3720 CreateMockRead(*wrapped_body
, 4, ASYNC
),
3721 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3722 MockRead(ASYNC
, 0, 7),
3725 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3726 arraysize(spdy_writes
));
3727 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3729 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3730 ssl
.SetNextProto(GetParam());
3731 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3732 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3733 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3735 TestCompletionCallback callback1
;
3737 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3738 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3740 rv
= callback1
.WaitForResult();
3743 LoadTimingInfo load_timing_info
;
3744 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3745 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3747 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3748 ASSERT_TRUE(response
!= NULL
);
3749 ASSERT_TRUE(response
->headers
.get() != NULL
);
3750 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3752 std::string response_data
;
3753 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3754 EXPECT_EQ("1234567890", response_data
);
3757 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3758 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3759 HttpRequestInfo request
;
3760 request
.method
= "GET";
3761 request
.url
= GURL("https://www.example.org/");
3762 request
.load_flags
= 0;
3764 // Configure against https proxy server "proxy:70".
3765 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3766 "https://proxy:70"));
3767 BoundTestNetLog log
;
3768 session_deps_
.net_log
= log
.bound().net_log();
3769 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3771 scoped_ptr
<HttpTransaction
> trans(
3772 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3774 // CONNECT to www.example.org:443 via SPDY
3775 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3776 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3777 // fetch https://www.example.org/ via SPDY
3778 const char kMyUrl
[] = "https://www.example.org/";
3779 scoped_ptr
<SpdyFrame
> get(
3780 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3781 scoped_ptr
<SpdyFrame
> wrapped_get(
3782 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3783 scoped_ptr
<SpdyFrame
> conn_resp(
3784 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3785 scoped_ptr
<SpdyFrame
> get_resp(
3786 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3787 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3788 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3789 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3790 scoped_ptr
<SpdyFrame
> wrapped_body(
3791 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3792 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3793 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3794 scoped_ptr
<SpdyFrame
> window_update_body(
3795 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3797 MockWrite spdy_writes
[] = {
3798 CreateMockWrite(*connect
, 0),
3799 CreateMockWrite(*wrapped_get
, 2),
3800 CreateMockWrite(*window_update_get_resp
, 6),
3801 CreateMockWrite(*window_update_body
, 7),
3804 MockRead spdy_reads
[] = {
3805 CreateMockRead(*conn_resp
, 1, ASYNC
),
3806 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3807 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3808 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3809 MockRead(ASYNC
, 0, 8),
3812 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3813 arraysize(spdy_writes
));
3814 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3816 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3817 ssl
.SetNextProto(GetParam());
3818 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3819 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3820 ssl2
.SetNextProto(GetParam());
3821 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3823 TestCompletionCallback callback1
;
3825 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3826 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3828 // Allow the SpdyProxyClientSocket's write callback to complete.
3829 base::MessageLoop::current()->RunUntilIdle();
3830 // Now allow the read of the response to complete.
3831 spdy_data
.CompleteRead();
3832 rv
= callback1
.WaitForResult();
3835 LoadTimingInfo load_timing_info
;
3836 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3837 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3839 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3840 ASSERT_TRUE(response
!= NULL
);
3841 ASSERT_TRUE(response
->headers
.get() != NULL
);
3842 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3844 std::string response_data
;
3845 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3846 EXPECT_EQ(kUploadData
, response_data
);
3849 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3850 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3851 HttpRequestInfo request
;
3852 request
.method
= "GET";
3853 request
.url
= GURL("https://www.example.org/");
3854 request
.load_flags
= 0;
3856 // Configure against https proxy server "proxy:70".
3857 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3858 "https://proxy:70"));
3859 BoundTestNetLog log
;
3860 session_deps_
.net_log
= log
.bound().net_log();
3861 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3863 scoped_ptr
<HttpTransaction
> trans(
3864 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3866 // CONNECT to www.example.org:443 via SPDY
3867 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3868 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3869 scoped_ptr
<SpdyFrame
> get(
3870 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3872 MockWrite spdy_writes
[] = {
3873 CreateMockWrite(*connect
, 0), CreateMockWrite(*get
, 2),
3876 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3877 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3878 MockRead spdy_reads
[] = {
3879 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3),
3882 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3883 arraysize(spdy_writes
));
3884 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3886 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3887 ssl
.SetNextProto(GetParam());
3888 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3889 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3890 ssl2
.SetNextProto(GetParam());
3891 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3893 TestCompletionCallback callback1
;
3895 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3896 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3898 rv
= callback1
.WaitForResult();
3899 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3901 // TODO(ttuttle): Anything else to check here?
3904 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3905 // HTTPS Proxy to different servers.
3906 TEST_P(HttpNetworkTransactionTest
,
3907 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3908 // Configure against https proxy server "proxy:70".
3909 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3910 "https://proxy:70"));
3911 BoundTestNetLog log
;
3912 session_deps_
.net_log
= log
.bound().net_log();
3913 scoped_refptr
<HttpNetworkSession
> session(
3914 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3916 HttpRequestInfo request1
;
3917 request1
.method
= "GET";
3918 request1
.url
= GURL("https://www.example.org/");
3919 request1
.load_flags
= 0;
3921 HttpRequestInfo request2
;
3922 request2
.method
= "GET";
3923 request2
.url
= GURL("https://mail.example.org/");
3924 request2
.load_flags
= 0;
3926 // CONNECT to www.example.org:443 via SPDY.
3927 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3928 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3929 scoped_ptr
<SpdyFrame
> conn_resp1(
3930 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3932 // Fetch https://www.example.org/ via HTTP.
3934 "GET / HTTP/1.1\r\n"
3935 "Host: www.example.org\r\n"
3936 "Connection: keep-alive\r\n\r\n";
3937 scoped_ptr
<SpdyFrame
> wrapped_get1(
3938 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3939 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3940 "Content-Length: 1\r\n\r\n";
3941 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3942 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3943 scoped_ptr
<SpdyFrame
> wrapped_body1(
3944 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3945 scoped_ptr
<SpdyFrame
> window_update(
3946 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3948 // CONNECT to mail.example.org:443 via SPDY.
3949 SpdyHeaderBlock connect2_block
;
3950 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3951 if (GetParam() == kProtoHTTP2
) {
3952 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org:443";
3954 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3955 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3957 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3958 scoped_ptr
<SpdyFrame
> connect2(
3959 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3961 scoped_ptr
<SpdyFrame
> conn_resp2(
3962 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3964 // Fetch https://mail.example.org/ via HTTP.
3966 "GET / HTTP/1.1\r\n"
3967 "Host: mail.example.org\r\n"
3968 "Connection: keep-alive\r\n\r\n";
3969 scoped_ptr
<SpdyFrame
> wrapped_get2(
3970 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3971 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3972 "Content-Length: 2\r\n\r\n";
3973 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3974 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3975 scoped_ptr
<SpdyFrame
> wrapped_body2(
3976 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3978 MockWrite spdy_writes
[] = {
3979 CreateMockWrite(*connect1
, 0),
3980 CreateMockWrite(*wrapped_get1
, 2),
3981 CreateMockWrite(*connect2
, 5),
3982 CreateMockWrite(*wrapped_get2
, 7),
3985 MockRead spdy_reads
[] = {
3986 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3987 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3988 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3989 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3990 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3991 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3992 MockRead(ASYNC
, 0, 10),
3995 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3996 arraysize(spdy_writes
));
3997 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3999 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4000 ssl
.SetNextProto(GetParam());
4001 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4002 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4003 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4004 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
4005 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl3
);
4007 TestCompletionCallback callback
;
4009 scoped_ptr
<HttpTransaction
> trans(
4010 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4011 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4012 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4014 LoadTimingInfo load_timing_info
;
4015 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4016 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4018 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4019 ASSERT_TRUE(response
!= NULL
);
4020 ASSERT_TRUE(response
->headers
.get() != NULL
);
4021 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4023 std::string response_data
;
4024 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4025 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4026 EXPECT_EQ(1, callback
.GetResult(rv
));
4028 scoped_ptr
<HttpTransaction
> trans2(
4029 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4030 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4031 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4033 LoadTimingInfo load_timing_info2
;
4034 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4035 // Even though the SPDY connection is reused, a new tunnelled connection has
4036 // to be created, so the socket's load timing looks like a fresh connection.
4037 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
4039 // The requests should have different IDs, since they each are using their own
4041 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4043 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4044 EXPECT_EQ(2, callback
.GetResult(rv
));
4047 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4048 // HTTPS Proxy to the same server.
4049 TEST_P(HttpNetworkTransactionTest
,
4050 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
4051 // Configure against https proxy server "proxy:70".
4052 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4053 "https://proxy:70"));
4054 BoundTestNetLog log
;
4055 session_deps_
.net_log
= log
.bound().net_log();
4056 scoped_refptr
<HttpNetworkSession
> session(
4057 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4059 HttpRequestInfo request1
;
4060 request1
.method
= "GET";
4061 request1
.url
= GURL("https://www.example.org/");
4062 request1
.load_flags
= 0;
4064 HttpRequestInfo request2
;
4065 request2
.method
= "GET";
4066 request2
.url
= GURL("https://www.example.org/2");
4067 request2
.load_flags
= 0;
4069 // CONNECT to www.example.org:443 via SPDY.
4070 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
4071 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
4072 scoped_ptr
<SpdyFrame
> conn_resp1(
4073 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4075 // Fetch https://www.example.org/ via HTTP.
4077 "GET / HTTP/1.1\r\n"
4078 "Host: www.example.org\r\n"
4079 "Connection: keep-alive\r\n\r\n";
4080 scoped_ptr
<SpdyFrame
> wrapped_get1(
4081 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
4082 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
4083 "Content-Length: 1\r\n\r\n";
4084 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
4085 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
4086 scoped_ptr
<SpdyFrame
> wrapped_body1(
4087 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
4088 scoped_ptr
<SpdyFrame
> window_update(
4089 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
4091 // Fetch https://www.example.org/2 via HTTP.
4093 "GET /2 HTTP/1.1\r\n"
4094 "Host: www.example.org\r\n"
4095 "Connection: keep-alive\r\n\r\n";
4096 scoped_ptr
<SpdyFrame
> wrapped_get2(
4097 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
4098 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
4099 "Content-Length: 2\r\n\r\n";
4100 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
4101 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
4102 scoped_ptr
<SpdyFrame
> wrapped_body2(
4103 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4105 MockWrite spdy_writes
[] = {
4106 CreateMockWrite(*connect1
, 0),
4107 CreateMockWrite(*wrapped_get1
, 2),
4108 CreateMockWrite(*wrapped_get2
, 5),
4111 MockRead spdy_reads
[] = {
4112 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4113 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4114 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4115 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4116 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4117 MockRead(ASYNC
, 0, 8),
4120 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4121 arraysize(spdy_writes
));
4122 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4124 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4125 ssl
.SetNextProto(GetParam());
4126 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4127 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4128 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4130 TestCompletionCallback callback
;
4132 scoped_ptr
<HttpTransaction
> trans(
4133 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4134 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4135 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4137 rv
= callback
.WaitForResult();
4140 LoadTimingInfo load_timing_info
;
4141 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4142 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4144 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4145 ASSERT_TRUE(response
!= NULL
);
4146 ASSERT_TRUE(response
->headers
.get() != NULL
);
4147 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4149 std::string response_data
;
4150 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4151 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4154 scoped_ptr
<HttpTransaction
> trans2(
4155 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4156 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4157 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4159 rv
= callback
.WaitForResult();
4162 LoadTimingInfo load_timing_info2
;
4163 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4164 TestLoadTimingReused(load_timing_info2
);
4166 // The requests should have the same ID.
4167 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4169 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4172 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4173 // Proxy to different servers.
4174 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4175 // Configure against https proxy server "proxy:70".
4176 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4177 "https://proxy:70"));
4178 BoundTestNetLog log
;
4179 session_deps_
.net_log
= log
.bound().net_log();
4180 scoped_refptr
<HttpNetworkSession
> session(
4181 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4183 HttpRequestInfo request1
;
4184 request1
.method
= "GET";
4185 request1
.url
= GURL("http://www.example.org/");
4186 request1
.load_flags
= 0;
4188 HttpRequestInfo request2
;
4189 request2
.method
= "GET";
4190 request2
.url
= GURL("http://mail.example.org/");
4191 request2
.load_flags
= 0;
4193 // http://www.example.org/
4194 scoped_ptr
<SpdyHeaderBlock
> headers(
4195 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4196 scoped_ptr
<SpdyFrame
> get1(
4197 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4198 scoped_ptr
<SpdyFrame
> get_resp1(
4199 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4200 scoped_ptr
<SpdyFrame
> body1(
4201 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4203 // http://mail.example.org/
4204 scoped_ptr
<SpdyHeaderBlock
> headers2(
4205 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4206 scoped_ptr
<SpdyFrame
> get2(
4207 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4208 scoped_ptr
<SpdyFrame
> get_resp2(
4209 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4210 scoped_ptr
<SpdyFrame
> body2(
4211 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4213 MockWrite spdy_writes
[] = {
4214 CreateMockWrite(*get1
, 0),
4215 CreateMockWrite(*get2
, 3),
4218 MockRead spdy_reads
[] = {
4219 CreateMockRead(*get_resp1
, 1, ASYNC
),
4220 CreateMockRead(*body1
, 2, ASYNC
),
4221 CreateMockRead(*get_resp2
, 4, ASYNC
),
4222 CreateMockRead(*body2
, 5, ASYNC
),
4223 MockRead(ASYNC
, 0, 6),
4226 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4227 arraysize(spdy_writes
));
4228 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4230 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4231 ssl
.SetNextProto(GetParam());
4232 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4234 TestCompletionCallback callback
;
4236 scoped_ptr
<HttpTransaction
> trans(
4237 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4238 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4239 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4241 LoadTimingInfo load_timing_info
;
4242 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4243 TestLoadTimingNotReused(load_timing_info
,
4244 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4246 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4247 ASSERT_TRUE(response
!= NULL
);
4248 ASSERT_TRUE(response
->headers
.get() != NULL
);
4249 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4251 std::string response_data
;
4252 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4253 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4254 EXPECT_EQ(1, callback
.GetResult(rv
));
4255 // Delete the first request, so the second one can reuse the socket.
4258 scoped_ptr
<HttpTransaction
> trans2(
4259 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4260 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4261 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4263 LoadTimingInfo load_timing_info2
;
4264 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4265 TestLoadTimingReused(load_timing_info2
);
4267 // The requests should have the same ID.
4268 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4270 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4271 EXPECT_EQ(2, callback
.GetResult(rv
));
4274 // Test the challenge-response-retry sequence through an HTTPS Proxy
4275 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4276 HttpRequestInfo request
;
4277 request
.method
= "GET";
4278 request
.url
= GURL("http://www.example.org/");
4279 // when the no authentication data flag is set.
4280 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4282 // Configure against https proxy server "myproxy:70".
4283 session_deps_
.proxy_service
.reset(
4284 ProxyService::CreateFixed("https://myproxy:70"));
4285 BoundTestNetLog log
;
4286 session_deps_
.net_log
= log
.bound().net_log();
4287 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4289 // Since we have proxy, should use full url
4290 MockWrite data_writes1
[] = {
4292 "GET http://www.example.org/ HTTP/1.1\r\n"
4293 "Host: www.example.org\r\n"
4294 "Proxy-Connection: keep-alive\r\n\r\n"),
4296 // After calling trans->RestartWithAuth(), this is the request we should
4297 // be issuing -- the final header line contains the credentials.
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"
4302 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4305 // The proxy responds to the GET with a 407, using a persistent
4307 MockRead data_reads1
[] = {
4309 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4310 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4311 MockRead("Proxy-Connection: keep-alive\r\n"),
4312 MockRead("Content-Length: 0\r\n\r\n"),
4314 MockRead("HTTP/1.1 200 OK\r\n"),
4315 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4316 MockRead("Content-Length: 100\r\n\r\n"),
4317 MockRead(SYNCHRONOUS
, OK
),
4320 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4321 data_writes1
, arraysize(data_writes1
));
4322 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4323 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4324 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4326 TestCompletionCallback callback1
;
4328 scoped_ptr
<HttpTransaction
> trans(
4329 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4331 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4332 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4334 rv
= callback1
.WaitForResult();
4337 LoadTimingInfo load_timing_info
;
4338 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4339 TestLoadTimingNotReused(load_timing_info
,
4340 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4342 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4343 ASSERT_TRUE(response
!= NULL
);
4344 ASSERT_FALSE(response
->headers
.get() == NULL
);
4345 EXPECT_EQ(407, response
->headers
->response_code());
4346 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4347 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4349 TestCompletionCallback callback2
;
4351 rv
= trans
->RestartWithAuth(
4352 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4353 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4355 rv
= callback2
.WaitForResult();
4358 load_timing_info
= LoadTimingInfo();
4359 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4360 // Retrying with HTTP AUTH is considered to be reusing a socket.
4361 TestLoadTimingReused(load_timing_info
);
4363 response
= trans
->GetResponseInfo();
4364 ASSERT_TRUE(response
!= NULL
);
4366 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4367 EXPECT_EQ(200, response
->headers
->response_code());
4368 EXPECT_EQ(100, response
->headers
->GetContentLength());
4369 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4371 // The password prompt info should not be set.
4372 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4375 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4376 const MockRead
& status
, int expected_status
) {
4377 HttpRequestInfo request
;
4378 request
.method
= "GET";
4379 request
.url
= GURL("https://www.example.org/");
4380 request
.load_flags
= 0;
4382 // Configure against proxy server "myproxy:70".
4383 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4384 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4386 // Since we have proxy, should try to establish tunnel.
4387 MockWrite data_writes
[] = {
4389 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4390 "Host: www.example.org\r\n"
4391 "Proxy-Connection: keep-alive\r\n\r\n"),
4394 MockRead data_reads
[] = {
4396 MockRead("Content-Length: 10\r\n\r\n"),
4397 // No response body because the test stops reading here.
4398 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4401 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4402 data_writes
, arraysize(data_writes
));
4403 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4405 TestCompletionCallback callback
;
4407 scoped_ptr
<HttpTransaction
> trans(
4408 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4410 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4411 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4413 rv
= callback
.WaitForResult();
4414 EXPECT_EQ(expected_status
, rv
);
4417 void HttpNetworkTransactionTest::ConnectStatusHelper(
4418 const MockRead
& status
) {
4419 ConnectStatusHelperWithExpectedStatus(
4420 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4423 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4424 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4427 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4428 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4431 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4432 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4435 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4436 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4439 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4440 ConnectStatusHelper(
4441 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4444 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4445 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4448 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4449 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4452 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4453 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4456 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4457 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4460 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4461 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4464 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4465 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4468 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4469 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4472 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4473 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4476 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4477 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4480 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4481 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4484 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4485 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4488 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4489 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4492 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4493 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4496 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4497 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4500 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4501 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4504 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4505 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4508 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4509 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4512 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4513 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4516 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4517 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4520 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4521 ConnectStatusHelperWithExpectedStatus(
4522 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4523 ERR_PROXY_AUTH_UNSUPPORTED
);
4526 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4527 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4530 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4531 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4534 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4535 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4538 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4539 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4542 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4543 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4546 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4547 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4550 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4551 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4554 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4555 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4558 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4559 ConnectStatusHelper(
4560 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4563 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4564 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4567 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4568 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4571 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4572 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4575 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4576 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4579 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4580 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4583 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4584 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4587 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4588 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4591 // Test the flow when both the proxy server AND origin server require
4592 // authentication. Again, this uses basic auth for both since that is
4593 // the simplest to mock.
4594 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4595 HttpRequestInfo request
;
4596 request
.method
= "GET";
4597 request
.url
= GURL("http://www.example.org/");
4598 request
.load_flags
= 0;
4600 // Configure against proxy server "myproxy:70".
4601 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4602 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4604 scoped_ptr
<HttpTransaction
> trans(
4605 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4607 MockWrite data_writes1
[] = {
4609 "GET http://www.example.org/ HTTP/1.1\r\n"
4610 "Host: www.example.org\r\n"
4611 "Proxy-Connection: keep-alive\r\n\r\n"),
4614 MockRead data_reads1
[] = {
4615 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4616 // Give a couple authenticate options (only the middle one is actually
4618 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4619 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4620 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4622 // Large content-length -- won't matter, as connection will be reset.
4623 MockRead("Content-Length: 10000\r\n\r\n"),
4624 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4627 // After calling trans->RestartWithAuth() the first time, this is the
4628 // request we should be issuing -- the final header line contains the
4629 // proxy's credentials.
4630 MockWrite data_writes2
[] = {
4632 "GET http://www.example.org/ HTTP/1.1\r\n"
4633 "Host: www.example.org\r\n"
4634 "Proxy-Connection: keep-alive\r\n"
4635 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4638 // Now the proxy server lets the request pass through to origin server.
4639 // The origin server responds with a 401.
4640 MockRead data_reads2
[] = {
4641 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4642 // Note: We are using the same realm-name as the proxy server. This is
4643 // completely valid, as realms are unique across hosts.
4644 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4645 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4646 MockRead("Content-Length: 2000\r\n\r\n"),
4647 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4650 // After calling trans->RestartWithAuth() the second time, we should send
4651 // the credentials for both the proxy and origin server.
4652 MockWrite data_writes3
[] = {
4654 "GET http://www.example.org/ HTTP/1.1\r\n"
4655 "Host: www.example.org\r\n"
4656 "Proxy-Connection: keep-alive\r\n"
4657 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4658 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4661 // Lastly we get the desired content.
4662 MockRead data_reads3
[] = {
4663 MockRead("HTTP/1.0 200 OK\r\n"),
4664 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4665 MockRead("Content-Length: 100\r\n\r\n"),
4666 MockRead(SYNCHRONOUS
, OK
),
4669 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4670 data_writes1
, arraysize(data_writes1
));
4671 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4672 data_writes2
, arraysize(data_writes2
));
4673 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4674 data_writes3
, arraysize(data_writes3
));
4675 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4676 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4677 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4679 TestCompletionCallback callback1
;
4681 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4682 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4684 rv
= callback1
.WaitForResult();
4687 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4688 ASSERT_TRUE(response
!= NULL
);
4689 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4691 TestCompletionCallback callback2
;
4693 rv
= trans
->RestartWithAuth(
4694 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4695 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4697 rv
= callback2
.WaitForResult();
4700 response
= trans
->GetResponseInfo();
4701 ASSERT_TRUE(response
!= NULL
);
4702 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4704 TestCompletionCallback callback3
;
4706 rv
= trans
->RestartWithAuth(
4707 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4708 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4710 rv
= callback3
.WaitForResult();
4713 response
= trans
->GetResponseInfo();
4714 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4715 EXPECT_EQ(100, response
->headers
->GetContentLength());
4718 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4719 // can't hook into its internals to cause it to generate predictable NTLM
4720 // authorization headers.
4721 #if defined(NTLM_PORTABLE)
4722 // The NTLM authentication unit tests were generated by capturing the HTTP
4723 // requests and responses using Fiddler 2 and inspecting the generated random
4724 // bytes in the debugger.
4726 // Enter the correct password and authenticate successfully.
4727 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4728 HttpRequestInfo request
;
4729 request
.method
= "GET";
4730 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4732 // Ensure load is not disrupted by flags which suppress behaviour specific
4733 // to other auth schemes.
4734 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4736 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4738 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4740 MockWrite data_writes1
[] = {
4741 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4742 "Host: 172.22.68.17\r\n"
4743 "Connection: keep-alive\r\n\r\n"),
4746 MockRead data_reads1
[] = {
4747 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4748 // Negotiate and NTLM are often requested together. However, we only want
4749 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4750 // the header that requests Negotiate for this test.
4751 MockRead("WWW-Authenticate: NTLM\r\n"),
4752 MockRead("Connection: close\r\n"),
4753 MockRead("Content-Length: 42\r\n"),
4754 MockRead("Content-Type: text/html\r\n\r\n"),
4755 // Missing content -- won't matter, as connection will be reset.
4756 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4759 MockWrite data_writes2
[] = {
4760 // After restarting with a null identity, this is the
4761 // request we should be issuing -- the final header line contains a Type
4763 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4764 "Host: 172.22.68.17\r\n"
4765 "Connection: keep-alive\r\n"
4766 "Authorization: NTLM "
4767 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4769 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4770 // (the credentials for the origin server). The second request continues
4771 // on the same connection.
4772 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4773 "Host: 172.22.68.17\r\n"
4774 "Connection: keep-alive\r\n"
4775 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4776 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4777 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4778 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4779 "ahlhx5I=\r\n\r\n"),
4782 MockRead data_reads2
[] = {
4783 // The origin server responds with a Type 2 message.
4784 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4785 MockRead("WWW-Authenticate: NTLM "
4786 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4787 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4788 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4789 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4790 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4791 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4793 MockRead("Content-Length: 42\r\n"),
4794 MockRead("Content-Type: text/html\r\n\r\n"),
4795 MockRead("You are not authorized to view this page\r\n"),
4797 // Lastly we get the desired content.
4798 MockRead("HTTP/1.1 200 OK\r\n"),
4799 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4800 MockRead("Content-Length: 13\r\n\r\n"),
4801 MockRead("Please Login\r\n"),
4802 MockRead(SYNCHRONOUS
, OK
),
4805 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4806 data_writes1
, arraysize(data_writes1
));
4807 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4808 data_writes2
, arraysize(data_writes2
));
4809 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4810 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4812 TestCompletionCallback callback1
;
4814 scoped_ptr
<HttpTransaction
> trans(
4815 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4817 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4818 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4820 rv
= callback1
.WaitForResult();
4823 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4825 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4826 ASSERT_FALSE(response
== NULL
);
4827 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4829 TestCompletionCallback callback2
;
4831 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4832 callback2
.callback());
4833 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4835 rv
= callback2
.WaitForResult();
4838 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4840 response
= trans
->GetResponseInfo();
4841 ASSERT_TRUE(response
!= NULL
);
4842 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4844 TestCompletionCallback callback3
;
4846 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4847 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4849 rv
= callback3
.WaitForResult();
4852 response
= trans
->GetResponseInfo();
4853 ASSERT_TRUE(response
!= NULL
);
4854 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4855 EXPECT_EQ(13, response
->headers
->GetContentLength());
4858 // Enter a wrong password, and then the correct one.
4859 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4860 HttpRequestInfo request
;
4861 request
.method
= "GET";
4862 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4863 request
.load_flags
= 0;
4865 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4867 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4869 MockWrite data_writes1
[] = {
4870 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4871 "Host: 172.22.68.17\r\n"
4872 "Connection: keep-alive\r\n\r\n"),
4875 MockRead data_reads1
[] = {
4876 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4877 // Negotiate and NTLM are often requested together. However, we only want
4878 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4879 // the header that requests Negotiate for this test.
4880 MockRead("WWW-Authenticate: NTLM\r\n"),
4881 MockRead("Connection: close\r\n"),
4882 MockRead("Content-Length: 42\r\n"),
4883 MockRead("Content-Type: text/html\r\n\r\n"),
4884 // Missing content -- won't matter, as connection will be reset.
4885 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4888 MockWrite data_writes2
[] = {
4889 // After restarting with a null identity, this is the
4890 // request we should be issuing -- the final header line contains a Type
4892 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4893 "Host: 172.22.68.17\r\n"
4894 "Connection: keep-alive\r\n"
4895 "Authorization: NTLM "
4896 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4898 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4899 // (the credentials for the origin server). The second request continues
4900 // on the same connection.
4901 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4902 "Host: 172.22.68.17\r\n"
4903 "Connection: keep-alive\r\n"
4904 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4905 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4906 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4907 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4908 "4Ww7b7E=\r\n\r\n"),
4911 MockRead data_reads2
[] = {
4912 // The origin server responds with a Type 2 message.
4913 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4914 MockRead("WWW-Authenticate: NTLM "
4915 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4916 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4917 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4918 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4919 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4920 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4922 MockRead("Content-Length: 42\r\n"),
4923 MockRead("Content-Type: text/html\r\n\r\n"),
4924 MockRead("You are not authorized to view this page\r\n"),
4927 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4928 MockRead("WWW-Authenticate: NTLM\r\n"),
4929 MockRead("Connection: close\r\n"),
4930 MockRead("Content-Length: 42\r\n"),
4931 MockRead("Content-Type: text/html\r\n\r\n"),
4932 // Missing content -- won't matter, as connection will be reset.
4933 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4936 MockWrite data_writes3
[] = {
4937 // After restarting with a null identity, this is the
4938 // request we should be issuing -- the final header line contains a Type
4940 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4941 "Host: 172.22.68.17\r\n"
4942 "Connection: keep-alive\r\n"
4943 "Authorization: NTLM "
4944 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4946 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4947 // (the credentials for the origin server). The second request continues
4948 // on the same connection.
4949 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4950 "Host: 172.22.68.17\r\n"
4951 "Connection: keep-alive\r\n"
4952 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4953 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4954 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4955 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4956 "+4MUm7c=\r\n\r\n"),
4959 MockRead data_reads3
[] = {
4960 // The origin server responds with a Type 2 message.
4961 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4962 MockRead("WWW-Authenticate: NTLM "
4963 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4964 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4965 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4966 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4967 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4968 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4970 MockRead("Content-Length: 42\r\n"),
4971 MockRead("Content-Type: text/html\r\n\r\n"),
4972 MockRead("You are not authorized to view this page\r\n"),
4974 // Lastly we get the desired content.
4975 MockRead("HTTP/1.1 200 OK\r\n"),
4976 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4977 MockRead("Content-Length: 13\r\n\r\n"),
4978 MockRead("Please Login\r\n"),
4979 MockRead(SYNCHRONOUS
, OK
),
4982 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4983 data_writes1
, arraysize(data_writes1
));
4984 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4985 data_writes2
, arraysize(data_writes2
));
4986 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4987 data_writes3
, arraysize(data_writes3
));
4988 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4989 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4990 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4992 TestCompletionCallback callback1
;
4994 scoped_ptr
<HttpTransaction
> trans(
4995 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4997 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4998 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5000 rv
= callback1
.WaitForResult();
5003 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5005 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5006 ASSERT_TRUE(response
!= NULL
);
5007 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
5009 TestCompletionCallback callback2
;
5011 // Enter the wrong password.
5012 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
5013 callback2
.callback());
5014 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5016 rv
= callback2
.WaitForResult();
5019 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5020 TestCompletionCallback callback3
;
5021 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
5022 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5023 rv
= callback3
.WaitForResult();
5025 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5027 response
= trans
->GetResponseInfo();
5028 ASSERT_FALSE(response
== NULL
);
5029 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
5031 TestCompletionCallback callback4
;
5033 // Now enter the right password.
5034 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
5035 callback4
.callback());
5036 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5038 rv
= callback4
.WaitForResult();
5041 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5043 TestCompletionCallback callback5
;
5045 // One more roundtrip
5046 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
5047 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5049 rv
= callback5
.WaitForResult();
5052 response
= trans
->GetResponseInfo();
5053 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5054 EXPECT_EQ(13, response
->headers
->GetContentLength());
5056 #endif // NTLM_PORTABLE
5058 // Test reading a server response which has only headers, and no body.
5059 // After some maximum number of bytes is consumed, the transaction should
5060 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
5061 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
5062 HttpRequestInfo request
;
5063 request
.method
= "GET";
5064 request
.url
= GURL("http://www.example.org/");
5065 request
.load_flags
= 0;
5067 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5068 scoped_ptr
<HttpTransaction
> trans(
5069 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5071 // Respond with 300 kb of headers (we should fail after 256 kb).
5072 std::string large_headers_string
;
5073 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
5075 MockRead data_reads
[] = {
5076 MockRead("HTTP/1.0 200 OK\r\n"),
5077 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
5078 MockRead("\r\nBODY"),
5079 MockRead(SYNCHRONOUS
, OK
),
5081 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5082 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5084 TestCompletionCallback callback
;
5086 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5087 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5089 rv
= callback
.WaitForResult();
5090 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
5093 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5094 // establish tunnel.
5095 // http://code.google.com/p/chromium/issues/detail?id=3772
5096 TEST_P(HttpNetworkTransactionTest
,
5097 DontRecycleTransportSocketForSSLTunnel
) {
5098 HttpRequestInfo request
;
5099 request
.method
= "GET";
5100 request
.url
= GURL("https://www.example.org/");
5101 request
.load_flags
= 0;
5103 // Configure against proxy server "myproxy:70".
5104 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5106 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5108 scoped_ptr
<HttpTransaction
> trans(
5109 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5111 // Since we have proxy, should try to establish tunnel.
5112 MockWrite data_writes1
[] = {
5114 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5115 "Host: www.example.org\r\n"
5116 "Proxy-Connection: keep-alive\r\n\r\n"),
5119 // The proxy responds to the connect with a 404, using a persistent
5120 // connection. Usually a proxy would return 501 (not implemented),
5121 // or 200 (tunnel established).
5122 MockRead data_reads1
[] = {
5123 MockRead("HTTP/1.1 404 Not Found\r\n"),
5124 MockRead("Content-Length: 10\r\n\r\n"),
5125 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5128 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5129 data_writes1
, arraysize(data_writes1
));
5130 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5132 TestCompletionCallback callback1
;
5134 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5135 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5137 rv
= callback1
.WaitForResult();
5138 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5140 // Empty the current queue. This is necessary because idle sockets are
5141 // added to the connection pool asynchronously with a PostTask.
5142 base::MessageLoop::current()->RunUntilIdle();
5144 // We now check to make sure the TCPClientSocket was not added back to
5146 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5148 base::MessageLoop::current()->RunUntilIdle();
5149 // Make sure that the socket didn't get recycled after calling the destructor.
5150 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5153 // Make sure that we recycle a socket after reading all of the response body.
5154 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5155 HttpRequestInfo request
;
5156 request
.method
= "GET";
5157 request
.url
= GURL("http://www.example.org/");
5158 request
.load_flags
= 0;
5160 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5162 scoped_ptr
<HttpTransaction
> trans(
5163 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5165 MockRead data_reads
[] = {
5166 // A part of the response body is received with the response headers.
5167 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5168 // The rest of the response body is received in two parts.
5171 MockRead("junk"), // Should not be read!!
5172 MockRead(SYNCHRONOUS
, OK
),
5175 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5176 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5178 TestCompletionCallback callback
;
5180 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5181 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5183 rv
= callback
.WaitForResult();
5186 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5187 ASSERT_TRUE(response
!= NULL
);
5189 EXPECT_TRUE(response
->headers
.get() != NULL
);
5190 std::string status_line
= response
->headers
->GetStatusLine();
5191 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5193 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5195 std::string response_data
;
5196 rv
= ReadTransaction(trans
.get(), &response_data
);
5198 EXPECT_EQ("hello world", response_data
);
5200 // Empty the current queue. This is necessary because idle sockets are
5201 // added to the connection pool asynchronously with a PostTask.
5202 base::MessageLoop::current()->RunUntilIdle();
5204 // We now check to make sure the socket was added back to the pool.
5205 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5208 // Make sure that we recycle a SSL socket after reading all of the response
5210 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5211 HttpRequestInfo request
;
5212 request
.method
= "GET";
5213 request
.url
= GURL("https://www.example.org/");
5214 request
.load_flags
= 0;
5216 MockWrite data_writes
[] = {
5218 "GET / HTTP/1.1\r\n"
5219 "Host: www.example.org\r\n"
5220 "Connection: keep-alive\r\n\r\n"),
5223 MockRead data_reads
[] = {
5224 MockRead("HTTP/1.1 200 OK\r\n"),
5225 MockRead("Content-Length: 11\r\n\r\n"),
5226 MockRead("hello world"),
5227 MockRead(SYNCHRONOUS
, OK
),
5230 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5231 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5233 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5234 data_writes
, arraysize(data_writes
));
5235 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5237 TestCompletionCallback callback
;
5239 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5240 scoped_ptr
<HttpTransaction
> trans(
5241 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5243 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5245 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5246 EXPECT_EQ(OK
, callback
.WaitForResult());
5248 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5249 ASSERT_TRUE(response
!= NULL
);
5250 ASSERT_TRUE(response
->headers
.get() != NULL
);
5251 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5253 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5255 std::string response_data
;
5256 rv
= ReadTransaction(trans
.get(), &response_data
);
5258 EXPECT_EQ("hello world", response_data
);
5260 // Empty the current queue. This is necessary because idle sockets are
5261 // added to the connection pool asynchronously with a PostTask.
5262 base::MessageLoop::current()->RunUntilIdle();
5264 // We now check to make sure the socket was added back to the pool.
5265 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5268 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5269 // from the pool and make sure that we recover okay.
5270 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5271 HttpRequestInfo request
;
5272 request
.method
= "GET";
5273 request
.url
= GURL("https://www.example.org/");
5274 request
.load_flags
= 0;
5276 MockWrite data_writes
[] = {
5278 "GET / HTTP/1.1\r\n"
5279 "Host: www.example.org\r\n"
5280 "Connection: keep-alive\r\n\r\n"),
5282 "GET / HTTP/1.1\r\n"
5283 "Host: www.example.org\r\n"
5284 "Connection: keep-alive\r\n\r\n"),
5287 MockRead data_reads
[] = {
5288 MockRead("HTTP/1.1 200 OK\r\n"),
5289 MockRead("Content-Length: 11\r\n\r\n"),
5290 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5291 MockRead("hello world"),
5292 MockRead(ASYNC
, 0, 0) // EOF
5295 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5296 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5297 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5298 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5300 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5301 data_writes
, arraysize(data_writes
));
5302 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5303 data_writes
, arraysize(data_writes
));
5304 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5305 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5307 TestCompletionCallback callback
;
5309 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5310 scoped_ptr
<HttpTransaction
> trans(
5311 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5313 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5315 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5316 EXPECT_EQ(OK
, callback
.WaitForResult());
5318 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5319 ASSERT_TRUE(response
!= NULL
);
5320 ASSERT_TRUE(response
->headers
.get() != NULL
);
5321 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5323 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5325 std::string response_data
;
5326 rv
= ReadTransaction(trans
.get(), &response_data
);
5328 EXPECT_EQ("hello world", response_data
);
5330 // Empty the current queue. This is necessary because idle sockets are
5331 // added to the connection pool asynchronously with a PostTask.
5332 base::MessageLoop::current()->RunUntilIdle();
5334 // We now check to make sure the socket was added back to the pool.
5335 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5337 // Now start the second transaction, which should reuse the previous socket.
5339 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5341 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5343 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5344 EXPECT_EQ(OK
, callback
.WaitForResult());
5346 response
= trans
->GetResponseInfo();
5347 ASSERT_TRUE(response
!= NULL
);
5348 ASSERT_TRUE(response
->headers
.get() != NULL
);
5349 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5351 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5353 rv
= ReadTransaction(trans
.get(), &response_data
);
5355 EXPECT_EQ("hello world", response_data
);
5357 // Empty the current queue. This is necessary because idle sockets are
5358 // added to the connection pool asynchronously with a PostTask.
5359 base::MessageLoop::current()->RunUntilIdle();
5361 // We now check to make sure the socket was added back to the pool.
5362 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5365 // Make sure that we recycle a socket after a zero-length response.
5366 // http://crbug.com/9880
5367 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5368 HttpRequestInfo request
;
5369 request
.method
= "GET";
5371 "http://www.example.org/csi?v=3&s=web&action=&"
5372 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5373 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5374 "rt=prt.2642,ol.2649,xjs.2951");
5375 request
.load_flags
= 0;
5377 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5379 scoped_ptr
<HttpTransaction
> trans(
5380 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5382 MockRead data_reads
[] = {
5383 MockRead("HTTP/1.1 204 No Content\r\n"
5384 "Content-Length: 0\r\n"
5385 "Content-Type: text/html\r\n\r\n"),
5386 MockRead("junk"), // Should not be read!!
5387 MockRead(SYNCHRONOUS
, OK
),
5390 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5391 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5393 TestCompletionCallback callback
;
5395 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5396 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5398 rv
= callback
.WaitForResult();
5401 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5402 ASSERT_TRUE(response
!= NULL
);
5404 EXPECT_TRUE(response
->headers
.get() != NULL
);
5405 std::string status_line
= response
->headers
->GetStatusLine();
5406 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5408 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5410 std::string response_data
;
5411 rv
= ReadTransaction(trans
.get(), &response_data
);
5413 EXPECT_EQ("", response_data
);
5415 // Empty the current queue. This is necessary because idle sockets are
5416 // added to the connection pool asynchronously with a PostTask.
5417 base::MessageLoop::current()->RunUntilIdle();
5419 // We now check to make sure the socket was added back to the pool.
5420 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5423 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5424 ScopedVector
<UploadElementReader
> element_readers
;
5425 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5426 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5428 HttpRequestInfo request
[2];
5429 // Transaction 1: a GET request that succeeds. The socket is recycled
5431 request
[0].method
= "GET";
5432 request
[0].url
= GURL("http://www.google.com/");
5433 request
[0].load_flags
= 0;
5434 // Transaction 2: a POST request. Reuses the socket kept alive from
5435 // transaction 1. The first attempts fails when writing the POST data.
5436 // This causes the transaction to retry with a new socket. The second
5437 // attempt succeeds.
5438 request
[1].method
= "POST";
5439 request
[1].url
= GURL("http://www.google.com/login.cgi");
5440 request
[1].upload_data_stream
= &upload_data_stream
;
5441 request
[1].load_flags
= 0;
5443 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5445 // The first socket is used for transaction 1 and the first attempt of
5448 // The response of transaction 1.
5449 MockRead data_reads1
[] = {
5450 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5451 MockRead("hello world"),
5452 MockRead(SYNCHRONOUS
, OK
),
5454 // The mock write results of transaction 1 and the first attempt of
5456 MockWrite data_writes1
[] = {
5457 MockWrite(SYNCHRONOUS
, 64), // GET
5458 MockWrite(SYNCHRONOUS
, 93), // POST
5459 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5461 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5462 data_writes1
, arraysize(data_writes1
));
5464 // The second socket is used for the second attempt of transaction 2.
5466 // The response of transaction 2.
5467 MockRead data_reads2
[] = {
5468 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5469 MockRead("welcome"),
5470 MockRead(SYNCHRONOUS
, OK
),
5472 // The mock write results of the second attempt of transaction 2.
5473 MockWrite data_writes2
[] = {
5474 MockWrite(SYNCHRONOUS
, 93), // POST
5475 MockWrite(SYNCHRONOUS
, 3), // POST data
5477 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5478 data_writes2
, arraysize(data_writes2
));
5480 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5481 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5483 const char* const kExpectedResponseData
[] = {
5484 "hello world", "welcome"
5487 for (int i
= 0; i
< 2; ++i
) {
5488 scoped_ptr
<HttpTransaction
> trans(
5489 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5491 TestCompletionCallback callback
;
5493 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5494 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5496 rv
= callback
.WaitForResult();
5499 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5500 ASSERT_TRUE(response
!= NULL
);
5502 EXPECT_TRUE(response
->headers
.get() != NULL
);
5503 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5505 std::string response_data
;
5506 rv
= ReadTransaction(trans
.get(), &response_data
);
5508 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5512 // Test the request-challenge-retry sequence for basic auth when there is
5513 // an identity in the URL. The request should be sent as normal, but when
5514 // it fails the identity from the URL is used to answer the challenge.
5515 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5516 HttpRequestInfo request
;
5517 request
.method
= "GET";
5518 request
.url
= GURL("http://foo:b@r@www.example.org/");
5519 request
.load_flags
= LOAD_NORMAL
;
5521 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5522 scoped_ptr
<HttpTransaction
> trans(
5523 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5525 // The password contains an escaped character -- for this test to pass it
5526 // will need to be unescaped by HttpNetworkTransaction.
5527 EXPECT_EQ("b%40r", request
.url
.password());
5529 MockWrite data_writes1
[] = {
5531 "GET / HTTP/1.1\r\n"
5532 "Host: www.example.org\r\n"
5533 "Connection: keep-alive\r\n\r\n"),
5536 MockRead data_reads1
[] = {
5537 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5538 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5539 MockRead("Content-Length: 10\r\n\r\n"),
5540 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5543 // After the challenge above, the transaction will be restarted using the
5544 // identity from the url (foo, b@r) to answer the challenge.
5545 MockWrite data_writes2
[] = {
5547 "GET / HTTP/1.1\r\n"
5548 "Host: www.example.org\r\n"
5549 "Connection: keep-alive\r\n"
5550 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5553 MockRead data_reads2
[] = {
5554 MockRead("HTTP/1.0 200 OK\r\n"),
5555 MockRead("Content-Length: 100\r\n\r\n"),
5556 MockRead(SYNCHRONOUS
, OK
),
5559 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5560 data_writes1
, arraysize(data_writes1
));
5561 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5562 data_writes2
, arraysize(data_writes2
));
5563 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5564 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5566 TestCompletionCallback callback1
;
5567 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5569 rv
= callback1
.WaitForResult();
5571 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5573 TestCompletionCallback callback2
;
5574 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5575 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5576 rv
= callback2
.WaitForResult();
5578 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5580 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5581 ASSERT_TRUE(response
!= NULL
);
5583 // There is no challenge info, since the identity in URL worked.
5584 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5586 EXPECT_EQ(100, response
->headers
->GetContentLength());
5588 // Empty the current queue.
5589 base::MessageLoop::current()->RunUntilIdle();
5592 // Test the request-challenge-retry sequence for basic auth when there is an
5593 // incorrect identity in the URL. The identity from the URL should be used only
5595 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5596 HttpRequestInfo request
;
5597 request
.method
= "GET";
5598 // Note: the URL has a username:password in it. The password "baz" is
5599 // wrong (should be "bar").
5600 request
.url
= GURL("http://foo:baz@www.example.org/");
5602 request
.load_flags
= LOAD_NORMAL
;
5604 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5605 scoped_ptr
<HttpTransaction
> trans(
5606 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5608 MockWrite data_writes1
[] = {
5610 "GET / HTTP/1.1\r\n"
5611 "Host: www.example.org\r\n"
5612 "Connection: keep-alive\r\n\r\n"),
5615 MockRead data_reads1
[] = {
5616 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5617 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5618 MockRead("Content-Length: 10\r\n\r\n"),
5619 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5622 // After the challenge above, the transaction will be restarted using the
5623 // identity from the url (foo, baz) to answer the challenge.
5624 MockWrite data_writes2
[] = {
5626 "GET / HTTP/1.1\r\n"
5627 "Host: www.example.org\r\n"
5628 "Connection: keep-alive\r\n"
5629 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5632 MockRead data_reads2
[] = {
5633 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5634 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5635 MockRead("Content-Length: 10\r\n\r\n"),
5636 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5639 // After the challenge above, the transaction will be restarted using the
5640 // identity supplied by the user (foo, bar) to answer the challenge.
5641 MockWrite data_writes3
[] = {
5643 "GET / HTTP/1.1\r\n"
5644 "Host: www.example.org\r\n"
5645 "Connection: keep-alive\r\n"
5646 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5649 MockRead data_reads3
[] = {
5650 MockRead("HTTP/1.0 200 OK\r\n"),
5651 MockRead("Content-Length: 100\r\n\r\n"),
5652 MockRead(SYNCHRONOUS
, OK
),
5655 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5656 data_writes1
, arraysize(data_writes1
));
5657 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5658 data_writes2
, arraysize(data_writes2
));
5659 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5660 data_writes3
, arraysize(data_writes3
));
5661 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5662 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5663 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5665 TestCompletionCallback callback1
;
5667 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5668 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5670 rv
= callback1
.WaitForResult();
5673 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5674 TestCompletionCallback callback2
;
5675 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5676 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5677 rv
= callback2
.WaitForResult();
5679 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5681 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5682 ASSERT_TRUE(response
!= NULL
);
5683 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5685 TestCompletionCallback callback3
;
5686 rv
= trans
->RestartWithAuth(
5687 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5688 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5689 rv
= callback3
.WaitForResult();
5691 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5693 response
= trans
->GetResponseInfo();
5694 ASSERT_TRUE(response
!= NULL
);
5696 // There is no challenge info, since the identity worked.
5697 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5699 EXPECT_EQ(100, response
->headers
->GetContentLength());
5701 // Empty the current queue.
5702 base::MessageLoop::current()->RunUntilIdle();
5706 // Test the request-challenge-retry sequence for basic auth when there is a
5707 // correct identity in the URL, but its use is being suppressed. The identity
5708 // from the URL should never be used.
5709 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5710 HttpRequestInfo request
;
5711 request
.method
= "GET";
5712 request
.url
= GURL("http://foo:bar@www.example.org/");
5713 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5715 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5716 scoped_ptr
<HttpTransaction
> trans(
5717 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5719 MockWrite data_writes1
[] = {
5721 "GET / HTTP/1.1\r\n"
5722 "Host: www.example.org\r\n"
5723 "Connection: keep-alive\r\n\r\n"),
5726 MockRead data_reads1
[] = {
5727 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5728 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5729 MockRead("Content-Length: 10\r\n\r\n"),
5730 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5733 // After the challenge above, the transaction will be restarted using the
5734 // identity supplied by the user, not the one in the URL, to answer the
5736 MockWrite data_writes3
[] = {
5738 "GET / HTTP/1.1\r\n"
5739 "Host: www.example.org\r\n"
5740 "Connection: keep-alive\r\n"
5741 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5744 MockRead data_reads3
[] = {
5745 MockRead("HTTP/1.0 200 OK\r\n"),
5746 MockRead("Content-Length: 100\r\n\r\n"),
5747 MockRead(SYNCHRONOUS
, OK
),
5750 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5751 data_writes1
, arraysize(data_writes1
));
5752 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5753 data_writes3
, arraysize(data_writes3
));
5754 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5755 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5757 TestCompletionCallback callback1
;
5758 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5759 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5760 rv
= callback1
.WaitForResult();
5762 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5764 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5765 ASSERT_TRUE(response
!= NULL
);
5766 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5768 TestCompletionCallback callback3
;
5769 rv
= trans
->RestartWithAuth(
5770 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5771 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5772 rv
= callback3
.WaitForResult();
5774 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5776 response
= trans
->GetResponseInfo();
5777 ASSERT_TRUE(response
!= NULL
);
5779 // There is no challenge info, since the identity worked.
5780 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5781 EXPECT_EQ(100, response
->headers
->GetContentLength());
5783 // Empty the current queue.
5784 base::MessageLoop::current()->RunUntilIdle();
5787 // Test that previously tried username/passwords for a realm get re-used.
5788 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5789 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5791 // Transaction 1: authenticate (foo, bar) on MyRealm1
5793 HttpRequestInfo request
;
5794 request
.method
= "GET";
5795 request
.url
= GURL("http://www.example.org/x/y/z");
5796 request
.load_flags
= 0;
5798 scoped_ptr
<HttpTransaction
> trans(
5799 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5801 MockWrite data_writes1
[] = {
5803 "GET /x/y/z HTTP/1.1\r\n"
5804 "Host: www.example.org\r\n"
5805 "Connection: keep-alive\r\n\r\n"),
5808 MockRead data_reads1
[] = {
5809 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5810 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5811 MockRead("Content-Length: 10000\r\n\r\n"),
5812 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5815 // Resend with authorization (username=foo, password=bar)
5816 MockWrite data_writes2
[] = {
5818 "GET /x/y/z HTTP/1.1\r\n"
5819 "Host: www.example.org\r\n"
5820 "Connection: keep-alive\r\n"
5821 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5824 // Sever accepts the authorization.
5825 MockRead data_reads2
[] = {
5826 MockRead("HTTP/1.0 200 OK\r\n"),
5827 MockRead("Content-Length: 100\r\n\r\n"),
5828 MockRead(SYNCHRONOUS
, OK
),
5831 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5832 data_writes1
, arraysize(data_writes1
));
5833 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5834 data_writes2
, arraysize(data_writes2
));
5835 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5836 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5838 TestCompletionCallback callback1
;
5840 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5841 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5843 rv
= callback1
.WaitForResult();
5846 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5847 ASSERT_TRUE(response
!= NULL
);
5848 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5850 TestCompletionCallback callback2
;
5852 rv
= trans
->RestartWithAuth(
5853 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5854 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5856 rv
= callback2
.WaitForResult();
5859 response
= trans
->GetResponseInfo();
5860 ASSERT_TRUE(response
!= NULL
);
5861 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5862 EXPECT_EQ(100, response
->headers
->GetContentLength());
5865 // ------------------------------------------------------------------------
5867 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5869 HttpRequestInfo request
;
5870 request
.method
= "GET";
5871 // Note that Transaction 1 was at /x/y/z, so this is in the same
5872 // protection space as MyRealm1.
5873 request
.url
= GURL("http://www.example.org/x/y/a/b");
5874 request
.load_flags
= 0;
5876 scoped_ptr
<HttpTransaction
> trans(
5877 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5879 MockWrite data_writes1
[] = {
5881 "GET /x/y/a/b HTTP/1.1\r\n"
5882 "Host: www.example.org\r\n"
5883 "Connection: keep-alive\r\n"
5884 // Send preemptive authorization for MyRealm1
5885 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5888 // The server didn't like the preemptive authorization, and
5889 // challenges us for a different realm (MyRealm2).
5890 MockRead data_reads1
[] = {
5891 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5892 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5893 MockRead("Content-Length: 10000\r\n\r\n"),
5894 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5897 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5898 MockWrite data_writes2
[] = {
5900 "GET /x/y/a/b HTTP/1.1\r\n"
5901 "Host: www.example.org\r\n"
5902 "Connection: keep-alive\r\n"
5903 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5906 // Sever accepts the authorization.
5907 MockRead data_reads2
[] = {
5908 MockRead("HTTP/1.0 200 OK\r\n"),
5909 MockRead("Content-Length: 100\r\n\r\n"),
5910 MockRead(SYNCHRONOUS
, OK
),
5913 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5914 data_writes1
, arraysize(data_writes1
));
5915 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5916 data_writes2
, arraysize(data_writes2
));
5917 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5918 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5920 TestCompletionCallback callback1
;
5922 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5923 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5925 rv
= callback1
.WaitForResult();
5928 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5929 ASSERT_TRUE(response
!= NULL
);
5930 ASSERT_TRUE(response
->auth_challenge
.get());
5931 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5932 EXPECT_EQ("www.example.org:80",
5933 response
->auth_challenge
->challenger
.ToString());
5934 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5935 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5937 TestCompletionCallback callback2
;
5939 rv
= trans
->RestartWithAuth(
5940 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5943 rv
= callback2
.WaitForResult();
5946 response
= trans
->GetResponseInfo();
5947 ASSERT_TRUE(response
!= NULL
);
5948 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5949 EXPECT_EQ(100, response
->headers
->GetContentLength());
5952 // ------------------------------------------------------------------------
5954 // Transaction 3: Resend a request in MyRealm's protection space --
5955 // succeed with preemptive authorization.
5957 HttpRequestInfo request
;
5958 request
.method
= "GET";
5959 request
.url
= GURL("http://www.example.org/x/y/z2");
5960 request
.load_flags
= 0;
5962 scoped_ptr
<HttpTransaction
> trans(
5963 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5965 MockWrite data_writes1
[] = {
5967 "GET /x/y/z2 HTTP/1.1\r\n"
5968 "Host: www.example.org\r\n"
5969 "Connection: keep-alive\r\n"
5970 // The authorization for MyRealm1 gets sent preemptively
5971 // (since the url is in the same protection space)
5972 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5975 // Sever accepts the preemptive authorization
5976 MockRead data_reads1
[] = {
5977 MockRead("HTTP/1.0 200 OK\r\n"),
5978 MockRead("Content-Length: 100\r\n\r\n"),
5979 MockRead(SYNCHRONOUS
, OK
),
5982 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5983 data_writes1
, arraysize(data_writes1
));
5984 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5986 TestCompletionCallback callback1
;
5988 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5989 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5991 rv
= callback1
.WaitForResult();
5994 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5995 ASSERT_TRUE(response
!= NULL
);
5997 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5998 EXPECT_EQ(100, response
->headers
->GetContentLength());
6001 // ------------------------------------------------------------------------
6003 // Transaction 4: request another URL in MyRealm (however the
6004 // url is not known to belong to the protection space, so no pre-auth).
6006 HttpRequestInfo request
;
6007 request
.method
= "GET";
6008 request
.url
= GURL("http://www.example.org/x/1");
6009 request
.load_flags
= 0;
6011 scoped_ptr
<HttpTransaction
> trans(
6012 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6014 MockWrite data_writes1
[] = {
6016 "GET /x/1 HTTP/1.1\r\n"
6017 "Host: www.example.org\r\n"
6018 "Connection: keep-alive\r\n\r\n"),
6021 MockRead data_reads1
[] = {
6022 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6023 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6024 MockRead("Content-Length: 10000\r\n\r\n"),
6025 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6028 // Resend with authorization from MyRealm's cache.
6029 MockWrite data_writes2
[] = {
6031 "GET /x/1 HTTP/1.1\r\n"
6032 "Host: www.example.org\r\n"
6033 "Connection: keep-alive\r\n"
6034 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6037 // Sever accepts the authorization.
6038 MockRead data_reads2
[] = {
6039 MockRead("HTTP/1.0 200 OK\r\n"),
6040 MockRead("Content-Length: 100\r\n\r\n"),
6041 MockRead(SYNCHRONOUS
, OK
),
6044 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6045 data_writes1
, arraysize(data_writes1
));
6046 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6047 data_writes2
, arraysize(data_writes2
));
6048 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6049 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6051 TestCompletionCallback callback1
;
6053 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6054 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6056 rv
= callback1
.WaitForResult();
6059 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6060 TestCompletionCallback callback2
;
6061 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6062 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6063 rv
= callback2
.WaitForResult();
6065 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6067 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6068 ASSERT_TRUE(response
!= NULL
);
6069 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6070 EXPECT_EQ(100, response
->headers
->GetContentLength());
6073 // ------------------------------------------------------------------------
6075 // Transaction 5: request a URL in MyRealm, but the server rejects the
6076 // cached identity. Should invalidate and re-prompt.
6078 HttpRequestInfo request
;
6079 request
.method
= "GET";
6080 request
.url
= GURL("http://www.example.org/p/q/t");
6081 request
.load_flags
= 0;
6083 scoped_ptr
<HttpTransaction
> trans(
6084 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6086 MockWrite data_writes1
[] = {
6088 "GET /p/q/t HTTP/1.1\r\n"
6089 "Host: www.example.org\r\n"
6090 "Connection: keep-alive\r\n\r\n"),
6093 MockRead data_reads1
[] = {
6094 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6095 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6096 MockRead("Content-Length: 10000\r\n\r\n"),
6097 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6100 // Resend with authorization from cache for MyRealm.
6101 MockWrite data_writes2
[] = {
6103 "GET /p/q/t HTTP/1.1\r\n"
6104 "Host: www.example.org\r\n"
6105 "Connection: keep-alive\r\n"
6106 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6109 // Sever rejects the authorization.
6110 MockRead data_reads2
[] = {
6111 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6112 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6113 MockRead("Content-Length: 10000\r\n\r\n"),
6114 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6117 // At this point we should prompt for new credentials for MyRealm.
6118 // Restart with username=foo3, password=foo4.
6119 MockWrite data_writes3
[] = {
6121 "GET /p/q/t HTTP/1.1\r\n"
6122 "Host: www.example.org\r\n"
6123 "Connection: keep-alive\r\n"
6124 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6127 // Sever accepts the authorization.
6128 MockRead data_reads3
[] = {
6129 MockRead("HTTP/1.0 200 OK\r\n"),
6130 MockRead("Content-Length: 100\r\n\r\n"),
6131 MockRead(SYNCHRONOUS
, OK
),
6134 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6135 data_writes1
, arraysize(data_writes1
));
6136 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6137 data_writes2
, arraysize(data_writes2
));
6138 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6139 data_writes3
, arraysize(data_writes3
));
6140 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6141 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6142 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6144 TestCompletionCallback callback1
;
6146 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6147 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6149 rv
= callback1
.WaitForResult();
6152 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6153 TestCompletionCallback callback2
;
6154 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6155 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6156 rv
= callback2
.WaitForResult();
6158 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6160 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6161 ASSERT_TRUE(response
!= NULL
);
6162 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6164 TestCompletionCallback callback3
;
6166 rv
= trans
->RestartWithAuth(
6167 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6168 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6170 rv
= callback3
.WaitForResult();
6173 response
= trans
->GetResponseInfo();
6174 ASSERT_TRUE(response
!= NULL
);
6175 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6176 EXPECT_EQ(100, response
->headers
->GetContentLength());
6180 // Tests that nonce count increments when multiple auth attempts
6181 // are started with the same nonce.
6182 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6183 HttpAuthHandlerDigest::Factory
* digest_factory
=
6184 new HttpAuthHandlerDigest::Factory();
6185 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6186 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6187 digest_factory
->set_nonce_generator(nonce_generator
);
6188 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6189 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6191 // Transaction 1: authenticate (foo, bar) on MyRealm1
6193 HttpRequestInfo request
;
6194 request
.method
= "GET";
6195 request
.url
= GURL("http://www.example.org/x/y/z");
6196 request
.load_flags
= 0;
6198 scoped_ptr
<HttpTransaction
> trans(
6199 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6201 MockWrite data_writes1
[] = {
6203 "GET /x/y/z HTTP/1.1\r\n"
6204 "Host: www.example.org\r\n"
6205 "Connection: keep-alive\r\n\r\n"),
6208 MockRead data_reads1
[] = {
6209 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6210 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6211 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6212 MockRead(SYNCHRONOUS
, OK
),
6215 // Resend with authorization (username=foo, password=bar)
6216 MockWrite data_writes2
[] = {
6218 "GET /x/y/z HTTP/1.1\r\n"
6219 "Host: www.example.org\r\n"
6220 "Connection: keep-alive\r\n"
6221 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6222 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6223 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6224 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6227 // Sever accepts the authorization.
6228 MockRead data_reads2
[] = {
6229 MockRead("HTTP/1.0 200 OK\r\n"),
6230 MockRead(SYNCHRONOUS
, OK
),
6233 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6234 data_writes1
, arraysize(data_writes1
));
6235 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6236 data_writes2
, arraysize(data_writes2
));
6237 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6238 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6240 TestCompletionCallback callback1
;
6242 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6243 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6245 rv
= callback1
.WaitForResult();
6248 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6249 ASSERT_TRUE(response
!= NULL
);
6250 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6252 TestCompletionCallback callback2
;
6254 rv
= trans
->RestartWithAuth(
6255 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6258 rv
= callback2
.WaitForResult();
6261 response
= trans
->GetResponseInfo();
6262 ASSERT_TRUE(response
!= NULL
);
6263 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6266 // ------------------------------------------------------------------------
6268 // Transaction 2: Request another resource in digestive's protection space.
6269 // This will preemptively add an Authorization header which should have an
6270 // "nc" value of 2 (as compared to 1 in the first use.
6272 HttpRequestInfo request
;
6273 request
.method
= "GET";
6274 // Note that Transaction 1 was at /x/y/z, so this is in the same
6275 // protection space as digest.
6276 request
.url
= GURL("http://www.example.org/x/y/a/b");
6277 request
.load_flags
= 0;
6279 scoped_ptr
<HttpTransaction
> trans(
6280 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6282 MockWrite data_writes1
[] = {
6284 "GET /x/y/a/b HTTP/1.1\r\n"
6285 "Host: www.example.org\r\n"
6286 "Connection: keep-alive\r\n"
6287 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6288 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6289 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6290 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6293 // Sever accepts the authorization.
6294 MockRead data_reads1
[] = {
6295 MockRead("HTTP/1.0 200 OK\r\n"),
6296 MockRead("Content-Length: 100\r\n\r\n"),
6297 MockRead(SYNCHRONOUS
, OK
),
6300 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6301 data_writes1
, arraysize(data_writes1
));
6302 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6304 TestCompletionCallback callback1
;
6306 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6307 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6309 rv
= callback1
.WaitForResult();
6312 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6313 ASSERT_TRUE(response
!= NULL
);
6314 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6318 // Test the ResetStateForRestart() private method.
6319 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6320 // Create a transaction (the dependencies aren't important).
6321 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6322 scoped_ptr
<HttpNetworkTransaction
> trans(
6323 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6325 // Setup some state (which we expect ResetStateForRestart() will clear).
6326 trans
->read_buf_
= new IOBuffer(15);
6327 trans
->read_buf_len_
= 15;
6328 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6330 // Setup state in response_
6331 HttpResponseInfo
* response
= &trans
->response_
;
6332 response
->auth_challenge
= new AuthChallengeInfo();
6333 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6334 response
->response_time
= base::Time::Now();
6335 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6337 { // Setup state for response_.vary_data
6338 HttpRequestInfo request
;
6339 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6340 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6341 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6342 request
.extra_headers
.SetHeader("Foo", "1");
6343 request
.extra_headers
.SetHeader("bar", "23");
6344 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6347 // Cause the above state to be reset.
6348 trans
->ResetStateForRestart();
6350 // Verify that the state that needed to be reset, has been reset.
6351 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6352 EXPECT_EQ(0, trans
->read_buf_len_
);
6353 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6354 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6355 EXPECT_TRUE(response
->headers
.get() == NULL
);
6356 EXPECT_FALSE(response
->was_cached
);
6357 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6358 EXPECT_FALSE(response
->vary_data
.is_valid());
6361 // Test HTTPS connections to a site with a bad certificate
6362 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6363 HttpRequestInfo request
;
6364 request
.method
= "GET";
6365 request
.url
= GURL("https://www.example.org/");
6366 request
.load_flags
= 0;
6368 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6369 scoped_ptr
<HttpTransaction
> trans(
6370 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6372 MockWrite data_writes
[] = {
6374 "GET / HTTP/1.1\r\n"
6375 "Host: www.example.org\r\n"
6376 "Connection: keep-alive\r\n\r\n"),
6379 MockRead data_reads
[] = {
6380 MockRead("HTTP/1.0 200 OK\r\n"),
6381 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6382 MockRead("Content-Length: 100\r\n\r\n"),
6383 MockRead(SYNCHRONOUS
, OK
),
6386 StaticSocketDataProvider ssl_bad_certificate
;
6387 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6388 data_writes
, arraysize(data_writes
));
6389 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6390 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6392 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6393 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6394 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6395 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6397 TestCompletionCallback callback
;
6399 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6400 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6402 rv
= callback
.WaitForResult();
6403 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6405 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6406 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6408 rv
= callback
.WaitForResult();
6411 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6413 ASSERT_TRUE(response
!= NULL
);
6414 EXPECT_EQ(100, response
->headers
->GetContentLength());
6417 // Test HTTPS connections to a site with a bad certificate, going through a
6419 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6420 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6422 HttpRequestInfo request
;
6423 request
.method
= "GET";
6424 request
.url
= GURL("https://www.example.org/");
6425 request
.load_flags
= 0;
6427 MockWrite proxy_writes
[] = {
6429 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6430 "Host: www.example.org\r\n"
6431 "Proxy-Connection: keep-alive\r\n\r\n"),
6434 MockRead proxy_reads
[] = {
6435 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6436 MockRead(SYNCHRONOUS
, OK
)
6439 MockWrite data_writes
[] = {
6441 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6442 "Host: www.example.org\r\n"
6443 "Proxy-Connection: keep-alive\r\n\r\n"),
6445 "GET / HTTP/1.1\r\n"
6446 "Host: www.example.org\r\n"
6447 "Connection: keep-alive\r\n\r\n"),
6450 MockRead data_reads
[] = {
6451 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6452 MockRead("HTTP/1.0 200 OK\r\n"),
6453 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6454 MockRead("Content-Length: 100\r\n\r\n"),
6455 MockRead(SYNCHRONOUS
, OK
),
6458 StaticSocketDataProvider
ssl_bad_certificate(
6459 proxy_reads
, arraysize(proxy_reads
),
6460 proxy_writes
, arraysize(proxy_writes
));
6461 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6462 data_writes
, arraysize(data_writes
));
6463 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6464 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6466 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6467 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6468 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6469 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6471 TestCompletionCallback callback
;
6473 for (int i
= 0; i
< 2; i
++) {
6474 session_deps_
.socket_factory
->ResetNextMockIndexes();
6476 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6477 scoped_ptr
<HttpTransaction
> trans(
6478 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6480 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6481 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6483 rv
= callback
.WaitForResult();
6484 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6486 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6487 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6489 rv
= callback
.WaitForResult();
6492 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6494 ASSERT_TRUE(response
!= NULL
);
6495 EXPECT_EQ(100, response
->headers
->GetContentLength());
6500 // Test HTTPS connections to a site, going through an HTTPS proxy
6501 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6502 session_deps_
.proxy_service
.reset(
6503 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6505 session_deps_
.net_log
= &net_log
;
6507 HttpRequestInfo request
;
6508 request
.method
= "GET";
6509 request
.url
= GURL("https://www.example.org/");
6510 request
.load_flags
= 0;
6512 MockWrite data_writes
[] = {
6514 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6515 "Host: www.example.org\r\n"
6516 "Proxy-Connection: keep-alive\r\n\r\n"),
6518 "GET / HTTP/1.1\r\n"
6519 "Host: www.example.org\r\n"
6520 "Connection: keep-alive\r\n\r\n"),
6523 MockRead data_reads
[] = {
6524 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6525 MockRead("HTTP/1.1 200 OK\r\n"),
6526 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6527 MockRead("Content-Length: 100\r\n\r\n"),
6528 MockRead(SYNCHRONOUS
, OK
),
6531 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6532 data_writes
, arraysize(data_writes
));
6533 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6534 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6536 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6537 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6538 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6540 TestCompletionCallback callback
;
6542 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6543 scoped_ptr
<HttpTransaction
> trans(
6544 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6546 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6547 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6549 rv
= callback
.WaitForResult();
6551 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6553 ASSERT_TRUE(response
!= NULL
);
6555 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6556 EXPECT_EQ(200, response
->headers
->response_code());
6557 EXPECT_EQ(100, response
->headers
->GetContentLength());
6558 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6560 LoadTimingInfo load_timing_info
;
6561 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6562 TestLoadTimingNotReusedWithPac(load_timing_info
,
6563 CONNECT_TIMING_HAS_SSL_TIMES
);
6566 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6567 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6568 session_deps_
.proxy_service
.reset(
6569 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6571 session_deps_
.net_log
= &net_log
;
6573 HttpRequestInfo request
;
6574 request
.method
= "GET";
6575 request
.url
= GURL("https://www.example.org/");
6576 request
.load_flags
= 0;
6578 MockWrite data_writes
[] = {
6580 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6581 "Host: www.example.org\r\n"
6582 "Proxy-Connection: keep-alive\r\n\r\n"),
6585 MockRead data_reads
[] = {
6586 MockRead("HTTP/1.1 302 Redirect\r\n"),
6587 MockRead("Location: http://login.example.com/\r\n"),
6588 MockRead("Content-Length: 0\r\n\r\n"),
6589 MockRead(SYNCHRONOUS
, OK
),
6592 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6593 data_writes
, arraysize(data_writes
));
6594 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6596 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6597 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6599 TestCompletionCallback callback
;
6601 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6602 scoped_ptr
<HttpTransaction
> trans(
6603 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6605 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6606 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6608 rv
= callback
.WaitForResult();
6610 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6612 ASSERT_TRUE(response
!= NULL
);
6614 EXPECT_EQ(302, response
->headers
->response_code());
6616 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6617 EXPECT_EQ("http://login.example.com/", url
);
6619 // In the case of redirects from proxies, HttpNetworkTransaction returns
6620 // timing for the proxy connection instead of the connection to the host,
6621 // and no send / receive times.
6622 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6623 LoadTimingInfo load_timing_info
;
6624 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6626 EXPECT_FALSE(load_timing_info
.socket_reused
);
6627 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6629 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6630 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6631 load_timing_info
.proxy_resolve_end
);
6632 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6633 load_timing_info
.connect_timing
.connect_start
);
6634 ExpectConnectTimingHasTimes(
6635 load_timing_info
.connect_timing
,
6636 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6638 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6639 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6640 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6643 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6644 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6645 session_deps_
.proxy_service
.reset(
6646 ProxyService::CreateFixed("https://proxy:70"));
6648 HttpRequestInfo request
;
6649 request
.method
= "GET";
6650 request
.url
= GURL("https://www.example.org/");
6651 request
.load_flags
= 0;
6653 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6654 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6655 scoped_ptr
<SpdyFrame
> goaway(
6656 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6657 MockWrite data_writes
[] = {
6658 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6659 CreateMockWrite(*goaway
.get(), 2, SYNCHRONOUS
),
6662 static const char* const kExtraHeaders
[] = {
6664 "http://login.example.com/",
6666 scoped_ptr
<SpdyFrame
> resp(
6667 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6668 arraysize(kExtraHeaders
)/2, 1));
6669 MockRead data_reads
[] = {
6670 CreateMockRead(*resp
.get(), 1), MockRead(ASYNC
, 0, 3), // EOF
6673 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6674 arraysize(data_writes
));
6675 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6676 proxy_ssl
.SetNextProto(GetParam());
6678 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6679 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6681 TestCompletionCallback callback
;
6683 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6684 scoped_ptr
<HttpTransaction
> trans(
6685 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6687 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6688 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6690 rv
= callback
.WaitForResult();
6692 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6694 ASSERT_TRUE(response
!= NULL
);
6696 EXPECT_EQ(302, response
->headers
->response_code());
6698 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6699 EXPECT_EQ("http://login.example.com/", url
);
6702 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6703 TEST_P(HttpNetworkTransactionTest
,
6704 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6705 session_deps_
.proxy_service
.reset(
6706 ProxyService::CreateFixed("https://proxy:70"));
6708 HttpRequestInfo request
;
6709 request
.method
= "GET";
6710 request
.url
= GURL("https://www.example.org/");
6711 request
.load_flags
= 0;
6713 MockWrite data_writes
[] = {
6715 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6716 "Host: www.example.org\r\n"
6717 "Proxy-Connection: keep-alive\r\n\r\n"),
6720 MockRead data_reads
[] = {
6721 MockRead("HTTP/1.1 404 Not Found\r\n"),
6722 MockRead("Content-Length: 23\r\n\r\n"),
6723 MockRead("The host does not exist"),
6724 MockRead(SYNCHRONOUS
, OK
),
6727 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6728 data_writes
, arraysize(data_writes
));
6729 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6731 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6732 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6734 TestCompletionCallback callback
;
6736 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6737 scoped_ptr
<HttpTransaction
> trans(
6738 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6740 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6741 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6743 rv
= callback
.WaitForResult();
6744 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6746 // TODO(ttuttle): Anything else to check here?
6749 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6750 TEST_P(HttpNetworkTransactionTest
,
6751 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6752 session_deps_
.proxy_service
.reset(
6753 ProxyService::CreateFixed("https://proxy:70"));
6755 HttpRequestInfo request
;
6756 request
.method
= "GET";
6757 request
.url
= GURL("https://www.example.org/");
6758 request
.load_flags
= 0;
6760 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6761 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6762 scoped_ptr
<SpdyFrame
> rst(
6763 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6764 MockWrite data_writes
[] = {
6765 CreateMockWrite(*conn
.get(), 0), CreateMockWrite(*rst
.get(), 3),
6768 static const char* const kExtraHeaders
[] = {
6770 "http://login.example.com/",
6772 scoped_ptr
<SpdyFrame
> resp(
6773 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6774 arraysize(kExtraHeaders
)/2, 1));
6775 scoped_ptr
<SpdyFrame
> body(
6776 spdy_util_
.ConstructSpdyBodyFrame(
6777 1, "The host does not exist", 23, true));
6778 MockRead data_reads
[] = {
6779 CreateMockRead(*resp
.get(), 1),
6780 CreateMockRead(*body
.get(), 2),
6781 MockRead(ASYNC
, 0, 4), // EOF
6784 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6785 arraysize(data_writes
));
6786 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6787 proxy_ssl
.SetNextProto(GetParam());
6789 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6790 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6792 TestCompletionCallback callback
;
6794 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6795 scoped_ptr
<HttpTransaction
> trans(
6796 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6798 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6799 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6801 rv
= callback
.WaitForResult();
6802 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6804 // TODO(ttuttle): Anything else to check here?
6807 // Test the request-challenge-retry sequence for basic auth, through
6808 // a SPDY proxy over a single SPDY session.
6809 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6810 HttpRequestInfo request
;
6811 request
.method
= "GET";
6812 request
.url
= GURL("https://www.example.org/");
6813 // when the no authentication data flag is set.
6814 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6816 // Configure against https proxy server "myproxy:70".
6817 session_deps_
.proxy_service
.reset(
6818 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6819 BoundTestNetLog log
;
6820 session_deps_
.net_log
= log
.bound().net_log();
6821 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6823 // Since we have proxy, should try to establish tunnel.
6824 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6825 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6826 scoped_ptr
<SpdyFrame
> rst(
6827 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6829 // After calling trans->RestartWithAuth(), this is the request we should
6830 // be issuing -- the final header line contains the credentials.
6831 const char* const kAuthCredentials
[] = {
6832 "proxy-authorization", "Basic Zm9vOmJhcg==",
6834 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6835 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6836 HostPortPair("www.example.org", 443)));
6837 // fetch https://www.example.org/ via HTTP
6839 "GET / HTTP/1.1\r\n"
6840 "Host: www.example.org\r\n"
6841 "Connection: keep-alive\r\n\r\n";
6842 scoped_ptr
<SpdyFrame
> wrapped_get(
6843 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6845 MockWrite spdy_writes
[] = {
6846 CreateMockWrite(*req
, 0, ASYNC
),
6847 CreateMockWrite(*rst
, 2, ASYNC
),
6848 CreateMockWrite(*connect2
, 3),
6849 CreateMockWrite(*wrapped_get
, 5),
6852 // The proxy responds to the connect with a 407, using a persistent
6854 const char kAuthStatus
[] = "407";
6855 const char* const kAuthChallenge
[] = {
6856 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6858 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6859 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6861 scoped_ptr
<SpdyFrame
> conn_resp(
6862 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6863 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6864 "Content-Length: 5\r\n\r\n";
6866 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6867 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6868 scoped_ptr
<SpdyFrame
> wrapped_body(
6869 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6870 MockRead spdy_reads
[] = {
6871 CreateMockRead(*conn_auth_resp
, 1, ASYNC
),
6872 CreateMockRead(*conn_resp
, 4, ASYNC
),
6873 CreateMockRead(*wrapped_get_resp
, 6, ASYNC
),
6874 CreateMockRead(*wrapped_body
, 7, ASYNC
),
6875 MockRead(ASYNC
, OK
, 8), // EOF. May or may not be read.
6878 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6879 arraysize(spdy_writes
));
6880 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6881 // Negotiate SPDY to the proxy
6882 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6883 proxy
.SetNextProto(GetParam());
6884 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6885 // Vanilla SSL to the server
6886 SSLSocketDataProvider
server(ASYNC
, OK
);
6887 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6889 TestCompletionCallback callback1
;
6891 scoped_ptr
<HttpTransaction
> trans(
6892 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6894 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6895 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6897 rv
= callback1
.WaitForResult();
6899 TestNetLogEntry::List entries
;
6900 log
.GetEntries(&entries
);
6901 size_t pos
= ExpectLogContainsSomewhere(
6902 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6903 NetLog::PHASE_NONE
);
6904 ExpectLogContainsSomewhere(
6906 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6907 NetLog::PHASE_NONE
);
6909 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6910 ASSERT_TRUE(response
!= NULL
);
6911 ASSERT_FALSE(response
->headers
.get() == NULL
);
6912 EXPECT_EQ(407, response
->headers
->response_code());
6913 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6914 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6915 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6917 TestCompletionCallback callback2
;
6919 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6920 callback2
.callback());
6921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6923 rv
= callback2
.WaitForResult();
6926 response
= trans
->GetResponseInfo();
6927 ASSERT_TRUE(response
!= NULL
);
6929 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6930 EXPECT_EQ(200, response
->headers
->response_code());
6931 EXPECT_EQ(5, response
->headers
->GetContentLength());
6932 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6934 // The password prompt info should not be set.
6935 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6937 LoadTimingInfo load_timing_info
;
6938 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6939 TestLoadTimingNotReusedWithPac(load_timing_info
,
6940 CONNECT_TIMING_HAS_SSL_TIMES
);
6943 session
->CloseAllConnections();
6946 // Test that an explicitly trusted SPDY proxy can push a resource from an
6947 // origin that is different from that of its associated resource.
6948 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6949 HttpRequestInfo request
;
6950 HttpRequestInfo push_request
;
6952 request
.method
= "GET";
6953 request
.url
= GURL("http://www.example.org/");
6954 push_request
.method
= "GET";
6955 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6957 // Configure against https proxy server "myproxy:70".
6958 session_deps_
.proxy_service
.reset(
6959 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6960 BoundTestNetLog log
;
6961 session_deps_
.net_log
= log
.bound().net_log();
6963 // Enable cross-origin push.
6964 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6966 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6968 scoped_ptr
<SpdyFrame
> stream1_syn(
6969 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6971 MockWrite spdy_writes
[] = {
6972 CreateMockWrite(*stream1_syn
, 0, ASYNC
),
6975 scoped_ptr
<SpdyFrame
>
6976 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6978 scoped_ptr
<SpdyFrame
>
6979 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6981 scoped_ptr
<SpdyFrame
>
6982 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6986 "http://www.another-origin.com/foo.dat"));
6987 const char kPushedData
[] = "pushed";
6988 scoped_ptr
<SpdyFrame
> stream2_body(
6989 spdy_util_
.ConstructSpdyBodyFrame(
6990 2, kPushedData
, strlen(kPushedData
), true));
6992 MockRead spdy_reads
[] = {
6993 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6994 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6995 CreateMockRead(*stream1_body
, 3, ASYNC
),
6996 CreateMockRead(*stream2_body
, 4, ASYNC
),
6997 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7000 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7001 arraysize(spdy_writes
));
7002 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7003 // Negotiate SPDY to the proxy
7004 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7005 proxy
.SetNextProto(GetParam());
7006 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7008 scoped_ptr
<HttpTransaction
> trans(
7009 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7010 TestCompletionCallback callback
;
7011 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7012 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7014 rv
= callback
.WaitForResult();
7016 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7018 scoped_ptr
<HttpTransaction
> push_trans(
7019 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7020 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
7021 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7023 rv
= callback
.WaitForResult();
7025 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
7027 ASSERT_TRUE(response
!= NULL
);
7028 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7030 EXPECT_EQ(200, response
->headers
->response_code());
7031 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7033 std::string response_data
;
7034 rv
= ReadTransaction(trans
.get(), &response_data
);
7036 EXPECT_EQ("hello!", response_data
);
7038 LoadTimingInfo load_timing_info
;
7039 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7040 TestLoadTimingNotReusedWithPac(load_timing_info
,
7041 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7043 // Verify the pushed stream.
7044 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
7045 EXPECT_EQ(200, push_response
->headers
->response_code());
7047 rv
= ReadTransaction(push_trans
.get(), &response_data
);
7049 EXPECT_EQ("pushed", response_data
);
7051 LoadTimingInfo push_load_timing_info
;
7052 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
7053 TestLoadTimingReusedWithPac(push_load_timing_info
);
7054 // The transactions should share a socket ID, despite being for different
7056 EXPECT_EQ(load_timing_info
.socket_log_id
,
7057 push_load_timing_info
.socket_log_id
);
7061 session
->CloseAllConnections();
7064 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
7065 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
7066 HttpRequestInfo request
;
7068 request
.method
= "GET";
7069 request
.url
= GURL("http://www.example.org/");
7071 // Configure against https proxy server "myproxy:70".
7072 session_deps_
.proxy_service
.reset(
7073 ProxyService::CreateFixed("https://myproxy:70"));
7074 BoundTestNetLog log
;
7075 session_deps_
.net_log
= log
.bound().net_log();
7077 // Enable cross-origin push.
7078 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
7080 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7082 scoped_ptr
<SpdyFrame
> stream1_syn(
7083 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
7085 scoped_ptr
<SpdyFrame
> push_rst(
7086 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
7088 MockWrite spdy_writes
[] = {
7089 CreateMockWrite(*stream1_syn
, 0, ASYNC
), CreateMockWrite(*push_rst
, 3),
7092 scoped_ptr
<SpdyFrame
>
7093 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
7095 scoped_ptr
<SpdyFrame
>
7096 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
7098 scoped_ptr
<SpdyFrame
>
7099 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7103 "https://www.another-origin.com/foo.dat"));
7105 MockRead spdy_reads
[] = {
7106 CreateMockRead(*stream1_reply
, 1, ASYNC
),
7107 CreateMockRead(*stream2_syn
, 2, ASYNC
),
7108 CreateMockRead(*stream1_body
, 4, ASYNC
),
7109 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7112 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7113 arraysize(spdy_writes
));
7114 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7115 // Negotiate SPDY to the proxy
7116 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7117 proxy
.SetNextProto(GetParam());
7118 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7120 scoped_ptr
<HttpTransaction
> trans(
7121 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7122 TestCompletionCallback callback
;
7123 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7124 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7126 rv
= callback
.WaitForResult();
7128 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7130 ASSERT_TRUE(response
!= NULL
);
7131 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7133 EXPECT_EQ(200, response
->headers
->response_code());
7134 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7136 std::string response_data
;
7137 rv
= ReadTransaction(trans
.get(), &response_data
);
7139 EXPECT_EQ("hello!", response_data
);
7142 session
->CloseAllConnections();
7145 // Test HTTPS connections to a site with a bad certificate, going through an
7147 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7148 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7149 "https://proxy:70"));
7151 HttpRequestInfo request
;
7152 request
.method
= "GET";
7153 request
.url
= GURL("https://www.example.org/");
7154 request
.load_flags
= 0;
7156 // Attempt to fetch the URL from a server with a bad cert
7157 MockWrite bad_cert_writes
[] = {
7159 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7160 "Host: www.example.org\r\n"
7161 "Proxy-Connection: keep-alive\r\n\r\n"),
7164 MockRead bad_cert_reads
[] = {
7165 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7166 MockRead(SYNCHRONOUS
, OK
)
7169 // Attempt to fetch the URL with a good cert
7170 MockWrite good_data_writes
[] = {
7172 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7173 "Host: www.example.org\r\n"
7174 "Proxy-Connection: keep-alive\r\n\r\n"),
7176 "GET / HTTP/1.1\r\n"
7177 "Host: www.example.org\r\n"
7178 "Connection: keep-alive\r\n\r\n"),
7181 MockRead good_cert_reads
[] = {
7182 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7183 MockRead("HTTP/1.0 200 OK\r\n"),
7184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7185 MockRead("Content-Length: 100\r\n\r\n"),
7186 MockRead(SYNCHRONOUS
, OK
),
7189 StaticSocketDataProvider
ssl_bad_certificate(
7190 bad_cert_reads
, arraysize(bad_cert_reads
),
7191 bad_cert_writes
, arraysize(bad_cert_writes
));
7192 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7193 good_data_writes
, arraysize(good_data_writes
));
7194 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7195 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7197 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7198 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7199 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7200 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7202 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7203 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7204 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7205 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7207 TestCompletionCallback callback
;
7209 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7210 scoped_ptr
<HttpTransaction
> trans(
7211 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7213 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7214 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7216 rv
= callback
.WaitForResult();
7217 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7219 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7220 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7222 rv
= callback
.WaitForResult();
7225 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7227 ASSERT_TRUE(response
!= NULL
);
7228 EXPECT_EQ(100, response
->headers
->GetContentLength());
7231 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7232 HttpRequestInfo request
;
7233 request
.method
= "GET";
7234 request
.url
= GURL("http://www.example.org/");
7235 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7236 "Chromium Ultra Awesome X Edition");
7238 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7239 scoped_ptr
<HttpTransaction
> trans(
7240 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7242 MockWrite data_writes
[] = {
7244 "GET / HTTP/1.1\r\n"
7245 "Host: www.example.org\r\n"
7246 "Connection: keep-alive\r\n"
7247 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7250 // Lastly, the server responds with the actual content.
7251 MockRead data_reads
[] = {
7252 MockRead("HTTP/1.0 200 OK\r\n"),
7253 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7254 MockRead("Content-Length: 100\r\n\r\n"),
7255 MockRead(SYNCHRONOUS
, OK
),
7258 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7259 data_writes
, arraysize(data_writes
));
7260 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7262 TestCompletionCallback callback
;
7264 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7265 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7267 rv
= callback
.WaitForResult();
7271 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7272 HttpRequestInfo request
;
7273 request
.method
= "GET";
7274 request
.url
= GURL("https://www.example.org/");
7275 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7276 "Chromium Ultra Awesome X Edition");
7278 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7279 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7280 scoped_ptr
<HttpTransaction
> trans(
7281 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7283 MockWrite data_writes
[] = {
7285 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7286 "Host: www.example.org\r\n"
7287 "Proxy-Connection: keep-alive\r\n"
7288 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7290 MockRead data_reads
[] = {
7291 // Return an error, so the transaction stops here (this test isn't
7292 // interested in the rest).
7293 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7294 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7295 MockRead("Proxy-Connection: close\r\n\r\n"),
7298 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7299 data_writes
, arraysize(data_writes
));
7300 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7302 TestCompletionCallback callback
;
7304 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7305 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7307 rv
= callback
.WaitForResult();
7311 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7312 HttpRequestInfo request
;
7313 request
.method
= "GET";
7314 request
.url
= GURL("http://www.example.org/");
7315 request
.load_flags
= 0;
7316 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7317 "http://the.previous.site.com/");
7319 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7320 scoped_ptr
<HttpTransaction
> trans(
7321 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7323 MockWrite data_writes
[] = {
7325 "GET / HTTP/1.1\r\n"
7326 "Host: www.example.org\r\n"
7327 "Connection: keep-alive\r\n"
7328 "Referer: http://the.previous.site.com/\r\n\r\n"),
7331 // Lastly, the server responds with the actual content.
7332 MockRead data_reads
[] = {
7333 MockRead("HTTP/1.0 200 OK\r\n"),
7334 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7335 MockRead("Content-Length: 100\r\n\r\n"),
7336 MockRead(SYNCHRONOUS
, OK
),
7339 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7340 data_writes
, arraysize(data_writes
));
7341 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7343 TestCompletionCallback callback
;
7345 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7346 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7348 rv
= callback
.WaitForResult();
7352 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7353 HttpRequestInfo request
;
7354 request
.method
= "POST";
7355 request
.url
= GURL("http://www.example.org/");
7357 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7358 scoped_ptr
<HttpTransaction
> trans(
7359 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7361 MockWrite data_writes
[] = {
7363 "POST / HTTP/1.1\r\n"
7364 "Host: www.example.org\r\n"
7365 "Connection: keep-alive\r\n"
7366 "Content-Length: 0\r\n\r\n"),
7369 // Lastly, the server responds with the actual content.
7370 MockRead data_reads
[] = {
7371 MockRead("HTTP/1.0 200 OK\r\n"),
7372 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7373 MockRead("Content-Length: 100\r\n\r\n"),
7374 MockRead(SYNCHRONOUS
, OK
),
7377 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7378 data_writes
, arraysize(data_writes
));
7379 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7381 TestCompletionCallback callback
;
7383 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7384 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7386 rv
= callback
.WaitForResult();
7390 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7391 HttpRequestInfo request
;
7392 request
.method
= "PUT";
7393 request
.url
= GURL("http://www.example.org/");
7395 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7396 scoped_ptr
<HttpTransaction
> trans(
7397 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7399 MockWrite data_writes
[] = {
7401 "PUT / HTTP/1.1\r\n"
7402 "Host: www.example.org\r\n"
7403 "Connection: keep-alive\r\n"
7404 "Content-Length: 0\r\n\r\n"),
7407 // Lastly, the server responds with the actual content.
7408 MockRead data_reads
[] = {
7409 MockRead("HTTP/1.0 200 OK\r\n"),
7410 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7411 MockRead("Content-Length: 100\r\n\r\n"),
7412 MockRead(SYNCHRONOUS
, OK
),
7415 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7416 data_writes
, arraysize(data_writes
));
7417 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7419 TestCompletionCallback callback
;
7421 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7422 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7424 rv
= callback
.WaitForResult();
7428 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7429 HttpRequestInfo request
;
7430 request
.method
= "HEAD";
7431 request
.url
= GURL("http://www.example.org/");
7433 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7434 scoped_ptr
<HttpTransaction
> trans(
7435 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7437 MockWrite data_writes
[] = {
7438 MockWrite("HEAD / HTTP/1.1\r\n"
7439 "Host: www.example.org\r\n"
7440 "Connection: keep-alive\r\n\r\n"),
7443 // Lastly, the server responds with the actual content.
7444 MockRead data_reads
[] = {
7445 MockRead("HTTP/1.0 200 OK\r\n"),
7446 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7447 MockRead("Content-Length: 100\r\n\r\n"),
7448 MockRead(SYNCHRONOUS
, OK
),
7451 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7452 data_writes
, arraysize(data_writes
));
7453 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7455 TestCompletionCallback callback
;
7457 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7458 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7460 rv
= callback
.WaitForResult();
7464 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7465 HttpRequestInfo request
;
7466 request
.method
= "GET";
7467 request
.url
= GURL("http://www.example.org/");
7468 request
.load_flags
= LOAD_BYPASS_CACHE
;
7470 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7471 scoped_ptr
<HttpTransaction
> trans(
7472 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7474 MockWrite data_writes
[] = {
7476 "GET / HTTP/1.1\r\n"
7477 "Host: www.example.org\r\n"
7478 "Connection: keep-alive\r\n"
7479 "Pragma: no-cache\r\n"
7480 "Cache-Control: no-cache\r\n\r\n"),
7483 // Lastly, the server responds with the actual content.
7484 MockRead data_reads
[] = {
7485 MockRead("HTTP/1.0 200 OK\r\n"),
7486 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7487 MockRead("Content-Length: 100\r\n\r\n"),
7488 MockRead(SYNCHRONOUS
, OK
),
7491 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7492 data_writes
, arraysize(data_writes
));
7493 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7495 TestCompletionCallback callback
;
7497 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7498 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7500 rv
= callback
.WaitForResult();
7504 TEST_P(HttpNetworkTransactionTest
,
7505 BuildRequest_CacheControlValidateCache
) {
7506 HttpRequestInfo request
;
7507 request
.method
= "GET";
7508 request
.url
= GURL("http://www.example.org/");
7509 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7511 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7512 scoped_ptr
<HttpTransaction
> trans(
7513 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7515 MockWrite data_writes
[] = {
7517 "GET / HTTP/1.1\r\n"
7518 "Host: www.example.org\r\n"
7519 "Connection: keep-alive\r\n"
7520 "Cache-Control: max-age=0\r\n\r\n"),
7523 // Lastly, the server responds with the actual content.
7524 MockRead data_reads
[] = {
7525 MockRead("HTTP/1.0 200 OK\r\n"),
7526 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7527 MockRead("Content-Length: 100\r\n\r\n"),
7528 MockRead(SYNCHRONOUS
, OK
),
7531 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7532 data_writes
, arraysize(data_writes
));
7533 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7535 TestCompletionCallback callback
;
7537 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7538 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7540 rv
= callback
.WaitForResult();
7544 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7545 HttpRequestInfo request
;
7546 request
.method
= "GET";
7547 request
.url
= GURL("http://www.example.org/");
7548 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7550 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7551 scoped_ptr
<HttpTransaction
> trans(
7552 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7554 MockWrite data_writes
[] = {
7556 "GET / HTTP/1.1\r\n"
7557 "Host: www.example.org\r\n"
7558 "Connection: keep-alive\r\n"
7559 "FooHeader: Bar\r\n\r\n"),
7562 // Lastly, the server responds with the actual content.
7563 MockRead data_reads
[] = {
7564 MockRead("HTTP/1.0 200 OK\r\n"),
7565 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7566 MockRead("Content-Length: 100\r\n\r\n"),
7567 MockRead(SYNCHRONOUS
, OK
),
7570 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7571 data_writes
, arraysize(data_writes
));
7572 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7574 TestCompletionCallback callback
;
7576 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7577 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7579 rv
= callback
.WaitForResult();
7583 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7584 HttpRequestInfo request
;
7585 request
.method
= "GET";
7586 request
.url
= GURL("http://www.example.org/");
7587 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7588 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7589 request
.extra_headers
.SetHeader("FoO", "bar");
7591 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7592 scoped_ptr
<HttpTransaction
> trans(
7593 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7595 MockWrite data_writes
[] = {
7597 "GET / HTTP/1.1\r\n"
7598 "Host: www.example.org\r\n"
7599 "Connection: keep-alive\r\n"
7600 "referer: www.foo.com\r\n"
7602 "FoO: bar\r\n\r\n"),
7605 // Lastly, the server responds with the actual content.
7606 MockRead data_reads
[] = {
7607 MockRead("HTTP/1.0 200 OK\r\n"),
7608 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7609 MockRead("Content-Length: 100\r\n\r\n"),
7610 MockRead(SYNCHRONOUS
, OK
),
7613 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7614 data_writes
, arraysize(data_writes
));
7615 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7617 TestCompletionCallback callback
;
7619 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7620 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7622 rv
= callback
.WaitForResult();
7626 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7627 HttpRequestInfo request
;
7628 request
.method
= "GET";
7629 request
.url
= GURL("http://www.example.org/");
7630 request
.load_flags
= 0;
7632 session_deps_
.proxy_service
.reset(
7633 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7635 session_deps_
.net_log
= &net_log
;
7637 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7638 scoped_ptr
<HttpTransaction
> trans(
7639 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7641 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7642 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7644 MockWrite data_writes
[] = {
7645 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7647 "GET / HTTP/1.1\r\n"
7648 "Host: www.example.org\r\n"
7649 "Connection: keep-alive\r\n\r\n")};
7651 MockRead data_reads
[] = {
7652 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7653 MockRead("HTTP/1.0 200 OK\r\n"),
7654 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7655 MockRead("Payload"),
7656 MockRead(SYNCHRONOUS
, OK
)
7659 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7660 data_writes
, arraysize(data_writes
));
7661 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7663 TestCompletionCallback callback
;
7665 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7666 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7668 rv
= callback
.WaitForResult();
7671 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7672 ASSERT_TRUE(response
!= NULL
);
7674 LoadTimingInfo load_timing_info
;
7675 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7676 TestLoadTimingNotReusedWithPac(load_timing_info
,
7677 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7679 std::string response_text
;
7680 rv
= ReadTransaction(trans
.get(), &response_text
);
7682 EXPECT_EQ("Payload", response_text
);
7685 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7686 HttpRequestInfo request
;
7687 request
.method
= "GET";
7688 request
.url
= GURL("https://www.example.org/");
7689 request
.load_flags
= 0;
7691 session_deps_
.proxy_service
.reset(
7692 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7694 session_deps_
.net_log
= &net_log
;
7696 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7697 scoped_ptr
<HttpTransaction
> trans(
7698 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7700 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7701 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7703 MockWrite data_writes
[] = {
7704 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7705 arraysize(write_buffer
)),
7707 "GET / HTTP/1.1\r\n"
7708 "Host: www.example.org\r\n"
7709 "Connection: keep-alive\r\n\r\n")};
7711 MockRead data_reads
[] = {
7712 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7713 arraysize(read_buffer
)),
7714 MockRead("HTTP/1.0 200 OK\r\n"),
7715 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7716 MockRead("Payload"),
7717 MockRead(SYNCHRONOUS
, OK
)
7720 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7721 data_writes
, arraysize(data_writes
));
7722 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7724 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7725 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7727 TestCompletionCallback callback
;
7729 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7730 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7732 rv
= callback
.WaitForResult();
7735 LoadTimingInfo load_timing_info
;
7736 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7737 TestLoadTimingNotReusedWithPac(load_timing_info
,
7738 CONNECT_TIMING_HAS_SSL_TIMES
);
7740 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7741 ASSERT_TRUE(response
!= NULL
);
7743 std::string response_text
;
7744 rv
= ReadTransaction(trans
.get(), &response_text
);
7746 EXPECT_EQ("Payload", response_text
);
7749 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7750 HttpRequestInfo request
;
7751 request
.method
= "GET";
7752 request
.url
= GURL("http://www.example.org/");
7753 request
.load_flags
= 0;
7755 session_deps_
.proxy_service
.reset(
7756 ProxyService::CreateFixed("socks4://myproxy:1080"));
7758 session_deps_
.net_log
= &net_log
;
7760 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7761 scoped_ptr
<HttpTransaction
> trans(
7762 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7764 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7765 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7767 MockWrite data_writes
[] = {
7768 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7770 "GET / HTTP/1.1\r\n"
7771 "Host: www.example.org\r\n"
7772 "Connection: keep-alive\r\n\r\n")};
7774 MockRead data_reads
[] = {
7775 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7776 MockRead("HTTP/1.0 200 OK\r\n"),
7777 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7778 MockRead("Payload"),
7779 MockRead(SYNCHRONOUS
, OK
)
7782 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7783 data_writes
, arraysize(data_writes
));
7784 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7786 TestCompletionCallback callback
;
7788 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7789 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7791 rv
= callback
.WaitForResult();
7794 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7795 ASSERT_TRUE(response
!= NULL
);
7797 LoadTimingInfo load_timing_info
;
7798 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7799 TestLoadTimingNotReused(load_timing_info
,
7800 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7802 std::string response_text
;
7803 rv
= ReadTransaction(trans
.get(), &response_text
);
7805 EXPECT_EQ("Payload", response_text
);
7808 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7809 HttpRequestInfo request
;
7810 request
.method
= "GET";
7811 request
.url
= GURL("http://www.example.org/");
7812 request
.load_flags
= 0;
7814 session_deps_
.proxy_service
.reset(
7815 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7817 session_deps_
.net_log
= &net_log
;
7819 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7820 scoped_ptr
<HttpTransaction
> trans(
7821 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7823 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7824 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7825 const char kSOCKS5OkRequest
[] = {
7827 0x01, // Command (CONNECT)
7829 0x03, // Address type (DOMAINNAME).
7830 0x0F, // Length of domain (15)
7831 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7832 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7834 const char kSOCKS5OkResponse
[] =
7835 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7837 MockWrite data_writes
[] = {
7838 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7839 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7841 "GET / HTTP/1.1\r\n"
7842 "Host: www.example.org\r\n"
7843 "Connection: keep-alive\r\n\r\n")};
7845 MockRead data_reads
[] = {
7846 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7847 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7848 MockRead("HTTP/1.0 200 OK\r\n"),
7849 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7850 MockRead("Payload"),
7851 MockRead(SYNCHRONOUS
, OK
)
7854 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7855 data_writes
, arraysize(data_writes
));
7856 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7858 TestCompletionCallback callback
;
7860 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7861 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7863 rv
= callback
.WaitForResult();
7866 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7867 ASSERT_TRUE(response
!= NULL
);
7869 LoadTimingInfo load_timing_info
;
7870 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7871 TestLoadTimingNotReusedWithPac(load_timing_info
,
7872 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7874 std::string response_text
;
7875 rv
= ReadTransaction(trans
.get(), &response_text
);
7877 EXPECT_EQ("Payload", response_text
);
7880 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7881 HttpRequestInfo request
;
7882 request
.method
= "GET";
7883 request
.url
= GURL("https://www.example.org/");
7884 request
.load_flags
= 0;
7886 session_deps_
.proxy_service
.reset(
7887 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7889 session_deps_
.net_log
= &net_log
;
7891 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7892 scoped_ptr
<HttpTransaction
> trans(
7893 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7895 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7896 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7897 const unsigned char kSOCKS5OkRequest
[] = {
7899 0x01, // Command (CONNECT)
7901 0x03, // Address type (DOMAINNAME).
7902 0x0F, // Length of domain (15)
7903 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7904 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7907 const char kSOCKS5OkResponse
[] =
7908 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7910 MockWrite data_writes
[] = {
7911 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7912 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7913 arraysize(kSOCKS5OkRequest
)),
7915 "GET / HTTP/1.1\r\n"
7916 "Host: www.example.org\r\n"
7917 "Connection: keep-alive\r\n\r\n")};
7919 MockRead data_reads
[] = {
7920 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7921 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7922 MockRead("HTTP/1.0 200 OK\r\n"),
7923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7924 MockRead("Payload"),
7925 MockRead(SYNCHRONOUS
, OK
)
7928 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7929 data_writes
, arraysize(data_writes
));
7930 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7932 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7933 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7935 TestCompletionCallback callback
;
7937 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7938 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7940 rv
= callback
.WaitForResult();
7943 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7944 ASSERT_TRUE(response
!= NULL
);
7946 LoadTimingInfo load_timing_info
;
7947 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7948 TestLoadTimingNotReusedWithPac(load_timing_info
,
7949 CONNECT_TIMING_HAS_SSL_TIMES
);
7951 std::string response_text
;
7952 rv
= ReadTransaction(trans
.get(), &response_text
);
7954 EXPECT_EQ("Payload", response_text
);
7959 // Tests that for connection endpoints the group names are correctly set.
7961 struct GroupNameTest
{
7962 std::string proxy_server
;
7964 std::string expected_group_name
;
7968 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7969 NextProto next_proto
,
7970 SpdySessionDependencies
* session_deps_
) {
7971 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7973 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7974 session
->http_server_properties();
7975 AlternativeService
alternative_service(
7976 AlternateProtocolFromNextProto(next_proto
), "", 443);
7977 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
7978 http_server_properties
->SetAlternativeService(
7979 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0,
7985 int GroupNameTransactionHelper(
7986 const std::string
& url
,
7987 const scoped_refptr
<HttpNetworkSession
>& session
) {
7988 HttpRequestInfo request
;
7989 request
.method
= "GET";
7990 request
.url
= GURL(url
);
7991 request
.load_flags
= 0;
7993 scoped_ptr
<HttpTransaction
> trans(
7994 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7996 TestCompletionCallback callback
;
7998 // We do not complete this request, the dtor will clean the transaction up.
7999 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
8004 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
8005 const GroupNameTest tests
[] = {
8008 "http://www.example.org/direct",
8009 "www.example.org:80",
8014 "http://[2001:1418:13:1::25]/direct",
8015 "[2001:1418:13:1::25]:80",
8022 "https://www.example.org/direct_ssl",
8023 "ssl/www.example.org:443",
8028 "https://[2001:1418:13:1::25]/direct",
8029 "ssl/[2001:1418:13:1::25]:443",
8034 "http://host.with.alternate/direct",
8035 "ssl/host.with.alternate:443",
8040 session_deps_
.use_alternative_services
= true;
8042 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8043 session_deps_
.proxy_service
.reset(
8044 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8045 scoped_refptr
<HttpNetworkSession
> session(
8046 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8048 HttpNetworkSessionPeer
peer(session
);
8049 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
8050 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
8051 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8052 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8053 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8054 new MockClientSocketPoolManager
);
8055 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
8056 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
8057 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8059 EXPECT_EQ(ERR_IO_PENDING
,
8060 GroupNameTransactionHelper(tests
[i
].url
, session
));
8062 EXPECT_EQ(tests
[i
].expected_group_name
,
8063 ssl_conn_pool
->last_group_name_received());
8065 EXPECT_EQ(tests
[i
].expected_group_name
,
8066 transport_conn_pool
->last_group_name_received());
8070 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
8071 const GroupNameTest tests
[] = {
8074 "http://www.example.org/http_proxy_normal",
8075 "www.example.org:80",
8082 "https://www.example.org/http_connect_ssl",
8083 "ssl/www.example.org:443",
8089 "http://host.with.alternate/direct",
8090 "ssl/host.with.alternate:443",
8096 "ftp://ftp.google.com/http_proxy_normal",
8097 "ftp/ftp.google.com:21",
8102 session_deps_
.use_alternative_services
= true;
8104 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8105 session_deps_
.proxy_service
.reset(
8106 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8107 scoped_refptr
<HttpNetworkSession
> session(
8108 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8110 HttpNetworkSessionPeer
peer(session
);
8112 HostPortPair
proxy_host("http_proxy", 80);
8113 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8114 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8115 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8116 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8118 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8119 new MockClientSocketPoolManager
);
8120 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8121 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8122 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8124 EXPECT_EQ(ERR_IO_PENDING
,
8125 GroupNameTransactionHelper(tests
[i
].url
, session
));
8127 EXPECT_EQ(tests
[i
].expected_group_name
,
8128 ssl_conn_pool
->last_group_name_received());
8130 EXPECT_EQ(tests
[i
].expected_group_name
,
8131 http_proxy_pool
->last_group_name_received());
8135 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8136 const GroupNameTest tests
[] = {
8138 "socks4://socks_proxy:1080",
8139 "http://www.example.org/socks4_direct",
8140 "socks4/www.example.org:80",
8144 "socks5://socks_proxy:1080",
8145 "http://www.example.org/socks5_direct",
8146 "socks5/www.example.org:80",
8152 "socks4://socks_proxy:1080",
8153 "https://www.example.org/socks4_ssl",
8154 "socks4/ssl/www.example.org:443",
8158 "socks5://socks_proxy:1080",
8159 "https://www.example.org/socks5_ssl",
8160 "socks5/ssl/www.example.org:443",
8165 "socks4://socks_proxy:1080",
8166 "http://host.with.alternate/direct",
8167 "socks4/ssl/host.with.alternate:443",
8172 session_deps_
.use_alternative_services
= true;
8174 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8175 session_deps_
.proxy_service
.reset(
8176 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8177 scoped_refptr
<HttpNetworkSession
> session(
8178 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8180 HttpNetworkSessionPeer
peer(session
);
8182 HostPortPair
proxy_host("socks_proxy", 1080);
8183 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8184 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8185 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8186 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8188 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8189 new MockClientSocketPoolManager
);
8190 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8191 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8192 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8194 scoped_ptr
<HttpTransaction
> trans(
8195 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8197 EXPECT_EQ(ERR_IO_PENDING
,
8198 GroupNameTransactionHelper(tests
[i
].url
, session
));
8200 EXPECT_EQ(tests
[i
].expected_group_name
,
8201 ssl_conn_pool
->last_group_name_received());
8203 EXPECT_EQ(tests
[i
].expected_group_name
,
8204 socks_conn_pool
->last_group_name_received());
8208 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8209 HttpRequestInfo request
;
8210 request
.method
= "GET";
8211 request
.url
= GURL("http://www.example.org/");
8213 session_deps_
.proxy_service
.reset(
8214 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8216 // This simulates failure resolving all hostnames; that means we will fail
8217 // connecting to both proxies (myproxy:70 and foobar:80).
8218 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8220 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8221 scoped_ptr
<HttpTransaction
> trans(
8222 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8224 TestCompletionCallback callback
;
8226 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8229 rv
= callback
.WaitForResult();
8230 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8233 // Base test to make sure that when the load flags for a request specify to
8234 // bypass the cache, the DNS cache is not used.
8235 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8237 // Issue a request, asking to bypass the cache(s).
8238 HttpRequestInfo request
;
8239 request
.method
= "GET";
8240 request
.load_flags
= load_flags
;
8241 request
.url
= GURL("http://www.example.org/");
8243 // Select a host resolver that does caching.
8244 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8246 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8247 scoped_ptr
<HttpTransaction
> trans(
8248 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8250 // Warm up the host cache so it has an entry for "www.example.org".
8251 AddressList addrlist
;
8252 TestCompletionCallback callback
;
8253 int rv
= session_deps_
.host_resolver
->Resolve(
8254 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8255 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8257 rv
= callback
.WaitForResult();
8260 // Verify that it was added to host cache, by doing a subsequent async lookup
8261 // and confirming it completes synchronously.
8262 rv
= session_deps_
.host_resolver
->Resolve(
8263 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8264 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8267 // Inject a failure the next time that "www.example.org" is resolved. This way
8268 // we can tell if the next lookup hit the cache, or the "network".
8269 // (cache --> success, "network" --> failure).
8270 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8272 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8273 // first read -- this won't be reached as the host resolution will fail first.
8274 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8275 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8276 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8279 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8280 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8281 rv
= callback
.WaitForResult();
8283 // If we bypassed the cache, we would have gotten a failure while resolving
8284 // "www.example.org".
8285 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8288 // There are multiple load flags that should trigger the host cache bypass.
8289 // Test each in isolation:
8290 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8291 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8294 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8295 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8298 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8299 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8302 // Make sure we can handle an error when writing the request.
8303 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8304 HttpRequestInfo request
;
8305 request
.method
= "GET";
8306 request
.url
= GURL("http://www.foo.com/");
8307 request
.load_flags
= 0;
8309 MockWrite write_failure
[] = {
8310 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8312 StaticSocketDataProvider
data(NULL
, 0,
8313 write_failure
, arraysize(write_failure
));
8314 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8315 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8317 TestCompletionCallback callback
;
8319 scoped_ptr
<HttpTransaction
> trans(
8320 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8322 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8323 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8325 rv
= callback
.WaitForResult();
8326 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8329 // Check that a connection closed after the start of the headers finishes ok.
8330 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8331 HttpRequestInfo request
;
8332 request
.method
= "GET";
8333 request
.url
= GURL("http://www.foo.com/");
8334 request
.load_flags
= 0;
8336 MockRead data_reads
[] = {
8337 MockRead("HTTP/1."),
8338 MockRead(SYNCHRONOUS
, OK
),
8341 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8342 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8343 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8345 TestCompletionCallback callback
;
8347 scoped_ptr
<HttpTransaction
> trans(
8348 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8350 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8351 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8353 rv
= callback
.WaitForResult();
8356 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8357 ASSERT_TRUE(response
!= NULL
);
8359 EXPECT_TRUE(response
->headers
.get() != NULL
);
8360 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8362 std::string response_data
;
8363 rv
= ReadTransaction(trans
.get(), &response_data
);
8365 EXPECT_EQ("", response_data
);
8368 // Make sure that a dropped connection while draining the body for auth
8369 // restart does the right thing.
8370 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8371 HttpRequestInfo request
;
8372 request
.method
= "GET";
8373 request
.url
= GURL("http://www.example.org/");
8374 request
.load_flags
= 0;
8376 MockWrite data_writes1
[] = {
8378 "GET / HTTP/1.1\r\n"
8379 "Host: www.example.org\r\n"
8380 "Connection: keep-alive\r\n\r\n"),
8383 MockRead data_reads1
[] = {
8384 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8385 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8386 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8387 MockRead("Content-Length: 14\r\n\r\n"),
8389 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8392 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8393 data_writes1
, arraysize(data_writes1
));
8394 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8396 // After calling trans->RestartWithAuth(), this is the request we should
8397 // be issuing -- the final header line contains the credentials.
8398 MockWrite data_writes2
[] = {
8400 "GET / HTTP/1.1\r\n"
8401 "Host: www.example.org\r\n"
8402 "Connection: keep-alive\r\n"
8403 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8406 // Lastly, the server responds with the actual content.
8407 MockRead data_reads2
[] = {
8408 MockRead("HTTP/1.1 200 OK\r\n"),
8409 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8410 MockRead("Content-Length: 100\r\n\r\n"),
8411 MockRead(SYNCHRONOUS
, OK
),
8414 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8415 data_writes2
, arraysize(data_writes2
));
8416 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8417 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8419 TestCompletionCallback callback1
;
8421 scoped_ptr
<HttpTransaction
> trans(
8422 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8424 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8425 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8427 rv
= callback1
.WaitForResult();
8430 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8431 ASSERT_TRUE(response
!= NULL
);
8432 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8434 TestCompletionCallback callback2
;
8436 rv
= trans
->RestartWithAuth(
8437 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8438 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8440 rv
= callback2
.WaitForResult();
8443 response
= trans
->GetResponseInfo();
8444 ASSERT_TRUE(response
!= NULL
);
8445 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8446 EXPECT_EQ(100, response
->headers
->GetContentLength());
8449 // Test HTTPS connections going through a proxy that sends extra data.
8450 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8451 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8453 HttpRequestInfo request
;
8454 request
.method
= "GET";
8455 request
.url
= GURL("https://www.example.org/");
8456 request
.load_flags
= 0;
8458 MockRead proxy_reads
[] = {
8459 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8460 MockRead(SYNCHRONOUS
, OK
)
8463 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8464 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8466 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8467 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8469 TestCompletionCallback callback
;
8471 session_deps_
.socket_factory
->ResetNextMockIndexes();
8473 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8474 scoped_ptr
<HttpTransaction
> trans(
8475 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8477 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8478 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8480 rv
= callback
.WaitForResult();
8481 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8484 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8485 HttpRequestInfo request
;
8486 request
.method
= "GET";
8487 request
.url
= GURL("http://www.example.org/");
8488 request
.load_flags
= 0;
8490 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8491 scoped_ptr
<HttpTransaction
> trans(
8492 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8494 MockRead data_reads
[] = {
8495 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8496 MockRead(SYNCHRONOUS
, OK
),
8499 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8500 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8502 TestCompletionCallback callback
;
8504 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8505 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8507 EXPECT_EQ(OK
, callback
.WaitForResult());
8509 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8510 ASSERT_TRUE(response
!= NULL
);
8512 EXPECT_TRUE(response
->headers
.get() != NULL
);
8513 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8515 std::string response_data
;
8516 rv
= ReadTransaction(trans
.get(), &response_data
);
8517 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8520 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8521 base::FilePath temp_file_path
;
8522 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8523 const uint64 kFakeSize
= 100000; // file is actually blank
8524 UploadFileElementReader::ScopedOverridingContentLengthForTests
8525 overriding_content_length(kFakeSize
);
8527 ScopedVector
<UploadElementReader
> element_readers
;
8528 element_readers
.push_back(
8529 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8530 temp_file_path
, 0, kuint64max
, base::Time()));
8531 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8533 HttpRequestInfo request
;
8534 request
.method
= "POST";
8535 request
.url
= GURL("http://www.example.org/upload");
8536 request
.upload_data_stream
= &upload_data_stream
;
8537 request
.load_flags
= 0;
8539 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8540 scoped_ptr
<HttpTransaction
> trans(
8541 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8543 MockRead data_reads
[] = {
8544 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8545 MockRead("hello world"),
8546 MockRead(SYNCHRONOUS
, OK
),
8548 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8549 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8551 TestCompletionCallback callback
;
8553 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8554 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8556 rv
= callback
.WaitForResult();
8559 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8560 ASSERT_TRUE(response
!= NULL
);
8562 EXPECT_TRUE(response
->headers
.get() != NULL
);
8563 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8565 std::string response_data
;
8566 rv
= ReadTransaction(trans
.get(), &response_data
);
8568 EXPECT_EQ("hello world", response_data
);
8570 base::DeleteFile(temp_file_path
, false);
8573 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8574 base::FilePath temp_file
;
8575 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8576 std::string
temp_file_content("Unreadable file.");
8577 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8578 temp_file_content
.length()));
8579 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8581 ScopedVector
<UploadElementReader
> element_readers
;
8582 element_readers
.push_back(
8583 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8584 temp_file
, 0, kuint64max
, base::Time()));
8585 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8587 HttpRequestInfo request
;
8588 request
.method
= "POST";
8589 request
.url
= GURL("http://www.example.org/upload");
8590 request
.upload_data_stream
= &upload_data_stream
;
8591 request
.load_flags
= 0;
8593 // If we try to upload an unreadable file, the transaction should fail.
8594 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8595 scoped_ptr
<HttpTransaction
> trans(
8596 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8598 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8599 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8601 TestCompletionCallback callback
;
8603 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8604 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8606 rv
= callback
.WaitForResult();
8607 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8609 base::DeleteFile(temp_file
, false);
8612 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8613 class FakeUploadElementReader
: public UploadElementReader
{
8615 FakeUploadElementReader() {}
8616 ~FakeUploadElementReader() override
{}
8618 const CompletionCallback
& callback() const { return callback_
; }
8620 // UploadElementReader overrides:
8621 int Init(const CompletionCallback
& callback
) override
{
8622 callback_
= callback
;
8623 return ERR_IO_PENDING
;
8625 uint64
GetContentLength() const override
{ return 0; }
8626 uint64
BytesRemaining() const override
{ return 0; }
8627 int Read(IOBuffer
* buf
,
8629 const CompletionCallback
& callback
) override
{
8634 CompletionCallback callback_
;
8637 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8638 ScopedVector
<UploadElementReader
> element_readers
;
8639 element_readers
.push_back(fake_reader
);
8640 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8642 HttpRequestInfo request
;
8643 request
.method
= "POST";
8644 request
.url
= GURL("http://www.example.org/upload");
8645 request
.upload_data_stream
= &upload_data_stream
;
8646 request
.load_flags
= 0;
8648 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8649 scoped_ptr
<HttpTransaction
> trans(
8650 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8652 StaticSocketDataProvider data
;
8653 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8655 TestCompletionCallback callback
;
8656 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8657 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8658 base::MessageLoop::current()->RunUntilIdle();
8660 // Transaction is pending on request body initialization.
8661 ASSERT_FALSE(fake_reader
->callback().is_null());
8663 // Return Init()'s result after the transaction gets destroyed.
8665 fake_reader
->callback().Run(OK
); // Should not crash.
8668 // Tests that changes to Auth realms are treated like auth rejections.
8669 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8670 HttpRequestInfo request
;
8671 request
.method
= "GET";
8672 request
.url
= GURL("http://www.example.org/");
8673 request
.load_flags
= 0;
8675 // First transaction will request a resource and receive a Basic challenge
8676 // with realm="first_realm".
8677 MockWrite data_writes1
[] = {
8679 "GET / HTTP/1.1\r\n"
8680 "Host: www.example.org\r\n"
8681 "Connection: keep-alive\r\n"
8684 MockRead data_reads1
[] = {
8685 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8686 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8690 // After calling trans->RestartWithAuth(), provide an Authentication header
8691 // for first_realm. The server will reject and provide a challenge with
8693 MockWrite data_writes2
[] = {
8695 "GET / HTTP/1.1\r\n"
8696 "Host: www.example.org\r\n"
8697 "Connection: keep-alive\r\n"
8698 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8701 MockRead data_reads2
[] = {
8702 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8703 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8707 // This again fails, and goes back to first_realm. Make sure that the
8708 // entry is removed from cache.
8709 MockWrite data_writes3
[] = {
8711 "GET / HTTP/1.1\r\n"
8712 "Host: www.example.org\r\n"
8713 "Connection: keep-alive\r\n"
8714 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8717 MockRead data_reads3
[] = {
8718 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8719 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8723 // Try one last time (with the correct password) and get the resource.
8724 MockWrite data_writes4
[] = {
8726 "GET / HTTP/1.1\r\n"
8727 "Host: www.example.org\r\n"
8728 "Connection: keep-alive\r\n"
8729 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8732 MockRead data_reads4
[] = {
8733 MockRead("HTTP/1.1 200 OK\r\n"
8734 "Content-Type: text/html; charset=iso-8859-1\r\n"
8735 "Content-Length: 5\r\n"
8740 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8741 data_writes1
, arraysize(data_writes1
));
8742 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8743 data_writes2
, arraysize(data_writes2
));
8744 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8745 data_writes3
, arraysize(data_writes3
));
8746 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8747 data_writes4
, arraysize(data_writes4
));
8748 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8749 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8750 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8751 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8753 TestCompletionCallback callback1
;
8755 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8756 scoped_ptr
<HttpTransaction
> trans(
8757 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8759 // Issue the first request with Authorize headers. There should be a
8760 // password prompt for first_realm waiting to be filled in after the
8761 // transaction completes.
8762 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8763 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8764 rv
= callback1
.WaitForResult();
8766 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8767 ASSERT_TRUE(response
!= NULL
);
8768 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8769 ASSERT_FALSE(challenge
== NULL
);
8770 EXPECT_FALSE(challenge
->is_proxy
);
8771 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8772 EXPECT_EQ("first_realm", challenge
->realm
);
8773 EXPECT_EQ("basic", challenge
->scheme
);
8775 // Issue the second request with an incorrect password. There should be a
8776 // password prompt for second_realm waiting to be filled in after the
8777 // transaction completes.
8778 TestCompletionCallback callback2
;
8779 rv
= trans
->RestartWithAuth(
8780 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8781 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8782 rv
= callback2
.WaitForResult();
8784 response
= trans
->GetResponseInfo();
8785 ASSERT_TRUE(response
!= NULL
);
8786 challenge
= response
->auth_challenge
.get();
8787 ASSERT_FALSE(challenge
== NULL
);
8788 EXPECT_FALSE(challenge
->is_proxy
);
8789 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8790 EXPECT_EQ("second_realm", challenge
->realm
);
8791 EXPECT_EQ("basic", challenge
->scheme
);
8793 // Issue the third request with another incorrect password. There should be
8794 // a password prompt for first_realm waiting to be filled in. If the password
8795 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8796 // first_realm was not correctly removed.
8797 TestCompletionCallback callback3
;
8798 rv
= trans
->RestartWithAuth(
8799 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8800 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8801 rv
= callback3
.WaitForResult();
8803 response
= trans
->GetResponseInfo();
8804 ASSERT_TRUE(response
!= NULL
);
8805 challenge
= response
->auth_challenge
.get();
8806 ASSERT_FALSE(challenge
== NULL
);
8807 EXPECT_FALSE(challenge
->is_proxy
);
8808 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8809 EXPECT_EQ("first_realm", challenge
->realm
);
8810 EXPECT_EQ("basic", challenge
->scheme
);
8812 // Issue the fourth request with the correct password and username.
8813 TestCompletionCallback callback4
;
8814 rv
= trans
->RestartWithAuth(
8815 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8816 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8817 rv
= callback4
.WaitForResult();
8819 response
= trans
->GetResponseInfo();
8820 ASSERT_TRUE(response
!= NULL
);
8821 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8824 TEST_P(HttpNetworkTransactionTest
, HonorAlternativeServiceHeader
) {
8825 session_deps_
.next_protos
= SpdyNextProtos();
8826 session_deps_
.use_alternative_services
= true;
8828 std::string alternative_service_http_header
=
8829 GetAlternativeServiceHttpHeader();
8831 MockRead data_reads
[] = {
8832 MockRead("HTTP/1.1 200 OK\r\n"),
8833 MockRead(alternative_service_http_header
.c_str()),
8835 MockRead("hello world"),
8836 MockRead(SYNCHRONOUS
, OK
),
8839 HttpRequestInfo request
;
8840 request
.method
= "GET";
8841 request
.url
= GURL("http://www.example.org/");
8842 request
.load_flags
= 0;
8844 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8846 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8848 TestCompletionCallback callback
;
8850 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8851 scoped_ptr
<HttpTransaction
> trans(
8852 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8854 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8855 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8857 HostPortPair
http_host_port_pair("www.example.org", 80);
8858 HttpServerProperties
& http_server_properties
=
8859 *session
->http_server_properties();
8860 AlternativeServiceVector alternative_service_vector
=
8861 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8862 EXPECT_TRUE(alternative_service_vector
.empty());
8864 EXPECT_EQ(OK
, callback
.WaitForResult());
8866 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8867 ASSERT_TRUE(response
!= NULL
);
8868 ASSERT_TRUE(response
->headers
.get() != NULL
);
8869 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8870 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8871 EXPECT_FALSE(response
->was_npn_negotiated
);
8873 std::string response_data
;
8874 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8875 EXPECT_EQ("hello world", response_data
);
8877 alternative_service_vector
=
8878 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8879 ASSERT_EQ(1u, alternative_service_vector
.size());
8880 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8881 alternative_service_vector
[0].protocol
);
8882 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
8883 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8886 // Alternative Service headers must be ignored when |use_alternative_services|
8888 TEST_P(HttpNetworkTransactionTest
, DoNotHonorAlternativeServiceHeader
) {
8889 session_deps_
.next_protos
= SpdyNextProtos();
8890 session_deps_
.use_alternative_services
= false;
8892 std::string alternative_service_http_header
=
8893 GetAlternativeServiceHttpHeader();
8895 MockRead data_reads
[] = {
8896 MockRead("HTTP/1.1 200 OK\r\n"),
8897 MockRead(alternative_service_http_header
.c_str()),
8899 MockRead("hello world"),
8900 MockRead(SYNCHRONOUS
, OK
),
8903 HttpRequestInfo request
;
8904 request
.method
= "GET";
8905 request
.url
= GURL("http://www.example.org/");
8906 request
.load_flags
= 0;
8908 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), nullptr, 0);
8910 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8912 TestCompletionCallback callback
;
8914 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8915 scoped_ptr
<HttpTransaction
> trans(
8916 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8918 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8919 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8921 HostPortPair
http_host_port_pair("www.example.org", 80);
8922 HttpServerProperties
& http_server_properties
=
8923 *session
->http_server_properties();
8924 AlternativeServiceVector alternative_service_vector
=
8925 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8926 EXPECT_TRUE(alternative_service_vector
.empty());
8928 EXPECT_EQ(OK
, callback
.WaitForResult());
8930 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8931 ASSERT_TRUE(response
!= nullptr);
8932 ASSERT_TRUE(response
->headers
.get() != nullptr);
8933 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8934 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8935 EXPECT_FALSE(response
->was_npn_negotiated
);
8937 std::string response_data
;
8938 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8939 EXPECT_EQ("hello world", response_data
);
8941 alternative_service_vector
=
8942 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8943 EXPECT_TRUE(alternative_service_vector
.empty());
8946 TEST_P(HttpNetworkTransactionTest
, HonorMultipleAlternativeServiceHeader
) {
8947 session_deps_
.next_protos
= SpdyNextProtos();
8948 session_deps_
.use_alternative_services
= true;
8950 MockRead data_reads
[] = {
8951 MockRead("HTTP/1.1 200 OK\r\n"),
8952 MockRead("Alt-Svc: "),
8953 MockRead(GetAlternateProtocolFromParam()),
8954 MockRead("=\"www.example.com:443\";p=1.0,"),
8955 MockRead("quic=\":1234\"\r\n\r\n"),
8956 MockRead("hello world"),
8957 MockRead(SYNCHRONOUS
, OK
),
8960 HttpRequestInfo request
;
8961 request
.method
= "GET";
8962 request
.url
= GURL("http://www.example.org/");
8963 request
.load_flags
= 0;
8965 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8967 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8969 TestCompletionCallback callback
;
8971 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8972 scoped_ptr
<HttpTransaction
> trans(
8973 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8975 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8976 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8978 HostPortPair
http_host_port_pair("www.example.org", 80);
8979 HttpServerProperties
& http_server_properties
=
8980 *session
->http_server_properties();
8981 AlternativeServiceVector alternative_service_vector
=
8982 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8983 EXPECT_TRUE(alternative_service_vector
.empty());
8985 EXPECT_EQ(OK
, callback
.WaitForResult());
8987 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8988 ASSERT_TRUE(response
!= NULL
);
8989 ASSERT_TRUE(response
->headers
.get() != NULL
);
8990 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8991 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8992 EXPECT_FALSE(response
->was_npn_negotiated
);
8994 std::string response_data
;
8995 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8996 EXPECT_EQ("hello world", response_data
);
8998 alternative_service_vector
=
8999 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9000 ASSERT_EQ(2u, alternative_service_vector
.size());
9001 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9002 alternative_service_vector
[0].protocol
);
9003 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
9004 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9005 EXPECT_EQ(QUIC
, alternative_service_vector
[1].protocol
);
9006 EXPECT_EQ("www.example.org", alternative_service_vector
[1].host
);
9007 EXPECT_EQ(1234, alternative_service_vector
[1].port
);
9010 // Alternate Protocol headers must be honored even if |use_alternative_services|
9012 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
9013 session_deps_
.next_protos
= SpdyNextProtos();
9014 session_deps_
.use_alternative_services
= false;
9016 std::string alternate_protocol_http_header
=
9017 GetAlternateProtocolHttpHeader();
9019 MockRead data_reads
[] = {
9020 MockRead("HTTP/1.1 200 OK\r\n"),
9021 MockRead(alternate_protocol_http_header
.c_str()),
9023 MockRead("hello world"),
9024 MockRead(SYNCHRONOUS
, OK
),
9027 HttpRequestInfo request
;
9028 request
.method
= "GET";
9029 request
.url
= GURL("http://www.example.org/");
9030 request
.load_flags
= 0;
9032 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9034 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9036 TestCompletionCallback callback
;
9038 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9039 scoped_ptr
<HttpTransaction
> trans(
9040 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9042 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9043 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9045 HostPortPair
http_host_port_pair("www.example.org", 80);
9046 HttpServerProperties
& http_server_properties
=
9047 *session
->http_server_properties();
9048 AlternativeServiceVector alternative_service_vector
=
9049 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9050 EXPECT_TRUE(alternative_service_vector
.empty());
9052 EXPECT_EQ(OK
, callback
.WaitForResult());
9054 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9055 ASSERT_TRUE(response
!= NULL
);
9056 ASSERT_TRUE(response
->headers
.get() != NULL
);
9057 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9058 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9059 EXPECT_FALSE(response
->was_npn_negotiated
);
9061 std::string response_data
;
9062 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9063 EXPECT_EQ("hello world", response_data
);
9065 alternative_service_vector
=
9066 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9067 ASSERT_EQ(1u, alternative_service_vector
.size());
9068 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9069 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9070 alternative_service_vector
[0].protocol
);
9073 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
9074 session_deps_
.next_protos
= SpdyNextProtos();
9075 session_deps_
.use_alternative_services
= true;
9077 MockRead data_reads
[] = {
9078 MockRead("HTTP/1.1 200 OK\r\n"),
9079 MockRead("Alternate-Protocol: \r\n\r\n"),
9080 MockRead("hello world"),
9081 MockRead(SYNCHRONOUS
, OK
),
9084 HttpRequestInfo request
;
9085 request
.method
= "GET";
9086 request
.url
= GURL("http://www.example.org/");
9087 request
.load_flags
= 0;
9089 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9091 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9093 TestCompletionCallback callback
;
9095 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9097 HostPortPair
http_host_port_pair("www.example.org", 80);
9098 HttpServerProperties
& http_server_properties
=
9099 *session
->http_server_properties();
9100 AlternativeService
alternative_service(QUIC
, "", 80);
9101 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9102 http_server_properties
.SetAlternativeService(
9103 http_host_port_pair
, alternative_service
, 1.0, expiration
);
9105 AlternativeServiceVector alternative_service_vector
=
9106 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9107 ASSERT_EQ(1u, alternative_service_vector
.size());
9108 EXPECT_EQ(QUIC
, alternative_service_vector
[0].protocol
);
9110 scoped_ptr
<HttpTransaction
> trans(
9111 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9113 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9114 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9116 EXPECT_EQ(OK
, callback
.WaitForResult());
9118 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9119 ASSERT_TRUE(response
!= NULL
);
9120 ASSERT_TRUE(response
->headers
.get() != NULL
);
9121 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9122 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9123 EXPECT_FALSE(response
->was_npn_negotiated
);
9125 std::string response_data
;
9126 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9127 EXPECT_EQ("hello world", response_data
);
9129 alternative_service_vector
=
9130 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9131 EXPECT_TRUE(alternative_service_vector
.empty());
9134 TEST_P(HttpNetworkTransactionTest
, AltSvcOverwritesAlternateProtocol
) {
9135 session_deps_
.next_protos
= SpdyNextProtos();
9136 session_deps_
.use_alternative_services
= true;
9138 std::string alternative_service_http_header
=
9139 GetAlternativeServiceHttpHeader();
9140 std::string alternate_protocol_http_header
= GetAlternateProtocolHttpHeader();
9142 MockRead data_reads
[] = {
9143 MockRead("HTTP/1.1 200 OK\r\n"),
9144 MockRead(alternative_service_http_header
.c_str()),
9145 MockRead(alternate_protocol_http_header
.c_str()),
9147 MockRead("hello world"),
9148 MockRead(SYNCHRONOUS
, OK
),
9151 HttpRequestInfo request
;
9152 request
.method
= "GET";
9153 request
.url
= GURL("http://www.example.org/");
9154 request
.load_flags
= 0;
9156 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9158 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9160 TestCompletionCallback callback
;
9162 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9163 scoped_ptr
<HttpTransaction
> trans(
9164 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9166 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9167 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9169 HostPortPair
http_host_port_pair("www.example.org", 80);
9170 HttpServerProperties
& http_server_properties
=
9171 *session
->http_server_properties();
9172 AlternativeServiceVector alternative_service_vector
=
9173 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9174 EXPECT_TRUE(alternative_service_vector
.empty());
9176 EXPECT_EQ(OK
, callback
.WaitForResult());
9178 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9179 ASSERT_TRUE(response
!= NULL
);
9180 ASSERT_TRUE(response
->headers
.get() != NULL
);
9181 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9182 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9183 EXPECT_FALSE(response
->was_npn_negotiated
);
9185 std::string response_data
;
9186 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9187 EXPECT_EQ("hello world", response_data
);
9189 alternative_service_vector
=
9190 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9191 ASSERT_EQ(1u, alternative_service_vector
.size());
9192 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9193 alternative_service_vector
[0].protocol
);
9194 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
9195 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9198 // When |use_alternative_services| is false, do not observe alternative service
9199 // entries that point to a different host.
9200 TEST_P(HttpNetworkTransactionTest
, DisableAlternativeServiceToDifferentHost
) {
9201 session_deps_
.use_alternative_services
= false;
9203 HttpRequestInfo request
;
9204 request
.method
= "GET";
9205 request
.url
= GURL("http://www.example.org/");
9206 request
.load_flags
= 0;
9208 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9209 StaticSocketDataProvider first_data
;
9210 first_data
.set_connect_data(mock_connect
);
9211 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9213 MockRead data_reads
[] = {
9214 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
9215 MockRead(ASYNC
, OK
),
9217 StaticSocketDataProvider
second_data(data_reads
, arraysize(data_reads
),
9219 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9221 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9223 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9224 session
->http_server_properties();
9225 AlternativeService
alternative_service(
9226 AlternateProtocolFromNextProto(GetParam()), "different.example.org", 80);
9227 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9228 http_server_properties
->SetAlternativeService(
9229 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0, expiration
);
9231 scoped_ptr
<HttpTransaction
> trans(
9232 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9233 TestCompletionCallback callback
;
9235 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9236 // The connetion to origin was refused, and the alternative service should not
9237 // be used (even though mock data are there), therefore the request should
9239 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.GetResult(rv
));
9242 TEST_P(HttpNetworkTransactionTest
,
9243 MarkBrokenAlternateProtocolAndFallback
) {
9244 session_deps_
.use_alternative_services
= true;
9246 HttpRequestInfo request
;
9247 request
.method
= "GET";
9248 request
.url
= GURL("http://www.example.org/");
9249 request
.load_flags
= 0;
9251 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9252 StaticSocketDataProvider first_data
;
9253 first_data
.set_connect_data(mock_connect
);
9254 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9256 MockRead data_reads
[] = {
9257 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9258 MockRead("hello world"),
9259 MockRead(ASYNC
, OK
),
9261 StaticSocketDataProvider
second_data(
9262 data_reads
, arraysize(data_reads
), NULL
, 0);
9263 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9265 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9267 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9268 session
->http_server_properties();
9269 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
9270 // Port must be < 1024, or the header will be ignored (since initial port was
9271 // port 80 (another restricted port).
9272 const AlternativeService
alternative_service(
9273 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9274 666); // Port is ignored by MockConnect anyway.
9275 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9276 http_server_properties
->SetAlternativeService(
9277 host_port_pair
, alternative_service
, 1.0, expiration
);
9279 scoped_ptr
<HttpTransaction
> trans(
9280 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9281 TestCompletionCallback callback
;
9283 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9284 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9285 EXPECT_EQ(OK
, callback
.WaitForResult());
9287 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9288 ASSERT_TRUE(response
!= NULL
);
9289 ASSERT_TRUE(response
->headers
.get() != NULL
);
9290 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9292 std::string response_data
;
9293 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9294 EXPECT_EQ("hello world", response_data
);
9296 const AlternativeServiceVector alternative_service_vector
=
9297 http_server_properties
->GetAlternativeServices(host_port_pair
);
9298 ASSERT_EQ(1u, alternative_service_vector
.size());
9299 EXPECT_EQ(alternative_service
, alternative_service_vector
[0]);
9300 EXPECT_TRUE(http_server_properties
->IsAlternativeServiceBroken(
9301 alternative_service_vector
[0]));
9304 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9305 // to an unrestricted (port >= 1024) when the original traffic was on a
9306 // restricted port (port < 1024). Ensure that we can redirect in all other
9308 TEST_P(HttpNetworkTransactionTest
,
9309 AlternateProtocolPortRestrictedBlocked
) {
9310 session_deps_
.use_alternative_services
= true;
9312 HttpRequestInfo restricted_port_request
;
9313 restricted_port_request
.method
= "GET";
9314 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9315 restricted_port_request
.load_flags
= 0;
9317 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9318 StaticSocketDataProvider first_data
;
9319 first_data
.set_connect_data(mock_connect
);
9320 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9322 MockRead data_reads
[] = {
9323 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9324 MockRead("hello world"),
9325 MockRead(ASYNC
, OK
),
9327 StaticSocketDataProvider
second_data(
9328 data_reads
, arraysize(data_reads
), NULL
, 0);
9329 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9331 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9333 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9334 session
->http_server_properties();
9335 const int kUnrestrictedAlternatePort
= 1024;
9336 AlternativeService
alternative_service(
9337 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9338 kUnrestrictedAlternatePort
);
9339 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9340 http_server_properties
->SetAlternativeService(
9341 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9344 scoped_ptr
<HttpTransaction
> trans(
9345 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9346 TestCompletionCallback callback
;
9348 int rv
= trans
->Start(
9349 &restricted_port_request
,
9350 callback
.callback(), BoundNetLog());
9351 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9352 // Invalid change to unrestricted port should fail.
9353 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
9356 // Ensure that we are allowed to redirect traffic via an alternate protocol to
9357 // an unrestricted (port >= 1024) when the original traffic was on a restricted
9358 // port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
9359 TEST_P(HttpNetworkTransactionTest
,
9360 AlternateProtocolPortRestrictedPermitted
) {
9361 session_deps_
.use_alternative_services
= true;
9362 session_deps_
.enable_user_alternate_protocol_ports
= true;
9364 HttpRequestInfo restricted_port_request
;
9365 restricted_port_request
.method
= "GET";
9366 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9367 restricted_port_request
.load_flags
= 0;
9369 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9370 StaticSocketDataProvider first_data
;
9371 first_data
.set_connect_data(mock_connect
);
9372 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9374 MockRead data_reads
[] = {
9375 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9376 MockRead("hello world"),
9377 MockRead(ASYNC
, OK
),
9379 StaticSocketDataProvider
second_data(
9380 data_reads
, arraysize(data_reads
), NULL
, 0);
9381 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9383 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9385 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9386 session
->http_server_properties();
9387 const int kUnrestrictedAlternatePort
= 1024;
9388 AlternativeService
alternative_service(
9389 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9390 kUnrestrictedAlternatePort
);
9391 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9392 http_server_properties
->SetAlternativeService(
9393 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9396 scoped_ptr
<HttpTransaction
> trans(
9397 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9398 TestCompletionCallback callback
;
9400 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9401 &restricted_port_request
,
9402 callback
.callback(), BoundNetLog()));
9403 // Change to unrestricted port should succeed.
9404 EXPECT_EQ(OK
, callback
.WaitForResult());
9407 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9408 // to an unrestricted (port >= 1024) when the original traffic was on a
9409 // restricted port (port < 1024). Ensure that we can redirect in all other
9411 TEST_P(HttpNetworkTransactionTest
,
9412 AlternateProtocolPortRestrictedAllowed
) {
9413 session_deps_
.use_alternative_services
= true;
9415 HttpRequestInfo restricted_port_request
;
9416 restricted_port_request
.method
= "GET";
9417 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9418 restricted_port_request
.load_flags
= 0;
9420 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9421 StaticSocketDataProvider first_data
;
9422 first_data
.set_connect_data(mock_connect
);
9423 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9425 MockRead data_reads
[] = {
9426 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9427 MockRead("hello world"),
9428 MockRead(ASYNC
, OK
),
9430 StaticSocketDataProvider
second_data(
9431 data_reads
, arraysize(data_reads
), NULL
, 0);
9432 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9434 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9436 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9437 session
->http_server_properties();
9438 const int kRestrictedAlternatePort
= 80;
9439 AlternativeService
alternative_service(
9440 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9441 kRestrictedAlternatePort
);
9442 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9443 http_server_properties
->SetAlternativeService(
9444 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9447 scoped_ptr
<HttpTransaction
> trans(
9448 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9449 TestCompletionCallback callback
;
9451 int rv
= trans
->Start(
9452 &restricted_port_request
,
9453 callback
.callback(), BoundNetLog());
9454 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9455 // Valid change to restricted port should pass.
9456 EXPECT_EQ(OK
, callback
.WaitForResult());
9459 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9460 // to an unrestricted (port >= 1024) when the original traffic was on a
9461 // restricted port (port < 1024). Ensure that we can redirect in all other
9463 TEST_P(HttpNetworkTransactionTest
,
9464 AlternateProtocolPortUnrestrictedAllowed1
) {
9465 session_deps_
.use_alternative_services
= true;
9467 HttpRequestInfo unrestricted_port_request
;
9468 unrestricted_port_request
.method
= "GET";
9469 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9470 unrestricted_port_request
.load_flags
= 0;
9472 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9473 StaticSocketDataProvider first_data
;
9474 first_data
.set_connect_data(mock_connect
);
9475 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9477 MockRead data_reads
[] = {
9478 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9479 MockRead("hello world"),
9480 MockRead(ASYNC
, OK
),
9482 StaticSocketDataProvider
second_data(
9483 data_reads
, arraysize(data_reads
), NULL
, 0);
9484 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9486 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9488 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9489 session
->http_server_properties();
9490 const int kRestrictedAlternatePort
= 80;
9491 AlternativeService
alternative_service(
9492 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9493 kRestrictedAlternatePort
);
9494 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9495 http_server_properties
->SetAlternativeService(
9496 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9499 scoped_ptr
<HttpTransaction
> trans(
9500 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9501 TestCompletionCallback callback
;
9503 int rv
= trans
->Start(
9504 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9505 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9506 // Valid change to restricted port should pass.
9507 EXPECT_EQ(OK
, callback
.WaitForResult());
9510 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9511 // to an unrestricted (port >= 1024) when the original traffic was on a
9512 // restricted port (port < 1024). Ensure that we can redirect in all other
9514 TEST_P(HttpNetworkTransactionTest
,
9515 AlternateProtocolPortUnrestrictedAllowed2
) {
9516 session_deps_
.use_alternative_services
= true;
9518 HttpRequestInfo unrestricted_port_request
;
9519 unrestricted_port_request
.method
= "GET";
9520 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9521 unrestricted_port_request
.load_flags
= 0;
9523 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9524 StaticSocketDataProvider first_data
;
9525 first_data
.set_connect_data(mock_connect
);
9526 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9528 MockRead data_reads
[] = {
9529 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9530 MockRead("hello world"),
9531 MockRead(ASYNC
, OK
),
9533 StaticSocketDataProvider
second_data(
9534 data_reads
, arraysize(data_reads
), NULL
, 0);
9535 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9537 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9539 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9540 session
->http_server_properties();
9541 const int kUnrestrictedAlternatePort
= 1025;
9542 AlternativeService
alternative_service(
9543 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9544 kUnrestrictedAlternatePort
);
9545 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9546 http_server_properties
->SetAlternativeService(
9547 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9550 scoped_ptr
<HttpTransaction
> trans(
9551 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9552 TestCompletionCallback callback
;
9554 int rv
= trans
->Start(
9555 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9556 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9557 // Valid change to an unrestricted port should pass.
9558 EXPECT_EQ(OK
, callback
.WaitForResult());
9561 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9562 // to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
9563 // once the alternate protocol request fails.
9564 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9565 session_deps_
.use_alternative_services
= true;
9567 HttpRequestInfo request
;
9568 request
.method
= "GET";
9569 request
.url
= GURL("http://www.example.org/");
9570 request
.load_flags
= 0;
9572 // The alternate protocol request will error out before we attempt to connect,
9573 // so only the standard HTTP request will try to connect.
9574 MockRead data_reads
[] = {
9575 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9576 MockRead("hello world"),
9577 MockRead(ASYNC
, OK
),
9579 StaticSocketDataProvider
data(
9580 data_reads
, arraysize(data_reads
), NULL
, 0);
9581 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9583 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9585 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9586 session
->http_server_properties();
9587 const int kUnsafePort
= 7;
9588 AlternativeService
alternative_service(
9589 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9591 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9592 http_server_properties
->SetAlternativeService(
9593 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0, expiration
);
9595 scoped_ptr
<HttpTransaction
> trans(
9596 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9597 TestCompletionCallback callback
;
9599 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9600 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9601 // The HTTP request should succeed.
9602 EXPECT_EQ(OK
, callback
.WaitForResult());
9604 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9605 ASSERT_TRUE(response
!= NULL
);
9606 ASSERT_TRUE(response
->headers
.get() != NULL
);
9607 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9609 std::string response_data
;
9610 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9611 EXPECT_EQ("hello world", response_data
);
9614 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9615 session_deps_
.use_alternative_services
= true;
9616 session_deps_
.next_protos
= SpdyNextProtos();
9618 HttpRequestInfo request
;
9619 request
.method
= "GET";
9620 request
.url
= GURL("http://www.example.org/");
9621 request
.load_flags
= 0;
9623 std::string alternate_protocol_http_header
=
9624 GetAlternateProtocolHttpHeader();
9626 MockRead data_reads
[] = {
9627 MockRead("HTTP/1.1 200 OK\r\n"),
9628 MockRead(alternate_protocol_http_header
.c_str()),
9630 MockRead("hello world"),
9631 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9632 MockRead(ASYNC
, OK
)};
9634 StaticSocketDataProvider
first_transaction(
9635 data_reads
, arraysize(data_reads
), NULL
, 0);
9636 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9638 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9639 ssl
.SetNextProto(GetParam());
9640 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9641 ASSERT_TRUE(ssl
.cert
.get());
9642 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9644 scoped_ptr
<SpdyFrame
> req(
9645 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9646 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9648 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9649 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9650 MockRead spdy_reads
[] = {
9651 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9654 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9655 arraysize(spdy_writes
));
9656 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9658 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9659 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9661 hanging_non_alternate_protocol_socket
.set_connect_data(
9662 never_finishing_connect
);
9663 session_deps_
.socket_factory
->AddSocketDataProvider(
9664 &hanging_non_alternate_protocol_socket
);
9666 TestCompletionCallback callback
;
9668 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9669 scoped_ptr
<HttpTransaction
> trans(
9670 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9672 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9673 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9674 EXPECT_EQ(OK
, callback
.WaitForResult());
9676 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9677 ASSERT_TRUE(response
!= NULL
);
9678 ASSERT_TRUE(response
->headers
.get() != NULL
);
9679 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9681 std::string response_data
;
9682 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9683 EXPECT_EQ("hello world", response_data
);
9685 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9687 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9688 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9689 EXPECT_EQ(OK
, callback
.WaitForResult());
9691 response
= trans
->GetResponseInfo();
9692 ASSERT_TRUE(response
!= NULL
);
9693 ASSERT_TRUE(response
->headers
.get() != NULL
);
9694 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9695 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9696 EXPECT_TRUE(response
->was_npn_negotiated
);
9698 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9699 EXPECT_EQ("hello!", response_data
);
9702 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9703 session_deps_
.use_alternative_services
= true;
9704 session_deps_
.next_protos
= SpdyNextProtos();
9706 HttpRequestInfo request
;
9707 request
.method
= "GET";
9708 request
.url
= GURL("http://www.example.org/");
9709 request
.load_flags
= 0;
9711 std::string alternate_protocol_http_header
=
9712 GetAlternateProtocolHttpHeader();
9714 MockRead data_reads
[] = {
9715 MockRead("HTTP/1.1 200 OK\r\n"),
9716 MockRead(alternate_protocol_http_header
.c_str()),
9718 MockRead("hello world"),
9719 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9720 MockRead(ASYNC
, OK
),
9723 StaticSocketDataProvider
first_transaction(
9724 data_reads
, arraysize(data_reads
), NULL
, 0);
9725 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9726 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9728 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9729 StaticSocketDataProvider
hanging_socket(
9731 hanging_socket
.set_connect_data(never_finishing_connect
);
9732 // Socket 2 and 3 are the hanging Alternate-Protocol and
9733 // non-Alternate-Protocol jobs from the 2nd transaction.
9734 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9735 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9737 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9738 ssl
.SetNextProto(GetParam());
9739 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9740 ASSERT_TRUE(ssl
.cert
.get());
9741 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9743 scoped_ptr
<SpdyFrame
> req1(
9744 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9745 scoped_ptr
<SpdyFrame
> req2(
9746 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9747 MockWrite spdy_writes
[] = {
9748 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
9750 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9751 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9752 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9753 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9754 MockRead spdy_reads
[] = {
9755 CreateMockRead(*resp1
, 2),
9756 CreateMockRead(*data1
, 3),
9757 CreateMockRead(*resp2
, 4),
9758 CreateMockRead(*data2
, 5),
9759 MockRead(ASYNC
, 0, 6),
9762 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9763 arraysize(spdy_writes
));
9764 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9765 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9767 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9768 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9770 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9771 TestCompletionCallback callback1
;
9772 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9774 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9776 EXPECT_EQ(OK
, callback1
.WaitForResult());
9778 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9779 ASSERT_TRUE(response
!= NULL
);
9780 ASSERT_TRUE(response
->headers
.get() != NULL
);
9781 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9783 std::string response_data
;
9784 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9785 EXPECT_EQ("hello world", response_data
);
9787 TestCompletionCallback callback2
;
9788 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9789 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9790 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9792 TestCompletionCallback callback3
;
9793 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9794 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9795 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9797 EXPECT_EQ(OK
, callback2
.WaitForResult());
9798 EXPECT_EQ(OK
, callback3
.WaitForResult());
9800 response
= trans2
.GetResponseInfo();
9801 ASSERT_TRUE(response
!= NULL
);
9802 ASSERT_TRUE(response
->headers
.get() != NULL
);
9803 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9804 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9805 EXPECT_TRUE(response
->was_npn_negotiated
);
9806 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9807 EXPECT_EQ("hello!", response_data
);
9809 response
= trans3
.GetResponseInfo();
9810 ASSERT_TRUE(response
!= NULL
);
9811 ASSERT_TRUE(response
->headers
.get() != NULL
);
9812 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9813 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9814 EXPECT_TRUE(response
->was_npn_negotiated
);
9815 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9816 EXPECT_EQ("hello!", response_data
);
9819 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9820 session_deps_
.use_alternative_services
= true;
9821 session_deps_
.next_protos
= SpdyNextProtos();
9823 HttpRequestInfo request
;
9824 request
.method
= "GET";
9825 request
.url
= GURL("http://www.example.org/");
9826 request
.load_flags
= 0;
9828 std::string alternate_protocol_http_header
=
9829 GetAlternateProtocolHttpHeader();
9831 MockRead data_reads
[] = {
9832 MockRead("HTTP/1.1 200 OK\r\n"),
9833 MockRead(alternate_protocol_http_header
.c_str()),
9835 MockRead("hello world"),
9836 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9837 MockRead(ASYNC
, OK
),
9840 StaticSocketDataProvider
first_transaction(
9841 data_reads
, arraysize(data_reads
), NULL
, 0);
9842 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9844 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9845 ssl
.SetNextProto(GetParam());
9846 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9848 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9849 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9851 hanging_alternate_protocol_socket
.set_connect_data(
9852 never_finishing_connect
);
9853 session_deps_
.socket_factory
->AddSocketDataProvider(
9854 &hanging_alternate_protocol_socket
);
9856 // 2nd request is just a copy of the first one, over HTTP again.
9857 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9859 TestCompletionCallback callback
;
9861 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9862 scoped_ptr
<HttpTransaction
> trans(
9863 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9865 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9866 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9867 EXPECT_EQ(OK
, callback
.WaitForResult());
9869 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9870 ASSERT_TRUE(response
!= NULL
);
9871 ASSERT_TRUE(response
->headers
.get() != NULL
);
9872 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9874 std::string response_data
;
9875 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9876 EXPECT_EQ("hello world", response_data
);
9878 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9880 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9881 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9882 EXPECT_EQ(OK
, callback
.WaitForResult());
9884 response
= trans
->GetResponseInfo();
9885 ASSERT_TRUE(response
!= NULL
);
9886 ASSERT_TRUE(response
->headers
.get() != NULL
);
9887 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9888 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9889 EXPECT_FALSE(response
->was_npn_negotiated
);
9891 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9892 EXPECT_EQ("hello world", response_data
);
9895 class CapturingProxyResolver
: public ProxyResolver
{
9897 CapturingProxyResolver() {}
9898 ~CapturingProxyResolver() override
{}
9900 int GetProxyForURL(const GURL
& url
,
9902 const CompletionCallback
& callback
,
9903 RequestHandle
* request
,
9904 const BoundNetLog
& net_log
) override
{
9905 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9906 HostPortPair("myproxy", 80));
9907 results
->UseProxyServer(proxy_server
);
9908 resolved_
.push_back(url
);
9912 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9914 LoadState
GetLoadState(RequestHandle request
) const override
{
9916 return LOAD_STATE_IDLE
;
9919 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9922 std::vector
<GURL
> resolved_
;
9924 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9927 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9929 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9930 : ProxyResolverFactory(false), resolver_(resolver
) {}
9932 int CreateProxyResolver(
9933 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9934 scoped_ptr
<ProxyResolver
>* resolver
,
9935 const net::CompletionCallback
& callback
,
9936 scoped_ptr
<Request
>* request
) override
{
9937 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9942 ProxyResolver
* resolver_
;
9945 TEST_P(HttpNetworkTransactionTest
,
9946 UseAlternateProtocolForTunneledNpnSpdy
) {
9947 session_deps_
.use_alternative_services
= true;
9948 session_deps_
.next_protos
= SpdyNextProtos();
9950 ProxyConfig proxy_config
;
9951 proxy_config
.set_auto_detect(true);
9952 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9954 CapturingProxyResolver capturing_proxy_resolver
;
9955 session_deps_
.proxy_service
.reset(new ProxyService(
9956 new ProxyConfigServiceFixed(proxy_config
),
9958 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9961 session_deps_
.net_log
= &net_log
;
9963 HttpRequestInfo request
;
9964 request
.method
= "GET";
9965 request
.url
= GURL("http://www.example.org/");
9966 request
.load_flags
= 0;
9968 std::string alternate_protocol_http_header
=
9969 GetAlternateProtocolHttpHeader();
9971 MockRead data_reads
[] = {
9972 MockRead("HTTP/1.1 200 OK\r\n"),
9973 MockRead(alternate_protocol_http_header
.c_str()),
9975 MockRead("hello world"),
9976 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9977 MockRead(ASYNC
, OK
),
9980 StaticSocketDataProvider
first_transaction(
9981 data_reads
, arraysize(data_reads
), NULL
, 0);
9982 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9984 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9985 ssl
.SetNextProto(GetParam());
9986 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9987 ASSERT_TRUE(ssl
.cert
.get());
9988 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9990 scoped_ptr
<SpdyFrame
> req(
9991 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9992 MockWrite spdy_writes
[] = {
9994 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9995 "Host: www.example.org\r\n"
9996 "Proxy-Connection: keep-alive\r\n\r\n"),
9997 CreateMockWrite(*req
, 2),
10000 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10002 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10003 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10004 MockRead spdy_reads
[] = {
10005 MockRead(ASYNC
, 1, kCONNECTResponse
),
10006 CreateMockRead(*resp
.get(), 3),
10007 CreateMockRead(*data
.get(), 4),
10008 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
10011 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10012 arraysize(spdy_writes
));
10013 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10015 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10016 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10018 hanging_non_alternate_protocol_socket
.set_connect_data(
10019 never_finishing_connect
);
10020 session_deps_
.socket_factory
->AddSocketDataProvider(
10021 &hanging_non_alternate_protocol_socket
);
10023 TestCompletionCallback callback
;
10025 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10026 scoped_ptr
<HttpTransaction
> trans(
10027 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10029 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10030 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10031 EXPECT_EQ(OK
, callback
.WaitForResult());
10033 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10034 ASSERT_TRUE(response
!= NULL
);
10035 ASSERT_TRUE(response
->headers
.get() != NULL
);
10036 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10037 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10038 EXPECT_FALSE(response
->was_npn_negotiated
);
10040 std::string response_data
;
10041 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10042 EXPECT_EQ("hello world", response_data
);
10044 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10046 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10047 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10048 EXPECT_EQ(OK
, callback
.WaitForResult());
10050 response
= trans
->GetResponseInfo();
10051 ASSERT_TRUE(response
!= NULL
);
10052 ASSERT_TRUE(response
->headers
.get() != NULL
);
10053 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10054 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10055 EXPECT_TRUE(response
->was_npn_negotiated
);
10057 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10058 EXPECT_EQ("hello!", response_data
);
10059 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
10060 EXPECT_EQ("http://www.example.org/",
10061 capturing_proxy_resolver
.resolved()[0].spec());
10062 EXPECT_EQ("https://www.example.org/",
10063 capturing_proxy_resolver
.resolved()[1].spec());
10065 LoadTimingInfo load_timing_info
;
10066 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10067 TestLoadTimingNotReusedWithPac(load_timing_info
,
10068 CONNECT_TIMING_HAS_SSL_TIMES
);
10071 TEST_P(HttpNetworkTransactionTest
,
10072 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
10073 session_deps_
.use_alternative_services
= true;
10074 session_deps_
.next_protos
= SpdyNextProtos();
10076 HttpRequestInfo request
;
10077 request
.method
= "GET";
10078 request
.url
= GURL("http://www.example.org/");
10079 request
.load_flags
= 0;
10081 std::string alternate_protocol_http_header
=
10082 GetAlternateProtocolHttpHeader();
10084 MockRead data_reads
[] = {
10085 MockRead("HTTP/1.1 200 OK\r\n"),
10086 MockRead(alternate_protocol_http_header
.c_str()),
10088 MockRead("hello world"),
10089 MockRead(ASYNC
, OK
),
10092 StaticSocketDataProvider
first_transaction(
10093 data_reads
, arraysize(data_reads
), NULL
, 0);
10094 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
10096 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10097 ssl
.SetNextProto(GetParam());
10098 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10099 ASSERT_TRUE(ssl
.cert
.get());
10100 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10102 scoped_ptr
<SpdyFrame
> req(
10103 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10104 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
10106 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10107 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10108 MockRead spdy_reads
[] = {
10109 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
10112 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10113 arraysize(spdy_writes
));
10114 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10116 TestCompletionCallback callback
;
10118 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10120 scoped_ptr
<HttpTransaction
> trans(
10121 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10123 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10124 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10125 EXPECT_EQ(OK
, callback
.WaitForResult());
10127 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10128 ASSERT_TRUE(response
!= NULL
);
10129 ASSERT_TRUE(response
->headers
.get() != NULL
);
10130 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10132 std::string response_data
;
10133 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10134 EXPECT_EQ("hello world", response_data
);
10136 // Set up an initial SpdySession in the pool to reuse.
10137 HostPortPair
host_port_pair("www.example.org", 443);
10138 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10139 PRIVACY_MODE_DISABLED
);
10140 base::WeakPtr
<SpdySession
> spdy_session
=
10141 CreateSecureSpdySession(session
, key
, BoundNetLog());
10143 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10145 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10146 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10147 EXPECT_EQ(OK
, callback
.WaitForResult());
10149 response
= trans
->GetResponseInfo();
10150 ASSERT_TRUE(response
!= NULL
);
10151 ASSERT_TRUE(response
->headers
.get() != NULL
);
10152 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10153 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10154 EXPECT_TRUE(response
->was_npn_negotiated
);
10156 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10157 EXPECT_EQ("hello!", response_data
);
10160 // GenerateAuthToken is a mighty big test.
10161 // It tests all permutation of GenerateAuthToken behavior:
10162 // - Synchronous and Asynchronous completion.
10163 // - OK or error on completion.
10164 // - Direct connection, non-authenticating proxy, and authenticating proxy.
10165 // - HTTP or HTTPS backend (to include proxy tunneling).
10166 // - Non-authenticating and authenticating backend.
10168 // In all, there are 44 reasonable permuations (for example, if there are
10169 // problems generating an auth token for an authenticating proxy, we don't
10170 // need to test all permutations of the backend server).
10172 // The test proceeds by going over each of the configuration cases, and
10173 // potentially running up to three rounds in each of the tests. The TestConfig
10174 // specifies both the configuration for the test as well as the expectations
10175 // for the results.
10176 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
10177 static const char kServer
[] = "http://www.example.com";
10178 static const char kSecureServer
[] = "https://www.example.com";
10179 static const char kProxy
[] = "myproxy:70";
10180 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
10188 const MockWrite
kGet(
10189 "GET / HTTP/1.1\r\n"
10190 "Host: www.example.com\r\n"
10191 "Connection: keep-alive\r\n\r\n");
10192 const MockWrite
kGetProxy(
10193 "GET http://www.example.com/ HTTP/1.1\r\n"
10194 "Host: www.example.com\r\n"
10195 "Proxy-Connection: keep-alive\r\n\r\n");
10196 const MockWrite
kGetAuth(
10197 "GET / HTTP/1.1\r\n"
10198 "Host: www.example.com\r\n"
10199 "Connection: keep-alive\r\n"
10200 "Authorization: auth_token\r\n\r\n");
10201 const MockWrite
kGetProxyAuth(
10202 "GET http://www.example.com/ HTTP/1.1\r\n"
10203 "Host: www.example.com\r\n"
10204 "Proxy-Connection: keep-alive\r\n"
10205 "Proxy-Authorization: auth_token\r\n\r\n");
10206 const MockWrite
kGetAuthThroughProxy(
10207 "GET http://www.example.com/ HTTP/1.1\r\n"
10208 "Host: www.example.com\r\n"
10209 "Proxy-Connection: keep-alive\r\n"
10210 "Authorization: auth_token\r\n\r\n");
10211 const MockWrite
kGetAuthWithProxyAuth(
10212 "GET http://www.example.com/ HTTP/1.1\r\n"
10213 "Host: www.example.com\r\n"
10214 "Proxy-Connection: keep-alive\r\n"
10215 "Proxy-Authorization: auth_token\r\n"
10216 "Authorization: auth_token\r\n\r\n");
10217 const MockWrite
kConnect(
10218 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10219 "Host: www.example.com\r\n"
10220 "Proxy-Connection: keep-alive\r\n\r\n");
10221 const MockWrite
kConnectProxyAuth(
10222 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10223 "Host: www.example.com\r\n"
10224 "Proxy-Connection: keep-alive\r\n"
10225 "Proxy-Authorization: auth_token\r\n\r\n");
10227 const MockRead
kSuccess(
10228 "HTTP/1.1 200 OK\r\n"
10229 "Content-Type: text/html; charset=iso-8859-1\r\n"
10230 "Content-Length: 3\r\n\r\n"
10232 const MockRead
kFailure(
10233 "Should not be called.");
10234 const MockRead
kServerChallenge(
10235 "HTTP/1.1 401 Unauthorized\r\n"
10236 "WWW-Authenticate: Mock realm=server\r\n"
10237 "Content-Type: text/html; charset=iso-8859-1\r\n"
10238 "Content-Length: 14\r\n\r\n"
10239 "Unauthorized\r\n");
10240 const MockRead
kProxyChallenge(
10241 "HTTP/1.1 407 Unauthorized\r\n"
10242 "Proxy-Authenticate: Mock realm=proxy\r\n"
10243 "Proxy-Connection: close\r\n"
10244 "Content-Type: text/html; charset=iso-8859-1\r\n"
10245 "Content-Length: 14\r\n\r\n"
10246 "Unauthorized\r\n");
10247 const MockRead
kProxyConnected(
10248 "HTTP/1.1 200 Connection Established\r\n\r\n");
10250 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10251 // no constructors, but the C++ compiler on Windows warns about
10252 // unspecified data in compound literals. So, moved to using constructors,
10253 // and TestRound's created with the default constructor should not be used.
10256 : expected_rv(ERR_UNEXPECTED
),
10260 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10261 int expected_rv_arg
)
10262 : write(write_arg
),
10264 expected_rv(expected_rv_arg
),
10268 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10269 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
10270 const MockRead
* extra_read_arg
)
10271 : write(write_arg
),
10273 expected_rv(expected_rv_arg
),
10274 extra_write(extra_write_arg
),
10275 extra_read(extra_read_arg
) {
10280 const MockWrite
* extra_write
;
10281 const MockRead
* extra_read
;
10284 static const int kNoSSL
= 500;
10286 struct TestConfig
{
10287 const char* const proxy_url
;
10288 AuthTiming proxy_auth_timing
;
10290 const char* const server_url
;
10291 AuthTiming server_auth_timing
;
10292 int server_auth_rv
;
10293 int num_auth_rounds
;
10294 int first_ssl_round
;
10295 TestRound rounds
[3];
10296 } test_configs
[] = {
10297 // Non-authenticating HTTP server with a direct connection.
10298 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10299 { TestRound(kGet
, kSuccess
, OK
)}},
10300 // Authenticating HTTP server with a direct connection.
10301 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10302 { TestRound(kGet
, kServerChallenge
, OK
),
10303 TestRound(kGetAuth
, kSuccess
, OK
)}},
10304 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10305 { TestRound(kGet
, kServerChallenge
, OK
),
10306 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10307 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10308 { TestRound(kGet
, kServerChallenge
, OK
),
10309 TestRound(kGetAuth
, kSuccess
, OK
)}},
10310 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10311 { TestRound(kGet
, kServerChallenge
, OK
),
10312 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10313 // Non-authenticating HTTP server through a non-authenticating proxy.
10314 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10315 { TestRound(kGetProxy
, kSuccess
, OK
)}},
10316 // Authenticating HTTP server through a non-authenticating proxy.
10317 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10318 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10319 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10320 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10321 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10322 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10323 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10324 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10325 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10326 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10327 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10328 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10329 // Non-authenticating HTTP server through an authenticating proxy.
10330 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10331 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10332 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10333 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10334 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10335 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10336 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10337 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10338 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10339 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10340 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10341 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10342 // Authenticating HTTP server through an authenticating proxy.
10343 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10344 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10345 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10346 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10347 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10348 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10349 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10350 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10351 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10352 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10353 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10354 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10355 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10356 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10357 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10358 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10359 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10360 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10361 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10362 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10363 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10364 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10365 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10366 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10367 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10368 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10369 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10370 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10371 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10372 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10373 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10374 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10375 // Non-authenticating HTTPS server with a direct connection.
10376 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10377 { TestRound(kGet
, kSuccess
, OK
)}},
10378 // Authenticating HTTPS server with a direct connection.
10379 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10380 { TestRound(kGet
, kServerChallenge
, OK
),
10381 TestRound(kGetAuth
, kSuccess
, OK
)}},
10382 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10383 { TestRound(kGet
, kServerChallenge
, OK
),
10384 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10385 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10386 { TestRound(kGet
, kServerChallenge
, OK
),
10387 TestRound(kGetAuth
, kSuccess
, OK
)}},
10388 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10389 { TestRound(kGet
, kServerChallenge
, OK
),
10390 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10391 // Non-authenticating HTTPS server with a non-authenticating proxy.
10392 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10393 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10394 // Authenticating HTTPS server through a non-authenticating proxy.
10395 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10396 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10397 TestRound(kGetAuth
, kSuccess
, OK
)}},
10398 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10399 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10400 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10401 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10402 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10403 TestRound(kGetAuth
, kSuccess
, OK
)}},
10404 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10405 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10406 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10407 // Non-Authenticating HTTPS server through an authenticating proxy.
10408 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10409 { TestRound(kConnect
, kProxyChallenge
, OK
),
10410 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10411 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10412 { TestRound(kConnect
, kProxyChallenge
, OK
),
10413 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10414 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10415 { TestRound(kConnect
, kProxyChallenge
, OK
),
10416 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10417 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10418 { TestRound(kConnect
, kProxyChallenge
, OK
),
10419 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10420 // Authenticating HTTPS server through an authenticating proxy.
10421 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10422 { TestRound(kConnect
, kProxyChallenge
, OK
),
10423 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10424 &kGet
, &kServerChallenge
),
10425 TestRound(kGetAuth
, kSuccess
, OK
)}},
10426 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10427 { TestRound(kConnect
, kProxyChallenge
, OK
),
10428 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10429 &kGet
, &kServerChallenge
),
10430 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10431 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10432 { TestRound(kConnect
, kProxyChallenge
, OK
),
10433 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10434 &kGet
, &kServerChallenge
),
10435 TestRound(kGetAuth
, kSuccess
, OK
)}},
10436 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10437 { TestRound(kConnect
, kProxyChallenge
, OK
),
10438 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10439 &kGet
, &kServerChallenge
),
10440 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10441 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10442 { TestRound(kConnect
, kProxyChallenge
, OK
),
10443 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10444 &kGet
, &kServerChallenge
),
10445 TestRound(kGetAuth
, kSuccess
, OK
)}},
10446 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10447 { TestRound(kConnect
, kProxyChallenge
, OK
),
10448 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10449 &kGet
, &kServerChallenge
),
10450 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10451 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10452 { TestRound(kConnect
, kProxyChallenge
, OK
),
10453 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10454 &kGet
, &kServerChallenge
),
10455 TestRound(kGetAuth
, kSuccess
, OK
)}},
10456 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10457 { TestRound(kConnect
, kProxyChallenge
, OK
),
10458 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10459 &kGet
, &kServerChallenge
),
10460 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10463 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10464 HttpAuthHandlerMock::Factory
* auth_factory(
10465 new HttpAuthHandlerMock::Factory());
10466 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10467 const TestConfig
& test_config
= test_configs
[i
];
10469 // Set up authentication handlers as necessary.
10470 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10471 for (int n
= 0; n
< 2; n
++) {
10472 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10473 std::string auth_challenge
= "Mock realm=proxy";
10474 GURL
origin(test_config
.proxy_url
);
10475 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10476 auth_challenge
.end());
10477 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10478 origin
, BoundNetLog());
10479 auth_handler
->SetGenerateExpectation(
10480 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10481 test_config
.proxy_auth_rv
);
10482 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10485 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10486 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10487 std::string auth_challenge
= "Mock realm=server";
10488 GURL
origin(test_config
.server_url
);
10489 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10490 auth_challenge
.end());
10491 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10492 origin
, BoundNetLog());
10493 auth_handler
->SetGenerateExpectation(
10494 test_config
.server_auth_timing
== AUTH_ASYNC
,
10495 test_config
.server_auth_rv
);
10496 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10498 if (test_config
.proxy_url
) {
10499 session_deps_
.proxy_service
.reset(
10500 ProxyService::CreateFixed(test_config
.proxy_url
));
10502 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10505 HttpRequestInfo request
;
10506 request
.method
= "GET";
10507 request
.url
= GURL(test_config
.server_url
);
10508 request
.load_flags
= 0;
10510 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10511 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10513 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10515 std::vector
<std::vector
<MockRead
>> mock_reads(1);
10516 std::vector
<std::vector
<MockWrite
>> mock_writes(1);
10517 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10518 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10520 // Set up expected reads and writes.
10521 mock_reads
.back().push_back(read_write_round
.read
);
10522 mock_writes
.back().push_back(read_write_round
.write
);
10524 // kProxyChallenge uses Proxy-Connection: close which means that the
10525 // socket is closed and a new one will be created for the next request.
10526 if (read_write_round
.read
.data
== kProxyChallenge
.data
) {
10527 mock_reads
.push_back(std::vector
<MockRead
>());
10528 mock_writes
.push_back(std::vector
<MockWrite
>());
10531 if (read_write_round
.extra_read
) {
10532 mock_reads
.back().push_back(*read_write_round
.extra_read
);
10534 if (read_write_round
.extra_write
) {
10535 mock_writes
.back().push_back(*read_write_round
.extra_write
);
10538 // Add an SSL sequence if necessary.
10539 if (round
>= test_config
.first_ssl_round
)
10540 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10541 &ssl_socket_data_provider
);
10544 ScopedVector
<StaticSocketDataProvider
> data_providers
;
10545 for (size_t i
= 0; i
< mock_reads
.size(); ++i
) {
10546 data_providers
.push_back(new StaticSocketDataProvider(
10547 vector_as_array(&mock_reads
[i
]), mock_reads
[i
].size(),
10548 vector_as_array(&mock_writes
[i
]), mock_writes
[i
].size()));
10549 session_deps_
.socket_factory
->AddSocketDataProvider(
10550 data_providers
.back());
10553 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10554 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10555 // Start or restart the transaction.
10556 TestCompletionCallback callback
;
10559 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10561 rv
= trans
.RestartWithAuth(
10562 AuthCredentials(kFoo
, kBar
), callback
.callback());
10564 if (rv
== ERR_IO_PENDING
)
10565 rv
= callback
.WaitForResult();
10567 // Compare results with expected data.
10568 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10569 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10570 if (read_write_round
.expected_rv
!= OK
) {
10571 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10574 if (round
+ 1 < test_config
.num_auth_rounds
) {
10575 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10577 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10583 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10584 // Do multi-round authentication and make sure it works correctly.
10585 HttpAuthHandlerMock::Factory
* auth_factory(
10586 new HttpAuthHandlerMock::Factory());
10587 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10588 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10589 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10590 session_deps_
.host_resolver
->set_synchronous_mode(true);
10592 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10593 auth_handler
->set_connection_based(true);
10594 std::string auth_challenge
= "Mock realm=server";
10595 GURL
origin("http://www.example.com");
10596 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10597 auth_challenge
.end());
10598 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10599 origin
, BoundNetLog());
10600 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10603 const HttpResponseInfo
* response
= NULL
;
10604 HttpRequestInfo request
;
10605 request
.method
= "GET";
10606 request
.url
= origin
;
10607 request
.load_flags
= 0;
10609 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10611 // Use a TCP Socket Pool with only one connection per group. This is used
10612 // to validate that the TCP socket is not released to the pool between
10613 // each round of multi-round authentication.
10614 HttpNetworkSessionPeer
session_peer(session
);
10615 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10616 50, // Max sockets for pool
10617 1, // Max sockets per group
10618 session_deps_
.host_resolver
.get(),
10619 session_deps_
.socket_factory
.get(),
10620 session_deps_
.net_log
);
10621 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10622 new MockClientSocketPoolManager
);
10623 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10624 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10626 scoped_ptr
<HttpTransaction
> trans(
10627 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10628 TestCompletionCallback callback
;
10630 const MockWrite
kGet(
10631 "GET / HTTP/1.1\r\n"
10632 "Host: www.example.com\r\n"
10633 "Connection: keep-alive\r\n\r\n");
10634 const MockWrite
kGetAuth(
10635 "GET / HTTP/1.1\r\n"
10636 "Host: www.example.com\r\n"
10637 "Connection: keep-alive\r\n"
10638 "Authorization: auth_token\r\n\r\n");
10640 const MockRead
kServerChallenge(
10641 "HTTP/1.1 401 Unauthorized\r\n"
10642 "WWW-Authenticate: Mock realm=server\r\n"
10643 "Content-Type: text/html; charset=iso-8859-1\r\n"
10644 "Content-Length: 14\r\n\r\n"
10645 "Unauthorized\r\n");
10646 const MockRead
kSuccess(
10647 "HTTP/1.1 200 OK\r\n"
10648 "Content-Type: text/html; charset=iso-8859-1\r\n"
10649 "Content-Length: 3\r\n\r\n"
10652 MockWrite writes
[] = {
10661 // Competing request
10664 MockRead reads
[] = {
10673 // Competing response
10676 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10677 writes
, arraysize(writes
));
10678 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10680 const char kSocketGroup
[] = "www.example.com:80";
10682 // First round of authentication.
10683 auth_handler
->SetGenerateExpectation(false, OK
);
10684 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10685 if (rv
== ERR_IO_PENDING
)
10686 rv
= callback
.WaitForResult();
10688 response
= trans
->GetResponseInfo();
10689 ASSERT_TRUE(response
!= NULL
);
10690 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10691 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10693 // In between rounds, another request comes in for the same domain.
10694 // It should not be able to grab the TCP socket that trans has already
10696 scoped_ptr
<HttpTransaction
> trans_compete(
10697 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10698 TestCompletionCallback callback_compete
;
10699 rv
= trans_compete
->Start(
10700 &request
, callback_compete
.callback(), BoundNetLog());
10701 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10702 // callback_compete.WaitForResult at this point would stall forever,
10703 // since the HttpNetworkTransaction does not release the request back to
10704 // the pool until after authentication completes.
10706 // Second round of authentication.
10707 auth_handler
->SetGenerateExpectation(false, OK
);
10708 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10709 if (rv
== ERR_IO_PENDING
)
10710 rv
= callback
.WaitForResult();
10712 response
= trans
->GetResponseInfo();
10713 ASSERT_TRUE(response
!= NULL
);
10714 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10715 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10717 // Third round of authentication.
10718 auth_handler
->SetGenerateExpectation(false, OK
);
10719 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10720 if (rv
== ERR_IO_PENDING
)
10721 rv
= callback
.WaitForResult();
10723 response
= trans
->GetResponseInfo();
10724 ASSERT_TRUE(response
!= NULL
);
10725 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10726 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10728 // Fourth round of authentication, which completes successfully.
10729 auth_handler
->SetGenerateExpectation(false, OK
);
10730 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10731 if (rv
== ERR_IO_PENDING
)
10732 rv
= callback
.WaitForResult();
10734 response
= trans
->GetResponseInfo();
10735 ASSERT_TRUE(response
!= NULL
);
10736 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10737 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10739 // Read the body since the fourth round was successful. This will also
10740 // release the socket back to the pool.
10741 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10742 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10743 if (rv
== ERR_IO_PENDING
)
10744 rv
= callback
.WaitForResult();
10746 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10748 // There are still 0 idle sockets, since the trans_compete transaction
10749 // will be handed it immediately after trans releases it to the group.
10750 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10752 // The competing request can now finish. Wait for the headers and then
10754 rv
= callback_compete
.WaitForResult();
10756 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10757 if (rv
== ERR_IO_PENDING
)
10758 rv
= callback
.WaitForResult();
10760 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10763 // Finally, the socket is released to the group.
10764 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10767 // This tests the case that a request is issued via http instead of spdy after
10768 // npn is negotiated.
10769 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10770 session_deps_
.use_alternative_services
= true;
10771 NextProtoVector next_protos
;
10772 next_protos
.push_back(kProtoHTTP11
);
10773 session_deps_
.next_protos
= next_protos
;
10775 HttpRequestInfo request
;
10776 request
.method
= "GET";
10777 request
.url
= GURL("https://www.example.org/");
10778 request
.load_flags
= 0;
10780 MockWrite data_writes
[] = {
10782 "GET / HTTP/1.1\r\n"
10783 "Host: www.example.org\r\n"
10784 "Connection: keep-alive\r\n\r\n"),
10787 std::string alternate_protocol_http_header
=
10788 GetAlternateProtocolHttpHeader();
10790 MockRead data_reads
[] = {
10791 MockRead("HTTP/1.1 200 OK\r\n"),
10792 MockRead(alternate_protocol_http_header
.c_str()),
10794 MockRead("hello world"),
10795 MockRead(SYNCHRONOUS
, OK
),
10798 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10799 ssl
.SetNextProto(kProtoHTTP11
);
10801 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10803 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10804 data_writes
, arraysize(data_writes
));
10805 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10807 TestCompletionCallback callback
;
10809 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10810 scoped_ptr
<HttpTransaction
> trans(
10811 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10813 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10815 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10816 EXPECT_EQ(OK
, callback
.WaitForResult());
10818 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10819 ASSERT_TRUE(response
!= NULL
);
10820 ASSERT_TRUE(response
->headers
.get() != NULL
);
10821 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10823 std::string response_data
;
10824 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10825 EXPECT_EQ("hello world", response_data
);
10827 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10828 EXPECT_TRUE(response
->was_npn_negotiated
);
10831 // Simulate the SSL handshake completing with an NPN negotiation followed by an
10832 // immediate server closing of the socket.
10833 // Regression test for https://crbug.com/46369.
10834 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10835 session_deps_
.use_alternative_services
= true;
10836 session_deps_
.next_protos
= SpdyNextProtos();
10838 HttpRequestInfo request
;
10839 request
.method
= "GET";
10840 request
.url
= GURL("https://www.example.org/");
10841 request
.load_flags
= 0;
10843 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10844 ssl
.SetNextProto(GetParam());
10845 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10847 scoped_ptr
<SpdyFrame
> req(
10848 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10849 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 1)};
10851 MockRead spdy_reads
[] = {
10852 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10855 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10856 arraysize(spdy_writes
));
10857 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10859 TestCompletionCallback callback
;
10861 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10862 scoped_ptr
<HttpTransaction
> trans(
10863 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10865 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10866 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10867 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10870 // A subclass of HttpAuthHandlerMock that records the request URL when
10871 // it gets it. This is needed since the auth handler may get destroyed
10872 // before we get a chance to query it.
10873 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10875 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10877 ~UrlRecordingHttpAuthHandlerMock() override
{}
10880 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10881 const HttpRequestInfo
* request
,
10882 const CompletionCallback
& callback
,
10883 std::string
* auth_token
) override
{
10884 *url_
= request
->url
;
10885 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10886 credentials
, request
, callback
, auth_token
);
10893 // This test ensures that the URL passed into the proxy is upgraded to https
10894 // when doing an Alternate Protocol upgrade.
10895 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10896 session_deps_
.use_alternative_services
= true;
10897 session_deps_
.next_protos
= SpdyNextProtos();
10899 session_deps_
.proxy_service
.reset(
10900 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10901 TestNetLog net_log
;
10902 session_deps_
.net_log
= &net_log
;
10905 HttpAuthHandlerMock::Factory
* auth_factory
=
10906 new HttpAuthHandlerMock::Factory();
10907 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10908 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10909 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10910 auth_factory
->set_do_init_from_challenge(true);
10911 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10914 HttpRequestInfo request
;
10915 request
.method
= "GET";
10916 request
.url
= GURL("http://www.example.org");
10917 request
.load_flags
= 0;
10919 // First round goes unauthenticated through the proxy.
10920 MockWrite data_writes_1
[] = {
10922 "GET http://www.example.org/ HTTP/1.1\r\n"
10923 "Host: www.example.org\r\n"
10924 "Proxy-Connection: keep-alive\r\n"
10927 MockRead data_reads_1
[] = {
10928 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10929 MockRead("HTTP/1.1 200 OK\r\n"),
10930 MockRead("Alternate-Protocol: 443:"),
10931 MockRead(GetAlternateProtocolFromParam()),
10933 MockRead("Proxy-Connection: close\r\n"),
10936 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10937 data_writes_1
, arraysize(data_writes_1
));
10939 // Second round tries to tunnel to www.example.org due to the
10940 // Alternate-Protocol announcement in the first round. It fails due
10941 // to a proxy authentication challenge.
10942 // After the failure, a tunnel is established to www.example.org using
10943 // Proxy-Authorization headers. There is then a SPDY request round.
10945 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10946 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10947 // does a Disconnect and Connect on the same socket, rather than trying
10948 // to obtain a new one.
10950 // NOTE: Originally, the proxy response to the second CONNECT request
10951 // simply returned another 407 so the unit test could skip the SSL connection
10952 // establishment and SPDY framing issues. Alas, the
10953 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10954 // complicated to set up expectations for than the SPDY session.
10956 scoped_ptr
<SpdyFrame
> req(
10957 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10958 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10959 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10961 MockWrite data_writes_2
[] = {
10962 // First connection attempt without Proxy-Authorization.
10963 MockWrite(ASYNC
, 0,
10964 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10965 "Host: www.example.org\r\n"
10966 "Proxy-Connection: keep-alive\r\n"
10969 // Second connection attempt with Proxy-Authorization.
10970 MockWrite(ASYNC
, 2,
10971 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10972 "Host: www.example.org\r\n"
10973 "Proxy-Connection: keep-alive\r\n"
10974 "Proxy-Authorization: auth_token\r\n"
10978 CreateMockWrite(*req
, 4),
10980 MockRead data_reads_2
[] = {
10981 // First connection attempt fails
10983 "HTTP/1.1 407 Unauthorized\r\n"
10984 "Proxy-Authenticate: Mock\r\n"
10985 "Content-Length: 0\r\n"
10986 "Proxy-Connection: keep-alive\r\n"
10989 // Second connection attempt passes
10990 MockRead(ASYNC
, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
10993 CreateMockRead(*resp
.get(), 5), CreateMockRead(*data
.get(), 6),
10994 MockRead(ASYNC
, 0, 0, 7),
10996 SequencedSocketData
data_2(data_reads_2
, arraysize(data_reads_2
),
10997 data_writes_2
, arraysize(data_writes_2
));
10999 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11000 ssl
.SetNextProto(GetParam());
11001 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11002 ASSERT_TRUE(ssl
.cert
.get());
11004 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
11005 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
11007 hanging_non_alternate_protocol_socket
.set_connect_data(
11008 never_finishing_connect
);
11010 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
11011 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
11012 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11013 session_deps_
.socket_factory
->AddSocketDataProvider(
11014 &hanging_non_alternate_protocol_socket
);
11015 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11017 // First round should work and provide the Alternate-Protocol state.
11018 TestCompletionCallback callback_1
;
11019 scoped_ptr
<HttpTransaction
> trans_1(
11020 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11021 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
11022 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11023 EXPECT_EQ(OK
, callback_1
.WaitForResult());
11025 // Second round should attempt a tunnel connect and get an auth challenge.
11026 TestCompletionCallback callback_2
;
11027 scoped_ptr
<HttpTransaction
> trans_2(
11028 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11029 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
11030 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11031 EXPECT_EQ(OK
, callback_2
.WaitForResult());
11032 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
11033 ASSERT_TRUE(response
!= NULL
);
11034 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
11036 // Restart with auth. Tunnel should work and response received.
11037 TestCompletionCallback callback_3
;
11038 rv
= trans_2
->RestartWithAuth(
11039 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
11040 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11041 EXPECT_EQ(OK
, callback_3
.WaitForResult());
11043 // After all that work, these two lines (or actually, just the scheme) are
11044 // what this test is all about. Make sure it happens correctly.
11045 EXPECT_EQ("https", request_url
.scheme());
11046 EXPECT_EQ("www.example.org", request_url
.host());
11048 LoadTimingInfo load_timing_info
;
11049 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
11050 TestLoadTimingNotReusedWithPac(load_timing_info
,
11051 CONNECT_TIMING_HAS_SSL_TIMES
);
11054 // Test that if we cancel the transaction as the connection is completing, that
11055 // everything tears down correctly.
11056 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
11057 // Setup everything about the connection to complete synchronously, so that
11058 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
11059 // for is the callback from the HttpStreamRequest.
11060 // Then cancel the transaction.
11061 // Verify that we don't crash.
11062 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
11063 MockRead data_reads
[] = {
11064 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
11065 MockRead(SYNCHRONOUS
, "hello world"),
11066 MockRead(SYNCHRONOUS
, OK
),
11069 HttpRequestInfo request
;
11070 request
.method
= "GET";
11071 request
.url
= GURL("http://www.example.org/");
11072 request
.load_flags
= 0;
11074 session_deps_
.host_resolver
->set_synchronous_mode(true);
11075 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11076 scoped_ptr
<HttpTransaction
> trans(
11077 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11079 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
11080 data
.set_connect_data(mock_connect
);
11081 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11083 TestCompletionCallback callback
;
11085 BoundTestNetLog log
;
11086 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
11087 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11088 trans
.reset(); // Cancel the transaction here.
11090 base::MessageLoop::current()->RunUntilIdle();
11093 // Test that if a transaction is cancelled after receiving the headers, the
11094 // stream is drained properly and added back to the socket pool. The main
11095 // purpose of this test is to make sure that an HttpStreamParser can be read
11096 // from after the HttpNetworkTransaction and the objects it owns have been
11098 // See http://crbug.com/368418
11099 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
11100 MockRead data_reads
[] = {
11101 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
11102 MockRead(ASYNC
, "Content-Length: 2\r\n"),
11103 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
11104 MockRead(ASYNC
, "1"),
11105 // 2 async reads are necessary to trigger a ReadResponseBody call after the
11106 // HttpNetworkTransaction has been deleted.
11107 MockRead(ASYNC
, "2"),
11108 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
11110 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
11111 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11113 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11116 HttpRequestInfo request
;
11117 request
.method
= "GET";
11118 request
.url
= GURL("http://www.example.org/");
11119 request
.load_flags
= 0;
11121 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
11122 TestCompletionCallback callback
;
11124 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
11125 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11126 callback
.WaitForResult();
11128 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
11129 ASSERT_TRUE(response
!= NULL
);
11130 EXPECT_TRUE(response
->headers
.get() != NULL
);
11131 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11133 // The transaction and HttpRequestInfo are deleted.
11136 // Let the HttpResponseBodyDrainer drain the socket.
11137 base::MessageLoop::current()->RunUntilIdle();
11139 // Socket should now be idle, waiting to be reused.
11140 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
11143 // Test a basic GET request through a proxy.
11144 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
11145 session_deps_
.proxy_service
.reset(
11146 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11147 BoundTestNetLog log
;
11148 session_deps_
.net_log
= log
.bound().net_log();
11149 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11151 HttpRequestInfo request
;
11152 request
.method
= "GET";
11153 request
.url
= GURL("http://www.example.org/");
11155 MockWrite data_writes1
[] = {
11157 "GET http://www.example.org/ HTTP/1.1\r\n"
11158 "Host: www.example.org\r\n"
11159 "Proxy-Connection: keep-alive\r\n\r\n"),
11162 MockRead data_reads1
[] = {
11163 MockRead("HTTP/1.1 200 OK\r\n"),
11164 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11165 MockRead("Content-Length: 100\r\n\r\n"),
11166 MockRead(SYNCHRONOUS
, OK
),
11169 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11170 data_writes1
, arraysize(data_writes1
));
11171 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11173 TestCompletionCallback callback1
;
11175 scoped_ptr
<HttpTransaction
> trans(
11176 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11177 BeforeProxyHeadersSentHandler proxy_headers_handler
;
11178 trans
->SetBeforeProxyHeadersSentCallback(
11179 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
11180 base::Unretained(&proxy_headers_handler
)));
11182 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11183 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11185 rv
= callback1
.WaitForResult();
11188 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11189 ASSERT_TRUE(response
!= NULL
);
11191 EXPECT_TRUE(response
->headers
->IsKeepAlive());
11192 EXPECT_EQ(200, response
->headers
->response_code());
11193 EXPECT_EQ(100, response
->headers
->GetContentLength());
11194 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11196 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11197 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
11198 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
11199 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11201 LoadTimingInfo load_timing_info
;
11202 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11203 TestLoadTimingNotReusedWithPac(load_timing_info
,
11204 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
11207 // Test a basic HTTPS GET request through a proxy.
11208 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
11209 session_deps_
.proxy_service
.reset(
11210 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11211 BoundTestNetLog log
;
11212 session_deps_
.net_log
= log
.bound().net_log();
11213 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11215 HttpRequestInfo request
;
11216 request
.method
= "GET";
11217 request
.url
= GURL("https://www.example.org/");
11219 // Since we have proxy, should try to establish tunnel.
11220 MockWrite data_writes1
[] = {
11222 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11223 "Host: www.example.org\r\n"
11224 "Proxy-Connection: keep-alive\r\n\r\n"),
11227 "GET / HTTP/1.1\r\n"
11228 "Host: www.example.org\r\n"
11229 "Connection: keep-alive\r\n\r\n"),
11232 MockRead data_reads1
[] = {
11233 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11235 MockRead("HTTP/1.1 200 OK\r\n"),
11236 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11237 MockRead("Content-Length: 100\r\n\r\n"),
11238 MockRead(SYNCHRONOUS
, OK
),
11241 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11242 data_writes1
, arraysize(data_writes1
));
11243 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11244 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11245 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11247 TestCompletionCallback callback1
;
11249 scoped_ptr
<HttpTransaction
> trans(
11250 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11252 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11255 rv
= callback1
.WaitForResult();
11257 TestNetLogEntry::List entries
;
11258 log
.GetEntries(&entries
);
11259 size_t pos
= ExpectLogContainsSomewhere(
11260 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11261 NetLog::PHASE_NONE
);
11262 ExpectLogContainsSomewhere(
11264 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11265 NetLog::PHASE_NONE
);
11267 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11268 ASSERT_TRUE(response
!= NULL
);
11270 EXPECT_TRUE(response
->headers
->IsKeepAlive());
11271 EXPECT_EQ(200, response
->headers
->response_code());
11272 EXPECT_EQ(100, response
->headers
->GetContentLength());
11273 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11274 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11276 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11278 LoadTimingInfo load_timing_info
;
11279 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11280 TestLoadTimingNotReusedWithPac(load_timing_info
,
11281 CONNECT_TIMING_HAS_SSL_TIMES
);
11284 // Test a basic HTTPS GET request through a proxy, but the server hangs up
11285 // while establishing the tunnel.
11286 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
11287 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
11288 BoundTestNetLog log
;
11289 session_deps_
.net_log
= log
.bound().net_log();
11290 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11292 HttpRequestInfo request
;
11293 request
.method
= "GET";
11294 request
.url
= GURL("https://www.example.org/");
11296 // Since we have proxy, should try to establish tunnel.
11297 MockWrite data_writes1
[] = {
11299 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11300 "Host: www.example.org\r\n"
11301 "Proxy-Connection: keep-alive\r\n\r\n"),
11304 "GET / HTTP/1.1\r\n"
11305 "Host: www.example.org\r\n"
11306 "Connection: keep-alive\r\n\r\n"),
11309 MockRead data_reads1
[] = {
11310 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
11311 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11312 MockRead(ASYNC
, 0, 0), // EOF
11315 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11316 data_writes1
, arraysize(data_writes1
));
11317 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11318 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11319 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11321 TestCompletionCallback callback1
;
11323 scoped_ptr
<HttpTransaction
> trans(
11324 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11326 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11327 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11329 rv
= callback1
.WaitForResult();
11330 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
11331 TestNetLogEntry::List entries
;
11332 log
.GetEntries(&entries
);
11333 size_t pos
= ExpectLogContainsSomewhere(
11334 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11335 NetLog::PHASE_NONE
);
11336 ExpectLogContainsSomewhere(
11338 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11339 NetLog::PHASE_NONE
);
11342 // Test for crbug.com/55424.
11343 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
11344 scoped_ptr
<SpdyFrame
> req(
11345 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11346 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
11348 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11349 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11350 MockRead spdy_reads
[] = {
11351 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
11354 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
11355 arraysize(spdy_writes
));
11356 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11358 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11359 ssl
.SetNextProto(GetParam());
11360 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11362 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11364 // Set up an initial SpdySession in the pool to reuse.
11365 HostPortPair
host_port_pair("www.example.org", 443);
11366 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
11367 PRIVACY_MODE_DISABLED
);
11368 base::WeakPtr
<SpdySession
> spdy_session
=
11369 CreateInsecureSpdySession(session
, key
, BoundNetLog());
11371 HttpRequestInfo request
;
11372 request
.method
= "GET";
11373 request
.url
= GURL("https://www.example.org/");
11374 request
.load_flags
= 0;
11376 // This is the important line that marks this as a preconnect.
11377 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11379 scoped_ptr
<HttpTransaction
> trans(
11380 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11382 TestCompletionCallback callback
;
11383 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11384 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11385 EXPECT_EQ(OK
, callback
.WaitForResult());
11388 // Given a net error, cause that error to be returned from the first Write()
11389 // call and verify that the HttpTransaction fails with that error.
11390 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11391 int error
, IoMode mode
) {
11392 HttpRequestInfo request_info
;
11393 request_info
.url
= GURL("https://www.example.com/");
11394 request_info
.method
= "GET";
11395 request_info
.load_flags
= LOAD_NORMAL
;
11397 SSLSocketDataProvider
ssl_data(mode
, OK
);
11398 MockWrite data_writes
[] = {
11399 MockWrite(mode
, error
),
11401 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11402 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11403 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11405 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11406 scoped_ptr
<HttpTransaction
> trans(
11407 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11409 TestCompletionCallback callback
;
11410 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11411 if (rv
== ERR_IO_PENDING
)
11412 rv
= callback
.WaitForResult();
11413 ASSERT_EQ(error
, rv
);
11416 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11417 // Just check a grab bag of cert errors.
11418 static const int kErrors
[] = {
11419 ERR_CERT_COMMON_NAME_INVALID
,
11420 ERR_CERT_AUTHORITY_INVALID
,
11421 ERR_CERT_DATE_INVALID
,
11423 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11424 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11425 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11429 // Ensure that a client certificate is removed from the SSL client auth
11431 // 1) No proxy is involved.
11432 // 2) TLS False Start is disabled.
11433 // 3) The initial TLS handshake requests a client certificate.
11434 // 4) The client supplies an invalid/unacceptable certificate.
11435 TEST_P(HttpNetworkTransactionTest
,
11436 ClientAuthCertCache_Direct_NoFalseStart
) {
11437 HttpRequestInfo request_info
;
11438 request_info
.url
= GURL("https://www.example.com/");
11439 request_info
.method
= "GET";
11440 request_info
.load_flags
= LOAD_NORMAL
;
11442 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11443 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11445 // [ssl_]data1 contains the data for the first SSL handshake. When a
11446 // CertificateRequest is received for the first time, the handshake will
11447 // be aborted to allow the caller to provide a certificate.
11448 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11449 ssl_data1
.cert_request_info
= cert_request
.get();
11450 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11451 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11452 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11454 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11455 // False Start is not being used, the result of the SSL handshake will be
11456 // returned as part of the SSLClientSocket::Connect() call. This test
11457 // matches the result of a server sending a handshake_failure alert,
11458 // rather than a Finished message, because it requires a client
11459 // certificate and none was supplied.
11460 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11461 ssl_data2
.cert_request_info
= cert_request
.get();
11462 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11463 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11464 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11466 // [ssl_]data3 contains the data for the third SSL handshake. When a
11467 // connection to a server fails during an SSL handshake,
11468 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11469 // connection was attempted with TLSv1.2. This is transparent to the caller
11470 // of the HttpNetworkTransaction. Because this test failure is due to
11471 // requiring a client certificate, this fallback handshake should also
11473 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11474 ssl_data3
.cert_request_info
= cert_request
.get();
11475 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11476 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11477 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11479 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11480 // connection to a server fails during an SSL handshake,
11481 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11482 // connection was attempted with TLSv1.1. This is transparent to the caller
11483 // of the HttpNetworkTransaction. Because this test failure is due to
11484 // requiring a client certificate, this fallback handshake should also
11486 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11487 ssl_data4
.cert_request_info
= cert_request
.get();
11488 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11489 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11490 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11492 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11493 scoped_ptr
<HttpTransaction
> trans(
11494 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11496 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11497 TestCompletionCallback callback
;
11498 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11499 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11501 // Complete the SSL handshake, which should abort due to requiring a
11502 // client certificate.
11503 rv
= callback
.WaitForResult();
11504 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11506 // Indicate that no certificate should be supplied. From the perspective
11507 // of SSLClientCertCache, NULL is just as meaningful as a real
11508 // certificate, so this is the same as supply a
11509 // legitimate-but-unacceptable certificate.
11510 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11511 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11513 // Ensure the certificate was added to the client auth cache before
11514 // allowing the connection to continue restarting.
11515 scoped_refptr
<X509Certificate
> client_cert
;
11516 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11517 HostPortPair("www.example.com", 443), &client_cert
));
11518 ASSERT_EQ(NULL
, client_cert
.get());
11520 // Restart the handshake. This will consume ssl_data2, which fails, and
11521 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11522 // The result code is checked against what ssl_data4 should return.
11523 rv
= callback
.WaitForResult();
11524 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11526 // Ensure that the client certificate is removed from the cache on a
11527 // handshake failure.
11528 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11529 HostPortPair("www.example.com", 443), &client_cert
));
11532 // Ensure that a client certificate is removed from the SSL client auth
11534 // 1) No proxy is involved.
11535 // 2) TLS False Start is enabled.
11536 // 3) The initial TLS handshake requests a client certificate.
11537 // 4) The client supplies an invalid/unacceptable certificate.
11538 TEST_P(HttpNetworkTransactionTest
,
11539 ClientAuthCertCache_Direct_FalseStart
) {
11540 HttpRequestInfo request_info
;
11541 request_info
.url
= GURL("https://www.example.com/");
11542 request_info
.method
= "GET";
11543 request_info
.load_flags
= LOAD_NORMAL
;
11545 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11546 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11548 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11549 // return successfully after reading up to the peer's Certificate message.
11550 // This is to allow the caller to call SSLClientSocket::Write(), which can
11551 // enqueue application data to be sent in the same packet as the
11552 // ChangeCipherSpec and Finished messages.
11553 // The actual handshake will be finished when SSLClientSocket::Read() is
11554 // called, which expects to process the peer's ChangeCipherSpec and
11555 // Finished messages. If there was an error negotiating with the peer,
11556 // such as due to the peer requiring a client certificate when none was
11557 // supplied, the alert sent by the peer won't be processed until Read() is
11560 // Like the non-False Start case, when a client certificate is requested by
11561 // the peer, the handshake is aborted during the Connect() call.
11562 // [ssl_]data1 represents the initial SSL handshake with the peer.
11563 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11564 ssl_data1
.cert_request_info
= cert_request
.get();
11565 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11566 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11567 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11569 // When a client certificate is supplied, Connect() will not be aborted
11570 // when the peer requests the certificate. Instead, the handshake will
11571 // artificially succeed, allowing the caller to write the HTTP request to
11572 // the socket. The handshake messages are not processed until Read() is
11573 // called, which then detects that the handshake was aborted, due to the
11574 // peer sending a handshake_failure because it requires a client
11576 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11577 ssl_data2
.cert_request_info
= cert_request
.get();
11578 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11579 MockRead data2_reads
[] = {
11580 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11582 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11583 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11585 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11586 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11587 // TLSv1. It has the same behaviour as [ssl_]data2.
11588 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11589 ssl_data3
.cert_request_info
= cert_request
.get();
11590 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11591 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11592 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11594 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11595 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11596 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11597 ssl_data4
.cert_request_info
= cert_request
.get();
11598 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11599 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11600 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11602 // Need one more if TLSv1.2 is enabled.
11603 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11604 ssl_data5
.cert_request_info
= cert_request
.get();
11605 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11606 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11607 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11609 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11610 scoped_ptr
<HttpTransaction
> trans(
11611 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11613 // Begin the initial SSL handshake.
11614 TestCompletionCallback callback
;
11615 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11616 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11618 // Complete the SSL handshake, which should abort due to requiring a
11619 // client certificate.
11620 rv
= callback
.WaitForResult();
11621 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11623 // Indicate that no certificate should be supplied. From the perspective
11624 // of SSLClientCertCache, NULL is just as meaningful as a real
11625 // certificate, so this is the same as supply a
11626 // legitimate-but-unacceptable certificate.
11627 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11628 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11630 // Ensure the certificate was added to the client auth cache before
11631 // allowing the connection to continue restarting.
11632 scoped_refptr
<X509Certificate
> client_cert
;
11633 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11634 HostPortPair("www.example.com", 443), &client_cert
));
11635 ASSERT_EQ(NULL
, client_cert
.get());
11637 // Restart the handshake. This will consume ssl_data2, which fails, and
11638 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11639 // The result code is checked against what ssl_data4 should return.
11640 rv
= callback
.WaitForResult();
11641 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11643 // Ensure that the client certificate is removed from the cache on a
11644 // handshake failure.
11645 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11646 HostPortPair("www.example.com", 443), &client_cert
));
11649 // Ensure that a client certificate is removed from the SSL client auth
11651 // 1) An HTTPS proxy is involved.
11652 // 3) The HTTPS proxy requests a client certificate.
11653 // 4) The client supplies an invalid/unacceptable certificate for the
11655 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11656 // then for connecting to an HTTP endpoint.
11657 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11658 session_deps_
.proxy_service
.reset(
11659 ProxyService::CreateFixed("https://proxy:70"));
11660 BoundTestNetLog log
;
11661 session_deps_
.net_log
= log
.bound().net_log();
11663 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11664 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11666 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11667 // [ssl_]data[1-3]. Rather than represending the endpoint
11668 // (www.example.com:443), they represent failures with the HTTPS proxy
11670 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11671 ssl_data1
.cert_request_info
= cert_request
.get();
11672 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11673 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11674 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11676 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11677 ssl_data2
.cert_request_info
= cert_request
.get();
11678 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11679 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11680 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11682 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11684 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11685 ssl_data3
.cert_request_info
= cert_request
.get();
11686 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11687 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11688 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11691 HttpRequestInfo requests
[2];
11692 requests
[0].url
= GURL("https://www.example.com/");
11693 requests
[0].method
= "GET";
11694 requests
[0].load_flags
= LOAD_NORMAL
;
11696 requests
[1].url
= GURL("http://www.example.com/");
11697 requests
[1].method
= "GET";
11698 requests
[1].load_flags
= LOAD_NORMAL
;
11700 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11701 session_deps_
.socket_factory
->ResetNextMockIndexes();
11702 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11703 scoped_ptr
<HttpNetworkTransaction
> trans(
11704 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11706 // Begin the SSL handshake with the proxy.
11707 TestCompletionCallback callback
;
11708 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11709 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11711 // Complete the SSL handshake, which should abort due to requiring a
11712 // client certificate.
11713 rv
= callback
.WaitForResult();
11714 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11716 // Indicate that no certificate should be supplied. From the perspective
11717 // of SSLClientCertCache, NULL is just as meaningful as a real
11718 // certificate, so this is the same as supply a
11719 // legitimate-but-unacceptable certificate.
11720 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11721 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11723 // Ensure the certificate was added to the client auth cache before
11724 // allowing the connection to continue restarting.
11725 scoped_refptr
<X509Certificate
> client_cert
;
11726 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11727 HostPortPair("proxy", 70), &client_cert
));
11728 ASSERT_EQ(NULL
, client_cert
.get());
11729 // Ensure the certificate was NOT cached for the endpoint. This only
11730 // applies to HTTPS requests, but is fine to check for HTTP requests.
11731 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11732 HostPortPair("www.example.com", 443), &client_cert
));
11734 // Restart the handshake. This will consume ssl_data2, which fails, and
11735 // then consume ssl_data3, which should also fail. The result code is
11736 // checked against what ssl_data3 should return.
11737 rv
= callback
.WaitForResult();
11738 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11740 // Now that the new handshake has failed, ensure that the client
11741 // certificate was removed from the client auth cache.
11742 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11743 HostPortPair("proxy", 70), &client_cert
));
11744 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11745 HostPortPair("www.example.com", 443), &client_cert
));
11749 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPooling
) {
11750 session_deps_
.use_alternative_services
= true;
11751 session_deps_
.next_protos
= SpdyNextProtos();
11753 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11754 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11755 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11756 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11757 pool_peer
.DisableDomainAuthenticationVerification();
11759 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11760 ssl
.SetNextProto(GetParam());
11761 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11763 scoped_ptr
<SpdyFrame
> host1_req(
11764 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11765 scoped_ptr
<SpdyFrame
> host2_req(
11766 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11767 MockWrite spdy_writes
[] = {
11768 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11770 scoped_ptr
<SpdyFrame
> host1_resp(
11771 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11772 scoped_ptr
<SpdyFrame
> host1_resp_body(
11773 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11774 scoped_ptr
<SpdyFrame
> host2_resp(
11775 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11776 scoped_ptr
<SpdyFrame
> host2_resp_body(
11777 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11778 MockRead spdy_reads
[] = {
11779 CreateMockRead(*host1_resp
, 1),
11780 CreateMockRead(*host1_resp_body
, 2),
11781 CreateMockRead(*host2_resp
, 4),
11782 CreateMockRead(*host2_resp_body
, 5),
11783 MockRead(ASYNC
, 0, 6),
11786 IPAddressNumber ip
;
11787 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11788 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11789 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11790 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11791 spdy_writes
, arraysize(spdy_writes
));
11792 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11794 TestCompletionCallback callback
;
11795 HttpRequestInfo request1
;
11796 request1
.method
= "GET";
11797 request1
.url
= GURL("https://www.example.org/");
11798 request1
.load_flags
= 0;
11799 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11801 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11802 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11803 EXPECT_EQ(OK
, callback
.WaitForResult());
11805 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11806 ASSERT_TRUE(response
!= NULL
);
11807 ASSERT_TRUE(response
->headers
.get() != NULL
);
11808 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11810 std::string response_data
;
11811 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11812 EXPECT_EQ("hello!", response_data
);
11814 // Preload www.gmail.com into HostCache.
11815 HostPortPair
host_port("www.gmail.com", 443);
11816 HostResolver::RequestInfo
resolve_info(host_port
);
11817 AddressList ignored
;
11818 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11821 callback
.callback(),
11824 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11825 rv
= callback
.WaitForResult();
11828 HttpRequestInfo request2
;
11829 request2
.method
= "GET";
11830 request2
.url
= GURL("https://www.gmail.com/");
11831 request2
.load_flags
= 0;
11832 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11834 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11835 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11836 EXPECT_EQ(OK
, callback
.WaitForResult());
11838 response
= trans2
.GetResponseInfo();
11839 ASSERT_TRUE(response
!= NULL
);
11840 ASSERT_TRUE(response
->headers
.get() != NULL
);
11841 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11842 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11843 EXPECT_TRUE(response
->was_npn_negotiated
);
11844 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11845 EXPECT_EQ("hello!", response_data
);
11848 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11849 session_deps_
.use_alternative_services
= true;
11850 session_deps_
.next_protos
= SpdyNextProtos();
11852 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11853 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11854 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11855 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11856 pool_peer
.DisableDomainAuthenticationVerification();
11858 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11859 ssl
.SetNextProto(GetParam());
11860 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11862 scoped_ptr
<SpdyFrame
> host1_req(
11863 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11864 scoped_ptr
<SpdyFrame
> host2_req(
11865 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11866 MockWrite spdy_writes
[] = {
11867 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11869 scoped_ptr
<SpdyFrame
> host1_resp(
11870 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11871 scoped_ptr
<SpdyFrame
> host1_resp_body(
11872 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11873 scoped_ptr
<SpdyFrame
> host2_resp(
11874 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11875 scoped_ptr
<SpdyFrame
> host2_resp_body(
11876 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11877 MockRead spdy_reads
[] = {
11878 CreateMockRead(*host1_resp
, 1),
11879 CreateMockRead(*host1_resp_body
, 2),
11880 CreateMockRead(*host2_resp
, 4),
11881 CreateMockRead(*host2_resp_body
, 5),
11882 MockRead(ASYNC
, 0, 6),
11885 IPAddressNumber ip
;
11886 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11887 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11888 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11889 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11890 spdy_writes
, arraysize(spdy_writes
));
11891 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11893 TestCompletionCallback callback
;
11894 HttpRequestInfo request1
;
11895 request1
.method
= "GET";
11896 request1
.url
= GURL("https://www.example.org/");
11897 request1
.load_flags
= 0;
11898 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11900 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11901 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11902 EXPECT_EQ(OK
, callback
.WaitForResult());
11904 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11905 ASSERT_TRUE(response
!= NULL
);
11906 ASSERT_TRUE(response
->headers
.get() != NULL
);
11907 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11909 std::string response_data
;
11910 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11911 EXPECT_EQ("hello!", response_data
);
11913 HttpRequestInfo request2
;
11914 request2
.method
= "GET";
11915 request2
.url
= GURL("https://www.gmail.com/");
11916 request2
.load_flags
= 0;
11917 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11919 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11920 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11921 EXPECT_EQ(OK
, callback
.WaitForResult());
11923 response
= trans2
.GetResponseInfo();
11924 ASSERT_TRUE(response
!= NULL
);
11925 ASSERT_TRUE(response
->headers
.get() != NULL
);
11926 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11927 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11928 EXPECT_TRUE(response
->was_npn_negotiated
);
11929 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11930 EXPECT_EQ("hello!", response_data
);
11933 class OneTimeCachingHostResolver
: public HostResolver
{
11935 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11936 : host_port_(host_port
) {}
11937 ~OneTimeCachingHostResolver() override
{}
11939 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11941 // HostResolver methods:
11942 int Resolve(const RequestInfo
& info
,
11943 RequestPriority priority
,
11944 AddressList
* addresses
,
11945 const CompletionCallback
& callback
,
11946 RequestHandle
* out_req
,
11947 const BoundNetLog
& net_log
) override
{
11948 return host_resolver_
.Resolve(
11949 info
, priority
, addresses
, callback
, out_req
, net_log
);
11952 int ResolveFromCache(const RequestInfo
& info
,
11953 AddressList
* addresses
,
11954 const BoundNetLog
& net_log
) override
{
11955 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11956 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11957 host_resolver_
.GetHostCache()->clear();
11961 void CancelRequest(RequestHandle req
) override
{
11962 host_resolver_
.CancelRequest(req
);
11965 MockCachingHostResolver
* GetMockHostResolver() {
11966 return &host_resolver_
;
11970 MockCachingHostResolver host_resolver_
;
11971 const HostPortPair host_port_
;
11974 TEST_P(HttpNetworkTransactionTest
,
11975 UseIPConnectionPoolingWithHostCacheExpiration
) {
11976 session_deps_
.use_alternative_services
= true;
11977 session_deps_
.next_protos
= SpdyNextProtos();
11979 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11980 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11981 HttpNetworkSession::Params params
=
11982 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11983 params
.host_resolver
= &host_resolver
;
11984 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11985 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11986 pool_peer
.DisableDomainAuthenticationVerification();
11988 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11989 ssl
.SetNextProto(GetParam());
11990 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11992 scoped_ptr
<SpdyFrame
> host1_req(
11993 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11994 scoped_ptr
<SpdyFrame
> host2_req(
11995 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11996 MockWrite spdy_writes
[] = {
11997 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11999 scoped_ptr
<SpdyFrame
> host1_resp(
12000 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12001 scoped_ptr
<SpdyFrame
> host1_resp_body(
12002 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12003 scoped_ptr
<SpdyFrame
> host2_resp(
12004 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12005 scoped_ptr
<SpdyFrame
> host2_resp_body(
12006 spdy_util_
.ConstructSpdyBodyFrame(3, true));
12007 MockRead spdy_reads
[] = {
12008 CreateMockRead(*host1_resp
, 1),
12009 CreateMockRead(*host1_resp_body
, 2),
12010 CreateMockRead(*host2_resp
, 4),
12011 CreateMockRead(*host2_resp_body
, 5),
12012 MockRead(ASYNC
, 0, 6),
12015 IPAddressNumber ip
;
12016 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
12017 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12018 MockConnect
connect(ASYNC
, OK
, peer_addr
);
12019 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
12020 spdy_writes
, arraysize(spdy_writes
));
12021 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
12023 TestCompletionCallback callback
;
12024 HttpRequestInfo request1
;
12025 request1
.method
= "GET";
12026 request1
.url
= GURL("https://www.example.org/");
12027 request1
.load_flags
= 0;
12028 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12030 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
12031 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12032 EXPECT_EQ(OK
, callback
.WaitForResult());
12034 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
12035 ASSERT_TRUE(response
!= NULL
);
12036 ASSERT_TRUE(response
->headers
.get() != NULL
);
12037 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12039 std::string response_data
;
12040 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
12041 EXPECT_EQ("hello!", response_data
);
12043 // Preload cache entries into HostCache.
12044 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
12045 AddressList ignored
;
12046 rv
= host_resolver
.Resolve(resolve_info
,
12049 callback
.callback(),
12052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12053 rv
= callback
.WaitForResult();
12056 HttpRequestInfo request2
;
12057 request2
.method
= "GET";
12058 request2
.url
= GURL("https://www.gmail.com/");
12059 request2
.load_flags
= 0;
12060 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12062 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
12063 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12064 EXPECT_EQ(OK
, callback
.WaitForResult());
12066 response
= trans2
.GetResponseInfo();
12067 ASSERT_TRUE(response
!= NULL
);
12068 ASSERT_TRUE(response
->headers
.get() != NULL
);
12069 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12070 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12071 EXPECT_TRUE(response
->was_npn_negotiated
);
12072 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
12073 EXPECT_EQ("hello!", response_data
);
12076 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
12077 const std::string https_url
= "https://www.example.org:8080/";
12078 const std::string http_url
= "http://www.example.org:8080/";
12080 // SPDY GET for HTTPS URL
12081 scoped_ptr
<SpdyFrame
> req1(
12082 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12084 MockWrite writes1
[] = {
12085 CreateMockWrite(*req1
, 0),
12088 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12089 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12090 MockRead reads1
[] = {
12091 CreateMockRead(*resp1
, 1),
12092 CreateMockRead(*body1
, 2),
12093 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
12096 SequencedSocketData
data1(reads1
, arraysize(reads1
), writes1
,
12097 arraysize(writes1
));
12098 MockConnect
connect_data1(ASYNC
, OK
);
12099 data1
.set_connect_data(connect_data1
);
12101 // HTTP GET for the HTTP URL
12102 MockWrite writes2
[] = {
12103 MockWrite(ASYNC
, 0,
12104 "GET / HTTP/1.1\r\n"
12105 "Host: www.example.org:8080\r\n"
12106 "Connection: keep-alive\r\n\r\n"),
12109 MockRead reads2
[] = {
12110 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
12111 MockRead(ASYNC
, 2, "hello"),
12112 MockRead(ASYNC
, OK
, 3),
12115 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12116 arraysize(writes2
));
12118 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12119 ssl
.SetNextProto(GetParam());
12120 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12121 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12122 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12124 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12126 // Start the first transaction to set up the SpdySession
12127 HttpRequestInfo request1
;
12128 request1
.method
= "GET";
12129 request1
.url
= GURL(https_url
);
12130 request1
.load_flags
= 0;
12131 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12132 TestCompletionCallback callback1
;
12133 EXPECT_EQ(ERR_IO_PENDING
,
12134 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12135 base::MessageLoop::current()->RunUntilIdle();
12137 EXPECT_EQ(OK
, callback1
.WaitForResult());
12138 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12140 // Now, start the HTTP request
12141 HttpRequestInfo request2
;
12142 request2
.method
= "GET";
12143 request2
.url
= GURL(http_url
);
12144 request2
.load_flags
= 0;
12145 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12146 TestCompletionCallback callback2
;
12147 EXPECT_EQ(ERR_IO_PENDING
,
12148 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12149 base::MessageLoop::current()->RunUntilIdle();
12151 EXPECT_EQ(OK
, callback2
.WaitForResult());
12152 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12155 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
12157 void Run(bool pooling
, bool valid
) {
12158 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
12160 HostPortPair
alternative("www.example.org", 443);
12162 base::FilePath certs_dir
= GetTestCertsDirectory();
12163 scoped_refptr
<X509Certificate
> cert(
12164 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
12165 ASSERT_TRUE(cert
.get());
12166 bool common_name_fallback_used
;
12168 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
12170 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
12171 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12172 ssl
.SetNextProto(GetParam());
12174 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12176 // If pooling, then start a request to alternative first to create a
12178 std::string url0
= "https://www.example.org:443";
12179 // Second request to origin, which has an alternative service, and could
12180 // open a connection to the alternative host or pool to the existing one.
12181 std::string
url1("https://");
12182 url1
.append(origin
.host());
12183 url1
.append(":443");
12185 scoped_ptr
<SpdyFrame
> req0
;
12186 scoped_ptr
<SpdyFrame
> req1
;
12187 scoped_ptr
<SpdyFrame
> resp0
;
12188 scoped_ptr
<SpdyFrame
> body0
;
12189 scoped_ptr
<SpdyFrame
> resp1
;
12190 scoped_ptr
<SpdyFrame
> body1
;
12191 std::vector
<MockWrite
> writes
;
12192 std::vector
<MockRead
> reads
;
12195 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
12196 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
12198 writes
.push_back(CreateMockWrite(*req0
, 0));
12199 writes
.push_back(CreateMockWrite(*req1
, 3));
12201 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12202 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12203 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12204 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12206 reads
.push_back(CreateMockRead(*resp0
, 1));
12207 reads
.push_back(CreateMockRead(*body0
, 2));
12208 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
12209 reads
.push_back(CreateMockRead(*resp1
, 5));
12210 reads
.push_back(CreateMockRead(*body1
, 6));
12211 reads
.push_back(MockRead(ASYNC
, OK
, 7));
12213 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
12215 writes
.push_back(CreateMockWrite(*req1
, 0));
12217 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12218 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12220 reads
.push_back(CreateMockRead(*resp1
, 1));
12221 reads
.push_back(CreateMockRead(*body1
, 2));
12222 reads
.push_back(MockRead(ASYNC
, OK
, 3));
12225 SequencedSocketData
data(vector_as_array(&reads
), reads
.size(),
12226 vector_as_array(&writes
), writes
.size());
12227 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12229 // Connection to the origin fails.
12230 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12231 StaticSocketDataProvider data_refused
;
12232 data_refused
.set_connect_data(mock_connect
);
12233 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12235 session_deps_
.use_alternative_services
= true;
12236 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12237 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12238 session
->http_server_properties();
12239 AlternativeService
alternative_service(
12240 AlternateProtocolFromNextProto(GetParam()), alternative
);
12241 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12242 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12245 // First request to alternative.
12247 scoped_ptr
<HttpTransaction
> trans0(
12248 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12249 HttpRequestInfo request0
;
12250 request0
.method
= "GET";
12251 request0
.url
= GURL(url0
);
12252 request0
.load_flags
= 0;
12253 TestCompletionCallback callback0
;
12255 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
12256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12257 rv
= callback0
.WaitForResult();
12261 // Second request to origin.
12262 scoped_ptr
<HttpTransaction
> trans1(
12263 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12264 HttpRequestInfo request1
;
12265 request1
.method
= "GET";
12266 request1
.url
= GURL(url1
);
12267 request1
.load_flags
= 0;
12268 TestCompletionCallback callback1
;
12270 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12271 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12272 base::MessageLoop::current()->RunUntilIdle();
12273 if (data
.IsReadPaused()) {
12274 data
.CompleteRead();
12276 rv
= callback1
.WaitForResult();
12281 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12283 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
12289 INSTANTIATE_TEST_CASE_P(NextProto
,
12290 AltSvcCertificateVerificationTest
,
12291 testing::Values(kProtoSPDY31
,
12294 // The alternative service host must exhibit a certificate that is valid for the
12295 // origin host. Test that this is enforced when pooling to an existing
12297 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
12301 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
12305 // The alternative service host must exhibit a certificate that is valid for the
12306 // origin host. Test that this is enforced when opening a new connection.
12307 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
12311 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
12315 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12316 // with the alternative server. That connection should not be used.
12317 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceNotOnHttp11
) {
12318 HostPortPair
origin("origin.example.org", 443);
12319 HostPortPair
alternative("alternative.example.org", 443);
12321 // Negotiate HTTP/1.1 with alternative.example.org.
12322 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12323 ssl
.SetNextProto(kProtoHTTP11
);
12324 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12326 // No data should be read from the alternative, because HTTP/1.1 is
12328 StaticSocketDataProvider data
;
12329 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12331 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12332 // negotiated. In order to test this, a failed connection to the origin is
12333 // mocked. This way the request relies on the alternate Job.
12334 StaticSocketDataProvider data_refused
;
12335 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12336 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12338 // Set up alternative service for origin.
12339 session_deps_
.use_alternative_services
= true;
12340 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12341 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12342 session
->http_server_properties();
12343 AlternativeService
alternative_service(
12344 AlternateProtocolFromNextProto(GetParam()), alternative
);
12345 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12346 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12349 scoped_ptr
<HttpTransaction
> trans(
12350 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12351 HttpRequestInfo request
;
12352 request
.method
= "GET";
12353 request
.url
= GURL("https://origin.example.org:443");
12354 request
.load_flags
= 0;
12355 TestCompletionCallback callback
;
12357 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12358 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12359 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12360 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED
, callback
.GetResult(rv
));
12363 // A request to a server with an alternative service fires two Jobs: one to the
12364 // origin, and an alternate one to the alternative server. If the former
12365 // succeeds, the request should succeed, even if the latter fails because
12366 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12367 TEST_P(HttpNetworkTransactionTest
, FailedAlternativeServiceIsNotUserVisible
) {
12368 HostPortPair
origin("origin.example.org", 443);
12369 HostPortPair
alternative("alternative.example.org", 443);
12371 // Negotiate HTTP/1.1 with alternative.
12372 SSLSocketDataProvider
alternative_ssl(ASYNC
, OK
);
12373 alternative_ssl
.SetNextProto(kProtoHTTP11
);
12374 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&alternative_ssl
);
12376 // No data should be read from the alternative, because HTTP/1.1 is
12378 StaticSocketDataProvider data
;
12379 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12381 // Negotiate HTTP/1.1 with origin.
12382 SSLSocketDataProvider
origin_ssl(ASYNC
, OK
);
12383 origin_ssl
.SetNextProto(kProtoHTTP11
);
12384 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&origin_ssl
);
12386 MockWrite http_writes
[] = {
12388 "GET / HTTP/1.1\r\n"
12389 "Host: origin.example.org\r\n"
12390 "Connection: keep-alive\r\n\r\n"),
12392 "GET /second HTTP/1.1\r\n"
12393 "Host: origin.example.org\r\n"
12394 "Connection: keep-alive\r\n\r\n"),
12397 MockRead http_reads
[] = {
12398 MockRead("HTTP/1.1 200 OK\r\n"),
12399 MockRead("Content-Type: text/html\r\n"),
12400 MockRead("Content-Length: 6\r\n\r\n"),
12401 MockRead("foobar"),
12402 MockRead("HTTP/1.1 200 OK\r\n"),
12403 MockRead("Content-Type: text/html\r\n"),
12404 MockRead("Content-Length: 7\r\n\r\n"),
12405 MockRead("another"),
12407 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12408 http_writes
, arraysize(http_writes
));
12409 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12411 // Set up alternative service for origin.
12412 session_deps_
.use_alternative_services
= true;
12413 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12414 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12415 session
->http_server_properties();
12416 AlternativeService
alternative_service(
12417 AlternateProtocolFromNextProto(GetParam()), alternative
);
12418 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12419 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12422 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12423 HttpRequestInfo request1
;
12424 request1
.method
= "GET";
12425 request1
.url
= GURL("https://origin.example.org:443");
12426 request1
.load_flags
= 0;
12427 TestCompletionCallback callback1
;
12429 int rv
= trans1
.Start(&request1
, callback1
.callback(), BoundNetLog());
12430 rv
= callback1
.GetResult(rv
);
12433 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
12434 ASSERT_TRUE(response1
!= nullptr);
12435 ASSERT_TRUE(response1
->headers
.get() != nullptr);
12436 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12438 std::string response_data1
;
12439 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data1
));
12440 EXPECT_EQ("foobar", response_data1
);
12442 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12443 // for alternative service.
12445 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
12447 // Since |alternative_service| is broken, a second transaction to origin
12448 // should not start an alternate Job. It should pool to existing connection
12450 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12451 HttpRequestInfo request2
;
12452 request2
.method
= "GET";
12453 request2
.url
= GURL("https://origin.example.org:443/second");
12454 request2
.load_flags
= 0;
12455 TestCompletionCallback callback2
;
12457 rv
= trans2
.Start(&request2
, callback2
.callback(), BoundNetLog());
12458 rv
= callback2
.GetResult(rv
);
12461 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
12462 ASSERT_TRUE(response2
!= nullptr);
12463 ASSERT_TRUE(response2
->headers
.get() != nullptr);
12464 EXPECT_EQ("HTTP/1.1 200 OK", response2
->headers
->GetStatusLine());
12466 std::string response_data2
;
12467 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data2
));
12468 EXPECT_EQ("another", response_data2
);
12471 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12472 // HTTP/1.1 socket open to the alternative server. That socket should not be
12474 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceShouldNotPoolToHttp11
) {
12475 HostPortPair
origin("origin.example.org", 443);
12476 HostPortPair
alternative("alternative.example.org", 443);
12477 std::string origin_url
= "https://origin.example.org:443";
12478 std::string alternative_url
= "https://alternative.example.org:443";
12480 // Negotiate HTTP/1.1 with alternative.example.org.
12481 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12482 ssl
.SetNextProto(kProtoHTTP11
);
12483 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12485 // HTTP/1.1 data for |request1| and |request2|.
12486 MockWrite http_writes
[] = {
12488 "GET / HTTP/1.1\r\n"
12489 "Host: alternative.example.org\r\n"
12490 "Connection: keep-alive\r\n\r\n"),
12492 "GET / HTTP/1.1\r\n"
12493 "Host: alternative.example.org\r\n"
12494 "Connection: keep-alive\r\n\r\n"),
12497 MockRead http_reads
[] = {
12499 "HTTP/1.1 200 OK\r\n"
12500 "Content-Type: text/html; charset=iso-8859-1\r\n"
12501 "Content-Length: 40\r\n\r\n"
12502 "first HTTP/1.1 response from alternative"),
12504 "HTTP/1.1 200 OK\r\n"
12505 "Content-Type: text/html; charset=iso-8859-1\r\n"
12506 "Content-Length: 41\r\n\r\n"
12507 "second HTTP/1.1 response from alternative"),
12509 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12510 http_writes
, arraysize(http_writes
));
12511 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12513 // This test documents that an alternate Job should not pool to an already
12514 // existing HTTP/1.1 connection. In order to test this, a failed connection
12515 // to the origin is mocked. This way |request2| relies on the alternate Job.
12516 StaticSocketDataProvider data_refused
;
12517 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12518 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12520 // Set up alternative service for origin.
12521 session_deps_
.use_alternative_services
= true;
12522 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12523 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12524 session
->http_server_properties();
12525 AlternativeService
alternative_service(
12526 AlternateProtocolFromNextProto(GetParam()), alternative
);
12527 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12528 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12531 // First transaction to alternative to open an HTTP/1.1 socket.
12532 scoped_ptr
<HttpTransaction
> trans1(
12533 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12534 HttpRequestInfo request1
;
12535 request1
.method
= "GET";
12536 request1
.url
= GURL(alternative_url
);
12537 request1
.load_flags
= 0;
12538 TestCompletionCallback callback1
;
12540 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12541 EXPECT_EQ(OK
, callback1
.GetResult(rv
));
12542 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12543 ASSERT_TRUE(response1
);
12544 ASSERT_TRUE(response1
->headers
.get());
12545 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12546 EXPECT_TRUE(response1
->was_npn_negotiated
);
12547 EXPECT_FALSE(response1
->was_fetched_via_spdy
);
12548 std::string response_data1
;
12549 ASSERT_EQ(OK
, ReadTransaction(trans1
.get(), &response_data1
));
12550 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1
);
12552 // Request for origin.example.org, which has an alternative service. This
12553 // will start two Jobs: the alternative looks for connections to pool to,
12554 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12555 // open other connections to alternative server. The Job to origin fails, so
12556 // this request fails.
12557 scoped_ptr
<HttpTransaction
> trans2(
12558 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12559 HttpRequestInfo request2
;
12560 request2
.method
= "GET";
12561 request2
.url
= GURL(origin_url
);
12562 request2
.load_flags
= 0;
12563 TestCompletionCallback callback2
;
12565 rv
= trans2
->Start(&request2
, callback2
.callback(), BoundNetLog());
12566 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback2
.GetResult(rv
));
12568 // Another transaction to alternative. This is to test that the HTTP/1.1
12569 // socket is still open and in the pool.
12570 scoped_ptr
<HttpTransaction
> trans3(
12571 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12572 HttpRequestInfo request3
;
12573 request3
.method
= "GET";
12574 request3
.url
= GURL(alternative_url
);
12575 request3
.load_flags
= 0;
12576 TestCompletionCallback callback3
;
12578 rv
= trans3
->Start(&request3
, callback3
.callback(), BoundNetLog());
12579 EXPECT_EQ(OK
, callback3
.GetResult(rv
));
12580 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
12581 ASSERT_TRUE(response3
);
12582 ASSERT_TRUE(response3
->headers
.get());
12583 EXPECT_EQ("HTTP/1.1 200 OK", response3
->headers
->GetStatusLine());
12584 EXPECT_TRUE(response3
->was_npn_negotiated
);
12585 EXPECT_FALSE(response3
->was_fetched_via_spdy
);
12586 std::string response_data3
;
12587 ASSERT_EQ(OK
, ReadTransaction(trans3
.get(), &response_data3
));
12588 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3
);
12591 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
12592 const std::string https_url
= "https://www.example.org:8080/";
12593 const std::string http_url
= "http://www.example.org:8080/";
12595 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12596 const HostPortPair
host_port_pair("www.example.org", 8080);
12597 scoped_ptr
<SpdyFrame
> connect(
12598 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
12599 scoped_ptr
<SpdyFrame
> req1(
12600 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12601 scoped_ptr
<SpdyFrame
> wrapped_req1(
12602 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
12604 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12605 SpdyHeaderBlock req2_block
;
12606 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
12607 req2_block
[spdy_util_
.GetPathKey()] = "/";
12608 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
12609 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
12610 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
12611 scoped_ptr
<SpdyFrame
> req2(
12612 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
12614 MockWrite writes1
[] = {
12615 CreateMockWrite(*connect
, 0),
12616 CreateMockWrite(*wrapped_req1
, 2),
12617 CreateMockWrite(*req2
, 5),
12620 scoped_ptr
<SpdyFrame
> conn_resp(
12621 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12622 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12623 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12624 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12625 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12626 scoped_ptr
<SpdyFrame
> wrapped_body1(
12627 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12628 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12629 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12630 MockRead reads1
[] = {
12631 CreateMockRead(*conn_resp
, 1),
12632 CreateMockRead(*wrapped_resp1
, 3),
12633 CreateMockRead(*wrapped_body1
, 4),
12634 CreateMockRead(*resp2
, 6),
12635 CreateMockRead(*body2
, 7),
12636 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12639 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12640 writes1
, arraysize(writes1
));
12641 MockConnect
connect_data1(ASYNC
, OK
);
12642 data1
.set_connect_data(connect_data1
);
12644 session_deps_
.proxy_service
.reset(
12645 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12647 session_deps_
.net_log
= &log
;
12648 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12649 ssl1
.SetNextProto(GetParam());
12650 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12651 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12652 ssl2
.SetNextProto(GetParam());
12653 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12654 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12656 scoped_refptr
<HttpNetworkSession
> session(
12657 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12659 // Start the first transaction to set up the SpdySession
12660 HttpRequestInfo request1
;
12661 request1
.method
= "GET";
12662 request1
.url
= GURL(https_url
);
12663 request1
.load_flags
= 0;
12664 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12665 TestCompletionCallback callback1
;
12666 EXPECT_EQ(ERR_IO_PENDING
,
12667 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12668 base::MessageLoop::current()->RunUntilIdle();
12671 EXPECT_EQ(OK
, callback1
.WaitForResult());
12672 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12674 LoadTimingInfo load_timing_info1
;
12675 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12676 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12677 CONNECT_TIMING_HAS_SSL_TIMES
);
12679 // Now, start the HTTP request
12680 HttpRequestInfo request2
;
12681 request2
.method
= "GET";
12682 request2
.url
= GURL(http_url
);
12683 request2
.load_flags
= 0;
12684 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12685 TestCompletionCallback callback2
;
12686 EXPECT_EQ(ERR_IO_PENDING
,
12687 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12688 base::MessageLoop::current()->RunUntilIdle();
12691 EXPECT_EQ(OK
, callback2
.WaitForResult());
12692 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12694 LoadTimingInfo load_timing_info2
;
12695 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12696 // The established SPDY sessions is considered reused by the HTTP request.
12697 TestLoadTimingReusedWithPac(load_timing_info2
);
12698 // HTTP requests over a SPDY session should have a different connection
12699 // socket_log_id than requests over a tunnel.
12700 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12703 // Test that in the case where we have a SPDY session to a SPDY proxy
12704 // that we do not pool other origins that resolve to the same IP when
12705 // the certificate does not match the new origin.
12706 // http://crbug.com/134690
12707 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12708 const std::string url1
= "http://www.example.org/";
12709 const std::string url2
= "https://news.example.org/";
12710 const std::string ip_addr
= "1.2.3.4";
12712 // SPDY GET for HTTP URL (through SPDY proxy)
12713 scoped_ptr
<SpdyHeaderBlock
> headers(
12714 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12715 scoped_ptr
<SpdyFrame
> req1(
12716 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12718 MockWrite writes1
[] = {
12719 CreateMockWrite(*req1
, 0),
12722 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12723 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12724 MockRead reads1
[] = {
12725 CreateMockRead(*resp1
, 1),
12726 CreateMockRead(*body1
, 2),
12727 MockRead(ASYNC
, OK
, 3) // EOF
12730 scoped_ptr
<DeterministicSocketData
> data1(
12731 new DeterministicSocketData(reads1
, arraysize(reads1
),
12732 writes1
, arraysize(writes1
)));
12733 IPAddressNumber ip
;
12734 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12735 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12736 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12737 data1
->set_connect_data(connect_data1
);
12739 // SPDY GET for HTTPS URL (direct)
12740 scoped_ptr
<SpdyFrame
> req2(
12741 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12743 MockWrite writes2
[] = {
12744 CreateMockWrite(*req2
, 0),
12747 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12748 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12749 MockRead reads2
[] = {
12750 CreateMockRead(*resp2
, 1),
12751 CreateMockRead(*body2
, 2),
12752 MockRead(ASYNC
, OK
, 3) // EOF
12755 scoped_ptr
<DeterministicSocketData
> data2(
12756 new DeterministicSocketData(reads2
, arraysize(reads2
),
12757 writes2
, arraysize(writes2
)));
12758 MockConnect
connect_data2(ASYNC
, OK
);
12759 data2
->set_connect_data(connect_data2
);
12761 // Set up a proxy config that sends HTTP requests to a proxy, and
12762 // all others direct.
12763 ProxyConfig proxy_config
;
12764 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12765 session_deps_
.proxy_service
.reset(new ProxyService(
12766 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12768 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12769 ssl1
.SetNextProto(GetParam());
12770 // Load a valid cert. Note, that this does not need to
12771 // be valid for proxy because the MockSSLClientSocket does
12772 // not actually verify it. But SpdySession will use this
12773 // to see if it is valid for the new origin
12774 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12775 ASSERT_TRUE(ssl1
.cert
.get());
12776 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12777 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12780 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12781 ssl2
.SetNextProto(GetParam());
12782 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12783 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12786 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12787 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12788 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12790 scoped_refptr
<HttpNetworkSession
> session(
12791 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12793 // Start the first transaction to set up the SpdySession
12794 HttpRequestInfo request1
;
12795 request1
.method
= "GET";
12796 request1
.url
= GURL(url1
);
12797 request1
.load_flags
= 0;
12798 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12799 TestCompletionCallback callback1
;
12800 ASSERT_EQ(ERR_IO_PENDING
,
12801 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12804 ASSERT_TRUE(callback1
.have_result());
12805 EXPECT_EQ(OK
, callback1
.WaitForResult());
12806 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12808 // Now, start the HTTP request
12809 HttpRequestInfo request2
;
12810 request2
.method
= "GET";
12811 request2
.url
= GURL(url2
);
12812 request2
.load_flags
= 0;
12813 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12814 TestCompletionCallback callback2
;
12815 EXPECT_EQ(ERR_IO_PENDING
,
12816 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12817 base::MessageLoop::current()->RunUntilIdle();
12820 ASSERT_TRUE(callback2
.have_result());
12821 EXPECT_EQ(OK
, callback2
.WaitForResult());
12822 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12825 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12826 // error) in SPDY session, removes the socket from pool and closes the SPDY
12827 // session. Verify that new url's from the same HttpNetworkSession (and a new
12828 // SpdySession) do work. http://crbug.com/224701
12829 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12830 const std::string https_url
= "https://www.example.org/";
12832 MockRead reads1
[] = {
12833 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12836 SequencedSocketData
data1(reads1
, arraysize(reads1
), NULL
, 0);
12838 scoped_ptr
<SpdyFrame
> req2(
12839 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12840 MockWrite writes2
[] = {
12841 CreateMockWrite(*req2
, 0),
12844 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12845 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12846 MockRead reads2
[] = {
12847 CreateMockRead(*resp2
, 1),
12848 CreateMockRead(*body2
, 2),
12849 MockRead(ASYNC
, OK
, 3) // EOF
12852 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12853 arraysize(writes2
));
12855 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12856 ssl1
.SetNextProto(GetParam());
12857 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12858 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12860 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12861 ssl2
.SetNextProto(GetParam());
12862 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12863 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12865 scoped_refptr
<HttpNetworkSession
> session(
12866 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
12868 // Start the first transaction to set up the SpdySession and verify that
12869 // connection was closed.
12870 HttpRequestInfo request1
;
12871 request1
.method
= "GET";
12872 request1
.url
= GURL(https_url
);
12873 request1
.load_flags
= 0;
12874 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12875 TestCompletionCallback callback1
;
12876 EXPECT_EQ(ERR_IO_PENDING
,
12877 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12878 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12880 // Now, start the second request and make sure it succeeds.
12881 HttpRequestInfo request2
;
12882 request2
.method
= "GET";
12883 request2
.url
= GURL(https_url
);
12884 request2
.load_flags
= 0;
12885 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12886 TestCompletionCallback callback2
;
12887 EXPECT_EQ(ERR_IO_PENDING
,
12888 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12890 ASSERT_EQ(OK
, callback2
.WaitForResult());
12891 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12894 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12895 session_deps_
.next_protos
= SpdyNextProtos();
12896 ClientSocketPoolManager::set_max_sockets_per_group(
12897 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12898 ClientSocketPoolManager::set_max_sockets_per_pool(
12899 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12901 // Use two different hosts with different IPs so they don't get pooled.
12902 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12903 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12904 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12906 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12907 ssl1
.SetNextProto(GetParam());
12908 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12909 ssl2
.SetNextProto(GetParam());
12910 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12911 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12913 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12914 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12915 MockWrite spdy1_writes
[] = {
12916 CreateMockWrite(*host1_req
, 0),
12918 scoped_ptr
<SpdyFrame
> host1_resp(
12919 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12920 scoped_ptr
<SpdyFrame
> host1_resp_body(
12921 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12922 MockRead spdy1_reads
[] = {
12923 CreateMockRead(*host1_resp
, 1),
12924 CreateMockRead(*host1_resp_body
, 2),
12925 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12928 scoped_ptr
<SequencedSocketData
> spdy1_data(
12929 new SequencedSocketData(spdy1_reads
, arraysize(spdy1_reads
), spdy1_writes
,
12930 arraysize(spdy1_writes
)));
12931 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12933 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12934 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12935 MockWrite spdy2_writes
[] = {
12936 CreateMockWrite(*host2_req
, 0),
12938 scoped_ptr
<SpdyFrame
> host2_resp(
12939 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12940 scoped_ptr
<SpdyFrame
> host2_resp_body(
12941 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12942 MockRead spdy2_reads
[] = {
12943 CreateMockRead(*host2_resp
, 1),
12944 CreateMockRead(*host2_resp_body
, 2),
12945 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12948 scoped_ptr
<SequencedSocketData
> spdy2_data(
12949 new SequencedSocketData(spdy2_reads
, arraysize(spdy2_reads
), spdy2_writes
,
12950 arraysize(spdy2_writes
)));
12951 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12953 MockWrite http_write
[] = {
12954 MockWrite("GET / HTTP/1.1\r\n"
12955 "Host: www.a.com\r\n"
12956 "Connection: keep-alive\r\n\r\n"),
12959 MockRead http_read
[] = {
12960 MockRead("HTTP/1.1 200 OK\r\n"),
12961 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12962 MockRead("Content-Length: 6\r\n\r\n"),
12963 MockRead("hello!"),
12965 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12966 http_write
, arraysize(http_write
));
12967 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12969 HostPortPair
host_port_pair_a("www.a.com", 443);
12970 SpdySessionKey
spdy_session_key_a(
12971 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12973 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12975 TestCompletionCallback callback
;
12976 HttpRequestInfo request1
;
12977 request1
.method
= "GET";
12978 request1
.url
= GURL("https://www.a.com/");
12979 request1
.load_flags
= 0;
12980 scoped_ptr
<HttpNetworkTransaction
> trans(
12981 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12983 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12984 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12985 EXPECT_EQ(OK
, callback
.WaitForResult());
12987 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12988 ASSERT_TRUE(response
!= NULL
);
12989 ASSERT_TRUE(response
->headers
.get() != NULL
);
12990 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12991 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12992 EXPECT_TRUE(response
->was_npn_negotiated
);
12994 std::string response_data
;
12995 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12996 EXPECT_EQ("hello!", response_data
);
12999 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
13001 HostPortPair
host_port_pair_b("www.b.com", 443);
13002 SpdySessionKey
spdy_session_key_b(
13003 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
13005 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13006 HttpRequestInfo request2
;
13007 request2
.method
= "GET";
13008 request2
.url
= GURL("https://www.b.com/");
13009 request2
.load_flags
= 0;
13010 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13012 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
13013 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13014 EXPECT_EQ(OK
, callback
.WaitForResult());
13016 response
= trans
->GetResponseInfo();
13017 ASSERT_TRUE(response
!= NULL
);
13018 ASSERT_TRUE(response
->headers
.get() != NULL
);
13019 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
13020 EXPECT_TRUE(response
->was_fetched_via_spdy
);
13021 EXPECT_TRUE(response
->was_npn_negotiated
);
13022 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
13023 EXPECT_EQ("hello!", response_data
);
13025 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
13027 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13029 HostPortPair
host_port_pair_a1("www.a.com", 80);
13030 SpdySessionKey
spdy_session_key_a1(
13031 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
13033 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
13034 HttpRequestInfo request3
;
13035 request3
.method
= "GET";
13036 request3
.url
= GURL("http://www.a.com/");
13037 request3
.load_flags
= 0;
13038 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13040 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
13041 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13042 EXPECT_EQ(OK
, callback
.WaitForResult());
13044 response
= trans
->GetResponseInfo();
13045 ASSERT_TRUE(response
!= NULL
);
13046 ASSERT_TRUE(response
->headers
.get() != NULL
);
13047 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
13048 EXPECT_FALSE(response
->was_fetched_via_spdy
);
13049 EXPECT_FALSE(response
->was_npn_negotiated
);
13050 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
13051 EXPECT_EQ("hello!", response_data
);
13053 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
13055 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13058 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
13059 HttpRequestInfo request
;
13060 request
.method
= "GET";
13061 request
.url
= GURL("http://www.example.org/");
13062 request
.load_flags
= 0;
13064 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13065 scoped_ptr
<HttpTransaction
> trans(
13066 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13068 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
13069 StaticSocketDataProvider data
;
13070 data
.set_connect_data(mock_connect
);
13071 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13073 TestCompletionCallback callback
;
13075 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13076 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13078 rv
= callback
.WaitForResult();
13079 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
13081 // We don't care whether this succeeds or fails, but it shouldn't crash.
13082 HttpRequestHeaders request_headers
;
13083 trans
->GetFullRequestHeaders(&request_headers
);
13085 ConnectionAttempts attempts
;
13086 trans
->GetConnectionAttempts(&attempts
);
13087 ASSERT_EQ(1u, attempts
.size());
13088 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
13091 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
13092 HttpRequestInfo request
;
13093 request
.method
= "GET";
13094 request
.url
= GURL("http://www.example.org/");
13095 request
.load_flags
= 0;
13097 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13098 scoped_ptr
<HttpTransaction
> trans(
13099 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13101 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
13102 StaticSocketDataProvider data
;
13103 data
.set_connect_data(mock_connect
);
13104 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13106 TestCompletionCallback callback
;
13108 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13109 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13111 rv
= callback
.WaitForResult();
13112 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
13114 // We don't care whether this succeeds or fails, but it shouldn't crash.
13115 HttpRequestHeaders request_headers
;
13116 trans
->GetFullRequestHeaders(&request_headers
);
13118 ConnectionAttempts attempts
;
13119 trans
->GetConnectionAttempts(&attempts
);
13120 ASSERT_EQ(1u, attempts
.size());
13121 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
13124 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
13125 HttpRequestInfo request
;
13126 request
.method
= "GET";
13127 request
.url
= GURL("http://www.example.org/");
13128 request
.load_flags
= 0;
13130 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13131 scoped_ptr
<HttpTransaction
> trans(
13132 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13134 MockWrite data_writes
[] = {
13135 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13137 MockRead data_reads
[] = {
13138 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
13141 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13142 data_writes
, arraysize(data_writes
));
13143 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13145 TestCompletionCallback callback
;
13147 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13148 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13150 rv
= callback
.WaitForResult();
13151 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13153 HttpRequestHeaders request_headers
;
13154 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13155 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13158 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
13159 HttpRequestInfo request
;
13160 request
.method
= "GET";
13161 request
.url
= GURL("http://www.example.org/");
13162 request
.load_flags
= 0;
13164 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13165 scoped_ptr
<HttpTransaction
> trans(
13166 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13168 MockWrite data_writes
[] = {
13169 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
13171 MockRead data_reads
[] = {
13172 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
13175 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13176 data_writes
, arraysize(data_writes
));
13177 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13179 TestCompletionCallback callback
;
13181 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13182 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13184 rv
= callback
.WaitForResult();
13185 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13187 HttpRequestHeaders request_headers
;
13188 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13189 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13192 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
13193 HttpRequestInfo request
;
13194 request
.method
= "GET";
13195 request
.url
= GURL("http://www.example.org/");
13196 request
.load_flags
= 0;
13198 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13199 scoped_ptr
<HttpTransaction
> trans(
13200 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13202 MockWrite data_writes
[] = {
13204 "GET / HTTP/1.1\r\n"
13205 "Host: www.example.org\r\n"
13206 "Connection: keep-alive\r\n\r\n"),
13208 MockRead data_reads
[] = {
13209 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13212 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13213 data_writes
, arraysize(data_writes
));
13214 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13216 TestCompletionCallback callback
;
13218 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13219 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13221 rv
= callback
.WaitForResult();
13222 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13224 HttpRequestHeaders request_headers
;
13225 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13226 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13229 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
13230 HttpRequestInfo request
;
13231 request
.method
= "GET";
13232 request
.url
= GURL("http://www.example.org/");
13233 request
.load_flags
= 0;
13235 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13236 scoped_ptr
<HttpTransaction
> trans(
13237 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13239 MockWrite data_writes
[] = {
13241 "GET / HTTP/1.1\r\n"
13242 "Host: www.example.org\r\n"
13243 "Connection: keep-alive\r\n\r\n"),
13245 MockRead data_reads
[] = {
13246 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
13249 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13250 data_writes
, arraysize(data_writes
));
13251 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13253 TestCompletionCallback callback
;
13255 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13258 rv
= callback
.WaitForResult();
13259 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13261 HttpRequestHeaders request_headers
;
13262 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13263 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13266 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
13267 HttpRequestInfo request
;
13268 request
.method
= "GET";
13269 request
.url
= GURL("http://www.example.org/");
13270 request
.load_flags
= 0;
13271 request
.extra_headers
.SetHeader("X-Foo", "bar");
13273 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13274 scoped_ptr
<HttpTransaction
> trans(
13275 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13277 MockWrite data_writes
[] = {
13279 "GET / HTTP/1.1\r\n"
13280 "Host: www.example.org\r\n"
13281 "Connection: keep-alive\r\n"
13282 "X-Foo: bar\r\n\r\n"),
13284 MockRead data_reads
[] = {
13285 MockRead("HTTP/1.1 200 OK\r\n"
13286 "Content-Length: 5\r\n\r\n"
13288 MockRead(ASYNC
, ERR_UNEXPECTED
),
13291 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13292 data_writes
, arraysize(data_writes
));
13293 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13295 TestCompletionCallback callback
;
13297 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13298 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13300 rv
= callback
.WaitForResult();
13303 HttpRequestHeaders request_headers
;
13304 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13306 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
13307 EXPECT_EQ("bar", foo
);
13312 // Fake HttpStream that simply records calls to SetPriority().
13313 class FakeStream
: public HttpStream
,
13314 public base::SupportsWeakPtr
<FakeStream
> {
13316 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
13317 ~FakeStream() override
{}
13319 RequestPriority
priority() const { return priority_
; }
13321 int InitializeStream(const HttpRequestInfo
* request_info
,
13322 RequestPriority priority
,
13323 const BoundNetLog
& net_log
,
13324 const CompletionCallback
& callback
) override
{
13325 return ERR_IO_PENDING
;
13328 int SendRequest(const HttpRequestHeaders
& request_headers
,
13329 HttpResponseInfo
* response
,
13330 const CompletionCallback
& callback
) override
{
13332 return ERR_UNEXPECTED
;
13335 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13337 return ERR_UNEXPECTED
;
13340 int ReadResponseBody(IOBuffer
* buf
,
13342 const CompletionCallback
& callback
) override
{
13344 return ERR_UNEXPECTED
;
13347 void Close(bool not_reusable
) override
{}
13349 bool IsResponseBodyComplete() const override
{
13354 bool IsConnectionReused() const override
{
13359 void SetConnectionReused() override
{ ADD_FAILURE(); }
13361 bool CanReuseConnection() const override
{ return false; }
13363 int64
GetTotalReceivedBytes() const override
{
13368 int64_t GetTotalSentBytes() const override
{
13373 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13378 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
13380 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13384 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
13386 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13388 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
13390 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
13393 RequestPriority priority_
;
13395 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
13398 // Fake HttpStreamRequest that simply records calls to SetPriority()
13399 // and vends FakeStreams with its current priority.
13400 class FakeStreamRequest
: public HttpStreamRequest
,
13401 public base::SupportsWeakPtr
<FakeStreamRequest
> {
13403 FakeStreamRequest(RequestPriority priority
,
13404 HttpStreamRequest::Delegate
* delegate
)
13405 : priority_(priority
),
13406 delegate_(delegate
),
13407 websocket_stream_create_helper_(NULL
) {}
13409 FakeStreamRequest(RequestPriority priority
,
13410 HttpStreamRequest::Delegate
* delegate
,
13411 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
13412 : priority_(priority
),
13413 delegate_(delegate
),
13414 websocket_stream_create_helper_(create_helper
) {}
13416 ~FakeStreamRequest() override
{}
13418 RequestPriority
priority() const { return priority_
; }
13420 const WebSocketHandshakeStreamBase::CreateHelper
*
13421 websocket_stream_create_helper() const {
13422 return websocket_stream_create_helper_
;
13425 // Create a new FakeStream and pass it to the request's
13426 // delegate. Returns a weak pointer to the FakeStream.
13427 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
13428 FakeStream
* fake_stream
= new FakeStream(priority_
);
13429 // Do this before calling OnStreamReady() as OnStreamReady() may
13430 // immediately delete |fake_stream|.
13431 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
13432 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
13433 return weak_stream
;
13436 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
13438 return ERR_UNEXPECTED
;
13441 LoadState
GetLoadState() const override
{
13443 return LoadState();
13446 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13448 bool was_npn_negotiated() const override
{ return false; }
13450 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
13452 bool using_spdy() const override
{ return false; }
13454 const ConnectionAttempts
& connection_attempts() const override
{
13455 static ConnectionAttempts no_attempts
;
13456 return no_attempts
;
13460 RequestPriority priority_
;
13461 HttpStreamRequest::Delegate
* const delegate_
;
13462 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
13464 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
13467 // Fake HttpStreamFactory that vends FakeStreamRequests.
13468 class FakeStreamFactory
: public HttpStreamFactory
{
13470 FakeStreamFactory() {}
13471 ~FakeStreamFactory() override
{}
13473 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13474 // RequestStream() (which may be NULL if it was destroyed already).
13475 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
13476 return last_stream_request_
;
13479 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
13480 RequestPriority priority
,
13481 const SSLConfig
& server_ssl_config
,
13482 const SSLConfig
& proxy_ssl_config
,
13483 HttpStreamRequest::Delegate
* delegate
,
13484 const BoundNetLog
& net_log
) override
{
13485 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
13486 last_stream_request_
= fake_request
->AsWeakPtr();
13487 return fake_request
;
13490 HttpStreamRequest
* RequestWebSocketHandshakeStream(
13491 const HttpRequestInfo
& info
,
13492 RequestPriority priority
,
13493 const SSLConfig
& server_ssl_config
,
13494 const SSLConfig
& proxy_ssl_config
,
13495 HttpStreamRequest::Delegate
* delegate
,
13496 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
13497 const BoundNetLog
& net_log
) override
{
13498 FakeStreamRequest
* fake_request
=
13499 new FakeStreamRequest(priority
, delegate
, create_helper
);
13500 last_stream_request_
= fake_request
->AsWeakPtr();
13501 return fake_request
;
13504 void PreconnectStreams(int num_streams
,
13505 const HttpRequestInfo
& info
,
13506 const SSLConfig
& server_ssl_config
,
13507 const SSLConfig
& proxy_ssl_config
) override
{
13511 const HostMappingRules
* GetHostMappingRules() const override
{
13517 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
13519 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
13522 // TODO(ricea): Maybe unify this with the one in
13523 // url_request_http_job_unittest.cc ?
13524 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
13526 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
13528 : state_(connection
.release(), using_proxy
) {}
13530 // Fake implementation of HttpStreamBase methods.
13531 // This ends up being quite "real" because this object has to really send data
13532 // on the mock socket. It might be easier to use the real implementation, but
13533 // the fact that the WebSocket code is not compiled on iOS makes that
13535 int InitializeStream(const HttpRequestInfo
* request_info
,
13536 RequestPriority priority
,
13537 const BoundNetLog
& net_log
,
13538 const CompletionCallback
& callback
) override
{
13539 state_
.Initialize(request_info
, priority
, net_log
, callback
);
13543 int SendRequest(const HttpRequestHeaders
& request_headers
,
13544 HttpResponseInfo
* response
,
13545 const CompletionCallback
& callback
) override
{
13546 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
13547 response
, callback
);
13550 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13551 return parser()->ReadResponseHeaders(callback
);
13554 int ReadResponseBody(IOBuffer
* buf
,
13556 const CompletionCallback
& callback
) override
{
13558 return ERR_IO_PENDING
;
13561 void Close(bool not_reusable
) override
{
13563 parser()->Close(true);
13566 bool IsResponseBodyComplete() const override
{
13571 bool IsConnectionReused() const override
{
13575 void SetConnectionReused() override
{ NOTREACHED(); }
13577 bool CanReuseConnection() const override
{ return false; }
13579 int64
GetTotalReceivedBytes() const override
{
13584 int64_t GetTotalSentBytes() const override
{
13589 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13594 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13596 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13600 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13602 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13604 UploadProgress
GetUploadProgress() const override
{
13606 return UploadProgress();
13609 HttpStream
* RenewStreamForAuth() override
{
13614 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13615 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13617 return scoped_ptr
<WebSocketStream
>();
13621 HttpStreamParser
* parser() const { return state_
.parser(); }
13622 HttpBasicState state_
;
13624 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13627 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13629 class FakeWebSocketStreamCreateHelper
:
13630 public WebSocketHandshakeStreamBase::CreateHelper
{
13632 WebSocketHandshakeStreamBase
* CreateBasicStream(
13633 scoped_ptr
<ClientSocketHandle
> connection
,
13634 bool using_proxy
) override
{
13635 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13639 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13640 const base::WeakPtr
<SpdySession
>& session
,
13641 bool use_relative_url
) override
{
13646 ~FakeWebSocketStreamCreateHelper() override
{}
13648 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13650 return scoped_ptr
<WebSocketStream
>();
13656 // Make sure that HttpNetworkTransaction passes on its priority to its
13657 // stream request on start.
13658 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13659 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13660 HttpNetworkSessionPeer
peer(session
);
13661 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13662 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13664 HttpNetworkTransaction
trans(LOW
, session
.get());
13666 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13668 HttpRequestInfo request
;
13669 TestCompletionCallback callback
;
13670 EXPECT_EQ(ERR_IO_PENDING
,
13671 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13673 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13674 fake_factory
->last_stream_request();
13675 ASSERT_TRUE(fake_request
!= NULL
);
13676 EXPECT_EQ(LOW
, fake_request
->priority());
13679 // Make sure that HttpNetworkTransaction passes on its priority
13680 // updates to its stream request.
13681 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13682 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13683 HttpNetworkSessionPeer
peer(session
);
13684 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13685 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13687 HttpNetworkTransaction
trans(LOW
, session
.get());
13689 HttpRequestInfo request
;
13690 TestCompletionCallback callback
;
13691 EXPECT_EQ(ERR_IO_PENDING
,
13692 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13694 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13695 fake_factory
->last_stream_request();
13696 ASSERT_TRUE(fake_request
!= NULL
);
13697 EXPECT_EQ(LOW
, fake_request
->priority());
13699 trans
.SetPriority(LOWEST
);
13700 ASSERT_TRUE(fake_request
!= NULL
);
13701 EXPECT_EQ(LOWEST
, fake_request
->priority());
13704 // Make sure that HttpNetworkTransaction passes on its priority
13705 // updates to its stream.
13706 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13707 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13708 HttpNetworkSessionPeer
peer(session
);
13709 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13710 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13712 HttpNetworkTransaction
trans(LOW
, session
.get());
13714 HttpRequestInfo request
;
13715 TestCompletionCallback callback
;
13716 EXPECT_EQ(ERR_IO_PENDING
,
13717 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13719 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13720 fake_factory
->last_stream_request();
13721 ASSERT_TRUE(fake_request
!= NULL
);
13722 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13723 ASSERT_TRUE(fake_stream
!= NULL
);
13724 EXPECT_EQ(LOW
, fake_stream
->priority());
13726 trans
.SetPriority(LOWEST
);
13727 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13730 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13731 // The same logic needs to be tested for both ws: and wss: schemes, but this
13732 // test is already parameterised on NextProto, so it uses a loop to verify
13733 // that the different schemes work.
13734 std::string test_cases
[] = {"ws://www.example.org/",
13735 "wss://www.example.org/"};
13736 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13737 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13738 HttpNetworkSessionPeer
peer(session
);
13739 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13740 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13741 peer
.SetHttpStreamFactoryForWebSocket(
13742 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13744 HttpNetworkTransaction
trans(LOW
, session
.get());
13745 trans
.SetWebSocketHandshakeStreamCreateHelper(
13746 &websocket_stream_create_helper
);
13748 HttpRequestInfo request
;
13749 TestCompletionCallback callback
;
13750 request
.method
= "GET";
13751 request
.url
= GURL(test_cases
[i
]);
13753 EXPECT_EQ(ERR_IO_PENDING
,
13754 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13756 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13757 fake_factory
->last_stream_request();
13758 ASSERT_TRUE(fake_request
!= NULL
);
13759 EXPECT_EQ(&websocket_stream_create_helper
,
13760 fake_request
->websocket_stream_create_helper());
13764 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13765 // if the transport socket pool is stalled on the global socket limit.
13766 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13767 ClientSocketPoolManager::set_max_sockets_per_group(
13768 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13769 ClientSocketPoolManager::set_max_sockets_per_pool(
13770 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13772 // Set up SSL request.
13774 HttpRequestInfo ssl_request
;
13775 ssl_request
.method
= "GET";
13776 ssl_request
.url
= GURL("https://www.example.org/");
13778 MockWrite ssl_writes
[] = {
13780 "GET / HTTP/1.1\r\n"
13781 "Host: www.example.org\r\n"
13782 "Connection: keep-alive\r\n\r\n"),
13784 MockRead ssl_reads
[] = {
13785 MockRead("HTTP/1.1 200 OK\r\n"),
13786 MockRead("Content-Length: 11\r\n\r\n"),
13787 MockRead("hello world"),
13788 MockRead(SYNCHRONOUS
, OK
),
13790 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13791 ssl_writes
, arraysize(ssl_writes
));
13792 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13794 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13795 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13797 // Set up HTTP request.
13799 HttpRequestInfo http_request
;
13800 http_request
.method
= "GET";
13801 http_request
.url
= GURL("http://www.example.org/");
13803 MockWrite http_writes
[] = {
13805 "GET / HTTP/1.1\r\n"
13806 "Host: www.example.org\r\n"
13807 "Connection: keep-alive\r\n\r\n"),
13809 MockRead http_reads
[] = {
13810 MockRead("HTTP/1.1 200 OK\r\n"),
13811 MockRead("Content-Length: 7\r\n\r\n"),
13812 MockRead("falafel"),
13813 MockRead(SYNCHRONOUS
, OK
),
13815 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13816 http_writes
, arraysize(http_writes
));
13817 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13819 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13821 // Start the SSL request.
13822 TestCompletionCallback ssl_callback
;
13823 scoped_ptr
<HttpTransaction
> ssl_trans(
13824 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13825 ASSERT_EQ(ERR_IO_PENDING
,
13826 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13829 // Start the HTTP request. Pool should stall.
13830 TestCompletionCallback http_callback
;
13831 scoped_ptr
<HttpTransaction
> http_trans(
13832 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13833 ASSERT_EQ(ERR_IO_PENDING
,
13834 http_trans
->Start(&http_request
, http_callback
.callback(),
13836 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13838 // Wait for response from SSL request.
13839 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13840 std::string response_data
;
13841 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13842 EXPECT_EQ("hello world", response_data
);
13844 // The SSL socket should automatically be closed, so the HTTP request can
13846 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13847 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13849 // The HTTP request can now complete.
13850 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13851 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13852 EXPECT_EQ("falafel", response_data
);
13854 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13857 // Tests that when a SSL connection is established but there's no corresponding
13858 // request that needs it, the new socket is closed if the transport socket pool
13859 // is stalled on the global socket limit.
13860 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13861 ClientSocketPoolManager::set_max_sockets_per_group(
13862 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13863 ClientSocketPoolManager::set_max_sockets_per_pool(
13864 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13866 // Set up an ssl request.
13868 HttpRequestInfo ssl_request
;
13869 ssl_request
.method
= "GET";
13870 ssl_request
.url
= GURL("https://www.foopy.com/");
13872 // No data will be sent on the SSL socket.
13873 StaticSocketDataProvider ssl_data
;
13874 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13876 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13877 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13879 // Set up HTTP request.
13881 HttpRequestInfo http_request
;
13882 http_request
.method
= "GET";
13883 http_request
.url
= GURL("http://www.example.org/");
13885 MockWrite http_writes
[] = {
13887 "GET / HTTP/1.1\r\n"
13888 "Host: www.example.org\r\n"
13889 "Connection: keep-alive\r\n\r\n"),
13891 MockRead http_reads
[] = {
13892 MockRead("HTTP/1.1 200 OK\r\n"),
13893 MockRead("Content-Length: 7\r\n\r\n"),
13894 MockRead("falafel"),
13895 MockRead(SYNCHRONOUS
, OK
),
13897 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13898 http_writes
, arraysize(http_writes
));
13899 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13901 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13903 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13904 // cancelled when a normal transaction is cancelled.
13905 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13906 SSLConfig ssl_config
;
13907 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13908 http_stream_factory
->PreconnectStreams(1, ssl_request
, ssl_config
,
13910 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13912 // Start the HTTP request. Pool should stall.
13913 TestCompletionCallback http_callback
;
13914 scoped_ptr
<HttpTransaction
> http_trans(
13915 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13916 ASSERT_EQ(ERR_IO_PENDING
,
13917 http_trans
->Start(&http_request
, http_callback
.callback(),
13919 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13921 // The SSL connection will automatically be closed once the connection is
13922 // established, to let the HTTP request start.
13923 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13924 std::string response_data
;
13925 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13926 EXPECT_EQ("falafel", response_data
);
13928 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13931 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13932 ScopedVector
<UploadElementReader
> element_readers
;
13933 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13934 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13936 HttpRequestInfo request
;
13937 request
.method
= "POST";
13938 request
.url
= GURL("http://www.foo.com/");
13939 request
.upload_data_stream
= &upload_data_stream
;
13940 request
.load_flags
= 0;
13942 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13943 scoped_ptr
<HttpTransaction
> trans(
13944 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13945 // Send headers successfully, but get an error while sending the body.
13946 MockWrite data_writes
[] = {
13947 MockWrite("POST / HTTP/1.1\r\n"
13948 "Host: www.foo.com\r\n"
13949 "Connection: keep-alive\r\n"
13950 "Content-Length: 3\r\n\r\n"),
13951 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13954 MockRead data_reads
[] = {
13955 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13956 MockRead("hello world"),
13957 MockRead(SYNCHRONOUS
, OK
),
13959 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13960 arraysize(data_writes
));
13961 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13963 TestCompletionCallback callback
;
13965 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13966 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13968 rv
= callback
.WaitForResult();
13971 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13972 ASSERT_TRUE(response
!= NULL
);
13974 EXPECT_TRUE(response
->headers
.get() != NULL
);
13975 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13977 std::string response_data
;
13978 rv
= ReadTransaction(trans
.get(), &response_data
);
13980 EXPECT_EQ("hello world", response_data
);
13983 // This test makes sure the retry logic doesn't trigger when reading an error
13984 // response from a server that rejected a POST with a CONNECTION_RESET.
13985 TEST_P(HttpNetworkTransactionTest
,
13986 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13987 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13988 MockWrite data_writes
[] = {
13989 MockWrite("GET / HTTP/1.1\r\n"
13990 "Host: www.foo.com\r\n"
13991 "Connection: keep-alive\r\n\r\n"),
13992 MockWrite("POST / HTTP/1.1\r\n"
13993 "Host: www.foo.com\r\n"
13994 "Connection: keep-alive\r\n"
13995 "Content-Length: 3\r\n\r\n"),
13996 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13999 MockRead data_reads
[] = {
14000 MockRead("HTTP/1.1 200 Peachy\r\n"
14001 "Content-Length: 14\r\n\r\n"),
14002 MockRead("first response"),
14003 MockRead("HTTP/1.1 400 Not OK\r\n"
14004 "Content-Length: 15\r\n\r\n"),
14005 MockRead("second response"),
14006 MockRead(SYNCHRONOUS
, OK
),
14008 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14009 arraysize(data_writes
));
14010 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14012 TestCompletionCallback callback
;
14013 HttpRequestInfo request1
;
14014 request1
.method
= "GET";
14015 request1
.url
= GURL("http://www.foo.com/");
14016 request1
.load_flags
= 0;
14018 scoped_ptr
<HttpTransaction
> trans1(
14019 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14020 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
14021 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14023 rv
= callback
.WaitForResult();
14026 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
14027 ASSERT_TRUE(response1
!= NULL
);
14029 EXPECT_TRUE(response1
->headers
.get() != NULL
);
14030 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
14032 std::string response_data1
;
14033 rv
= ReadTransaction(trans1
.get(), &response_data1
);
14035 EXPECT_EQ("first response", response_data1
);
14036 // Delete the transaction to release the socket back into the socket pool.
14039 ScopedVector
<UploadElementReader
> element_readers
;
14040 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14041 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14043 HttpRequestInfo request2
;
14044 request2
.method
= "POST";
14045 request2
.url
= GURL("http://www.foo.com/");
14046 request2
.upload_data_stream
= &upload_data_stream
;
14047 request2
.load_flags
= 0;
14049 scoped_ptr
<HttpTransaction
> trans2(
14050 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14051 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
14052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14054 rv
= callback
.WaitForResult();
14057 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
14058 ASSERT_TRUE(response2
!= NULL
);
14060 EXPECT_TRUE(response2
->headers
.get() != NULL
);
14061 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
14063 std::string response_data2
;
14064 rv
= ReadTransaction(trans2
.get(), &response_data2
);
14066 EXPECT_EQ("second response", response_data2
);
14069 TEST_P(HttpNetworkTransactionTest
,
14070 PostReadsErrorResponseAfterResetPartialBodySent
) {
14071 ScopedVector
<UploadElementReader
> element_readers
;
14072 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14073 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14075 HttpRequestInfo request
;
14076 request
.method
= "POST";
14077 request
.url
= GURL("http://www.foo.com/");
14078 request
.upload_data_stream
= &upload_data_stream
;
14079 request
.load_flags
= 0;
14081 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14082 scoped_ptr
<HttpTransaction
> trans(
14083 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14084 // Send headers successfully, but get an error while sending the body.
14085 MockWrite data_writes
[] = {
14086 MockWrite("POST / HTTP/1.1\r\n"
14087 "Host: www.foo.com\r\n"
14088 "Connection: keep-alive\r\n"
14089 "Content-Length: 3\r\n\r\n"
14091 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14094 MockRead data_reads
[] = {
14095 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14096 MockRead("hello world"),
14097 MockRead(SYNCHRONOUS
, OK
),
14099 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14100 arraysize(data_writes
));
14101 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14103 TestCompletionCallback callback
;
14105 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14108 rv
= callback
.WaitForResult();
14111 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14112 ASSERT_TRUE(response
!= NULL
);
14114 EXPECT_TRUE(response
->headers
.get() != NULL
);
14115 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14117 std::string response_data
;
14118 rv
= ReadTransaction(trans
.get(), &response_data
);
14120 EXPECT_EQ("hello world", response_data
);
14123 // This tests the more common case than the previous test, where headers and
14124 // body are not merged into a single request.
14125 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
14126 ScopedVector
<UploadElementReader
> element_readers
;
14127 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14128 ChunkedUploadDataStream
upload_data_stream(0);
14130 HttpRequestInfo request
;
14131 request
.method
= "POST";
14132 request
.url
= GURL("http://www.foo.com/");
14133 request
.upload_data_stream
= &upload_data_stream
;
14134 request
.load_flags
= 0;
14136 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14137 scoped_ptr
<HttpTransaction
> trans(
14138 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14139 // Send headers successfully, but get an error while sending the body.
14140 MockWrite data_writes
[] = {
14141 MockWrite("POST / HTTP/1.1\r\n"
14142 "Host: www.foo.com\r\n"
14143 "Connection: keep-alive\r\n"
14144 "Transfer-Encoding: chunked\r\n\r\n"),
14145 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14148 MockRead data_reads
[] = {
14149 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14150 MockRead("hello world"),
14151 MockRead(SYNCHRONOUS
, OK
),
14153 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14154 arraysize(data_writes
));
14155 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14157 TestCompletionCallback callback
;
14159 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14160 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14161 // Make sure the headers are sent before adding a chunk. This ensures that
14162 // they can't be merged with the body in a single send. Not currently
14163 // necessary since a chunked body is never merged with headers, but this makes
14164 // the test more future proof.
14165 base::RunLoop().RunUntilIdle();
14167 upload_data_stream
.AppendData("last chunk", 10, true);
14169 rv
= callback
.WaitForResult();
14172 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14173 ASSERT_TRUE(response
!= NULL
);
14175 EXPECT_TRUE(response
->headers
.get() != NULL
);
14176 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14178 std::string response_data
;
14179 rv
= ReadTransaction(trans
.get(), &response_data
);
14181 EXPECT_EQ("hello world", response_data
);
14184 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
14185 ScopedVector
<UploadElementReader
> element_readers
;
14186 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14187 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14189 HttpRequestInfo request
;
14190 request
.method
= "POST";
14191 request
.url
= GURL("http://www.foo.com/");
14192 request
.upload_data_stream
= &upload_data_stream
;
14193 request
.load_flags
= 0;
14195 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14196 scoped_ptr
<HttpTransaction
> trans(
14197 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14199 MockWrite data_writes
[] = {
14200 MockWrite("POST / HTTP/1.1\r\n"
14201 "Host: www.foo.com\r\n"
14202 "Connection: keep-alive\r\n"
14203 "Content-Length: 3\r\n\r\n"),
14204 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14207 MockRead data_reads
[] = {
14208 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14209 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14210 MockRead("hello world"),
14211 MockRead(SYNCHRONOUS
, OK
),
14213 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14214 arraysize(data_writes
));
14215 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14217 TestCompletionCallback callback
;
14219 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14220 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14222 rv
= callback
.WaitForResult();
14225 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14226 ASSERT_TRUE(response
!= NULL
);
14228 EXPECT_TRUE(response
->headers
.get() != NULL
);
14229 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14231 std::string response_data
;
14232 rv
= ReadTransaction(trans
.get(), &response_data
);
14234 EXPECT_EQ("hello world", response_data
);
14237 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
14238 ScopedVector
<UploadElementReader
> element_readers
;
14239 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14240 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14242 HttpRequestInfo request
;
14243 request
.method
= "POST";
14244 request
.url
= GURL("http://www.foo.com/");
14245 request
.upload_data_stream
= &upload_data_stream
;
14246 request
.load_flags
= 0;
14248 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14249 scoped_ptr
<HttpTransaction
> trans(
14250 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14251 // Send headers successfully, but get an error while sending the body.
14252 MockWrite data_writes
[] = {
14253 MockWrite("POST / HTTP/1.1\r\n"
14254 "Host: www.foo.com\r\n"
14255 "Connection: keep-alive\r\n"
14256 "Content-Length: 3\r\n\r\n"),
14257 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14260 MockRead data_reads
[] = {
14261 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14262 MockRead("hello world"),
14263 MockRead(SYNCHRONOUS
, OK
),
14265 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14266 arraysize(data_writes
));
14267 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14269 TestCompletionCallback callback
;
14271 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14274 rv
= callback
.WaitForResult();
14275 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14278 TEST_P(HttpNetworkTransactionTest
,
14279 PostIgnoresNonErrorResponseAfterResetAnd100
) {
14280 ScopedVector
<UploadElementReader
> element_readers
;
14281 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14282 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14284 HttpRequestInfo request
;
14285 request
.method
= "POST";
14286 request
.url
= GURL("http://www.foo.com/");
14287 request
.upload_data_stream
= &upload_data_stream
;
14288 request
.load_flags
= 0;
14290 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14291 scoped_ptr
<HttpTransaction
> trans(
14292 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14293 // Send headers successfully, but get an error while sending the body.
14294 MockWrite data_writes
[] = {
14295 MockWrite("POST / HTTP/1.1\r\n"
14296 "Host: www.foo.com\r\n"
14297 "Connection: keep-alive\r\n"
14298 "Content-Length: 3\r\n\r\n"),
14299 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14302 MockRead data_reads
[] = {
14303 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14304 MockRead("HTTP/1.0 302 Redirect\r\n"),
14305 MockRead("Location: http://somewhere-else.com/\r\n"),
14306 MockRead("Content-Length: 0\r\n\r\n"),
14307 MockRead(SYNCHRONOUS
, OK
),
14309 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14310 arraysize(data_writes
));
14311 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14313 TestCompletionCallback callback
;
14315 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14316 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14318 rv
= callback
.WaitForResult();
14319 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14322 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
14323 ScopedVector
<UploadElementReader
> element_readers
;
14324 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14325 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14327 HttpRequestInfo request
;
14328 request
.method
= "POST";
14329 request
.url
= GURL("http://www.foo.com/");
14330 request
.upload_data_stream
= &upload_data_stream
;
14331 request
.load_flags
= 0;
14333 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14334 scoped_ptr
<HttpTransaction
> trans(
14335 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14336 // Send headers successfully, but get an error while sending the body.
14337 MockWrite data_writes
[] = {
14338 MockWrite("POST / HTTP/1.1\r\n"
14339 "Host: www.foo.com\r\n"
14340 "Connection: keep-alive\r\n"
14341 "Content-Length: 3\r\n\r\n"),
14342 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14345 MockRead data_reads
[] = {
14346 MockRead("HTTP 0.9 rocks!"),
14347 MockRead(SYNCHRONOUS
, OK
),
14349 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14350 arraysize(data_writes
));
14351 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14353 TestCompletionCallback callback
;
14355 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14356 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14358 rv
= callback
.WaitForResult();
14359 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14362 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
14363 ScopedVector
<UploadElementReader
> element_readers
;
14364 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14365 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14367 HttpRequestInfo request
;
14368 request
.method
= "POST";
14369 request
.url
= GURL("http://www.foo.com/");
14370 request
.upload_data_stream
= &upload_data_stream
;
14371 request
.load_flags
= 0;
14373 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14374 scoped_ptr
<HttpTransaction
> trans(
14375 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14376 // Send headers successfully, but get an error while sending the body.
14377 MockWrite data_writes
[] = {
14378 MockWrite("POST / HTTP/1.1\r\n"
14379 "Host: www.foo.com\r\n"
14380 "Connection: keep-alive\r\n"
14381 "Content-Length: 3\r\n\r\n"),
14382 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14385 MockRead data_reads
[] = {
14386 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14387 MockRead(SYNCHRONOUS
, OK
),
14389 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14390 arraysize(data_writes
));
14391 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14393 TestCompletionCallback callback
;
14395 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14396 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14398 rv
= callback
.WaitForResult();
14399 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14402 // Verify that proxy headers are not sent to the destination server when
14403 // establishing a tunnel for a secure WebSocket connection.
14404 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
14405 HttpRequestInfo request
;
14406 request
.method
= "GET";
14407 request
.url
= GURL("wss://www.example.org/");
14408 AddWebSocketHeaders(&request
.extra_headers
);
14410 // Configure against proxy server "myproxy:70".
14411 session_deps_
.proxy_service
.reset(
14412 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14414 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14416 // Since a proxy is configured, try to establish a tunnel.
14417 MockWrite data_writes
[] = {
14419 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14420 "Host: www.example.org\r\n"
14421 "Proxy-Connection: keep-alive\r\n\r\n"),
14423 // After calling trans->RestartWithAuth(), this is the request we should
14424 // be issuing -- the final header line contains the credentials.
14426 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14427 "Host: www.example.org\r\n"
14428 "Proxy-Connection: keep-alive\r\n"
14429 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14432 "GET / HTTP/1.1\r\n"
14433 "Host: www.example.org\r\n"
14434 "Connection: Upgrade\r\n"
14435 "Upgrade: websocket\r\n"
14436 "Origin: http://www.example.org\r\n"
14437 "Sec-WebSocket-Version: 13\r\n"
14438 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14441 // The proxy responds to the connect with a 407, using a persistent
14443 MockRead data_reads
[] = {
14445 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14446 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14447 MockRead("Content-Length: 0\r\n"),
14448 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
14450 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14452 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14453 MockRead("Upgrade: websocket\r\n"),
14454 MockRead("Connection: Upgrade\r\n"),
14455 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14458 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14459 arraysize(data_writes
));
14460 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14461 SSLSocketDataProvider
ssl(ASYNC
, OK
);
14462 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
14464 scoped_ptr
<HttpTransaction
> trans(
14465 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14466 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14467 trans
->SetWebSocketHandshakeStreamCreateHelper(
14468 &websocket_stream_create_helper
);
14471 TestCompletionCallback callback
;
14473 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14474 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14476 rv
= callback
.WaitForResult();
14480 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14481 ASSERT_TRUE(response
);
14482 ASSERT_TRUE(response
->headers
.get());
14483 EXPECT_EQ(407, response
->headers
->response_code());
14486 TestCompletionCallback callback
;
14488 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
14489 callback
.callback());
14490 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14492 rv
= callback
.WaitForResult();
14496 response
= trans
->GetResponseInfo();
14497 ASSERT_TRUE(response
);
14498 ASSERT_TRUE(response
->headers
.get());
14500 EXPECT_EQ(101, response
->headers
->response_code());
14503 session
->CloseAllConnections();
14506 // Verify that proxy headers are not sent to the destination server when
14507 // establishing a tunnel for an insecure WebSocket connection.
14508 // This requires the authentication info to be injected into the auth cache
14509 // due to crbug.com/395064
14510 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14511 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
14512 HttpRequestInfo request
;
14513 request
.method
= "GET";
14514 request
.url
= GURL("ws://www.example.org/");
14515 AddWebSocketHeaders(&request
.extra_headers
);
14517 // Configure against proxy server "myproxy:70".
14518 session_deps_
.proxy_service
.reset(
14519 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14521 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14523 MockWrite data_writes
[] = {
14524 // Try to establish a tunnel for the WebSocket connection, with
14525 // credentials. Because WebSockets have a separate set of socket pools,
14526 // they cannot and will not use the same TCP/IP connection as the
14527 // preflight HTTP request.
14529 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14530 "Host: www.example.org:80\r\n"
14531 "Proxy-Connection: keep-alive\r\n"
14532 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14535 "GET / HTTP/1.1\r\n"
14536 "Host: www.example.org\r\n"
14537 "Connection: Upgrade\r\n"
14538 "Upgrade: websocket\r\n"
14539 "Origin: http://www.example.org\r\n"
14540 "Sec-WebSocket-Version: 13\r\n"
14541 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14544 MockRead data_reads
[] = {
14545 // HTTP CONNECT with credentials.
14546 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14548 // WebSocket connection established inside tunnel.
14549 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14550 MockRead("Upgrade: websocket\r\n"),
14551 MockRead("Connection: Upgrade\r\n"),
14552 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14555 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14556 arraysize(data_writes
));
14557 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14559 session
->http_auth_cache()->Add(
14560 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
14561 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
14563 scoped_ptr
<HttpTransaction
> trans(
14564 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14565 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14566 trans
->SetWebSocketHandshakeStreamCreateHelper(
14567 &websocket_stream_create_helper
);
14569 TestCompletionCallback callback
;
14571 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14572 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14574 rv
= callback
.WaitForResult();
14577 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14578 ASSERT_TRUE(response
);
14579 ASSERT_TRUE(response
->headers
.get());
14581 EXPECT_EQ(101, response
->headers
->response_code());
14584 session
->CloseAllConnections();