1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/json/json_writer.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/test/test_file_util.h"
21 #include "net/base/auth.h"
22 #include "net/base/capturing_net_log.h"
23 #include "net/base/completion_callback.h"
24 #include "net/base/load_timing_info.h"
25 #include "net/base/load_timing_info_test_util.h"
26 #include "net/base/net_log.h"
27 #include "net/base/net_log_unittest.h"
28 #include "net/base/request_priority.h"
29 #include "net/base/test_completion_callback.h"
30 #include "net/base/test_data_directory.h"
31 #include "net/base/upload_bytes_element_reader.h"
32 #include "net/base/upload_data_stream.h"
33 #include "net/base/upload_file_element_reader.h"
34 #include "net/cert/mock_cert_verifier.h"
35 #include "net/dns/host_cache.h"
36 #include "net/dns/mock_host_resolver.h"
37 #include "net/http/http_auth_handler_digest.h"
38 #include "net/http/http_auth_handler_mock.h"
39 #include "net/http/http_auth_handler_ntlm.h"
40 #include "net/http/http_basic_stream.h"
41 #include "net/http/http_network_session.h"
42 #include "net/http/http_network_session_peer.h"
43 #include "net/http/http_server_properties_impl.h"
44 #include "net/http/http_stream.h"
45 #include "net/http/http_stream_factory.h"
46 #include "net/http/http_transaction_unittest.h"
47 #include "net/proxy/proxy_config_service_fixed.h"
48 #include "net/proxy/proxy_resolver.h"
49 #include "net/proxy/proxy_service.h"
50 #include "net/socket/client_socket_factory.h"
51 #include "net/socket/client_socket_pool_manager.h"
52 #include "net/socket/mock_client_socket_pool_manager.h"
53 #include "net/socket/next_proto.h"
54 #include "net/socket/socket_test_util.h"
55 #include "net/socket/ssl_client_socket.h"
56 #include "net/spdy/spdy_framer.h"
57 #include "net/spdy/spdy_session.h"
58 #include "net/spdy/spdy_session_pool.h"
59 #include "net/spdy/spdy_test_util_common.h"
60 #include "net/ssl/ssl_cert_request_info.h"
61 #include "net/ssl/ssl_config_service_defaults.h"
62 #include "net/ssl/ssl_info.h"
63 #include "net/test/cert_test_util.h"
64 #include "testing/gtest/include/gtest/gtest.h"
65 #include "testing/platform_test.h"
68 //-----------------------------------------------------------------------------
72 const base::string16
kBar(ASCIIToUTF16("bar"));
73 const base::string16
kBar2(ASCIIToUTF16("bar2"));
74 const base::string16
kBar3(ASCIIToUTF16("bar3"));
75 const base::string16
kBaz(ASCIIToUTF16("baz"));
76 const base::string16
kFirst(ASCIIToUTF16("first"));
77 const base::string16
kFoo(ASCIIToUTF16("foo"));
78 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
79 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
80 const base::string16
kFou(ASCIIToUTF16("fou"));
81 const base::string16
kSecond(ASCIIToUTF16("second"));
82 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
83 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
85 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession
* session
) {
86 return session
->GetTransportSocketPool(
87 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
90 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession
* session
) {
91 return session
->GetSSLSocketPool(
92 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
95 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
96 // a JSONified list of headers as a single string. Uses single quotes instead
97 // of double quotes for easier comparison. Returns false on failure.
98 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
101 base::ListValue
* header_list
;
102 if (!params
->GetList("headers", &header_list
))
104 std::string double_quote_headers
;
105 base::JSONWriter::Write(header_list
, &double_quote_headers
);
106 ReplaceChars(double_quote_headers
, "\"", "'", headers
);
110 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
112 void TestLoadTimingReused(const net::LoadTimingInfo
& load_timing_info
) {
113 EXPECT_TRUE(load_timing_info
.socket_reused
);
114 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
116 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
117 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
119 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
120 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
122 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
124 // Set at a higher level.
125 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
126 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
127 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
130 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
132 void TestLoadTimingNotReused(const net::LoadTimingInfo
& load_timing_info
,
133 int connect_timing_flags
) {
134 EXPECT_FALSE(load_timing_info
.socket_reused
);
135 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
137 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
138 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
140 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
141 connect_timing_flags
);
142 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
143 load_timing_info
.send_start
);
145 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
147 // Set at a higher level.
148 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
149 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
150 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
153 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
155 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo
& load_timing_info
) {
156 EXPECT_TRUE(load_timing_info
.socket_reused
);
157 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
159 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
161 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
162 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
163 load_timing_info
.proxy_resolve_end
);
164 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
165 load_timing_info
.send_start
);
166 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
168 // Set at a higher level.
169 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
170 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
171 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
174 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
176 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo
& load_timing_info
,
177 int connect_timing_flags
) {
178 EXPECT_FALSE(load_timing_info
.socket_reused
);
179 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
181 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
182 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
183 load_timing_info
.proxy_resolve_end
);
184 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
185 load_timing_info
.connect_timing
.connect_start
);
186 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
187 connect_timing_flags
);
188 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
189 load_timing_info
.send_start
);
191 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
193 // Set at a higher level.
194 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
195 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
196 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
205 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
206 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
211 class HttpNetworkTransactionTest
212 : public PlatformTest
,
213 public ::testing::WithParamInterface
<NextProto
> {
215 virtual ~HttpNetworkTransactionTest() {
216 // Important to restore the per-pool limit first, since the pool limit must
217 // always be greater than group limit, and the tests reduce both limits.
218 ClientSocketPoolManager::set_max_sockets_per_pool(
219 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
220 ClientSocketPoolManager::set_max_sockets_per_group(
221 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
225 HttpNetworkTransactionTest()
226 : spdy_util_(GetParam()),
227 session_deps_(GetParam()),
228 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
229 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
230 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
231 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
234 struct SimpleGetHelperResult
{
236 std::string status_line
;
237 std::string response_data
;
238 LoadTimingInfo load_timing_info
;
241 virtual void SetUp() {
242 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
243 base::MessageLoop::current()->RunUntilIdle();
246 virtual void TearDown() {
247 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
248 base::MessageLoop::current()->RunUntilIdle();
249 // Empty the current queue.
250 base::MessageLoop::current()->RunUntilIdle();
251 PlatformTest::TearDown();
252 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
253 base::MessageLoop::current()->RunUntilIdle();
254 HttpStreamFactory::set_use_alternate_protocols(false);
255 HttpStreamFactory::SetNextProtos(std::vector
<NextProto
>());
258 // This is the expected return from a current server advertising SPDY.
259 std::string
GetAlternateProtocolHttpHeader() {
261 std::string("Alternate-Protocol: 443:") +
262 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
266 // Either |write_failure| specifies a write failure or |read_failure|
267 // specifies a read failure when using a reused socket. In either case, the
268 // failure should cause the network transaction to resend the request, and the
269 // other argument should be NULL.
270 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
271 const MockRead
* read_failure
);
273 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
275 SimpleGetHelperResult out
;
277 HttpRequestInfo request
;
278 request
.method
= "GET";
279 request
.url
= GURL("http://www.google.com/");
280 request
.load_flags
= 0;
282 CapturingBoundNetLog log
;
283 session_deps_
.net_log
= log
.bound().net_log();
284 scoped_ptr
<HttpTransaction
> trans(
285 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
286 CreateSession(&session_deps_
)));
288 for (size_t i
= 0; i
< data_count
; ++i
) {
289 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
292 TestCompletionCallback callback
;
294 EXPECT_TRUE(log
.bound().IsLoggingAllEvents());
295 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
296 EXPECT_EQ(ERR_IO_PENDING
, rv
);
298 out
.rv
= callback
.WaitForResult();
300 // Even in the failure cases that use this function, connections are always
301 // successfully established before the error.
302 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
303 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
308 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
309 // Can't use ASSERT_* inside helper functions like this, so
311 if (response
== NULL
|| response
->headers
.get() == NULL
) {
312 out
.rv
= ERR_UNEXPECTED
;
315 out
.status_line
= response
->headers
->GetStatusLine();
317 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
318 EXPECT_EQ(80, response
->socket_address
.port());
320 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
323 net::CapturingNetLog::CapturedEntryList entries
;
324 log
.GetEntries(&entries
);
325 size_t pos
= ExpectLogContainsSomewhere(
326 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
328 ExpectLogContainsSomewhere(
330 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
334 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
335 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
337 HttpRequestHeaders request_headers
;
338 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
340 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
341 EXPECT_EQ("www.google.com", value
);
342 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
343 EXPECT_EQ("keep-alive", value
);
345 std::string response_headers
;
346 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
347 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
353 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
354 size_t reads_count
) {
355 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
356 StaticSocketDataProvider
* data
[] = { &reads
};
357 return SimpleGetHelperForData(data
, 1);
360 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
361 int expected_status
);
363 void ConnectStatusHelper(const MockRead
& status
);
365 void BypassHostCacheOnRefreshHelper(int load_flags
);
367 void CheckErrorIsPassedBack(int error
, IoMode mode
);
369 SpdyTestUtil spdy_util_
;
370 SpdySessionDependencies session_deps_
;
372 // Original socket limits. Some tests set these. Safest to always restore
373 // them once each test has been run.
374 int old_max_group_sockets_
;
375 int old_max_pool_sockets_
;
378 INSTANTIATE_TEST_CASE_P(
380 HttpNetworkTransactionTest
,
381 testing::Values(kProtoSPDY2
, kProtoSPDY3
, kProtoSPDY31
, kProtoSPDY4a2
,
382 kProtoHTTP2Draft04
));
386 // Fill |str| with a long header list that consumes >= |size| bytes.
387 void FillLargeHeadersString(std::string
* str
, int size
) {
389 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
390 const int sizeof_row
= strlen(row
);
391 const int num_rows
= static_cast<int>(
392 ceil(static_cast<float>(size
) / sizeof_row
));
393 const int sizeof_data
= num_rows
* sizeof_row
;
394 DCHECK(sizeof_data
>= size
);
395 str
->reserve(sizeof_data
);
397 for (int i
= 0; i
< num_rows
; ++i
)
398 str
->append(row
, sizeof_row
);
401 // Alternative functions that eliminate randomness and dependency on the local
402 // host name so that the generated NTLM messages are reproducible.
403 void MockGenerateRandom1(uint8
* output
, size_t n
) {
404 static const uint8 bytes
[] = {
405 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
407 static size_t current_byte
= 0;
408 for (size_t i
= 0; i
< n
; ++i
) {
409 output
[i
] = bytes
[current_byte
++];
410 current_byte
%= arraysize(bytes
);
414 void MockGenerateRandom2(uint8
* output
, size_t n
) {
415 static const uint8 bytes
[] = {
416 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
417 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
419 static size_t current_byte
= 0;
420 for (size_t i
= 0; i
< n
; ++i
) {
421 output
[i
] = bytes
[current_byte
++];
422 current_byte
%= arraysize(bytes
);
426 std::string
MockGetHostName() {
430 template<typename ParentPool
>
431 class CaptureGroupNameSocketPool
: public ParentPool
{
433 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
434 CertVerifier
* cert_verifier
);
436 const std::string
last_group_name_received() const {
437 return last_group_name_
;
440 virtual int RequestSocket(const std::string
& group_name
,
441 const void* socket_params
,
442 RequestPriority priority
,
443 ClientSocketHandle
* handle
,
444 const CompletionCallback
& callback
,
445 const BoundNetLog
& net_log
) {
446 last_group_name_
= group_name
;
447 return ERR_IO_PENDING
;
449 virtual void CancelRequest(const std::string
& group_name
,
450 ClientSocketHandle
* handle
) {}
451 virtual void ReleaseSocket(const std::string
& group_name
,
452 StreamSocket
* socket
,
454 virtual void CloseIdleSockets() {}
455 virtual int IdleSocketCount() const {
458 virtual int IdleSocketCountInGroup(const std::string
& group_name
) const {
461 virtual LoadState
GetLoadState(const std::string
& group_name
,
462 const ClientSocketHandle
* handle
) const {
463 return LOAD_STATE_IDLE
;
465 virtual base::TimeDelta
ConnectionTimeout() const {
466 return base::TimeDelta();
470 std::string last_group_name_
;
473 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
474 CaptureGroupNameTransportSocketPool
;
475 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
476 CaptureGroupNameHttpProxySocketPool
;
477 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
478 CaptureGroupNameSOCKSSocketPool
;
479 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
480 CaptureGroupNameSSLSocketPool
;
482 template<typename ParentPool
>
483 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
484 HostResolver
* host_resolver
,
485 CertVerifier
* /* cert_verifier */)
486 : ParentPool(0, 0, NULL
, host_resolver
, NULL
, NULL
) {}
489 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
490 HostResolver
* host_resolver
,
491 CertVerifier
* /* cert_verifier */)
492 : HttpProxyClientSocketPool(0, 0, NULL
, host_resolver
, NULL
, NULL
, NULL
) {}
495 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
496 HostResolver
* host_resolver
,
497 CertVerifier
* cert_verifier
)
498 : SSLClientSocketPool(0,
513 //-----------------------------------------------------------------------------
515 // Helper functions for validating that AuthChallengeInfo's are correctly
516 // configured for common cases.
517 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
520 EXPECT_FALSE(auth_challenge
->is_proxy
);
521 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
522 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
523 EXPECT_EQ("basic", auth_challenge
->scheme
);
527 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
530 EXPECT_TRUE(auth_challenge
->is_proxy
);
531 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
532 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
533 EXPECT_EQ("basic", auth_challenge
->scheme
);
537 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
540 EXPECT_FALSE(auth_challenge
->is_proxy
);
541 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
542 EXPECT_EQ("digestive", auth_challenge
->realm
);
543 EXPECT_EQ("digest", auth_challenge
->scheme
);
547 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
550 EXPECT_FALSE(auth_challenge
->is_proxy
);
551 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
552 EXPECT_EQ(std::string(), auth_challenge
->realm
);
553 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
559 TEST_P(HttpNetworkTransactionTest
, Basic
) {
560 scoped_ptr
<HttpTransaction
> trans(
561 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
562 CreateSession(&session_deps_
)));
565 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
566 MockRead data_reads
[] = {
567 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
568 MockRead("hello world"),
569 MockRead(SYNCHRONOUS
, OK
),
571 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
572 arraysize(data_reads
));
573 EXPECT_EQ(OK
, out
.rv
);
574 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
575 EXPECT_EQ("hello world", out
.response_data
);
578 // Response with no status line.
579 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
580 MockRead data_reads
[] = {
581 MockRead("hello world"),
582 MockRead(SYNCHRONOUS
, OK
),
584 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
585 arraysize(data_reads
));
586 EXPECT_EQ(OK
, out
.rv
);
587 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
588 EXPECT_EQ("hello world", out
.response_data
);
591 // Allow up to 4 bytes of junk to precede status line.
592 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
593 MockRead data_reads
[] = {
594 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
595 MockRead(SYNCHRONOUS
, OK
),
597 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
598 arraysize(data_reads
));
599 EXPECT_EQ(OK
, out
.rv
);
600 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
601 EXPECT_EQ("DATA", out
.response_data
);
604 // Allow up to 4 bytes of junk to precede status line.
605 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
606 MockRead data_reads
[] = {
607 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
608 MockRead(SYNCHRONOUS
, OK
),
610 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
611 arraysize(data_reads
));
612 EXPECT_EQ(OK
, out
.rv
);
613 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
614 EXPECT_EQ("DATA", out
.response_data
);
617 // Beyond 4 bytes of slop and it should fail to find a status line.
618 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
619 MockRead data_reads
[] = {
620 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
621 MockRead(SYNCHRONOUS
, OK
),
623 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
624 arraysize(data_reads
));
625 EXPECT_EQ(OK
, out
.rv
);
626 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
627 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
630 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
631 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
632 MockRead data_reads
[] = {
637 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
638 MockRead(SYNCHRONOUS
, OK
),
640 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
641 arraysize(data_reads
));
642 EXPECT_EQ(OK
, out
.rv
);
643 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
644 EXPECT_EQ("DATA", out
.response_data
);
647 // Close the connection before enough bytes to have a status line.
648 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
649 MockRead data_reads
[] = {
651 MockRead(SYNCHRONOUS
, OK
),
653 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
654 arraysize(data_reads
));
655 EXPECT_EQ(OK
, out
.rv
);
656 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
657 EXPECT_EQ("HTT", out
.response_data
);
660 // Simulate a 204 response, lacking a Content-Length header, sent over a
661 // persistent connection. The response should still terminate since a 204
662 // cannot have a response body.
663 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
664 MockRead data_reads
[] = {
665 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
666 MockRead("junk"), // Should not be read!!
667 MockRead(SYNCHRONOUS
, OK
),
669 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
670 arraysize(data_reads
));
671 EXPECT_EQ(OK
, out
.rv
);
672 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
673 EXPECT_EQ("", out
.response_data
);
676 // A simple request using chunked encoding with some extra data after.
677 // (Like might be seen in a pipelined response.)
678 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
679 MockRead data_reads
[] = {
680 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
681 MockRead("5\r\nHello\r\n"),
684 MockRead("5\r\nworld\r\n"),
685 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
686 MockRead(SYNCHRONOUS
, OK
),
688 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
689 arraysize(data_reads
));
690 EXPECT_EQ(OK
, out
.rv
);
691 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
692 EXPECT_EQ("Hello world", out
.response_data
);
695 // Next tests deal with http://crbug.com/56344.
697 TEST_P(HttpNetworkTransactionTest
,
698 MultipleContentLengthHeadersNoTransferEncoding
) {
699 MockRead data_reads
[] = {
700 MockRead("HTTP/1.1 200 OK\r\n"),
701 MockRead("Content-Length: 10\r\n"),
702 MockRead("Content-Length: 5\r\n\r\n"),
704 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
705 arraysize(data_reads
));
706 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
709 TEST_P(HttpNetworkTransactionTest
,
710 DuplicateContentLengthHeadersNoTransferEncoding
) {
711 MockRead data_reads
[] = {
712 MockRead("HTTP/1.1 200 OK\r\n"),
713 MockRead("Content-Length: 5\r\n"),
714 MockRead("Content-Length: 5\r\n\r\n"),
717 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
718 arraysize(data_reads
));
719 EXPECT_EQ(OK
, out
.rv
);
720 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
721 EXPECT_EQ("Hello", out
.response_data
);
724 TEST_P(HttpNetworkTransactionTest
,
725 ComplexContentLengthHeadersNoTransferEncoding
) {
726 // More than 2 dupes.
728 MockRead data_reads
[] = {
729 MockRead("HTTP/1.1 200 OK\r\n"),
730 MockRead("Content-Length: 5\r\n"),
731 MockRead("Content-Length: 5\r\n"),
732 MockRead("Content-Length: 5\r\n\r\n"),
735 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
736 arraysize(data_reads
));
737 EXPECT_EQ(OK
, out
.rv
);
738 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
739 EXPECT_EQ("Hello", out
.response_data
);
743 MockRead data_reads
[] = {
744 MockRead("HTTP/1.0 200 OK\r\n"),
745 MockRead("Content-Length: 5\r\n"),
746 MockRead("Content-Length: 5\r\n"),
747 MockRead("Content-Length: 5\r\n\r\n"),
750 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
751 arraysize(data_reads
));
752 EXPECT_EQ(OK
, out
.rv
);
753 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
754 EXPECT_EQ("Hello", out
.response_data
);
756 // 2 dupes and one mismatched.
758 MockRead data_reads
[] = {
759 MockRead("HTTP/1.1 200 OK\r\n"),
760 MockRead("Content-Length: 10\r\n"),
761 MockRead("Content-Length: 10\r\n"),
762 MockRead("Content-Length: 5\r\n\r\n"),
764 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
765 arraysize(data_reads
));
766 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
770 TEST_P(HttpNetworkTransactionTest
,
771 MultipleContentLengthHeadersTransferEncoding
) {
772 MockRead data_reads
[] = {
773 MockRead("HTTP/1.1 200 OK\r\n"),
774 MockRead("Content-Length: 666\r\n"),
775 MockRead("Content-Length: 1337\r\n"),
776 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
777 MockRead("5\r\nHello\r\n"),
780 MockRead("5\r\nworld\r\n"),
781 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
782 MockRead(SYNCHRONOUS
, OK
),
784 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
785 arraysize(data_reads
));
786 EXPECT_EQ(OK
, out
.rv
);
787 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
788 EXPECT_EQ("Hello world", out
.response_data
);
791 // Next tests deal with http://crbug.com/98895.
793 // Checks that a single Content-Disposition header results in no error.
794 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
795 MockRead data_reads
[] = {
796 MockRead("HTTP/1.1 200 OK\r\n"),
797 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
798 MockRead("Content-Length: 5\r\n\r\n"),
801 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
802 arraysize(data_reads
));
803 EXPECT_EQ(OK
, out
.rv
);
804 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
805 EXPECT_EQ("Hello", out
.response_data
);
808 // Checks that two identical Content-Disposition headers result in no error.
809 TEST_P(HttpNetworkTransactionTest
,
810 TwoIdenticalContentDispositionHeaders
) {
811 MockRead data_reads
[] = {
812 MockRead("HTTP/1.1 200 OK\r\n"),
813 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
814 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
815 MockRead("Content-Length: 5\r\n\r\n"),
818 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
819 arraysize(data_reads
));
820 EXPECT_EQ(OK
, out
.rv
);
821 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
822 EXPECT_EQ("Hello", out
.response_data
);
825 // Checks that two distinct Content-Disposition headers result in an error.
826 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
827 MockRead data_reads
[] = {
828 MockRead("HTTP/1.1 200 OK\r\n"),
829 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
830 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
831 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_DISPOSITION
, out
.rv
);
839 // Checks that two identical Location headers result in no error.
840 // Also tests Location header behavior.
841 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
842 MockRead data_reads
[] = {
843 MockRead("HTTP/1.1 302 Redirect\r\n"),
844 MockRead("Location: http://good.com/\r\n"),
845 MockRead("Location: http://good.com/\r\n"),
846 MockRead("Content-Length: 0\r\n\r\n"),
847 MockRead(SYNCHRONOUS
, OK
),
850 HttpRequestInfo request
;
851 request
.method
= "GET";
852 request
.url
= GURL("http://redirect.com/");
853 request
.load_flags
= 0;
855 scoped_ptr
<HttpTransaction
> trans(
856 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
857 CreateSession(&session_deps_
)));
859 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
860 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
862 TestCompletionCallback callback
;
864 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
865 EXPECT_EQ(ERR_IO_PENDING
, rv
);
867 EXPECT_EQ(OK
, callback
.WaitForResult());
869 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
870 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
871 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
873 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
874 EXPECT_EQ("http://good.com/", url
);
877 // Checks that two distinct Location headers result in an error.
878 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
879 MockRead data_reads
[] = {
880 MockRead("HTTP/1.1 302 Redirect\r\n"),
881 MockRead("Location: http://good.com/\r\n"),
882 MockRead("Location: http://evil.com/\r\n"),
883 MockRead("Content-Length: 0\r\n\r\n"),
884 MockRead(SYNCHRONOUS
, OK
),
886 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
887 arraysize(data_reads
));
888 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
891 // Do a request using the HEAD method. Verify that we don't try to read the
892 // message body (since HEAD has none).
893 TEST_P(HttpNetworkTransactionTest
, Head
) {
894 HttpRequestInfo request
;
895 request
.method
= "HEAD";
896 request
.url
= GURL("http://www.google.com/");
897 request
.load_flags
= 0;
899 scoped_ptr
<HttpTransaction
> trans(
900 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
901 CreateSession(&session_deps_
)));
903 MockWrite data_writes1
[] = {
904 MockWrite("HEAD / HTTP/1.1\r\n"
905 "Host: www.google.com\r\n"
906 "Connection: keep-alive\r\n"
907 "Content-Length: 0\r\n\r\n"),
909 MockRead data_reads1
[] = {
910 MockRead("HTTP/1.1 404 Not Found\r\n"),
911 MockRead("Server: Blah\r\n"),
912 MockRead("Content-Length: 1234\r\n\r\n"),
914 // No response body because the test stops reading here.
915 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
918 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
919 data_writes1
, arraysize(data_writes1
));
920 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
922 TestCompletionCallback callback1
;
924 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
925 EXPECT_EQ(ERR_IO_PENDING
, rv
);
927 rv
= callback1
.WaitForResult();
930 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
931 ASSERT_TRUE(response
!= NULL
);
933 // Check that the headers got parsed.
934 EXPECT_TRUE(response
->headers
.get() != NULL
);
935 EXPECT_EQ(1234, response
->headers
->GetContentLength());
936 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
938 std::string server_header
;
940 bool has_server_header
= response
->headers
->EnumerateHeader(
941 &iter
, "Server", &server_header
);
942 EXPECT_TRUE(has_server_header
);
943 EXPECT_EQ("Blah", server_header
);
945 // Reading should give EOF right away, since there is no message body
946 // (despite non-zero content-length).
947 std::string response_data
;
948 rv
= ReadTransaction(trans
.get(), &response_data
);
950 EXPECT_EQ("", response_data
);
953 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
954 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
956 MockRead data_reads
[] = {
957 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
959 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
961 MockRead(SYNCHRONOUS
, OK
),
963 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
964 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
966 const char* const kExpectedResponseData
[] = {
970 for (int i
= 0; i
< 2; ++i
) {
971 HttpRequestInfo request
;
972 request
.method
= "GET";
973 request
.url
= GURL("http://www.google.com/");
974 request
.load_flags
= 0;
976 scoped_ptr
<HttpTransaction
> trans(
977 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
979 TestCompletionCallback callback
;
981 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
982 EXPECT_EQ(ERR_IO_PENDING
, rv
);
984 rv
= callback
.WaitForResult();
987 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
988 ASSERT_TRUE(response
!= NULL
);
990 EXPECT_TRUE(response
->headers
.get() != NULL
);
991 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
993 std::string response_data
;
994 rv
= ReadTransaction(trans
.get(), &response_data
);
996 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1000 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1001 ScopedVector
<UploadElementReader
> element_readers
;
1002 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1003 UploadDataStream
upload_data_stream(&element_readers
, 0);
1005 HttpRequestInfo request
;
1006 request
.method
= "POST";
1007 request
.url
= GURL("http://www.foo.com/");
1008 request
.upload_data_stream
= &upload_data_stream
;
1009 request
.load_flags
= 0;
1011 scoped_ptr
<HttpTransaction
> trans(
1012 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
1013 CreateSession(&session_deps_
)));
1015 MockRead data_reads
[] = {
1016 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1017 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1018 MockRead("hello world"),
1019 MockRead(SYNCHRONOUS
, OK
),
1021 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1022 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1024 TestCompletionCallback callback
;
1026 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1027 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1029 rv
= callback
.WaitForResult();
1032 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1033 ASSERT_TRUE(response
!= NULL
);
1035 EXPECT_TRUE(response
->headers
.get() != NULL
);
1036 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1038 std::string response_data
;
1039 rv
= ReadTransaction(trans
.get(), &response_data
);
1041 EXPECT_EQ("hello world", response_data
);
1044 // This test is almost the same as Ignores100 above, but the response contains
1045 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1046 // HTTP/1.1 and the two status headers are read in one read.
1047 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1048 HttpRequestInfo request
;
1049 request
.method
= "GET";
1050 request
.url
= GURL("http://www.foo.com/");
1051 request
.load_flags
= 0;
1053 scoped_ptr
<HttpTransaction
> trans(
1054 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
1055 CreateSession(&session_deps_
)));
1057 MockRead data_reads
[] = {
1058 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1059 "HTTP/1.1 200 OK\r\n\r\n"),
1060 MockRead("hello world"),
1061 MockRead(SYNCHRONOUS
, OK
),
1063 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1064 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1066 TestCompletionCallback callback
;
1068 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1071 rv
= callback
.WaitForResult();
1074 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1075 ASSERT_TRUE(response
!= NULL
);
1077 EXPECT_TRUE(response
->headers
.get() != NULL
);
1078 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1080 std::string response_data
;
1081 rv
= ReadTransaction(trans
.get(), &response_data
);
1083 EXPECT_EQ("hello world", response_data
);
1086 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1087 HttpRequestInfo request
;
1088 request
.method
= "POST";
1089 request
.url
= GURL("http://www.foo.com/");
1090 request
.load_flags
= 0;
1092 scoped_ptr
<HttpTransaction
> trans(
1093 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
1094 CreateSession(&session_deps_
)));
1096 MockRead data_reads
[] = {
1097 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1100 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1101 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1103 TestCompletionCallback callback
;
1105 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1108 rv
= callback
.WaitForResult();
1111 std::string response_data
;
1112 rv
= ReadTransaction(trans
.get(), &response_data
);
1114 EXPECT_EQ("", response_data
);
1117 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1118 HttpRequestInfo request
;
1119 request
.method
= "POST";
1120 request
.url
= GURL("http://www.foo.com/");
1121 request
.load_flags
= 0;
1123 scoped_ptr
<HttpTransaction
> trans(
1124 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
1125 CreateSession(&session_deps_
)));
1127 MockRead data_reads
[] = {
1130 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1131 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1133 TestCompletionCallback callback
;
1135 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1136 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1138 rv
= callback
.WaitForResult();
1139 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1142 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1143 const MockWrite
* write_failure
,
1144 const MockRead
* read_failure
) {
1145 HttpRequestInfo request
;
1146 request
.method
= "GET";
1147 request
.url
= GURL("http://www.foo.com/");
1148 request
.load_flags
= 0;
1150 CapturingNetLog net_log
;
1151 session_deps_
.net_log
= &net_log
;
1152 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1154 // Written data for successfully sending both requests.
1155 MockWrite data1_writes
[] = {
1156 MockWrite("GET / HTTP/1.1\r\n"
1157 "Host: www.foo.com\r\n"
1158 "Connection: keep-alive\r\n\r\n"),
1159 MockWrite("GET / HTTP/1.1\r\n"
1160 "Host: www.foo.com\r\n"
1161 "Connection: keep-alive\r\n\r\n")
1164 // Read results for the first request.
1165 MockRead data1_reads
[] = {
1166 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1168 MockRead(ASYNC
, OK
),
1171 if (write_failure
) {
1172 ASSERT_TRUE(!read_failure
);
1173 data1_writes
[1] = *write_failure
;
1175 ASSERT_TRUE(read_failure
);
1176 data1_reads
[2] = *read_failure
;
1179 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1180 data1_writes
, arraysize(data1_writes
));
1181 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1183 MockRead data2_reads
[] = {
1184 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1186 MockRead(ASYNC
, OK
),
1188 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1189 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1191 const char* kExpectedResponseData
[] = {
1195 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1196 for (int i
= 0; i
< 2; ++i
) {
1197 TestCompletionCallback callback
;
1199 scoped_ptr
<HttpTransaction
> trans(
1200 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1202 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1205 rv
= callback
.WaitForResult();
1208 LoadTimingInfo load_timing_info
;
1209 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1210 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1212 first_socket_log_id
= load_timing_info
.socket_log_id
;
1214 // The second request should be using a new socket.
1215 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1218 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1219 ASSERT_TRUE(response
!= NULL
);
1221 EXPECT_TRUE(response
->headers
.get() != NULL
);
1222 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1224 std::string response_data
;
1225 rv
= ReadTransaction(trans
.get(), &response_data
);
1227 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1231 TEST_P(HttpNetworkTransactionTest
,
1232 KeepAliveConnectionNotConnectedOnWrite
) {
1233 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1234 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1237 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1238 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1239 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1242 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1243 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1244 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1247 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1248 HttpRequestInfo request
;
1249 request
.method
= "GET";
1250 request
.url
= GURL("http://www.google.com/");
1251 request
.load_flags
= 0;
1253 scoped_ptr
<HttpTransaction
> trans(
1254 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
1255 CreateSession(&session_deps_
)));
1257 MockRead data_reads
[] = {
1258 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1259 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1260 MockRead("hello world"),
1261 MockRead(SYNCHRONOUS
, OK
),
1263 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1264 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1266 TestCompletionCallback callback
;
1268 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1269 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1271 rv
= callback
.WaitForResult();
1272 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1274 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1275 EXPECT_TRUE(response
== NULL
);
1278 // What do various browsers do when the server closes a non-keepalive
1279 // connection without sending any response header or body?
1282 // Safari 3.1.2 (Windows): error page
1283 // Firefox 3.0.1: blank page
1284 // Opera 9.52: after five attempts, blank page
1285 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1286 // Us: error page (EMPTY_RESPONSE)
1287 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1288 MockRead data_reads
[] = {
1289 MockRead(SYNCHRONOUS
, OK
), // EOF
1290 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1291 MockRead("hello world"),
1292 MockRead(SYNCHRONOUS
, OK
),
1294 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1295 arraysize(data_reads
));
1296 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1299 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1300 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1301 // destructor in such situations.
1302 // See http://crbug.com/154712 and http://crbug.com/156609.
1303 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1304 HttpRequestInfo request
;
1305 request
.method
= "GET";
1306 request
.url
= GURL("http://www.google.com/");
1307 request
.load_flags
= 0;
1309 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1310 scoped_ptr
<HttpTransaction
> trans(
1311 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1313 MockRead data_reads
[] = {
1314 MockRead("HTTP/1.0 200 OK\r\n"),
1315 MockRead("Connection: keep-alive\r\n"),
1316 MockRead("Content-Length: 100\r\n\r\n"),
1318 MockRead(SYNCHRONOUS
, 0),
1320 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1321 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1323 TestCompletionCallback callback
;
1325 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1326 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1328 rv
= callback
.WaitForResult();
1331 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1332 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1333 if (rv
== ERR_IO_PENDING
)
1334 rv
= callback
.WaitForResult();
1336 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1337 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1340 base::MessageLoop::current()->RunUntilIdle();
1341 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1344 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1345 HttpRequestInfo request
;
1346 request
.method
= "GET";
1347 request
.url
= GURL("http://www.google.com/");
1348 request
.load_flags
= 0;
1350 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1351 scoped_ptr
<HttpTransaction
> trans(
1352 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1354 MockRead data_reads
[] = {
1355 MockRead("HTTP/1.0 200 OK\r\n"),
1356 MockRead("Connection: keep-alive\r\n"),
1357 MockRead("Content-Length: 100\r\n\r\n"),
1358 MockRead(SYNCHRONOUS
, 0),
1360 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1361 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1363 TestCompletionCallback callback
;
1365 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1366 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1368 rv
= callback
.WaitForResult();
1371 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1372 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1373 if (rv
== ERR_IO_PENDING
)
1374 rv
= callback
.WaitForResult();
1375 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1378 base::MessageLoop::current()->RunUntilIdle();
1379 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1382 // Test that we correctly reuse a keep-alive connection after not explicitly
1383 // reading the body.
1384 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1385 HttpRequestInfo request
;
1386 request
.method
= "GET";
1387 request
.url
= GURL("http://www.foo.com/");
1388 request
.load_flags
= 0;
1390 CapturingNetLog net_log
;
1391 session_deps_
.net_log
= &net_log
;
1392 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1394 // Note that because all these reads happen in the same
1395 // StaticSocketDataProvider, it shows that the same socket is being reused for
1396 // all transactions.
1397 MockRead data1_reads
[] = {
1398 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1399 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1400 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1401 MockRead("HTTP/1.1 302 Found\r\n"
1402 "Content-Length: 0\r\n\r\n"),
1403 MockRead("HTTP/1.1 302 Found\r\n"
1404 "Content-Length: 5\r\n\r\n"
1406 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1407 "Content-Length: 0\r\n\r\n"),
1408 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1409 "Content-Length: 5\r\n\r\n"
1411 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1414 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1415 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1417 MockRead data2_reads
[] = {
1418 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1420 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1421 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1423 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1424 std::string response_lines
[kNumUnreadBodies
];
1426 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1427 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1428 TestCompletionCallback callback
;
1430 scoped_ptr
<HttpTransaction
> trans(
1431 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1433 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1434 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1436 rv
= callback
.WaitForResult();
1439 LoadTimingInfo load_timing_info
;
1440 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1442 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1443 first_socket_log_id
= load_timing_info
.socket_log_id
;
1445 TestLoadTimingReused(load_timing_info
);
1446 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1449 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1450 ASSERT_TRUE(response
!= NULL
);
1452 ASSERT_TRUE(response
->headers
.get() != NULL
);
1453 response_lines
[i
] = response
->headers
->GetStatusLine();
1455 // We intentionally don't read the response bodies.
1458 const char* const kStatusLines
[] = {
1459 "HTTP/1.1 204 No Content",
1460 "HTTP/1.1 205 Reset Content",
1461 "HTTP/1.1 304 Not Modified",
1462 "HTTP/1.1 302 Found",
1463 "HTTP/1.1 302 Found",
1464 "HTTP/1.1 301 Moved Permanently",
1465 "HTTP/1.1 301 Moved Permanently",
1468 COMPILE_ASSERT(kNumUnreadBodies
== arraysize(kStatusLines
),
1469 forgot_to_update_kStatusLines
);
1471 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1472 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1474 TestCompletionCallback callback
;
1475 scoped_ptr
<HttpTransaction
> trans(
1476 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1477 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1478 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1479 rv
= callback
.WaitForResult();
1481 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1482 ASSERT_TRUE(response
!= NULL
);
1483 ASSERT_TRUE(response
->headers
.get() != NULL
);
1484 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1485 std::string response_data
;
1486 rv
= ReadTransaction(trans
.get(), &response_data
);
1488 EXPECT_EQ("hello", response_data
);
1491 // Test the request-challenge-retry sequence for basic auth.
1492 // (basic auth is the easiest to mock, because it has no randomness).
1493 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1494 HttpRequestInfo request
;
1495 request
.method
= "GET";
1496 request
.url
= GURL("http://www.google.com/");
1497 request
.load_flags
= 0;
1499 CapturingNetLog log
;
1500 session_deps_
.net_log
= &log
;
1501 scoped_ptr
<HttpTransaction
> trans(
1502 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
1503 CreateSession(&session_deps_
)));
1505 MockWrite data_writes1
[] = {
1506 MockWrite("GET / HTTP/1.1\r\n"
1507 "Host: www.google.com\r\n"
1508 "Connection: keep-alive\r\n\r\n"),
1511 MockRead data_reads1
[] = {
1512 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1513 // Give a couple authenticate options (only the middle one is actually
1515 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1516 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1517 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1518 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1519 // Large content-length -- won't matter, as connection will be reset.
1520 MockRead("Content-Length: 10000\r\n\r\n"),
1521 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1524 // After calling trans->RestartWithAuth(), this is the request we should
1525 // be issuing -- the final header line contains the credentials.
1526 MockWrite data_writes2
[] = {
1527 MockWrite("GET / HTTP/1.1\r\n"
1528 "Host: www.google.com\r\n"
1529 "Connection: keep-alive\r\n"
1530 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1533 // Lastly, the server responds with the actual content.
1534 MockRead data_reads2
[] = {
1535 MockRead("HTTP/1.0 200 OK\r\n"),
1536 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1537 MockRead("Content-Length: 100\r\n\r\n"),
1538 MockRead(SYNCHRONOUS
, OK
),
1541 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1542 data_writes1
, arraysize(data_writes1
));
1543 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1544 data_writes2
, arraysize(data_writes2
));
1545 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1546 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1548 TestCompletionCallback callback1
;
1550 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1551 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1553 rv
= callback1
.WaitForResult();
1556 LoadTimingInfo load_timing_info1
;
1557 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1558 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1560 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1561 ASSERT_TRUE(response
!= NULL
);
1562 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1564 TestCompletionCallback callback2
;
1566 rv
= trans
->RestartWithAuth(
1567 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1570 rv
= callback2
.WaitForResult();
1573 LoadTimingInfo load_timing_info2
;
1574 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1575 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1576 // The load timing after restart should have a new socket ID, and times after
1577 // those of the first load timing.
1578 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1579 load_timing_info2
.connect_timing
.connect_start
);
1580 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1582 response
= trans
->GetResponseInfo();
1583 ASSERT_TRUE(response
!= NULL
);
1584 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1585 EXPECT_EQ(100, response
->headers
->GetContentLength());
1588 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1589 HttpRequestInfo request
;
1590 request
.method
= "GET";
1591 request
.url
= GURL("http://www.google.com/");
1592 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1594 scoped_ptr
<HttpTransaction
> trans(
1595 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
1596 CreateSession(&session_deps_
)));
1598 MockWrite data_writes
[] = {
1599 MockWrite("GET / HTTP/1.1\r\n"
1600 "Host: www.google.com\r\n"
1601 "Connection: keep-alive\r\n\r\n"),
1604 MockRead data_reads
[] = {
1605 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1606 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1607 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1608 // Large content-length -- won't matter, as connection will be reset.
1609 MockRead("Content-Length: 10000\r\n\r\n"),
1610 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1613 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
1614 data_writes
, arraysize(data_writes
));
1615 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1616 TestCompletionCallback callback
;
1618 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1619 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1621 rv
= callback
.WaitForResult();
1624 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1625 ASSERT_TRUE(response
!= NULL
);
1626 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1629 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1631 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
1632 HttpRequestInfo request
;
1633 request
.method
= "GET";
1634 request
.url
= GURL("http://www.google.com/");
1635 request
.load_flags
= 0;
1637 CapturingNetLog log
;
1638 session_deps_
.net_log
= &log
;
1639 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1641 MockWrite data_writes1
[] = {
1642 MockWrite("GET / HTTP/1.1\r\n"
1643 "Host: www.google.com\r\n"
1644 "Connection: keep-alive\r\n\r\n"),
1646 // After calling trans->RestartWithAuth(), this is the request we should
1647 // be issuing -- the final header line contains the credentials.
1648 MockWrite("GET / HTTP/1.1\r\n"
1649 "Host: www.google.com\r\n"
1650 "Connection: keep-alive\r\n"
1651 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1654 MockRead data_reads1
[] = {
1655 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1656 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1657 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1658 MockRead("Content-Length: 14\r\n\r\n"),
1659 MockRead("Unauthorized\r\n"),
1661 // Lastly, the server responds with the actual content.
1662 MockRead("HTTP/1.1 200 OK\r\n"),
1663 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1664 MockRead("Content-Length: 5\r\n\r\n"),
1668 // If there is a regression where we disconnect a Keep-Alive
1669 // connection during an auth roundtrip, we'll end up reading this.
1670 MockRead data_reads2
[] = {
1671 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1674 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1675 data_writes1
, arraysize(data_writes1
));
1676 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1678 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1679 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1681 TestCompletionCallback callback1
;
1683 scoped_ptr
<HttpTransaction
> trans(
1684 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1685 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1686 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1688 rv
= callback1
.WaitForResult();
1691 LoadTimingInfo load_timing_info1
;
1692 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1693 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1695 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1696 ASSERT_TRUE(response
!= NULL
);
1697 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1699 TestCompletionCallback callback2
;
1701 rv
= trans
->RestartWithAuth(
1702 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1703 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1705 rv
= callback2
.WaitForResult();
1708 LoadTimingInfo load_timing_info2
;
1709 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1710 TestLoadTimingReused(load_timing_info2
);
1711 // The load timing after restart should have the same socket ID, and times
1712 // those of the first load timing.
1713 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1714 load_timing_info2
.send_start
);
1715 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1717 response
= trans
->GetResponseInfo();
1718 ASSERT_TRUE(response
!= NULL
);
1719 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1720 EXPECT_EQ(5, response
->headers
->GetContentLength());
1723 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1724 // connection and with no response body to drain.
1725 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
1726 HttpRequestInfo request
;
1727 request
.method
= "GET";
1728 request
.url
= GURL("http://www.google.com/");
1729 request
.load_flags
= 0;
1731 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1733 MockWrite data_writes1
[] = {
1734 MockWrite("GET / HTTP/1.1\r\n"
1735 "Host: www.google.com\r\n"
1736 "Connection: keep-alive\r\n\r\n"),
1738 // After calling trans->RestartWithAuth(), this is the request we should
1739 // be issuing -- the final header line contains the credentials.
1740 MockWrite("GET / HTTP/1.1\r\n"
1741 "Host: www.google.com\r\n"
1742 "Connection: keep-alive\r\n"
1743 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1746 MockRead data_reads1
[] = {
1747 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1748 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1749 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
1751 // Lastly, the server responds with the actual content.
1752 MockRead("HTTP/1.1 200 OK\r\n"),
1753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1754 MockRead("Content-Length: 5\r\n\r\n"),
1758 // An incorrect reconnect would cause this to be read.
1759 MockRead data_reads2
[] = {
1760 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1763 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1764 data_writes1
, arraysize(data_writes1
));
1765 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1767 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1768 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1770 TestCompletionCallback callback1
;
1772 scoped_ptr
<HttpTransaction
> trans(
1773 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1774 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1777 rv
= callback1
.WaitForResult();
1780 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1781 ASSERT_TRUE(response
!= NULL
);
1782 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1784 TestCompletionCallback callback2
;
1786 rv
= trans
->RestartWithAuth(
1787 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1788 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1790 rv
= callback2
.WaitForResult();
1793 response
= trans
->GetResponseInfo();
1794 ASSERT_TRUE(response
!= NULL
);
1795 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1796 EXPECT_EQ(5, response
->headers
->GetContentLength());
1799 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1800 // connection and with a large response body to drain.
1801 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
1802 HttpRequestInfo request
;
1803 request
.method
= "GET";
1804 request
.url
= GURL("http://www.google.com/");
1805 request
.load_flags
= 0;
1807 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1809 MockWrite data_writes1
[] = {
1810 MockWrite("GET / HTTP/1.1\r\n"
1811 "Host: www.google.com\r\n"
1812 "Connection: keep-alive\r\n\r\n"),
1814 // After calling trans->RestartWithAuth(), this is the request we should
1815 // be issuing -- the final header line contains the credentials.
1816 MockWrite("GET / HTTP/1.1\r\n"
1817 "Host: www.google.com\r\n"
1818 "Connection: keep-alive\r\n"
1819 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1822 // Respond with 5 kb of response body.
1823 std::string
large_body_string("Unauthorized");
1824 large_body_string
.append(5 * 1024, ' ');
1825 large_body_string
.append("\r\n");
1827 MockRead data_reads1
[] = {
1828 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1829 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1830 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1831 // 5134 = 12 + 5 * 1024 + 2
1832 MockRead("Content-Length: 5134\r\n\r\n"),
1833 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
1835 // Lastly, the server responds with the actual content.
1836 MockRead("HTTP/1.1 200 OK\r\n"),
1837 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1838 MockRead("Content-Length: 5\r\n\r\n"),
1842 // An incorrect reconnect would cause this to be read.
1843 MockRead data_reads2
[] = {
1844 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1847 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1848 data_writes1
, arraysize(data_writes1
));
1849 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1851 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1852 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1854 TestCompletionCallback callback1
;
1856 scoped_ptr
<HttpTransaction
> trans(
1857 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1858 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1859 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1861 rv
= callback1
.WaitForResult();
1864 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1865 ASSERT_TRUE(response
!= NULL
);
1866 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1868 TestCompletionCallback callback2
;
1870 rv
= trans
->RestartWithAuth(
1871 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1872 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1874 rv
= callback2
.WaitForResult();
1877 response
= trans
->GetResponseInfo();
1878 ASSERT_TRUE(response
!= NULL
);
1879 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1880 EXPECT_EQ(5, response
->headers
->GetContentLength());
1883 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1884 // connection, but the server gets impatient and closes the connection.
1885 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
1886 HttpRequestInfo request
;
1887 request
.method
= "GET";
1888 request
.url
= GURL("http://www.google.com/");
1889 request
.load_flags
= 0;
1891 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1893 MockWrite data_writes1
[] = {
1894 MockWrite("GET / HTTP/1.1\r\n"
1895 "Host: www.google.com\r\n"
1896 "Connection: keep-alive\r\n\r\n"),
1897 // This simulates the seemingly successful write to a closed connection
1898 // if the bug is not fixed.
1899 MockWrite("GET / HTTP/1.1\r\n"
1900 "Host: www.google.com\r\n"
1901 "Connection: keep-alive\r\n"
1902 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1905 MockRead data_reads1
[] = {
1906 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1907 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1909 MockRead("Content-Length: 14\r\n\r\n"),
1910 // Tell MockTCPClientSocket to simulate the server closing the connection.
1911 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
1912 MockRead("Unauthorized\r\n"),
1913 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
1916 // After calling trans->RestartWithAuth(), this is the request we should
1917 // be issuing -- the final header line contains the credentials.
1918 MockWrite data_writes2
[] = {
1919 MockWrite("GET / HTTP/1.1\r\n"
1920 "Host: www.google.com\r\n"
1921 "Connection: keep-alive\r\n"
1922 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1925 // Lastly, the server responds with the actual content.
1926 MockRead data_reads2
[] = {
1927 MockRead("HTTP/1.1 200 OK\r\n"),
1928 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1929 MockRead("Content-Length: 5\r\n\r\n"),
1933 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1934 data_writes1
, arraysize(data_writes1
));
1935 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1936 data_writes2
, arraysize(data_writes2
));
1937 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1938 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1940 TestCompletionCallback callback1
;
1942 scoped_ptr
<HttpTransaction
> trans(
1943 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1944 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1947 rv
= callback1
.WaitForResult();
1950 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1951 ASSERT_TRUE(response
!= NULL
);
1952 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1954 TestCompletionCallback callback2
;
1956 rv
= trans
->RestartWithAuth(
1957 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1958 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1960 rv
= callback2
.WaitForResult();
1963 response
= trans
->GetResponseInfo();
1964 ASSERT_TRUE(response
!= NULL
);
1965 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1966 EXPECT_EQ(5, response
->headers
->GetContentLength());
1969 // Test the request-challenge-retry sequence for basic auth, over a connection
1970 // that requires a restart when setting up an SSL tunnel.
1971 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAlive
) {
1972 HttpRequestInfo request
;
1973 request
.method
= "GET";
1974 request
.url
= GURL("https://www.google.com/");
1975 // when the no authentication data flag is set.
1976 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1978 // Configure against proxy server "myproxy:70".
1979 session_deps_
.proxy_service
.reset(
1980 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
1981 CapturingBoundNetLog log
;
1982 session_deps_
.net_log
= log
.bound().net_log();
1983 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1985 // Since we have proxy, should try to establish tunnel.
1986 MockWrite data_writes1
[] = {
1987 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1988 "Host: www.google.com\r\n"
1989 "Proxy-Connection: keep-alive\r\n\r\n"),
1991 // After calling trans->RestartWithAuth(), this is the request we should
1992 // be issuing -- the final header line contains the credentials.
1993 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1994 "Host: www.google.com\r\n"
1995 "Proxy-Connection: keep-alive\r\n"
1996 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1998 MockWrite("GET / HTTP/1.1\r\n"
1999 "Host: www.google.com\r\n"
2000 "Connection: keep-alive\r\n\r\n"),
2003 // The proxy responds to the connect with a 407, using a persistent
2005 MockRead data_reads1
[] = {
2007 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2008 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2009 MockRead("Proxy-Connection: close\r\n\r\n"),
2011 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2013 MockRead("HTTP/1.1 200 OK\r\n"),
2014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2015 MockRead("Content-Length: 5\r\n\r\n"),
2016 MockRead(SYNCHRONOUS
, "hello"),
2019 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2020 data_writes1
, arraysize(data_writes1
));
2021 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2022 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2023 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2025 TestCompletionCallback callback1
;
2027 scoped_ptr
<HttpTransaction
> trans(
2028 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2030 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2031 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2033 rv
= callback1
.WaitForResult();
2035 net::CapturingNetLog::CapturedEntryList entries
;
2036 log
.GetEntries(&entries
);
2037 size_t pos
= ExpectLogContainsSomewhere(
2038 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2039 NetLog::PHASE_NONE
);
2040 ExpectLogContainsSomewhere(
2042 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2043 NetLog::PHASE_NONE
);
2045 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2046 ASSERT_TRUE(response
!= NULL
);
2047 ASSERT_FALSE(response
->headers
.get() == NULL
);
2048 EXPECT_EQ(407, response
->headers
->response_code());
2049 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2050 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2052 LoadTimingInfo load_timing_info
;
2053 // CONNECT requests and responses are handled at the connect job level, so
2054 // the transaction does not yet have a connection.
2055 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2057 TestCompletionCallback callback2
;
2059 rv
= trans
->RestartWithAuth(
2060 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2061 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2063 rv
= callback2
.WaitForResult();
2066 response
= trans
->GetResponseInfo();
2067 ASSERT_TRUE(response
!= NULL
);
2069 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2070 EXPECT_EQ(200, response
->headers
->response_code());
2071 EXPECT_EQ(5, response
->headers
->GetContentLength());
2072 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2074 // The password prompt info should not be set.
2075 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2077 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2078 TestLoadTimingNotReusedWithPac(load_timing_info
,
2079 CONNECT_TIMING_HAS_SSL_TIMES
);
2082 session
->CloseAllConnections();
2085 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2086 // proxy connection, when setting up an SSL tunnel.
2087 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAlive
) {
2088 HttpRequestInfo request
;
2089 request
.method
= "GET";
2090 request
.url
= GURL("https://www.google.com/");
2091 // Ensure that proxy authentication is attempted even
2092 // when the no authentication data flag is set.
2093 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2095 // Configure against proxy server "myproxy:70".
2096 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2097 CapturingBoundNetLog log
;
2098 session_deps_
.net_log
= log
.bound().net_log();
2099 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2101 scoped_ptr
<HttpTransaction
> trans(
2102 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2104 // Since we have proxy, should try to establish tunnel.
2105 MockWrite data_writes1
[] = {
2106 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2107 "Host: www.google.com\r\n"
2108 "Proxy-Connection: keep-alive\r\n\r\n"),
2110 // After calling trans->RestartWithAuth(), this is the request we should
2111 // be issuing -- the final header line contains the credentials.
2112 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2113 "Host: www.google.com\r\n"
2114 "Proxy-Connection: keep-alive\r\n"
2115 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2118 // The proxy responds to the connect with a 407, using a persistent
2120 MockRead data_reads1
[] = {
2122 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2123 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2124 MockRead("Content-Length: 10\r\n\r\n"),
2125 MockRead("0123456789"),
2127 // Wrong credentials (wrong password).
2128 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2129 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2130 MockRead("Content-Length: 10\r\n\r\n"),
2131 // No response body because the test stops reading here.
2132 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2135 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2136 data_writes1
, arraysize(data_writes1
));
2137 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2139 TestCompletionCallback callback1
;
2141 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2142 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2144 rv
= callback1
.WaitForResult();
2146 net::CapturingNetLog::CapturedEntryList entries
;
2147 log
.GetEntries(&entries
);
2148 size_t pos
= ExpectLogContainsSomewhere(
2149 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2150 NetLog::PHASE_NONE
);
2151 ExpectLogContainsSomewhere(
2153 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2154 NetLog::PHASE_NONE
);
2156 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2157 ASSERT_TRUE(response
!= NULL
);
2158 ASSERT_FALSE(response
->headers
.get() == NULL
);
2159 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2160 EXPECT_EQ(407, response
->headers
->response_code());
2161 EXPECT_EQ(10, response
->headers
->GetContentLength());
2162 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2163 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2165 TestCompletionCallback callback2
;
2167 // Wrong password (should be "bar").
2168 rv
= trans
->RestartWithAuth(
2169 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2170 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2172 rv
= callback2
.WaitForResult();
2175 response
= trans
->GetResponseInfo();
2176 ASSERT_TRUE(response
!= NULL
);
2177 ASSERT_FALSE(response
->headers
.get() == NULL
);
2178 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2179 EXPECT_EQ(407, response
->headers
->response_code());
2180 EXPECT_EQ(10, response
->headers
->GetContentLength());
2181 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2182 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2184 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2186 session
->CloseAllConnections();
2189 // Test that we don't read the response body when we fail to establish a tunnel,
2190 // even if the user cancels the proxy's auth attempt.
2191 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2192 HttpRequestInfo request
;
2193 request
.method
= "GET";
2194 request
.url
= GURL("https://www.google.com/");
2195 request
.load_flags
= 0;
2197 // Configure against proxy server "myproxy:70".
2198 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2202 scoped_ptr
<HttpTransaction
> trans(
2203 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2205 // Since we have proxy, should try to establish tunnel.
2206 MockWrite data_writes
[] = {
2207 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2208 "Host: www.google.com\r\n"
2209 "Proxy-Connection: keep-alive\r\n\r\n"),
2212 // The proxy responds to the connect with a 407.
2213 MockRead data_reads
[] = {
2214 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2215 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2216 MockRead("Content-Length: 10\r\n\r\n"),
2217 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2220 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2221 data_writes
, arraysize(data_writes
));
2222 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2224 TestCompletionCallback callback
;
2226 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2229 rv
= callback
.WaitForResult();
2232 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2233 ASSERT_TRUE(response
!= NULL
);
2235 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2236 EXPECT_EQ(407, response
->headers
->response_code());
2237 EXPECT_EQ(10, response
->headers
->GetContentLength());
2238 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2240 std::string response_data
;
2241 rv
= ReadTransaction(trans
.get(), &response_data
);
2242 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2244 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2245 session
->CloseAllConnections();
2248 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2249 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2250 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2251 HttpRequestInfo request
;
2252 request
.method
= "GET";
2253 request
.url
= GURL("http://www.google.com/");
2254 request
.load_flags
= 0;
2256 // We are using a DIRECT connection (i.e. no proxy) for this session.
2257 scoped_ptr
<HttpTransaction
> trans(
2258 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
2259 CreateSession(&session_deps_
)));
2261 MockWrite data_writes1
[] = {
2262 MockWrite("GET / HTTP/1.1\r\n"
2263 "Host: www.google.com\r\n"
2264 "Connection: keep-alive\r\n\r\n"),
2267 MockRead data_reads1
[] = {
2268 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2269 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2270 // Large content-length -- won't matter, as connection will be reset.
2271 MockRead("Content-Length: 10000\r\n\r\n"),
2272 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2275 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2276 data_writes1
, arraysize(data_writes1
));
2277 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2279 TestCompletionCallback callback
;
2281 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2282 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2284 rv
= callback
.WaitForResult();
2285 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2288 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2289 // through a non-authenticating proxy. The request should fail with
2290 // ERR_UNEXPECTED_PROXY_AUTH.
2291 // Note that it is impossible to detect if an HTTP server returns a 407 through
2292 // a non-authenticating proxy - there is nothing to indicate whether the
2293 // response came from the proxy or the server, so it is treated as if the proxy
2294 // issued the challenge.
2295 TEST_P(HttpNetworkTransactionTest
,
2296 HttpsServerRequestsProxyAuthThroughProxy
) {
2297 HttpRequestInfo request
;
2298 request
.method
= "GET";
2299 request
.url
= GURL("https://www.google.com/");
2301 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2302 CapturingBoundNetLog log
;
2303 session_deps_
.net_log
= log
.bound().net_log();
2304 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2306 // Since we have proxy, should try to establish tunnel.
2307 MockWrite data_writes1
[] = {
2308 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2309 "Host: www.google.com\r\n"
2310 "Proxy-Connection: keep-alive\r\n\r\n"),
2312 MockWrite("GET / HTTP/1.1\r\n"
2313 "Host: www.google.com\r\n"
2314 "Connection: keep-alive\r\n\r\n"),
2317 MockRead data_reads1
[] = {
2318 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2320 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2321 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2323 MockRead(SYNCHRONOUS
, OK
),
2326 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2327 data_writes1
, arraysize(data_writes1
));
2328 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2329 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2330 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2332 TestCompletionCallback callback1
;
2334 scoped_ptr
<HttpTransaction
> trans(
2335 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2337 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2338 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2340 rv
= callback1
.WaitForResult();
2341 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2342 net::CapturingNetLog::CapturedEntryList entries
;
2343 log
.GetEntries(&entries
);
2344 size_t pos
= ExpectLogContainsSomewhere(
2345 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2346 NetLog::PHASE_NONE
);
2347 ExpectLogContainsSomewhere(
2349 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2350 NetLog::PHASE_NONE
);
2353 // Test the load timing for HTTPS requests with an HTTP proxy.
2354 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
2355 HttpRequestInfo request1
;
2356 request1
.method
= "GET";
2357 request1
.url
= GURL("https://www.google.com/1");
2359 HttpRequestInfo request2
;
2360 request2
.method
= "GET";
2361 request2
.url
= GURL("https://www.google.com/2");
2363 // Configure against proxy server "myproxy:70".
2364 session_deps_
.proxy_service
.reset(
2365 ProxyService::CreateFixed("PROXY myproxy:70"));
2366 CapturingBoundNetLog log
;
2367 session_deps_
.net_log
= log
.bound().net_log();
2368 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2370 // Since we have proxy, should try to establish tunnel.
2371 MockWrite data_writes1
[] = {
2372 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2373 "Host: www.google.com\r\n"
2374 "Proxy-Connection: keep-alive\r\n\r\n"),
2376 MockWrite("GET /1 HTTP/1.1\r\n"
2377 "Host: www.google.com\r\n"
2378 "Connection: keep-alive\r\n\r\n"),
2380 MockWrite("GET /2 HTTP/1.1\r\n"
2381 "Host: www.google.com\r\n"
2382 "Connection: keep-alive\r\n\r\n"),
2385 // The proxy responds to the connect with a 407, using a persistent
2387 MockRead data_reads1
[] = {
2388 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2390 MockRead("HTTP/1.1 200 OK\r\n"),
2391 MockRead("Content-Length: 1\r\n\r\n"),
2392 MockRead(SYNCHRONOUS
, "1"),
2394 MockRead("HTTP/1.1 200 OK\r\n"),
2395 MockRead("Content-Length: 2\r\n\r\n"),
2396 MockRead(SYNCHRONOUS
, "22"),
2399 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2400 data_writes1
, arraysize(data_writes1
));
2401 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2402 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2403 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2405 TestCompletionCallback callback1
;
2406 scoped_ptr
<HttpTransaction
> trans1(
2407 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2409 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2410 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2412 rv
= callback1
.WaitForResult();
2415 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2416 ASSERT_TRUE(response1
!= NULL
);
2417 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2418 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2420 LoadTimingInfo load_timing_info1
;
2421 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2422 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
2426 TestCompletionCallback callback2
;
2427 scoped_ptr
<HttpTransaction
> trans2(
2428 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2430 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2431 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2433 rv
= callback2
.WaitForResult();
2436 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2437 ASSERT_TRUE(response2
!= NULL
);
2438 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2439 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2441 LoadTimingInfo load_timing_info2
;
2442 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2443 TestLoadTimingReused(load_timing_info2
);
2445 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2448 session
->CloseAllConnections();
2451 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2452 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
2453 HttpRequestInfo request1
;
2454 request1
.method
= "GET";
2455 request1
.url
= GURL("https://www.google.com/1");
2457 HttpRequestInfo request2
;
2458 request2
.method
= "GET";
2459 request2
.url
= GURL("https://www.google.com/2");
2461 // Configure against proxy server "myproxy:70".
2462 session_deps_
.proxy_service
.reset(
2463 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2464 CapturingBoundNetLog log
;
2465 session_deps_
.net_log
= log
.bound().net_log();
2466 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2468 // Since we have proxy, should try to establish tunnel.
2469 MockWrite data_writes1
[] = {
2470 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2471 "Host: www.google.com\r\n"
2472 "Proxy-Connection: keep-alive\r\n\r\n"),
2474 MockWrite("GET /1 HTTP/1.1\r\n"
2475 "Host: www.google.com\r\n"
2476 "Connection: keep-alive\r\n\r\n"),
2478 MockWrite("GET /2 HTTP/1.1\r\n"
2479 "Host: www.google.com\r\n"
2480 "Connection: keep-alive\r\n\r\n"),
2483 // The proxy responds to the connect with a 407, using a persistent
2485 MockRead data_reads1
[] = {
2486 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2488 MockRead("HTTP/1.1 200 OK\r\n"),
2489 MockRead("Content-Length: 1\r\n\r\n"),
2490 MockRead(SYNCHRONOUS
, "1"),
2492 MockRead("HTTP/1.1 200 OK\r\n"),
2493 MockRead("Content-Length: 2\r\n\r\n"),
2494 MockRead(SYNCHRONOUS
, "22"),
2497 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2498 data_writes1
, arraysize(data_writes1
));
2499 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2500 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2501 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2503 TestCompletionCallback callback1
;
2504 scoped_ptr
<HttpTransaction
> trans1(
2505 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2507 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2508 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2510 rv
= callback1
.WaitForResult();
2513 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2514 ASSERT_TRUE(response1
!= NULL
);
2515 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2516 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2518 LoadTimingInfo load_timing_info1
;
2519 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2520 TestLoadTimingNotReusedWithPac(load_timing_info1
,
2521 CONNECT_TIMING_HAS_SSL_TIMES
);
2525 TestCompletionCallback callback2
;
2526 scoped_ptr
<HttpTransaction
> trans2(
2527 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2529 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2530 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2532 rv
= callback2
.WaitForResult();
2535 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2536 ASSERT_TRUE(response2
!= NULL
);
2537 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2538 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2540 LoadTimingInfo load_timing_info2
;
2541 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2542 TestLoadTimingReusedWithPac(load_timing_info2
);
2544 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2547 session
->CloseAllConnections();
2550 // Test a simple get through an HTTPS Proxy.
2551 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
2552 HttpRequestInfo request
;
2553 request
.method
= "GET";
2554 request
.url
= GURL("http://www.google.com/");
2556 // Configure against https proxy server "proxy:70".
2557 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2558 "https://proxy:70"));
2559 CapturingBoundNetLog log
;
2560 session_deps_
.net_log
= log
.bound().net_log();
2561 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2563 // Since we have proxy, should use full url
2564 MockWrite data_writes1
[] = {
2565 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2566 "Host: www.google.com\r\n"
2567 "Proxy-Connection: keep-alive\r\n\r\n"),
2570 MockRead data_reads1
[] = {
2571 MockRead("HTTP/1.1 200 OK\r\n"),
2572 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2573 MockRead("Content-Length: 100\r\n\r\n"),
2574 MockRead(SYNCHRONOUS
, OK
),
2577 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2578 data_writes1
, arraysize(data_writes1
));
2579 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2580 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2581 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2583 TestCompletionCallback callback1
;
2585 scoped_ptr
<HttpTransaction
> trans(
2586 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2588 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2589 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2591 rv
= callback1
.WaitForResult();
2594 LoadTimingInfo load_timing_info
;
2595 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2596 TestLoadTimingNotReused(load_timing_info
,
2597 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2599 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2600 ASSERT_TRUE(response
!= NULL
);
2602 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2603 EXPECT_EQ(200, response
->headers
->response_code());
2604 EXPECT_EQ(100, response
->headers
->GetContentLength());
2605 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2607 // The password prompt info should not be set.
2608 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2611 // Test a SPDY get through an HTTPS Proxy.
2612 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
2613 HttpRequestInfo request
;
2614 request
.method
= "GET";
2615 request
.url
= GURL("http://www.google.com/");
2616 request
.load_flags
= 0;
2618 // Configure against https proxy server "proxy:70".
2619 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2620 "https://proxy:70"));
2621 CapturingBoundNetLog log
;
2622 session_deps_
.net_log
= log
.bound().net_log();
2623 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2625 // fetch http://www.google.com/ via SPDY
2626 scoped_ptr
<SpdyFrame
> req(
2627 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
2628 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
2630 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2631 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2632 MockRead spdy_reads
[] = {
2633 CreateMockRead(*resp
),
2634 CreateMockRead(*data
),
2635 MockRead(ASYNC
, 0, 0),
2638 DelayedSocketData
spdy_data(
2639 1, // wait for one write to finish before reading.
2640 spdy_reads
, arraysize(spdy_reads
),
2641 spdy_writes
, arraysize(spdy_writes
));
2642 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
2644 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2645 ssl
.SetNextProto(GetParam());
2646 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2648 TestCompletionCallback callback1
;
2650 scoped_ptr
<HttpTransaction
> trans(
2651 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2653 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2654 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2656 rv
= callback1
.WaitForResult();
2659 LoadTimingInfo load_timing_info
;
2660 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2661 TestLoadTimingNotReused(load_timing_info
,
2662 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2664 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2665 ASSERT_TRUE(response
!= NULL
);
2666 ASSERT_TRUE(response
->headers
.get() != NULL
);
2667 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2669 std::string response_data
;
2670 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
2671 EXPECT_EQ(kUploadData
, response_data
);
2674 // Test a SPDY get through an HTTPS Proxy.
2675 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
2676 HttpRequestInfo request
;
2677 request
.method
= "GET";
2678 request
.url
= GURL("http://www.google.com/");
2679 request
.load_flags
= 0;
2681 // Configure against https proxy server "myproxy:70".
2682 session_deps_
.proxy_service
.reset(
2683 ProxyService::CreateFixed("https://myproxy:70"));
2684 CapturingBoundNetLog log
;
2685 session_deps_
.net_log
= log
.bound().net_log();
2686 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2688 // The first request will be a bare GET, the second request will be a
2689 // GET with a Proxy-Authorization header.
2690 scoped_ptr
<SpdyFrame
> req_get(
2691 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
2692 const char* const kExtraAuthorizationHeaders
[] = {
2693 "proxy-authorization", "Basic Zm9vOmJhcg=="
2695 scoped_ptr
<SpdyFrame
> req_get_authorization(
2696 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
2697 arraysize(kExtraAuthorizationHeaders
) / 2,
2702 MockWrite spdy_writes
[] = {
2703 CreateMockWrite(*req_get
, 1),
2704 CreateMockWrite(*req_get_authorization
, 4),
2707 // The first response is a 407 proxy authentication challenge, and the second
2708 // response will be a 200 response since the second request includes a valid
2709 // Authorization header.
2710 const char* const kExtraAuthenticationHeaders
[] = {
2711 "proxy-authenticate", "Basic realm=\"MyRealm1\""
2713 scoped_ptr
<SpdyFrame
> resp_authentication(
2714 spdy_util_
.ConstructSpdySynReplyError(
2715 "407 Proxy Authentication Required",
2716 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
2718 scoped_ptr
<SpdyFrame
> body_authentication(
2719 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2720 scoped_ptr
<SpdyFrame
> resp_data(
2721 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
2722 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2723 MockRead spdy_reads
[] = {
2724 CreateMockRead(*resp_authentication
, 2),
2725 CreateMockRead(*body_authentication
, 3),
2726 CreateMockRead(*resp_data
, 5),
2727 CreateMockRead(*body_data
, 6),
2728 MockRead(ASYNC
, 0, 7),
2731 OrderedSocketData
data(
2732 spdy_reads
, arraysize(spdy_reads
),
2733 spdy_writes
, arraysize(spdy_writes
));
2734 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2736 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2737 ssl
.SetNextProto(GetParam());
2738 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2740 TestCompletionCallback callback1
;
2742 scoped_ptr
<HttpTransaction
> trans(
2743 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2745 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2746 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2748 rv
= callback1
.WaitForResult();
2751 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
2753 ASSERT_TRUE(response
!= NULL
);
2754 ASSERT_TRUE(response
->headers
.get() != NULL
);
2755 EXPECT_EQ(407, response
->headers
->response_code());
2756 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2757 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2759 TestCompletionCallback callback2
;
2761 rv
= trans
->RestartWithAuth(
2762 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2763 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2765 rv
= callback2
.WaitForResult();
2768 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
2770 ASSERT_TRUE(response_restart
!= NULL
);
2771 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
2772 EXPECT_EQ(200, response_restart
->headers
->response_code());
2773 // The password prompt info should not be set.
2774 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
2777 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2778 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
2779 HttpRequestInfo request
;
2780 request
.method
= "GET";
2781 request
.url
= GURL("https://www.google.com/");
2782 request
.load_flags
= 0;
2784 // Configure against https proxy server "proxy:70".
2785 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2786 "https://proxy:70"));
2787 CapturingBoundNetLog log
;
2788 session_deps_
.net_log
= log
.bound().net_log();
2789 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2791 scoped_ptr
<HttpTransaction
> trans(
2792 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2794 // CONNECT to www.google.com:443 via SPDY
2795 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
2796 // fetch https://www.google.com/ via HTTP
2798 const char get
[] = "GET / HTTP/1.1\r\n"
2799 "Host: www.google.com\r\n"
2800 "Connection: keep-alive\r\n\r\n";
2801 scoped_ptr
<SpdyFrame
> wrapped_get(
2802 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
2803 scoped_ptr
<SpdyFrame
> conn_resp(
2804 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2805 const char resp
[] = "HTTP/1.1 200 OK\r\n"
2806 "Content-Length: 10\r\n\r\n";
2807 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
2808 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
2809 scoped_ptr
<SpdyFrame
> wrapped_body(
2810 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2811 scoped_ptr
<SpdyFrame
> window_update(
2812 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
2814 MockWrite spdy_writes
[] = {
2815 CreateMockWrite(*connect
, 1),
2816 CreateMockWrite(*wrapped_get
, 3),
2817 CreateMockWrite(*window_update
, 5),
2820 MockRead spdy_reads
[] = {
2821 CreateMockRead(*conn_resp
, 2, ASYNC
),
2822 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
2823 CreateMockRead(*wrapped_body
, 6, ASYNC
),
2824 CreateMockRead(*wrapped_body
, 7, ASYNC
),
2825 MockRead(ASYNC
, 0, 8),
2828 OrderedSocketData
spdy_data(
2829 spdy_reads
, arraysize(spdy_reads
),
2830 spdy_writes
, arraysize(spdy_writes
));
2831 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
2833 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2834 ssl
.SetNextProto(GetParam());
2835 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2836 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
2837 ssl2
.was_npn_negotiated
= false;
2838 ssl2
.protocol_negotiated
= kProtoUnknown
;
2839 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
2841 TestCompletionCallback callback1
;
2843 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2844 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2846 rv
= callback1
.WaitForResult();
2849 LoadTimingInfo load_timing_info
;
2850 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2851 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
2853 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2854 ASSERT_TRUE(response
!= NULL
);
2855 ASSERT_TRUE(response
->headers
.get() != NULL
);
2856 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2858 std::string response_data
;
2859 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
2860 EXPECT_EQ("1234567890", response_data
);
2863 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2864 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
2865 HttpRequestInfo request
;
2866 request
.method
= "GET";
2867 request
.url
= GURL("https://www.google.com/");
2868 request
.load_flags
= 0;
2870 // Configure against https proxy server "proxy:70".
2871 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2872 "https://proxy:70"));
2873 CapturingBoundNetLog log
;
2874 session_deps_
.net_log
= log
.bound().net_log();
2875 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2877 scoped_ptr
<HttpTransaction
> trans(
2878 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2880 // CONNECT to www.google.com:443 via SPDY
2881 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
2882 // fetch https://www.google.com/ via SPDY
2883 const char* const kMyUrl
= "https://www.google.com/";
2884 scoped_ptr
<SpdyFrame
> get(
2885 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
2886 scoped_ptr
<SpdyFrame
> wrapped_get(
2887 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
2888 scoped_ptr
<SpdyFrame
> conn_resp(
2889 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2890 scoped_ptr
<SpdyFrame
> get_resp(
2891 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2892 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
2893 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
2894 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2895 scoped_ptr
<SpdyFrame
> wrapped_body(
2896 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
2897 scoped_ptr
<SpdyFrame
> window_update_get_resp(
2898 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
2899 scoped_ptr
<SpdyFrame
> window_update_body(
2900 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
2902 MockWrite spdy_writes
[] = {
2903 CreateMockWrite(*connect
, 1),
2904 CreateMockWrite(*wrapped_get
, 3),
2905 CreateMockWrite(*window_update_get_resp
, 5),
2906 CreateMockWrite(*window_update_body
, 7),
2909 MockRead spdy_reads
[] = {
2910 CreateMockRead(*conn_resp
, 2, ASYNC
),
2911 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
2912 CreateMockRead(*wrapped_body
, 6, ASYNC
),
2913 MockRead(ASYNC
, 0, 8),
2916 OrderedSocketData
spdy_data(
2917 spdy_reads
, arraysize(spdy_reads
),
2918 spdy_writes
, arraysize(spdy_writes
));
2919 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
2921 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2922 ssl
.SetNextProto(GetParam());
2923 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2924 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
2925 ssl2
.SetNextProto(GetParam());
2926 ssl2
.protocol_negotiated
= GetParam();
2927 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
2929 TestCompletionCallback callback1
;
2931 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2932 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2934 rv
= callback1
.WaitForResult();
2937 LoadTimingInfo load_timing_info
;
2938 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2939 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
2941 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2942 ASSERT_TRUE(response
!= NULL
);
2943 ASSERT_TRUE(response
->headers
.get() != NULL
);
2944 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2946 std::string response_data
;
2947 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
2948 EXPECT_EQ(kUploadData
, response_data
);
2951 // Test a SPDY CONNECT failure through an HTTPS Proxy.
2952 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
2953 HttpRequestInfo request
;
2954 request
.method
= "GET";
2955 request
.url
= GURL("https://www.google.com/");
2956 request
.load_flags
= 0;
2958 // Configure against https proxy server "proxy:70".
2959 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2960 "https://proxy:70"));
2961 CapturingBoundNetLog log
;
2962 session_deps_
.net_log
= log
.bound().net_log();
2963 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2965 scoped_ptr
<HttpTransaction
> trans(
2966 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2968 // CONNECT to www.google.com:443 via SPDY
2969 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
2970 scoped_ptr
<SpdyFrame
> get(
2971 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2973 MockWrite spdy_writes
[] = {
2974 CreateMockWrite(*connect
, 1),
2975 CreateMockWrite(*get
, 3),
2978 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
2979 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2980 MockRead spdy_reads
[] = {
2981 CreateMockRead(*resp
, 2, ASYNC
),
2982 MockRead(ASYNC
, 0, 4),
2985 OrderedSocketData
spdy_data(
2986 spdy_reads
, arraysize(spdy_reads
),
2987 spdy_writes
, arraysize(spdy_writes
));
2988 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
2990 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2991 ssl
.SetNextProto(GetParam());
2992 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2993 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
2994 ssl2
.SetNextProto(GetParam());
2995 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
2997 TestCompletionCallback callback1
;
2999 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3000 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3002 rv
= callback1
.WaitForResult();
3003 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3005 // TODO(ttuttle): Anything else to check here?
3008 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3009 // HTTPS Proxy to different servers.
3010 TEST_P(HttpNetworkTransactionTest
,
3011 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3012 // Configure against https proxy server "proxy:70".
3013 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3014 "https://proxy:70"));
3015 CapturingBoundNetLog log
;
3016 session_deps_
.net_log
= log
.bound().net_log();
3017 scoped_refptr
<HttpNetworkSession
> session(
3018 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3020 HttpRequestInfo request1
;
3021 request1
.method
= "GET";
3022 request1
.url
= GURL("https://www.google.com/");
3023 request1
.load_flags
= 0;
3025 HttpRequestInfo request2
;
3026 request2
.method
= "GET";
3027 request2
.url
= GURL("https://news.google.com/");
3028 request2
.load_flags
= 0;
3030 // CONNECT to www.google.com:443 via SPDY.
3031 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
3032 scoped_ptr
<SpdyFrame
> conn_resp1(
3033 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3035 // Fetch https://www.google.com/ via HTTP.
3036 const char get1
[] = "GET / HTTP/1.1\r\n"
3037 "Host: www.google.com\r\n"
3038 "Connection: keep-alive\r\n\r\n";
3039 scoped_ptr
<SpdyFrame
> wrapped_get1(
3040 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3041 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3042 "Content-Length: 1\r\n\r\n";
3043 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3044 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3045 scoped_ptr
<SpdyFrame
> wrapped_body1(
3046 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3047 scoped_ptr
<SpdyFrame
> window_update(
3048 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3050 // CONNECT to news.google.com:443 via SPDY.
3051 const char* const kConnectHeaders2
[] = {
3052 spdy_util_
.GetMethodKey(), "CONNECT",
3053 spdy_util_
.GetPathKey(), "news.google.com:443",
3054 spdy_util_
.GetHostKey(), "news.google.com",
3055 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3057 scoped_ptr
<SpdyFrame
> connect2(
3058 spdy_util_
.ConstructSpdyControlFrame(NULL
,
3060 /*compressed*/ false,
3066 arraysize(kConnectHeaders2
),
3068 scoped_ptr
<SpdyFrame
> conn_resp2(
3069 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3071 // Fetch https://news.google.com/ via HTTP.
3072 const char get2
[] = "GET / HTTP/1.1\r\n"
3073 "Host: news.google.com\r\n"
3074 "Connection: keep-alive\r\n\r\n";
3075 scoped_ptr
<SpdyFrame
> wrapped_get2(
3076 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3077 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3078 "Content-Length: 2\r\n\r\n";
3079 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3080 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3081 scoped_ptr
<SpdyFrame
> wrapped_body2(
3082 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3084 MockWrite spdy_writes
[] = {
3085 CreateMockWrite(*connect1
, 0),
3086 CreateMockWrite(*wrapped_get1
, 2),
3087 CreateMockWrite(*connect2
, 5),
3088 CreateMockWrite(*wrapped_get2
, 7),
3091 MockRead spdy_reads
[] = {
3092 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3093 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3094 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3095 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3096 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3097 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3098 MockRead(ASYNC
, 0, 10),
3101 DeterministicSocketData
spdy_data(
3102 spdy_reads
, arraysize(spdy_reads
),
3103 spdy_writes
, arraysize(spdy_writes
));
3104 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3106 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3107 ssl
.SetNextProto(GetParam());
3108 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3109 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3110 ssl2
.was_npn_negotiated
= false;
3111 ssl2
.protocol_negotiated
= kProtoUnknown
;
3112 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3113 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3114 ssl3
.was_npn_negotiated
= false;
3115 ssl3
.protocol_negotiated
= kProtoUnknown
;
3116 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3118 TestCompletionCallback callback
;
3120 scoped_ptr
<HttpTransaction
> trans(
3121 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3122 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3124 // The first connect and request, each of their responses, and the body.
3125 spdy_data
.RunFor(5);
3127 rv
= callback
.WaitForResult();
3130 LoadTimingInfo load_timing_info
;
3131 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3132 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3134 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3135 ASSERT_TRUE(response
!= NULL
);
3136 ASSERT_TRUE(response
->headers
.get() != NULL
);
3137 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3139 std::string response_data
;
3140 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3141 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3143 scoped_ptr
<HttpTransaction
> trans2(
3144 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3145 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3146 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3148 // The second connect and request, each of their responses, and the body.
3149 spdy_data
.RunFor(5);
3150 rv
= callback
.WaitForResult();
3153 LoadTimingInfo load_timing_info2
;
3154 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3155 // Even though the SPDY connection is reused, a new tunnelled connection has
3156 // to be created, so the socket's load timing looks like a fresh connection.
3157 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3159 // The requests should have different IDs, since they each are using their own
3161 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3163 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3166 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3167 // HTTPS Proxy to the same server.
3168 TEST_P(HttpNetworkTransactionTest
,
3169 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3170 // Configure against https proxy server "proxy:70".
3171 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3172 "https://proxy:70"));
3173 CapturingBoundNetLog log
;
3174 session_deps_
.net_log
= log
.bound().net_log();
3175 scoped_refptr
<HttpNetworkSession
> session(
3176 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3178 HttpRequestInfo request1
;
3179 request1
.method
= "GET";
3180 request1
.url
= GURL("https://www.google.com/");
3181 request1
.load_flags
= 0;
3183 HttpRequestInfo request2
;
3184 request2
.method
= "GET";
3185 request2
.url
= GURL("https://www.google.com/2");
3186 request2
.load_flags
= 0;
3188 // CONNECT to www.google.com:443 via SPDY.
3189 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
3190 scoped_ptr
<SpdyFrame
> conn_resp1(
3191 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3193 // Fetch https://www.google.com/ via HTTP.
3194 const char get1
[] = "GET / HTTP/1.1\r\n"
3195 "Host: www.google.com\r\n"
3196 "Connection: keep-alive\r\n\r\n";
3197 scoped_ptr
<SpdyFrame
> wrapped_get1(
3198 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3199 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3200 "Content-Length: 1\r\n\r\n";
3201 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3202 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3203 scoped_ptr
<SpdyFrame
> wrapped_body1(
3204 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3205 scoped_ptr
<SpdyFrame
> window_update(
3206 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3208 // Fetch https://www.google.com/2 via HTTP.
3209 const char get2
[] = "GET /2 HTTP/1.1\r\n"
3210 "Host: www.google.com\r\n"
3211 "Connection: keep-alive\r\n\r\n";
3212 scoped_ptr
<SpdyFrame
> wrapped_get2(
3213 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3214 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3215 "Content-Length: 2\r\n\r\n";
3216 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3217 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3218 scoped_ptr
<SpdyFrame
> wrapped_body2(
3219 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3221 MockWrite spdy_writes
[] = {
3222 CreateMockWrite(*connect1
, 0),
3223 CreateMockWrite(*wrapped_get1
, 2),
3224 CreateMockWrite(*wrapped_get2
, 5),
3227 MockRead spdy_reads
[] = {
3228 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3229 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3230 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3231 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
3232 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
3233 MockRead(ASYNC
, 0, 8),
3236 DeterministicSocketData
spdy_data(
3237 spdy_reads
, arraysize(spdy_reads
),
3238 spdy_writes
, arraysize(spdy_writes
));
3239 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3241 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3242 ssl
.SetNextProto(GetParam());
3243 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3244 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3245 ssl2
.was_npn_negotiated
= false;
3246 ssl2
.protocol_negotiated
= kProtoUnknown
;
3247 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3249 TestCompletionCallback callback
;
3251 scoped_ptr
<HttpTransaction
> trans(
3252 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3253 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3255 // The first connect and request, each of their responses, and the body.
3256 spdy_data
.RunFor(5);
3258 rv
= callback
.WaitForResult();
3261 LoadTimingInfo load_timing_info
;
3262 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3263 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3265 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3266 ASSERT_TRUE(response
!= NULL
);
3267 ASSERT_TRUE(response
->headers
.get() != NULL
);
3268 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3270 std::string response_data
;
3271 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3272 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3275 scoped_ptr
<HttpTransaction
> trans2(
3276 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3277 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3278 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3280 // The second request, response, and body. There should not be a second
3282 spdy_data
.RunFor(3);
3283 rv
= callback
.WaitForResult();
3286 LoadTimingInfo load_timing_info2
;
3287 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3288 TestLoadTimingReused(load_timing_info2
);
3290 // The requests should have the same ID.
3291 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3293 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3296 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3297 // Proxy to different servers.
3298 TEST_P(HttpNetworkTransactionTest
,
3299 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
3300 // Configure against https proxy server "proxy:70".
3301 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3302 "https://proxy:70"));
3303 CapturingBoundNetLog log
;
3304 session_deps_
.net_log
= log
.bound().net_log();
3305 scoped_refptr
<HttpNetworkSession
> session(
3306 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3308 HttpRequestInfo request1
;
3309 request1
.method
= "GET";
3310 request1
.url
= GURL("http://www.google.com/");
3311 request1
.load_flags
= 0;
3313 HttpRequestInfo request2
;
3314 request2
.method
= "GET";
3315 request2
.url
= GURL("http://news.google.com/");
3316 request2
.load_flags
= 0;
3318 // http://www.google.com/
3319 scoped_ptr
<SpdyHeaderBlock
> headers(
3320 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3321 scoped_ptr
<SpdyFrame
> get1(spdy_util_
.ConstructSpdyControlFrame(
3322 headers
.Pass(), false, 1, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
3323 scoped_ptr
<SpdyFrame
> get_resp1(
3324 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3325 scoped_ptr
<SpdyFrame
> body1(
3326 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
3328 // http://news.google.com/
3329 scoped_ptr
<SpdyHeaderBlock
> headers2(
3330 spdy_util_
.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3331 scoped_ptr
<SpdyFrame
> get2(spdy_util_
.ConstructSpdyControlFrame(
3332 headers2
.Pass(), false, 3, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
3333 scoped_ptr
<SpdyFrame
> get_resp2(
3334 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3335 scoped_ptr
<SpdyFrame
> body2(
3336 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
3338 MockWrite spdy_writes
[] = {
3339 CreateMockWrite(*get1
, 0),
3340 CreateMockWrite(*get2
, 3),
3343 MockRead spdy_reads
[] = {
3344 CreateMockRead(*get_resp1
, 1, ASYNC
),
3345 CreateMockRead(*body1
, 2, ASYNC
),
3346 CreateMockRead(*get_resp2
, 4, ASYNC
),
3347 CreateMockRead(*body2
, 5, ASYNC
),
3348 MockRead(ASYNC
, 0, 6),
3351 DeterministicSocketData
spdy_data(
3352 spdy_reads
, arraysize(spdy_reads
),
3353 spdy_writes
, arraysize(spdy_writes
));
3354 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3356 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3357 ssl
.SetNextProto(GetParam());
3358 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3360 TestCompletionCallback callback
;
3362 scoped_ptr
<HttpTransaction
> trans(
3363 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3364 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3365 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3366 spdy_data
.RunFor(2);
3368 rv
= callback
.WaitForResult();
3371 LoadTimingInfo load_timing_info
;
3372 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3373 TestLoadTimingNotReused(load_timing_info
,
3374 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3376 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3377 ASSERT_TRUE(response
!= NULL
);
3378 ASSERT_TRUE(response
->headers
.get() != NULL
);
3379 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3381 std::string response_data
;
3382 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3383 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
3384 spdy_data
.RunFor(1);
3385 EXPECT_EQ(1, callback
.WaitForResult());
3386 // Delete the first request, so the second one can reuse the socket.
3389 scoped_ptr
<HttpTransaction
> trans2(
3390 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3391 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3392 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3394 spdy_data
.RunFor(2);
3395 rv
= callback
.WaitForResult();
3398 LoadTimingInfo load_timing_info2
;
3399 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3400 TestLoadTimingReused(load_timing_info2
);
3402 // The requests should have the same ID.
3403 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3405 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
3406 spdy_data
.RunFor(1);
3407 EXPECT_EQ(2, callback
.WaitForResult());
3410 // Test the challenge-response-retry sequence through an HTTPS Proxy
3411 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
3412 HttpRequestInfo request
;
3413 request
.method
= "GET";
3414 request
.url
= GURL("http://www.google.com/");
3415 // when the no authentication data flag is set.
3416 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
3418 // Configure against https proxy server "myproxy:70".
3419 session_deps_
.proxy_service
.reset(
3420 ProxyService::CreateFixed("https://myproxy:70"));
3421 CapturingBoundNetLog log
;
3422 session_deps_
.net_log
= log
.bound().net_log();
3423 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3425 // Since we have proxy, should use full url
3426 MockWrite data_writes1
[] = {
3427 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3428 "Host: www.google.com\r\n"
3429 "Proxy-Connection: keep-alive\r\n\r\n"),
3431 // After calling trans->RestartWithAuth(), this is the request we should
3432 // be issuing -- the final header line contains the credentials.
3433 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3434 "Host: www.google.com\r\n"
3435 "Proxy-Connection: keep-alive\r\n"
3436 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3439 // The proxy responds to the GET with a 407, using a persistent
3441 MockRead data_reads1
[] = {
3443 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3444 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3445 MockRead("Proxy-Connection: keep-alive\r\n"),
3446 MockRead("Content-Length: 0\r\n\r\n"),
3448 MockRead("HTTP/1.1 200 OK\r\n"),
3449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3450 MockRead("Content-Length: 100\r\n\r\n"),
3451 MockRead(SYNCHRONOUS
, OK
),
3454 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3455 data_writes1
, arraysize(data_writes1
));
3456 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3457 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3458 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3460 TestCompletionCallback callback1
;
3462 scoped_ptr
<HttpTransaction
> trans(
3463 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3465 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3466 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3468 rv
= callback1
.WaitForResult();
3471 LoadTimingInfo load_timing_info
;
3472 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3473 TestLoadTimingNotReused(load_timing_info
,
3474 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3476 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3477 ASSERT_TRUE(response
!= NULL
);
3478 ASSERT_FALSE(response
->headers
.get() == NULL
);
3479 EXPECT_EQ(407, response
->headers
->response_code());
3480 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3481 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3483 TestCompletionCallback callback2
;
3485 rv
= trans
->RestartWithAuth(
3486 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3487 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3489 rv
= callback2
.WaitForResult();
3492 load_timing_info
= LoadTimingInfo();
3493 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3494 // Retrying with HTTP AUTH is considered to be reusing a socket.
3495 TestLoadTimingReused(load_timing_info
);
3497 response
= trans
->GetResponseInfo();
3498 ASSERT_TRUE(response
!= NULL
);
3500 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3501 EXPECT_EQ(200, response
->headers
->response_code());
3502 EXPECT_EQ(100, response
->headers
->GetContentLength());
3503 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3505 // The password prompt info should not be set.
3506 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3509 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3510 const MockRead
& status
, int expected_status
) {
3511 HttpRequestInfo request
;
3512 request
.method
= "GET";
3513 request
.url
= GURL("https://www.google.com/");
3514 request
.load_flags
= 0;
3516 // Configure against proxy server "myproxy:70".
3517 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3519 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3521 // Since we have proxy, should try to establish tunnel.
3522 MockWrite data_writes
[] = {
3523 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3524 "Host: www.google.com\r\n"
3525 "Proxy-Connection: keep-alive\r\n\r\n"),
3528 MockRead data_reads
[] = {
3530 MockRead("Content-Length: 10\r\n\r\n"),
3531 // No response body because the test stops reading here.
3532 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3535 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
3536 data_writes
, arraysize(data_writes
));
3537 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3539 TestCompletionCallback callback
;
3541 scoped_ptr
<HttpTransaction
> trans(
3542 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3544 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3545 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3547 rv
= callback
.WaitForResult();
3548 EXPECT_EQ(expected_status
, rv
);
3551 void HttpNetworkTransactionTest::ConnectStatusHelper(
3552 const MockRead
& status
) {
3553 ConnectStatusHelperWithExpectedStatus(
3554 status
, ERR_TUNNEL_CONNECTION_FAILED
);
3557 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
3558 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3561 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
3562 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3565 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
3566 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3569 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
3570 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3573 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
3574 ConnectStatusHelper(
3575 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3578 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
3579 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3582 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
3583 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3586 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
3587 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3590 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
3591 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3594 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
3595 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3598 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
3599 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3602 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
3603 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3606 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
3607 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3610 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
3611 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3614 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
3615 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3618 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
3619 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3622 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
3623 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3626 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
3627 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3630 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
3631 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3634 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
3635 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3638 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
3639 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3642 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
3643 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3646 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
3647 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3650 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
3651 ConnectStatusHelperWithExpectedStatus(
3652 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3653 ERR_PROXY_AUTH_UNSUPPORTED
);
3656 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
3657 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3660 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
3661 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3664 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
3665 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
3668 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
3669 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
3672 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
3673 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
3676 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
3677 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
3680 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
3681 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
3684 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
3685 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
3688 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
3689 ConnectStatusHelper(
3690 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
3693 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
3694 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
3697 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
3698 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
3701 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
3702 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
3705 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
3706 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
3709 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
3710 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
3713 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
3714 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
3717 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
3718 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
3721 // Test the flow when both the proxy server AND origin server require
3722 // authentication. Again, this uses basic auth for both since that is
3723 // the simplest to mock.
3724 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
3725 HttpRequestInfo request
;
3726 request
.method
= "GET";
3727 request
.url
= GURL("http://www.google.com/");
3728 request
.load_flags
= 0;
3730 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3732 // Configure against proxy server "myproxy:70".
3733 scoped_ptr
<HttpTransaction
> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY
,
3734 CreateSession(&session_deps_
)));
3736 MockWrite data_writes1
[] = {
3737 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3738 "Host: www.google.com\r\n"
3739 "Proxy-Connection: keep-alive\r\n\r\n"),
3742 MockRead data_reads1
[] = {
3743 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
3744 // Give a couple authenticate options (only the middle one is actually
3746 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
3747 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3748 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3749 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3750 // Large content-length -- won't matter, as connection will be reset.
3751 MockRead("Content-Length: 10000\r\n\r\n"),
3752 MockRead(SYNCHRONOUS
, ERR_FAILED
),
3755 // After calling trans->RestartWithAuth() the first time, this is the
3756 // request we should be issuing -- the final header line contains the
3757 // proxy's credentials.
3758 MockWrite data_writes2
[] = {
3759 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3760 "Host: www.google.com\r\n"
3761 "Proxy-Connection: keep-alive\r\n"
3762 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3765 // Now the proxy server lets the request pass through to origin server.
3766 // The origin server responds with a 401.
3767 MockRead data_reads2
[] = {
3768 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3769 // Note: We are using the same realm-name as the proxy server. This is
3770 // completely valid, as realms are unique across hosts.
3771 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3772 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3773 MockRead("Content-Length: 2000\r\n\r\n"),
3774 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
3777 // After calling trans->RestartWithAuth() the second time, we should send
3778 // the credentials for both the proxy and origin server.
3779 MockWrite data_writes3
[] = {
3780 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3781 "Host: www.google.com\r\n"
3782 "Proxy-Connection: keep-alive\r\n"
3783 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
3784 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3787 // Lastly we get the desired content.
3788 MockRead data_reads3
[] = {
3789 MockRead("HTTP/1.0 200 OK\r\n"),
3790 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3791 MockRead("Content-Length: 100\r\n\r\n"),
3792 MockRead(SYNCHRONOUS
, OK
),
3795 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3796 data_writes1
, arraysize(data_writes1
));
3797 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
3798 data_writes2
, arraysize(data_writes2
));
3799 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
3800 data_writes3
, arraysize(data_writes3
));
3801 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3802 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
3803 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
3805 TestCompletionCallback callback1
;
3807 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
3808 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3810 rv
= callback1
.WaitForResult();
3813 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3814 ASSERT_TRUE(response
!= NULL
);
3815 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3817 TestCompletionCallback callback2
;
3819 rv
= trans
->RestartWithAuth(
3820 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3821 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3823 rv
= callback2
.WaitForResult();
3826 response
= trans
->GetResponseInfo();
3827 ASSERT_TRUE(response
!= NULL
);
3828 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
3830 TestCompletionCallback callback3
;
3832 rv
= trans
->RestartWithAuth(
3833 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
3834 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3836 rv
= callback3
.WaitForResult();
3839 response
= trans
->GetResponseInfo();
3840 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3841 EXPECT_EQ(100, response
->headers
->GetContentLength());
3844 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
3845 // can't hook into its internals to cause it to generate predictable NTLM
3846 // authorization headers.
3847 #if defined(NTLM_PORTABLE)
3848 // The NTLM authentication unit tests were generated by capturing the HTTP
3849 // requests and responses using Fiddler 2 and inspecting the generated random
3850 // bytes in the debugger.
3852 // Enter the correct password and authenticate successfully.
3853 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
3854 HttpRequestInfo request
;
3855 request
.method
= "GET";
3856 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
3857 request
.load_flags
= 0;
3859 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
3861 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3863 MockWrite data_writes1
[] = {
3864 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3865 "Host: 172.22.68.17\r\n"
3866 "Connection: keep-alive\r\n\r\n"),
3869 MockRead data_reads1
[] = {
3870 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3871 // Negotiate and NTLM are often requested together. However, we only want
3872 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3873 // the header that requests Negotiate for this test.
3874 MockRead("WWW-Authenticate: NTLM\r\n"),
3875 MockRead("Connection: close\r\n"),
3876 MockRead("Content-Length: 42\r\n"),
3877 MockRead("Content-Type: text/html\r\n\r\n"),
3878 // Missing content -- won't matter, as connection will be reset.
3879 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
3882 MockWrite data_writes2
[] = {
3883 // After restarting with a null identity, this is the
3884 // request we should be issuing -- the final header line contains a Type
3886 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3887 "Host: 172.22.68.17\r\n"
3888 "Connection: keep-alive\r\n"
3889 "Authorization: NTLM "
3890 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3892 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3893 // (the credentials for the origin server). The second request continues
3894 // on the same connection.
3895 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3896 "Host: 172.22.68.17\r\n"
3897 "Connection: keep-alive\r\n"
3898 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3899 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3900 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
3901 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
3902 "ahlhx5I=\r\n\r\n"),
3905 MockRead data_reads2
[] = {
3906 // The origin server responds with a Type 2 message.
3907 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3908 MockRead("WWW-Authenticate: NTLM "
3909 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
3910 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3911 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3912 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3913 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3914 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3916 MockRead("Content-Length: 42\r\n"),
3917 MockRead("Content-Type: text/html\r\n\r\n"),
3918 MockRead("You are not authorized to view this page\r\n"),
3920 // Lastly we get the desired content.
3921 MockRead("HTTP/1.1 200 OK\r\n"),
3922 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3923 MockRead("Content-Length: 13\r\n\r\n"),
3924 MockRead("Please Login\r\n"),
3925 MockRead(SYNCHRONOUS
, OK
),
3928 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3929 data_writes1
, arraysize(data_writes1
));
3930 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
3931 data_writes2
, arraysize(data_writes2
));
3932 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3933 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
3935 TestCompletionCallback callback1
;
3937 scoped_ptr
<HttpTransaction
> trans(
3938 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3940 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
3941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3943 rv
= callback1
.WaitForResult();
3946 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
3948 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3949 ASSERT_FALSE(response
== NULL
);
3950 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
3952 TestCompletionCallback callback2
;
3954 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
3955 callback2
.callback());
3956 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3958 rv
= callback2
.WaitForResult();
3961 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
3963 response
= trans
->GetResponseInfo();
3964 ASSERT_TRUE(response
!= NULL
);
3965 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3967 TestCompletionCallback callback3
;
3969 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
3970 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3972 rv
= callback3
.WaitForResult();
3975 response
= trans
->GetResponseInfo();
3976 ASSERT_TRUE(response
!= NULL
);
3977 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3978 EXPECT_EQ(13, response
->headers
->GetContentLength());
3981 // Enter a wrong password, and then the correct one.
3982 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
3983 HttpRequestInfo request
;
3984 request
.method
= "GET";
3985 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
3986 request
.load_flags
= 0;
3988 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
3990 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3992 MockWrite data_writes1
[] = {
3993 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3994 "Host: 172.22.68.17\r\n"
3995 "Connection: keep-alive\r\n\r\n"),
3998 MockRead data_reads1
[] = {
3999 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4000 // Negotiate and NTLM are often requested together. However, we only want
4001 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4002 // the header that requests Negotiate for this test.
4003 MockRead("WWW-Authenticate: NTLM\r\n"),
4004 MockRead("Connection: close\r\n"),
4005 MockRead("Content-Length: 42\r\n"),
4006 MockRead("Content-Type: text/html\r\n\r\n"),
4007 // Missing content -- won't matter, as connection will be reset.
4008 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4011 MockWrite data_writes2
[] = {
4012 // After restarting with a null identity, this is the
4013 // request we should be issuing -- the final header line contains a Type
4015 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4016 "Host: 172.22.68.17\r\n"
4017 "Connection: keep-alive\r\n"
4018 "Authorization: NTLM "
4019 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4021 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4022 // (the credentials for the origin server). The second request continues
4023 // on the same connection.
4024 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4025 "Host: 172.22.68.17\r\n"
4026 "Connection: keep-alive\r\n"
4027 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4028 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4029 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4030 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4031 "4Ww7b7E=\r\n\r\n"),
4034 MockRead data_reads2
[] = {
4035 // The origin server responds with a Type 2 message.
4036 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4037 MockRead("WWW-Authenticate: NTLM "
4038 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4039 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4040 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4041 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4042 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4043 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4045 MockRead("Content-Length: 42\r\n"),
4046 MockRead("Content-Type: text/html\r\n\r\n"),
4047 MockRead("You are not authorized to view this page\r\n"),
4050 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4051 MockRead("WWW-Authenticate: NTLM\r\n"),
4052 MockRead("Connection: close\r\n"),
4053 MockRead("Content-Length: 42\r\n"),
4054 MockRead("Content-Type: text/html\r\n\r\n"),
4055 // Missing content -- won't matter, as connection will be reset.
4056 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4059 MockWrite data_writes3
[] = {
4060 // After restarting with a null identity, this is the
4061 // request we should be issuing -- the final header line contains a Type
4063 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4064 "Host: 172.22.68.17\r\n"
4065 "Connection: keep-alive\r\n"
4066 "Authorization: NTLM "
4067 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4069 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4070 // (the credentials for the origin server). The second request continues
4071 // on the same connection.
4072 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4073 "Host: 172.22.68.17\r\n"
4074 "Connection: keep-alive\r\n"
4075 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4076 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4077 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4078 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4079 "+4MUm7c=\r\n\r\n"),
4082 MockRead data_reads3
[] = {
4083 // The origin server responds with a Type 2 message.
4084 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4085 MockRead("WWW-Authenticate: NTLM "
4086 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4087 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4088 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4089 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4090 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4091 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4093 MockRead("Content-Length: 42\r\n"),
4094 MockRead("Content-Type: text/html\r\n\r\n"),
4095 MockRead("You are not authorized to view this page\r\n"),
4097 // Lastly we get the desired content.
4098 MockRead("HTTP/1.1 200 OK\r\n"),
4099 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4100 MockRead("Content-Length: 13\r\n\r\n"),
4101 MockRead("Please Login\r\n"),
4102 MockRead(SYNCHRONOUS
, OK
),
4105 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4106 data_writes1
, arraysize(data_writes1
));
4107 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4108 data_writes2
, arraysize(data_writes2
));
4109 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4110 data_writes3
, arraysize(data_writes3
));
4111 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4112 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4113 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4115 TestCompletionCallback callback1
;
4117 scoped_ptr
<HttpTransaction
> trans(
4118 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4120 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4121 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4123 rv
= callback1
.WaitForResult();
4126 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4128 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4129 ASSERT_TRUE(response
!= NULL
);
4130 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4132 TestCompletionCallback callback2
;
4134 // Enter the wrong password.
4135 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4136 callback2
.callback());
4137 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4139 rv
= callback2
.WaitForResult();
4142 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4143 TestCompletionCallback callback3
;
4144 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4145 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4146 rv
= callback3
.WaitForResult();
4148 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4150 response
= trans
->GetResponseInfo();
4151 ASSERT_FALSE(response
== NULL
);
4152 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4154 TestCompletionCallback callback4
;
4156 // Now enter the right password.
4157 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4158 callback4
.callback());
4159 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4161 rv
= callback4
.WaitForResult();
4164 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4166 TestCompletionCallback callback5
;
4168 // One more roundtrip
4169 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4170 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4172 rv
= callback5
.WaitForResult();
4175 response
= trans
->GetResponseInfo();
4176 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4177 EXPECT_EQ(13, response
->headers
->GetContentLength());
4179 #endif // NTLM_PORTABLE
4181 // Test reading a server response which has only headers, and no body.
4182 // After some maximum number of bytes is consumed, the transaction should
4183 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4184 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4185 HttpRequestInfo request
;
4186 request
.method
= "GET";
4187 request
.url
= GURL("http://www.google.com/");
4188 request
.load_flags
= 0;
4190 scoped_ptr
<HttpTransaction
> trans(
4191 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
4192 CreateSession(&session_deps_
)));
4194 // Respond with 300 kb of headers (we should fail after 256 kb).
4195 std::string large_headers_string
;
4196 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4198 MockRead data_reads
[] = {
4199 MockRead("HTTP/1.0 200 OK\r\n"),
4200 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4201 MockRead("\r\nBODY"),
4202 MockRead(SYNCHRONOUS
, OK
),
4204 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4205 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4207 TestCompletionCallback callback
;
4209 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4210 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4212 rv
= callback
.WaitForResult();
4213 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4215 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4216 EXPECT_TRUE(response
== NULL
);
4219 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4220 // establish tunnel.
4221 // http://code.google.com/p/chromium/issues/detail?id=3772
4222 TEST_P(HttpNetworkTransactionTest
,
4223 DontRecycleTransportSocketForSSLTunnel
) {
4224 HttpRequestInfo request
;
4225 request
.method
= "GET";
4226 request
.url
= GURL("https://www.google.com/");
4227 request
.load_flags
= 0;
4229 // Configure against proxy server "myproxy:70".
4230 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4232 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4234 scoped_ptr
<HttpTransaction
> trans(
4235 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4237 // Since we have proxy, should try to establish tunnel.
4238 MockWrite data_writes1
[] = {
4239 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4240 "Host: www.google.com\r\n"
4241 "Proxy-Connection: keep-alive\r\n\r\n"),
4244 // The proxy responds to the connect with a 404, using a persistent
4245 // connection. Usually a proxy would return 501 (not implemented),
4246 // or 200 (tunnel established).
4247 MockRead data_reads1
[] = {
4248 MockRead("HTTP/1.1 404 Not Found\r\n"),
4249 MockRead("Content-Length: 10\r\n\r\n"),
4250 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4253 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4254 data_writes1
, arraysize(data_writes1
));
4255 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4257 TestCompletionCallback callback1
;
4259 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4260 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4262 rv
= callback1
.WaitForResult();
4263 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
4265 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4266 EXPECT_TRUE(response
== NULL
);
4268 // Empty the current queue. This is necessary because idle sockets are
4269 // added to the connection pool asynchronously with a PostTask.
4270 base::MessageLoop::current()->RunUntilIdle();
4272 // We now check to make sure the TCPClientSocket was not added back to
4274 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4276 base::MessageLoop::current()->RunUntilIdle();
4277 // Make sure that the socket didn't get recycled after calling the destructor.
4278 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4281 // Make sure that we recycle a socket after reading all of the response body.
4282 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
4283 HttpRequestInfo request
;
4284 request
.method
= "GET";
4285 request
.url
= GURL("http://www.google.com/");
4286 request
.load_flags
= 0;
4288 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4290 scoped_ptr
<HttpTransaction
> trans(
4291 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4293 MockRead data_reads
[] = {
4294 // A part of the response body is received with the response headers.
4295 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4296 // The rest of the response body is received in two parts.
4299 MockRead("junk"), // Should not be read!!
4300 MockRead(SYNCHRONOUS
, OK
),
4303 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4304 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4306 TestCompletionCallback callback
;
4308 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4309 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4311 rv
= callback
.WaitForResult();
4314 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4315 ASSERT_TRUE(response
!= NULL
);
4317 EXPECT_TRUE(response
->headers
.get() != NULL
);
4318 std::string status_line
= response
->headers
->GetStatusLine();
4319 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
4321 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4323 std::string response_data
;
4324 rv
= ReadTransaction(trans
.get(), &response_data
);
4326 EXPECT_EQ("hello world", response_data
);
4328 // Empty the current queue. This is necessary because idle sockets are
4329 // added to the connection pool asynchronously with a PostTask.
4330 base::MessageLoop::current()->RunUntilIdle();
4332 // We now check to make sure the socket was added back to the pool.
4333 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4336 // Make sure that we recycle a SSL socket after reading all of the response
4338 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
4339 HttpRequestInfo request
;
4340 request
.method
= "GET";
4341 request
.url
= GURL("https://www.google.com/");
4342 request
.load_flags
= 0;
4344 MockWrite data_writes
[] = {
4345 MockWrite("GET / HTTP/1.1\r\n"
4346 "Host: www.google.com\r\n"
4347 "Connection: keep-alive\r\n\r\n"),
4350 MockRead data_reads
[] = {
4351 MockRead("HTTP/1.1 200 OK\r\n"),
4352 MockRead("Content-Length: 11\r\n\r\n"),
4353 MockRead("hello world"),
4354 MockRead(SYNCHRONOUS
, OK
),
4357 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4358 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4360 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4361 data_writes
, arraysize(data_writes
));
4362 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4364 TestCompletionCallback callback
;
4366 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4367 scoped_ptr
<HttpTransaction
> trans(
4368 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4370 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4372 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4373 EXPECT_EQ(OK
, callback
.WaitForResult());
4375 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4376 ASSERT_TRUE(response
!= NULL
);
4377 ASSERT_TRUE(response
->headers
.get() != NULL
);
4378 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4380 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4382 std::string response_data
;
4383 rv
= ReadTransaction(trans
.get(), &response_data
);
4385 EXPECT_EQ("hello world", response_data
);
4387 // Empty the current queue. This is necessary because idle sockets are
4388 // added to the connection pool asynchronously with a PostTask.
4389 base::MessageLoop::current()->RunUntilIdle();
4391 // We now check to make sure the socket was added back to the pool.
4392 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4395 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4396 // from the pool and make sure that we recover okay.
4397 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
4398 HttpRequestInfo request
;
4399 request
.method
= "GET";
4400 request
.url
= GURL("https://www.google.com/");
4401 request
.load_flags
= 0;
4403 MockWrite data_writes
[] = {
4404 MockWrite("GET / HTTP/1.1\r\n"
4405 "Host: www.google.com\r\n"
4406 "Connection: keep-alive\r\n\r\n"),
4407 MockWrite("GET / HTTP/1.1\r\n"
4408 "Host: www.google.com\r\n"
4409 "Connection: keep-alive\r\n\r\n"),
4412 MockRead data_reads
[] = {
4413 MockRead("HTTP/1.1 200 OK\r\n"),
4414 MockRead("Content-Length: 11\r\n\r\n"),
4415 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
4416 MockRead("hello world"),
4417 MockRead(ASYNC
, 0, 0) // EOF
4420 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4421 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4422 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4423 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4425 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4426 data_writes
, arraysize(data_writes
));
4427 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
4428 data_writes
, arraysize(data_writes
));
4429 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4430 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4432 TestCompletionCallback callback
;
4434 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4435 scoped_ptr
<HttpTransaction
> trans(
4436 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4438 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4440 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4441 EXPECT_EQ(OK
, callback
.WaitForResult());
4443 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4444 ASSERT_TRUE(response
!= NULL
);
4445 ASSERT_TRUE(response
->headers
.get() != NULL
);
4446 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4448 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4450 std::string response_data
;
4451 rv
= ReadTransaction(trans
.get(), &response_data
);
4453 EXPECT_EQ("hello world", response_data
);
4455 // Empty the current queue. This is necessary because idle sockets are
4456 // added to the connection pool asynchronously with a PostTask.
4457 base::MessageLoop::current()->RunUntilIdle();
4459 // We now check to make sure the socket was added back to the pool.
4460 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4462 // Now start the second transaction, which should reuse the previous socket.
4464 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4466 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4468 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4469 EXPECT_EQ(OK
, callback
.WaitForResult());
4471 response
= trans
->GetResponseInfo();
4472 ASSERT_TRUE(response
!= NULL
);
4473 ASSERT_TRUE(response
->headers
.get() != NULL
);
4474 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4476 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4478 rv
= ReadTransaction(trans
.get(), &response_data
);
4480 EXPECT_EQ("hello world", response_data
);
4482 // Empty the current queue. This is necessary because idle sockets are
4483 // added to the connection pool asynchronously with a PostTask.
4484 base::MessageLoop::current()->RunUntilIdle();
4486 // We now check to make sure the socket was added back to the pool.
4487 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4490 // Make sure that we recycle a socket after a zero-length response.
4491 // http://crbug.com/9880
4492 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
4493 HttpRequestInfo request
;
4494 request
.method
= "GET";
4495 request
.url
= GURL("http://www.google.com/csi?v=3&s=web&action=&"
4496 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4497 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4498 "rt=prt.2642,ol.2649,xjs.2951");
4499 request
.load_flags
= 0;
4501 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4503 scoped_ptr
<HttpTransaction
> trans(
4504 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4506 MockRead data_reads
[] = {
4507 MockRead("HTTP/1.1 204 No Content\r\n"
4508 "Content-Length: 0\r\n"
4509 "Content-Type: text/html\r\n\r\n"),
4510 MockRead("junk"), // Should not be read!!
4511 MockRead(SYNCHRONOUS
, OK
),
4514 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4515 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4517 TestCompletionCallback callback
;
4519 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4520 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4522 rv
= callback
.WaitForResult();
4525 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4526 ASSERT_TRUE(response
!= NULL
);
4528 EXPECT_TRUE(response
->headers
.get() != NULL
);
4529 std::string status_line
= response
->headers
->GetStatusLine();
4530 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
4532 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4534 std::string response_data
;
4535 rv
= ReadTransaction(trans
.get(), &response_data
);
4537 EXPECT_EQ("", response_data
);
4539 // Empty the current queue. This is necessary because idle sockets are
4540 // added to the connection pool asynchronously with a PostTask.
4541 base::MessageLoop::current()->RunUntilIdle();
4543 // We now check to make sure the socket was added back to the pool.
4544 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4547 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
4548 ScopedVector
<UploadElementReader
> element_readers
;
4549 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
4550 UploadDataStream
upload_data_stream(&element_readers
, 0);
4552 HttpRequestInfo request
[2];
4553 // Transaction 1: a GET request that succeeds. The socket is recycled
4555 request
[0].method
= "GET";
4556 request
[0].url
= GURL("http://www.google.com/");
4557 request
[0].load_flags
= 0;
4558 // Transaction 2: a POST request. Reuses the socket kept alive from
4559 // transaction 1. The first attempts fails when writing the POST data.
4560 // This causes the transaction to retry with a new socket. The second
4561 // attempt succeeds.
4562 request
[1].method
= "POST";
4563 request
[1].url
= GURL("http://www.google.com/login.cgi");
4564 request
[1].upload_data_stream
= &upload_data_stream
;
4565 request
[1].load_flags
= 0;
4567 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4569 // The first socket is used for transaction 1 and the first attempt of
4572 // The response of transaction 1.
4573 MockRead data_reads1
[] = {
4574 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4575 MockRead("hello world"),
4576 MockRead(SYNCHRONOUS
, OK
),
4578 // The mock write results of transaction 1 and the first attempt of
4580 MockWrite data_writes1
[] = {
4581 MockWrite(SYNCHRONOUS
, 64), // GET
4582 MockWrite(SYNCHRONOUS
, 93), // POST
4583 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
4585 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4586 data_writes1
, arraysize(data_writes1
));
4588 // The second socket is used for the second attempt of transaction 2.
4590 // The response of transaction 2.
4591 MockRead data_reads2
[] = {
4592 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4593 MockRead("welcome"),
4594 MockRead(SYNCHRONOUS
, OK
),
4596 // The mock write results of the second attempt of transaction 2.
4597 MockWrite data_writes2
[] = {
4598 MockWrite(SYNCHRONOUS
, 93), // POST
4599 MockWrite(SYNCHRONOUS
, 3), // POST data
4601 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4602 data_writes2
, arraysize(data_writes2
));
4604 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4605 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4607 const char* kExpectedResponseData
[] = {
4608 "hello world", "welcome"
4611 for (int i
= 0; i
< 2; ++i
) {
4612 scoped_ptr
<HttpTransaction
> trans(
4613 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4615 TestCompletionCallback callback
;
4617 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
4618 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4620 rv
= callback
.WaitForResult();
4623 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4624 ASSERT_TRUE(response
!= NULL
);
4626 EXPECT_TRUE(response
->headers
.get() != NULL
);
4627 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4629 std::string response_data
;
4630 rv
= ReadTransaction(trans
.get(), &response_data
);
4632 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
4636 // Test the request-challenge-retry sequence for basic auth when there is
4637 // an identity in the URL. The request should be sent as normal, but when
4638 // it fails the identity from the URL is used to answer the challenge.
4639 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
4640 HttpRequestInfo request
;
4641 request
.method
= "GET";
4642 request
.url
= GURL("http://foo:b@r@www.google.com/");
4643 request
.load_flags
= LOAD_NORMAL
;
4645 scoped_ptr
<HttpTransaction
> trans(
4646 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
4647 CreateSession(&session_deps_
)));
4649 // The password contains an escaped character -- for this test to pass it
4650 // will need to be unescaped by HttpNetworkTransaction.
4651 EXPECT_EQ("b%40r", request
.url
.password());
4653 MockWrite data_writes1
[] = {
4654 MockWrite("GET / HTTP/1.1\r\n"
4655 "Host: www.google.com\r\n"
4656 "Connection: keep-alive\r\n\r\n"),
4659 MockRead data_reads1
[] = {
4660 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4661 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4662 MockRead("Content-Length: 10\r\n\r\n"),
4663 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4666 // After the challenge above, the transaction will be restarted using the
4667 // identity from the url (foo, b@r) to answer the challenge.
4668 MockWrite data_writes2
[] = {
4669 MockWrite("GET / HTTP/1.1\r\n"
4670 "Host: www.google.com\r\n"
4671 "Connection: keep-alive\r\n"
4672 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
4675 MockRead data_reads2
[] = {
4676 MockRead("HTTP/1.0 200 OK\r\n"),
4677 MockRead("Content-Length: 100\r\n\r\n"),
4678 MockRead(SYNCHRONOUS
, OK
),
4681 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4682 data_writes1
, arraysize(data_writes1
));
4683 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4684 data_writes2
, arraysize(data_writes2
));
4685 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4686 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4688 TestCompletionCallback callback1
;
4689 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4690 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4691 rv
= callback1
.WaitForResult();
4693 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4695 TestCompletionCallback callback2
;
4696 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
4697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4698 rv
= callback2
.WaitForResult();
4700 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4702 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4703 ASSERT_TRUE(response
!= NULL
);
4705 // There is no challenge info, since the identity in URL worked.
4706 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4708 EXPECT_EQ(100, response
->headers
->GetContentLength());
4710 // Empty the current queue.
4711 base::MessageLoop::current()->RunUntilIdle();
4714 // Test the request-challenge-retry sequence for basic auth when there is an
4715 // incorrect identity in the URL. The identity from the URL should be used only
4717 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
4718 HttpRequestInfo request
;
4719 request
.method
= "GET";
4720 // Note: the URL has a username:password in it. The password "baz" is
4721 // wrong (should be "bar").
4722 request
.url
= GURL("http://foo:baz@www.google.com/");
4724 request
.load_flags
= LOAD_NORMAL
;
4726 scoped_ptr
<HttpTransaction
> trans(
4727 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
4728 CreateSession(&session_deps_
)));
4730 MockWrite data_writes1
[] = {
4731 MockWrite("GET / HTTP/1.1\r\n"
4732 "Host: www.google.com\r\n"
4733 "Connection: keep-alive\r\n\r\n"),
4736 MockRead data_reads1
[] = {
4737 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4738 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4739 MockRead("Content-Length: 10\r\n\r\n"),
4740 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4743 // After the challenge above, the transaction will be restarted using the
4744 // identity from the url (foo, baz) to answer the challenge.
4745 MockWrite data_writes2
[] = {
4746 MockWrite("GET / HTTP/1.1\r\n"
4747 "Host: www.google.com\r\n"
4748 "Connection: keep-alive\r\n"
4749 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
4752 MockRead data_reads2
[] = {
4753 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4754 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4755 MockRead("Content-Length: 10\r\n\r\n"),
4756 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4759 // After the challenge above, the transaction will be restarted using the
4760 // identity supplied by the user (foo, bar) to answer the challenge.
4761 MockWrite data_writes3
[] = {
4762 MockWrite("GET / HTTP/1.1\r\n"
4763 "Host: www.google.com\r\n"
4764 "Connection: keep-alive\r\n"
4765 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4768 MockRead data_reads3
[] = {
4769 MockRead("HTTP/1.0 200 OK\r\n"),
4770 MockRead("Content-Length: 100\r\n\r\n"),
4771 MockRead(SYNCHRONOUS
, OK
),
4774 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4775 data_writes1
, arraysize(data_writes1
));
4776 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4777 data_writes2
, arraysize(data_writes2
));
4778 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4779 data_writes3
, arraysize(data_writes3
));
4780 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4781 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4782 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4784 TestCompletionCallback callback1
;
4786 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4787 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4789 rv
= callback1
.WaitForResult();
4792 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4793 TestCompletionCallback callback2
;
4794 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
4795 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4796 rv
= callback2
.WaitForResult();
4798 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4800 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4801 ASSERT_TRUE(response
!= NULL
);
4802 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4804 TestCompletionCallback callback3
;
4805 rv
= trans
->RestartWithAuth(
4806 AuthCredentials(kFoo
, kBar
), callback3
.callback());
4807 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4808 rv
= callback3
.WaitForResult();
4810 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4812 response
= trans
->GetResponseInfo();
4813 ASSERT_TRUE(response
!= NULL
);
4815 // There is no challenge info, since the identity worked.
4816 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4818 EXPECT_EQ(100, response
->headers
->GetContentLength());
4820 // Empty the current queue.
4821 base::MessageLoop::current()->RunUntilIdle();
4824 // Test that previously tried username/passwords for a realm get re-used.
4825 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
4826 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4828 // Transaction 1: authenticate (foo, bar) on MyRealm1
4830 HttpRequestInfo request
;
4831 request
.method
= "GET";
4832 request
.url
= GURL("http://www.google.com/x/y/z");
4833 request
.load_flags
= 0;
4835 scoped_ptr
<HttpTransaction
> trans(
4836 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4838 MockWrite data_writes1
[] = {
4839 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4840 "Host: www.google.com\r\n"
4841 "Connection: keep-alive\r\n\r\n"),
4844 MockRead data_reads1
[] = {
4845 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4846 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4847 MockRead("Content-Length: 10000\r\n\r\n"),
4848 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4851 // Resend with authorization (username=foo, password=bar)
4852 MockWrite data_writes2
[] = {
4853 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4854 "Host: www.google.com\r\n"
4855 "Connection: keep-alive\r\n"
4856 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4859 // Sever accepts the authorization.
4860 MockRead data_reads2
[] = {
4861 MockRead("HTTP/1.0 200 OK\r\n"),
4862 MockRead("Content-Length: 100\r\n\r\n"),
4863 MockRead(SYNCHRONOUS
, OK
),
4866 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4867 data_writes1
, arraysize(data_writes1
));
4868 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4869 data_writes2
, arraysize(data_writes2
));
4870 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4871 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4873 TestCompletionCallback callback1
;
4875 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4876 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4878 rv
= callback1
.WaitForResult();
4881 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4882 ASSERT_TRUE(response
!= NULL
);
4883 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4885 TestCompletionCallback callback2
;
4887 rv
= trans
->RestartWithAuth(
4888 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4889 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4891 rv
= callback2
.WaitForResult();
4894 response
= trans
->GetResponseInfo();
4895 ASSERT_TRUE(response
!= NULL
);
4896 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4897 EXPECT_EQ(100, response
->headers
->GetContentLength());
4900 // ------------------------------------------------------------------------
4902 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
4904 HttpRequestInfo request
;
4905 request
.method
= "GET";
4906 // Note that Transaction 1 was at /x/y/z, so this is in the same
4907 // protection space as MyRealm1.
4908 request
.url
= GURL("http://www.google.com/x/y/a/b");
4909 request
.load_flags
= 0;
4911 scoped_ptr
<HttpTransaction
> trans(
4912 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4914 MockWrite data_writes1
[] = {
4915 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4916 "Host: www.google.com\r\n"
4917 "Connection: keep-alive\r\n"
4918 // Send preemptive authorization for MyRealm1
4919 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4922 // The server didn't like the preemptive authorization, and
4923 // challenges us for a different realm (MyRealm2).
4924 MockRead data_reads1
[] = {
4925 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4926 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
4927 MockRead("Content-Length: 10000\r\n\r\n"),
4928 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4931 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
4932 MockWrite data_writes2
[] = {
4933 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4934 "Host: www.google.com\r\n"
4935 "Connection: keep-alive\r\n"
4936 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4939 // Sever accepts the authorization.
4940 MockRead data_reads2
[] = {
4941 MockRead("HTTP/1.0 200 OK\r\n"),
4942 MockRead("Content-Length: 100\r\n\r\n"),
4943 MockRead(SYNCHRONOUS
, OK
),
4946 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4947 data_writes1
, arraysize(data_writes1
));
4948 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4949 data_writes2
, arraysize(data_writes2
));
4950 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4951 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4953 TestCompletionCallback callback1
;
4955 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4956 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4958 rv
= callback1
.WaitForResult();
4961 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4962 ASSERT_TRUE(response
!= NULL
);
4963 ASSERT_TRUE(response
->auth_challenge
.get());
4964 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
4965 EXPECT_EQ("www.google.com:80",
4966 response
->auth_challenge
->challenger
.ToString());
4967 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
4968 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
4970 TestCompletionCallback callback2
;
4972 rv
= trans
->RestartWithAuth(
4973 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
4974 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4976 rv
= callback2
.WaitForResult();
4979 response
= trans
->GetResponseInfo();
4980 ASSERT_TRUE(response
!= NULL
);
4981 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4982 EXPECT_EQ(100, response
->headers
->GetContentLength());
4985 // ------------------------------------------------------------------------
4987 // Transaction 3: Resend a request in MyRealm's protection space --
4988 // succeed with preemptive authorization.
4990 HttpRequestInfo request
;
4991 request
.method
= "GET";
4992 request
.url
= GURL("http://www.google.com/x/y/z2");
4993 request
.load_flags
= 0;
4995 scoped_ptr
<HttpTransaction
> trans(
4996 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4998 MockWrite data_writes1
[] = {
4999 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5000 "Host: www.google.com\r\n"
5001 "Connection: keep-alive\r\n"
5002 // The authorization for MyRealm1 gets sent preemptively
5003 // (since the url is in the same protection space)
5004 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5007 // Sever accepts the preemptive authorization
5008 MockRead data_reads1
[] = {
5009 MockRead("HTTP/1.0 200 OK\r\n"),
5010 MockRead("Content-Length: 100\r\n\r\n"),
5011 MockRead(SYNCHRONOUS
, OK
),
5014 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5015 data_writes1
, arraysize(data_writes1
));
5016 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5018 TestCompletionCallback callback1
;
5020 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5021 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5023 rv
= callback1
.WaitForResult();
5026 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5027 ASSERT_TRUE(response
!= NULL
);
5029 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5030 EXPECT_EQ(100, response
->headers
->GetContentLength());
5033 // ------------------------------------------------------------------------
5035 // Transaction 4: request another URL in MyRealm (however the
5036 // url is not known to belong to the protection space, so no pre-auth).
5038 HttpRequestInfo request
;
5039 request
.method
= "GET";
5040 request
.url
= GURL("http://www.google.com/x/1");
5041 request
.load_flags
= 0;
5043 scoped_ptr
<HttpTransaction
> trans(
5044 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5046 MockWrite data_writes1
[] = {
5047 MockWrite("GET /x/1 HTTP/1.1\r\n"
5048 "Host: www.google.com\r\n"
5049 "Connection: keep-alive\r\n\r\n"),
5052 MockRead data_reads1
[] = {
5053 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5054 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5055 MockRead("Content-Length: 10000\r\n\r\n"),
5056 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5059 // Resend with authorization from MyRealm's cache.
5060 MockWrite data_writes2
[] = {
5061 MockWrite("GET /x/1 HTTP/1.1\r\n"
5062 "Host: www.google.com\r\n"
5063 "Connection: keep-alive\r\n"
5064 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5067 // Sever accepts the authorization.
5068 MockRead data_reads2
[] = {
5069 MockRead("HTTP/1.0 200 OK\r\n"),
5070 MockRead("Content-Length: 100\r\n\r\n"),
5071 MockRead(SYNCHRONOUS
, OK
),
5074 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5075 data_writes1
, arraysize(data_writes1
));
5076 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5077 data_writes2
, arraysize(data_writes2
));
5078 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5079 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5081 TestCompletionCallback callback1
;
5083 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5084 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5086 rv
= callback1
.WaitForResult();
5089 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5090 TestCompletionCallback callback2
;
5091 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5092 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5093 rv
= callback2
.WaitForResult();
5095 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5097 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5098 ASSERT_TRUE(response
!= NULL
);
5099 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5100 EXPECT_EQ(100, response
->headers
->GetContentLength());
5103 // ------------------------------------------------------------------------
5105 // Transaction 5: request a URL in MyRealm, but the server rejects the
5106 // cached identity. Should invalidate and re-prompt.
5108 HttpRequestInfo request
;
5109 request
.method
= "GET";
5110 request
.url
= GURL("http://www.google.com/p/q/t");
5111 request
.load_flags
= 0;
5113 scoped_ptr
<HttpTransaction
> trans(
5114 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5116 MockWrite data_writes1
[] = {
5117 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5118 "Host: www.google.com\r\n"
5119 "Connection: keep-alive\r\n\r\n"),
5122 MockRead data_reads1
[] = {
5123 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5124 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5125 MockRead("Content-Length: 10000\r\n\r\n"),
5126 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5129 // Resend with authorization from cache for MyRealm.
5130 MockWrite data_writes2
[] = {
5131 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5132 "Host: www.google.com\r\n"
5133 "Connection: keep-alive\r\n"
5134 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5137 // Sever rejects the authorization.
5138 MockRead data_reads2
[] = {
5139 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5140 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5141 MockRead("Content-Length: 10000\r\n\r\n"),
5142 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5145 // At this point we should prompt for new credentials for MyRealm.
5146 // Restart with username=foo3, password=foo4.
5147 MockWrite data_writes3
[] = {
5148 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5149 "Host: www.google.com\r\n"
5150 "Connection: keep-alive\r\n"
5151 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5154 // Sever accepts the authorization.
5155 MockRead data_reads3
[] = {
5156 MockRead("HTTP/1.0 200 OK\r\n"),
5157 MockRead("Content-Length: 100\r\n\r\n"),
5158 MockRead(SYNCHRONOUS
, OK
),
5161 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5162 data_writes1
, arraysize(data_writes1
));
5163 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5164 data_writes2
, arraysize(data_writes2
));
5165 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5166 data_writes3
, arraysize(data_writes3
));
5167 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5168 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5169 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5171 TestCompletionCallback callback1
;
5173 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5174 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5176 rv
= callback1
.WaitForResult();
5179 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5180 TestCompletionCallback callback2
;
5181 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5182 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5183 rv
= callback2
.WaitForResult();
5185 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5187 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5188 ASSERT_TRUE(response
!= NULL
);
5189 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5191 TestCompletionCallback callback3
;
5193 rv
= trans
->RestartWithAuth(
5194 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
5195 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5197 rv
= callback3
.WaitForResult();
5200 response
= trans
->GetResponseInfo();
5201 ASSERT_TRUE(response
!= NULL
);
5202 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5203 EXPECT_EQ(100, response
->headers
->GetContentLength());
5207 // Tests that nonce count increments when multiple auth attempts
5208 // are started with the same nonce.
5209 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
5210 HttpAuthHandlerDigest::Factory
* digest_factory
=
5211 new HttpAuthHandlerDigest::Factory();
5212 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
5213 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5214 digest_factory
->set_nonce_generator(nonce_generator
);
5215 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
5216 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5218 // Transaction 1: authenticate (foo, bar) on MyRealm1
5220 HttpRequestInfo request
;
5221 request
.method
= "GET";
5222 request
.url
= GURL("http://www.google.com/x/y/z");
5223 request
.load_flags
= 0;
5225 scoped_ptr
<HttpTransaction
> trans(
5226 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5228 MockWrite data_writes1
[] = {
5229 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5230 "Host: www.google.com\r\n"
5231 "Connection: keep-alive\r\n\r\n"),
5234 MockRead data_reads1
[] = {
5235 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5236 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5237 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5238 MockRead(SYNCHRONOUS
, OK
),
5241 // Resend with authorization (username=foo, password=bar)
5242 MockWrite data_writes2
[] = {
5243 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5244 "Host: www.google.com\r\n"
5245 "Connection: keep-alive\r\n"
5246 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5247 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5248 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5249 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5252 // Sever accepts the authorization.
5253 MockRead data_reads2
[] = {
5254 MockRead("HTTP/1.0 200 OK\r\n"),
5255 MockRead(SYNCHRONOUS
, OK
),
5258 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5259 data_writes1
, arraysize(data_writes1
));
5260 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5261 data_writes2
, arraysize(data_writes2
));
5262 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5263 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5265 TestCompletionCallback callback1
;
5267 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5268 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5270 rv
= callback1
.WaitForResult();
5273 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5274 ASSERT_TRUE(response
!= NULL
);
5275 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
5277 TestCompletionCallback callback2
;
5279 rv
= trans
->RestartWithAuth(
5280 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5281 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5283 rv
= callback2
.WaitForResult();
5286 response
= trans
->GetResponseInfo();
5287 ASSERT_TRUE(response
!= NULL
);
5288 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5291 // ------------------------------------------------------------------------
5293 // Transaction 2: Request another resource in digestive's protection space.
5294 // This will preemptively add an Authorization header which should have an
5295 // "nc" value of 2 (as compared to 1 in the first use.
5297 HttpRequestInfo request
;
5298 request
.method
= "GET";
5299 // Note that Transaction 1 was at /x/y/z, so this is in the same
5300 // protection space as digest.
5301 request
.url
= GURL("http://www.google.com/x/y/a/b");
5302 request
.load_flags
= 0;
5304 scoped_ptr
<HttpTransaction
> trans(
5305 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5307 MockWrite data_writes1
[] = {
5308 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5309 "Host: www.google.com\r\n"
5310 "Connection: keep-alive\r\n"
5311 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5312 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5313 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5314 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5317 // Sever accepts the authorization.
5318 MockRead data_reads1
[] = {
5319 MockRead("HTTP/1.0 200 OK\r\n"),
5320 MockRead("Content-Length: 100\r\n\r\n"),
5321 MockRead(SYNCHRONOUS
, OK
),
5324 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5325 data_writes1
, arraysize(data_writes1
));
5326 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5328 TestCompletionCallback callback1
;
5330 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5331 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5333 rv
= callback1
.WaitForResult();
5336 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5337 ASSERT_TRUE(response
!= NULL
);
5338 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5342 // Test the ResetStateForRestart() private method.
5343 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
5344 // Create a transaction (the dependencies aren't important).
5345 scoped_ptr
<HttpNetworkTransaction
> trans(
5346 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
5347 CreateSession(&session_deps_
)));
5349 // Setup some state (which we expect ResetStateForRestart() will clear).
5350 trans
->read_buf_
= new IOBuffer(15);
5351 trans
->read_buf_len_
= 15;
5352 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
5354 // Setup state in response_
5355 HttpResponseInfo
* response
= &trans
->response_
;
5356 response
->auth_challenge
= new AuthChallengeInfo();
5357 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
5358 response
->response_time
= base::Time::Now();
5359 response
->was_cached
= true; // (Wouldn't ever actually be true...)
5361 { // Setup state for response_.vary_data
5362 HttpRequestInfo request
;
5363 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5364 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
5365 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
5366 request
.extra_headers
.SetHeader("Foo", "1");
5367 request
.extra_headers
.SetHeader("bar", "23");
5368 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
5371 // Cause the above state to be reset.
5372 trans
->ResetStateForRestart();
5374 // Verify that the state that needed to be reset, has been reset.
5375 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
5376 EXPECT_EQ(0, trans
->read_buf_len_
);
5377 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
5378 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5379 EXPECT_TRUE(response
->headers
.get() == NULL
);
5380 EXPECT_FALSE(response
->was_cached
);
5381 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
5382 EXPECT_FALSE(response
->vary_data
.is_valid());
5385 // Test HTTPS connections to a site with a bad certificate
5386 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
5387 HttpRequestInfo request
;
5388 request
.method
= "GET";
5389 request
.url
= GURL("https://www.google.com/");
5390 request
.load_flags
= 0;
5392 scoped_ptr
<HttpTransaction
> trans(
5393 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
5394 CreateSession(&session_deps_
)));
5396 MockWrite data_writes
[] = {
5397 MockWrite("GET / HTTP/1.1\r\n"
5398 "Host: www.google.com\r\n"
5399 "Connection: keep-alive\r\n\r\n"),
5402 MockRead data_reads
[] = {
5403 MockRead("HTTP/1.0 200 OK\r\n"),
5404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5405 MockRead("Content-Length: 100\r\n\r\n"),
5406 MockRead(SYNCHRONOUS
, OK
),
5409 StaticSocketDataProvider ssl_bad_certificate
;
5410 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5411 data_writes
, arraysize(data_writes
));
5412 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5413 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5415 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5416 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5417 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5418 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5420 TestCompletionCallback callback
;
5422 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5425 rv
= callback
.WaitForResult();
5426 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5428 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5429 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5431 rv
= callback
.WaitForResult();
5434 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5436 ASSERT_TRUE(response
!= NULL
);
5437 EXPECT_EQ(100, response
->headers
->GetContentLength());
5440 // Test HTTPS connections to a site with a bad certificate, going through a
5442 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
5443 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5445 HttpRequestInfo request
;
5446 request
.method
= "GET";
5447 request
.url
= GURL("https://www.google.com/");
5448 request
.load_flags
= 0;
5450 MockWrite proxy_writes
[] = {
5451 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5452 "Host: www.google.com\r\n"
5453 "Proxy-Connection: keep-alive\r\n\r\n"),
5456 MockRead proxy_reads
[] = {
5457 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5458 MockRead(SYNCHRONOUS
, OK
)
5461 MockWrite data_writes
[] = {
5462 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5463 "Host: www.google.com\r\n"
5464 "Proxy-Connection: keep-alive\r\n\r\n"),
5465 MockWrite("GET / HTTP/1.1\r\n"
5466 "Host: www.google.com\r\n"
5467 "Connection: keep-alive\r\n\r\n"),
5470 MockRead data_reads
[] = {
5471 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5472 MockRead("HTTP/1.0 200 OK\r\n"),
5473 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5474 MockRead("Content-Length: 100\r\n\r\n"),
5475 MockRead(SYNCHRONOUS
, OK
),
5478 StaticSocketDataProvider
ssl_bad_certificate(
5479 proxy_reads
, arraysize(proxy_reads
),
5480 proxy_writes
, arraysize(proxy_writes
));
5481 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5482 data_writes
, arraysize(data_writes
));
5483 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5484 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5486 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5487 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5488 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5489 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5491 TestCompletionCallback callback
;
5493 for (int i
= 0; i
< 2; i
++) {
5494 session_deps_
.socket_factory
->ResetNextMockIndexes();
5496 scoped_ptr
<HttpTransaction
> trans(
5497 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
5498 CreateSession(&session_deps_
)));
5500 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5501 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5503 rv
= callback
.WaitForResult();
5504 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5506 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5507 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5509 rv
= callback
.WaitForResult();
5512 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5514 ASSERT_TRUE(response
!= NULL
);
5515 EXPECT_EQ(100, response
->headers
->GetContentLength());
5520 // Test HTTPS connections to a site, going through an HTTPS proxy
5521 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
5522 session_deps_
.proxy_service
.reset(
5523 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5524 CapturingNetLog net_log
;
5525 session_deps_
.net_log
= &net_log
;
5527 HttpRequestInfo request
;
5528 request
.method
= "GET";
5529 request
.url
= GURL("https://www.google.com/");
5530 request
.load_flags
= 0;
5532 MockWrite data_writes
[] = {
5533 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5534 "Host: www.google.com\r\n"
5535 "Proxy-Connection: keep-alive\r\n\r\n"),
5536 MockWrite("GET / HTTP/1.1\r\n"
5537 "Host: www.google.com\r\n"
5538 "Connection: keep-alive\r\n\r\n"),
5541 MockRead data_reads
[] = {
5542 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5543 MockRead("HTTP/1.1 200 OK\r\n"),
5544 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5545 MockRead("Content-Length: 100\r\n\r\n"),
5546 MockRead(SYNCHRONOUS
, OK
),
5549 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5550 data_writes
, arraysize(data_writes
));
5551 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
5552 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
5554 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5555 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
5556 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
5558 TestCompletionCallback callback
;
5560 scoped_ptr
<HttpTransaction
> trans(
5561 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
5562 CreateSession(&session_deps_
)));
5564 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5565 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5567 rv
= callback
.WaitForResult();
5569 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5571 ASSERT_TRUE(response
!= NULL
);
5573 EXPECT_TRUE(response
->headers
->IsKeepAlive());
5574 EXPECT_EQ(200, response
->headers
->response_code());
5575 EXPECT_EQ(100, response
->headers
->GetContentLength());
5576 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
5578 LoadTimingInfo load_timing_info
;
5579 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
5580 TestLoadTimingNotReusedWithPac(load_timing_info
,
5581 CONNECT_TIMING_HAS_SSL_TIMES
);
5584 // Test an HTTPS Proxy's ability to redirect a CONNECT request
5585 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
5586 session_deps_
.proxy_service
.reset(
5587 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5588 CapturingNetLog net_log
;
5589 session_deps_
.net_log
= &net_log
;
5591 HttpRequestInfo request
;
5592 request
.method
= "GET";
5593 request
.url
= GURL("https://www.google.com/");
5594 request
.load_flags
= 0;
5596 MockWrite data_writes
[] = {
5597 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5598 "Host: www.google.com\r\n"
5599 "Proxy-Connection: keep-alive\r\n\r\n"),
5602 MockRead data_reads
[] = {
5603 MockRead("HTTP/1.1 302 Redirect\r\n"),
5604 MockRead("Location: http://login.example.com/\r\n"),
5605 MockRead("Content-Length: 0\r\n\r\n"),
5606 MockRead(SYNCHRONOUS
, OK
),
5609 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5610 data_writes
, arraysize(data_writes
));
5611 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
5613 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5614 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
5616 TestCompletionCallback callback
;
5618 scoped_ptr
<HttpTransaction
> trans(
5619 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
5620 CreateSession(&session_deps_
)));
5622 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5623 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5625 rv
= callback
.WaitForResult();
5627 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5629 ASSERT_TRUE(response
!= NULL
);
5631 EXPECT_EQ(302, response
->headers
->response_code());
5633 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
5634 EXPECT_EQ("http://login.example.com/", url
);
5636 // In the case of redirects from proxies, HttpNetworkTransaction returns
5637 // timing for the proxy connection instead of the connection to the host,
5638 // and no send / receive times.
5639 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
5640 LoadTimingInfo load_timing_info
;
5641 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
5643 EXPECT_FALSE(load_timing_info
.socket_reused
);
5644 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
5646 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
5647 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
5648 load_timing_info
.proxy_resolve_end
);
5649 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
5650 load_timing_info
.connect_timing
.connect_start
);
5651 ExpectConnectTimingHasTimes(
5652 load_timing_info
.connect_timing
,
5653 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
5655 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
5656 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
5657 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
5660 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
5661 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
5662 session_deps_
.proxy_service
.reset(
5663 ProxyService::CreateFixed("https://proxy:70"));
5665 HttpRequestInfo request
;
5666 request
.method
= "GET";
5667 request
.url
= GURL("https://www.google.com/");
5668 request
.load_flags
= 0;
5670 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
5671 scoped_ptr
<SpdyFrame
> goaway(
5672 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
5673 MockWrite data_writes
[] = {
5674 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
5675 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
5678 static const char* const kExtraHeaders
[] = {
5680 "http://login.example.com/",
5682 scoped_ptr
<SpdyFrame
> resp(
5683 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
5684 arraysize(kExtraHeaders
)/2, 1));
5685 MockRead data_reads
[] = {
5686 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
5687 MockRead(ASYNC
, 0, 2), // EOF
5690 DelayedSocketData
data(
5691 1, // wait for one write to finish before reading.
5692 data_reads
, arraysize(data_reads
),
5693 data_writes
, arraysize(data_writes
));
5694 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
5695 proxy_ssl
.SetNextProto(GetParam());
5697 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5698 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
5700 TestCompletionCallback callback
;
5702 scoped_ptr
<HttpTransaction
> trans(
5703 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
5704 CreateSession(&session_deps_
)));
5706 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5707 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5709 rv
= callback
.WaitForResult();
5711 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5713 ASSERT_TRUE(response
!= NULL
);
5715 EXPECT_EQ(302, response
->headers
->response_code());
5717 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
5718 EXPECT_EQ("http://login.example.com/", url
);
5721 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
5722 TEST_P(HttpNetworkTransactionTest
,
5723 ErrorResponseToHttpsConnectViaHttpsProxy
) {
5724 session_deps_
.proxy_service
.reset(
5725 ProxyService::CreateFixed("https://proxy:70"));
5727 HttpRequestInfo request
;
5728 request
.method
= "GET";
5729 request
.url
= GURL("https://www.google.com/");
5730 request
.load_flags
= 0;
5732 MockWrite data_writes
[] = {
5733 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5734 "Host: www.google.com\r\n"
5735 "Proxy-Connection: keep-alive\r\n\r\n"),
5738 MockRead data_reads
[] = {
5739 MockRead("HTTP/1.1 404 Not Found\r\n"),
5740 MockRead("Content-Length: 23\r\n\r\n"),
5741 MockRead("The host does not exist"),
5742 MockRead(SYNCHRONOUS
, OK
),
5745 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5746 data_writes
, arraysize(data_writes
));
5747 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
5749 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5750 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
5752 TestCompletionCallback callback
;
5754 scoped_ptr
<HttpTransaction
> trans(
5755 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
5756 CreateSession(&session_deps_
)));
5758 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5759 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5761 rv
= callback
.WaitForResult();
5762 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5764 // TODO(ttuttle): Anything else to check here?
5767 // Test that a SPDY proxy's response to a CONNECT request is filtered.
5768 TEST_P(HttpNetworkTransactionTest
,
5769 ErrorResponseToHttpsConnectViaSpdyProxy
) {
5770 session_deps_
.proxy_service
.reset(
5771 ProxyService::CreateFixed("https://proxy:70"));
5773 HttpRequestInfo request
;
5774 request
.method
= "GET";
5775 request
.url
= GURL("https://www.google.com/");
5776 request
.load_flags
= 0;
5778 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
5779 scoped_ptr
<SpdyFrame
> rst(
5780 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
5781 MockWrite data_writes
[] = {
5782 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
5783 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
5786 static const char* const kExtraHeaders
[] = {
5788 "http://login.example.com/",
5790 scoped_ptr
<SpdyFrame
> resp(
5791 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
5792 arraysize(kExtraHeaders
)/2, 1));
5793 scoped_ptr
<SpdyFrame
> body(
5794 spdy_util_
.ConstructSpdyBodyFrame(
5795 1, "The host does not exist", 23, true));
5796 MockRead data_reads
[] = {
5797 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
5798 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
5799 MockRead(ASYNC
, 0, 4), // EOF
5802 DelayedSocketData
data(
5803 1, // wait for one write to finish before reading.
5804 data_reads
, arraysize(data_reads
),
5805 data_writes
, arraysize(data_writes
));
5806 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
5807 proxy_ssl
.SetNextProto(GetParam());
5809 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5810 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
5812 TestCompletionCallback callback
;
5814 scoped_ptr
<HttpTransaction
> trans(
5815 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
5816 CreateSession(&session_deps_
)));
5818 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5819 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5821 rv
= callback
.WaitForResult();
5822 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5824 // TODO(ttuttle): Anything else to check here?
5827 // Test the request-challenge-retry sequence for basic auth, through
5828 // a SPDY proxy over a single SPDY session.
5829 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
5830 HttpRequestInfo request
;
5831 request
.method
= "GET";
5832 request
.url
= GURL("https://www.google.com/");
5833 // when the no authentication data flag is set.
5834 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
5836 // Configure against https proxy server "myproxy:70".
5837 session_deps_
.proxy_service
.reset(
5838 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
5839 CapturingBoundNetLog log
;
5840 session_deps_
.net_log
= log
.bound().net_log();
5841 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5843 // Since we have proxy, should try to establish tunnel.
5844 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
5845 scoped_ptr
<SpdyFrame
> rst(
5846 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
5848 // After calling trans->RestartWithAuth(), this is the request we should
5849 // be issuing -- the final header line contains the credentials.
5850 const char* const kAuthCredentials
[] = {
5851 "proxy-authorization", "Basic Zm9vOmJhcg==",
5853 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
5854 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3));
5855 // fetch https://www.google.com/ via HTTP
5856 const char get
[] = "GET / HTTP/1.1\r\n"
5857 "Host: www.google.com\r\n"
5858 "Connection: keep-alive\r\n\r\n";
5859 scoped_ptr
<SpdyFrame
> wrapped_get(
5860 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
5862 MockWrite spdy_writes
[] = {
5863 CreateMockWrite(*req
, 1, ASYNC
),
5864 CreateMockWrite(*rst
, 4, ASYNC
),
5865 CreateMockWrite(*connect2
, 5),
5866 CreateMockWrite(*wrapped_get
, 8),
5869 // The proxy responds to the connect with a 407, using a persistent
5871 const char* const kAuthChallenge
[] = {
5872 spdy_util_
.GetStatusKey(), "407 Proxy Authentication Required",
5873 spdy_util_
.GetVersionKey(), "HTTP/1.1",
5874 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
5877 scoped_ptr
<SpdyFrame
> conn_auth_resp(
5878 spdy_util_
.ConstructSpdyControlFrame(NULL
,
5886 arraysize(kAuthChallenge
),
5889 scoped_ptr
<SpdyFrame
> conn_resp(
5890 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5891 const char resp
[] = "HTTP/1.1 200 OK\r\n"
5892 "Content-Length: 5\r\n\r\n";
5894 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
5895 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
5896 scoped_ptr
<SpdyFrame
> wrapped_body(
5897 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
5898 MockRead spdy_reads
[] = {
5899 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
5900 CreateMockRead(*conn_resp
, 6, ASYNC
),
5901 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
5902 CreateMockRead(*wrapped_body
, 10, ASYNC
),
5903 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
5906 OrderedSocketData
spdy_data(
5907 spdy_reads
, arraysize(spdy_reads
),
5908 spdy_writes
, arraysize(spdy_writes
));
5909 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
5910 // Negotiate SPDY to the proxy
5911 SSLSocketDataProvider
proxy(ASYNC
, OK
);
5912 proxy
.SetNextProto(GetParam());
5913 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
5914 // Vanilla SSL to the server
5915 SSLSocketDataProvider
server(ASYNC
, OK
);
5916 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
5918 TestCompletionCallback callback1
;
5920 scoped_ptr
<HttpTransaction
> trans(
5921 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5923 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
5924 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5926 rv
= callback1
.WaitForResult();
5928 net::CapturingNetLog::CapturedEntryList entries
;
5929 log
.GetEntries(&entries
);
5930 size_t pos
= ExpectLogContainsSomewhere(
5931 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
5932 NetLog::PHASE_NONE
);
5933 ExpectLogContainsSomewhere(
5935 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
5936 NetLog::PHASE_NONE
);
5938 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5939 ASSERT_TRUE(response
!= NULL
);
5940 ASSERT_FALSE(response
->headers
.get() == NULL
);
5941 EXPECT_EQ(407, response
->headers
->response_code());
5942 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
5943 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
5944 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
5946 TestCompletionCallback callback2
;
5948 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
5949 callback2
.callback());
5950 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5952 rv
= callback2
.WaitForResult();
5955 response
= trans
->GetResponseInfo();
5956 ASSERT_TRUE(response
!= NULL
);
5958 EXPECT_TRUE(response
->headers
->IsKeepAlive());
5959 EXPECT_EQ(200, response
->headers
->response_code());
5960 EXPECT_EQ(5, response
->headers
->GetContentLength());
5961 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
5963 // The password prompt info should not be set.
5964 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5966 LoadTimingInfo load_timing_info
;
5967 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
5968 TestLoadTimingNotReusedWithPac(load_timing_info
,
5969 CONNECT_TIMING_HAS_SSL_TIMES
);
5972 session
->CloseAllConnections();
5975 // Test that an explicitly trusted SPDY proxy can push a resource from an
5976 // origin that is different from that of its associated resource.
5977 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
5978 HttpRequestInfo request
;
5979 HttpRequestInfo push_request
;
5981 request
.method
= "GET";
5982 request
.url
= GURL("http://www.google.com/");
5983 push_request
.method
= "GET";
5984 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
5986 // Configure against https proxy server "myproxy:70".
5987 session_deps_
.proxy_service
.reset(
5988 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
5989 CapturingBoundNetLog log
;
5990 session_deps_
.net_log
= log
.bound().net_log();
5992 // Enable cross-origin push.
5993 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
5995 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5997 scoped_ptr
<SpdyFrame
> stream1_syn(
5998 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6000 MockWrite spdy_writes
[] = {
6001 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6004 scoped_ptr
<SpdyFrame
>
6005 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6007 scoped_ptr
<SpdyFrame
>
6008 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6010 scoped_ptr
<SpdyFrame
>
6011 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6015 "http://www.another-origin.com/foo.dat"));
6016 const char kPushedData
[] = "pushed";
6017 scoped_ptr
<SpdyFrame
> stream2_body(
6018 spdy_util_
.ConstructSpdyBodyFrame(
6019 2, kPushedData
, strlen(kPushedData
), true));
6021 MockRead spdy_reads
[] = {
6022 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6023 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6024 CreateMockRead(*stream1_body
, 4, ASYNC
),
6025 CreateMockRead(*stream2_body
, 5, ASYNC
),
6026 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6029 OrderedSocketData
spdy_data(
6030 spdy_reads
, arraysize(spdy_reads
),
6031 spdy_writes
, arraysize(spdy_writes
));
6032 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6033 // Negotiate SPDY to the proxy
6034 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6035 proxy
.SetNextProto(GetParam());
6036 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6038 scoped_ptr
<HttpTransaction
> trans(
6039 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6040 TestCompletionCallback callback
;
6041 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6042 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6044 rv
= callback
.WaitForResult();
6046 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6048 scoped_ptr
<HttpTransaction
> push_trans(
6049 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6050 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6051 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6053 rv
= callback
.WaitForResult();
6055 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6057 ASSERT_TRUE(response
!= NULL
);
6058 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6060 EXPECT_EQ(200, response
->headers
->response_code());
6061 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6063 std::string response_data
;
6064 rv
= ReadTransaction(trans
.get(), &response_data
);
6066 EXPECT_EQ("hello!", response_data
);
6068 LoadTimingInfo load_timing_info
;
6069 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6070 TestLoadTimingNotReusedWithPac(load_timing_info
,
6071 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6073 // Verify the pushed stream.
6074 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6075 EXPECT_EQ(200, push_response
->headers
->response_code());
6077 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6079 EXPECT_EQ("pushed", response_data
);
6081 LoadTimingInfo push_load_timing_info
;
6082 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6083 TestLoadTimingReusedWithPac(push_load_timing_info
);
6084 // The transactions should share a socket ID, despite being for different
6086 EXPECT_EQ(load_timing_info
.socket_log_id
,
6087 push_load_timing_info
.socket_log_id
);
6091 session
->CloseAllConnections();
6094 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6095 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6096 HttpRequestInfo request
;
6098 request
.method
= "GET";
6099 request
.url
= GURL("http://www.google.com/");
6101 // Configure against https proxy server "myproxy:70".
6102 session_deps_
.proxy_service
.reset(
6103 ProxyService::CreateFixed("https://myproxy:70"));
6104 CapturingBoundNetLog log
;
6105 session_deps_
.net_log
= log
.bound().net_log();
6107 // Enable cross-origin push.
6108 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6110 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6112 scoped_ptr
<SpdyFrame
> stream1_syn(
6113 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6115 scoped_ptr
<SpdyFrame
> push_rst(
6116 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6118 MockWrite spdy_writes
[] = {
6119 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6120 CreateMockWrite(*push_rst
, 4),
6123 scoped_ptr
<SpdyFrame
>
6124 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6126 scoped_ptr
<SpdyFrame
>
6127 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6129 scoped_ptr
<SpdyFrame
>
6130 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6134 "https://www.another-origin.com/foo.dat"));
6136 MockRead spdy_reads
[] = {
6137 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6138 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6139 CreateMockRead(*stream1_body
, 5, ASYNC
),
6140 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6143 OrderedSocketData
spdy_data(
6144 spdy_reads
, arraysize(spdy_reads
),
6145 spdy_writes
, arraysize(spdy_writes
));
6146 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6147 // Negotiate SPDY to the proxy
6148 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6149 proxy
.SetNextProto(GetParam());
6150 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6152 scoped_ptr
<HttpTransaction
> trans(
6153 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6154 TestCompletionCallback callback
;
6155 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6156 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6158 rv
= callback
.WaitForResult();
6160 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6162 ASSERT_TRUE(response
!= NULL
);
6163 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6165 EXPECT_EQ(200, response
->headers
->response_code());
6166 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6168 std::string response_data
;
6169 rv
= ReadTransaction(trans
.get(), &response_data
);
6171 EXPECT_EQ("hello!", response_data
);
6174 session
->CloseAllConnections();
6177 // Test HTTPS connections to a site with a bad certificate, going through an
6179 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
6180 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
6181 "https://proxy:70"));
6183 HttpRequestInfo request
;
6184 request
.method
= "GET";
6185 request
.url
= GURL("https://www.google.com/");
6186 request
.load_flags
= 0;
6188 // Attempt to fetch the URL from a server with a bad cert
6189 MockWrite bad_cert_writes
[] = {
6190 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6191 "Host: www.google.com\r\n"
6192 "Proxy-Connection: keep-alive\r\n\r\n"),
6195 MockRead bad_cert_reads
[] = {
6196 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6197 MockRead(SYNCHRONOUS
, OK
)
6200 // Attempt to fetch the URL with a good cert
6201 MockWrite good_data_writes
[] = {
6202 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6203 "Host: www.google.com\r\n"
6204 "Proxy-Connection: keep-alive\r\n\r\n"),
6205 MockWrite("GET / HTTP/1.1\r\n"
6206 "Host: www.google.com\r\n"
6207 "Connection: keep-alive\r\n\r\n"),
6210 MockRead good_cert_reads
[] = {
6211 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6212 MockRead("HTTP/1.0 200 OK\r\n"),
6213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6214 MockRead("Content-Length: 100\r\n\r\n"),
6215 MockRead(SYNCHRONOUS
, OK
),
6218 StaticSocketDataProvider
ssl_bad_certificate(
6219 bad_cert_reads
, arraysize(bad_cert_reads
),
6220 bad_cert_writes
, arraysize(bad_cert_writes
));
6221 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
6222 good_data_writes
, arraysize(good_data_writes
));
6223 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6224 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6226 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6227 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6228 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6229 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6231 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6232 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6233 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6234 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6236 TestCompletionCallback callback
;
6238 scoped_ptr
<HttpTransaction
> trans(
6239 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6240 CreateSession(&session_deps_
)));
6242 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6243 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6245 rv
= callback
.WaitForResult();
6246 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6248 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6249 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6251 rv
= callback
.WaitForResult();
6254 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6256 ASSERT_TRUE(response
!= NULL
);
6257 EXPECT_EQ(100, response
->headers
->GetContentLength());
6260 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
6261 HttpRequestInfo request
;
6262 request
.method
= "GET";
6263 request
.url
= GURL("http://www.google.com/");
6264 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6265 "Chromium Ultra Awesome X Edition");
6267 scoped_ptr
<HttpTransaction
> trans(
6268 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6269 CreateSession(&session_deps_
)));
6271 MockWrite data_writes
[] = {
6272 MockWrite("GET / HTTP/1.1\r\n"
6273 "Host: www.google.com\r\n"
6274 "Connection: keep-alive\r\n"
6275 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6278 // Lastly, the server responds with the actual content.
6279 MockRead data_reads
[] = {
6280 MockRead("HTTP/1.0 200 OK\r\n"),
6281 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6282 MockRead("Content-Length: 100\r\n\r\n"),
6283 MockRead(SYNCHRONOUS
, OK
),
6286 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6287 data_writes
, arraysize(data_writes
));
6288 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6290 TestCompletionCallback callback
;
6292 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6295 rv
= callback
.WaitForResult();
6299 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
6300 HttpRequestInfo request
;
6301 request
.method
= "GET";
6302 request
.url
= GURL("https://www.google.com/");
6303 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6304 "Chromium Ultra Awesome X Edition");
6306 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6307 scoped_ptr
<HttpTransaction
> trans(
6308 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6309 CreateSession(&session_deps_
)));
6311 MockWrite data_writes
[] = {
6312 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6313 "Host: www.google.com\r\n"
6314 "Proxy-Connection: keep-alive\r\n"
6315 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6317 MockRead data_reads
[] = {
6318 // Return an error, so the transaction stops here (this test isn't
6319 // interested in the rest).
6320 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6321 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6322 MockRead("Proxy-Connection: close\r\n\r\n"),
6325 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6326 data_writes
, arraysize(data_writes
));
6327 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6329 TestCompletionCallback callback
;
6331 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6332 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6334 rv
= callback
.WaitForResult();
6338 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
6339 HttpRequestInfo request
;
6340 request
.method
= "GET";
6341 request
.url
= GURL("http://www.google.com/");
6342 request
.load_flags
= 0;
6343 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
6344 "http://the.previous.site.com/");
6346 scoped_ptr
<HttpTransaction
> trans(
6347 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6348 CreateSession(&session_deps_
)));
6350 MockWrite data_writes
[] = {
6351 MockWrite("GET / HTTP/1.1\r\n"
6352 "Host: www.google.com\r\n"
6353 "Connection: keep-alive\r\n"
6354 "Referer: http://the.previous.site.com/\r\n\r\n"),
6357 // Lastly, the server responds with the actual content.
6358 MockRead data_reads
[] = {
6359 MockRead("HTTP/1.0 200 OK\r\n"),
6360 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6361 MockRead("Content-Length: 100\r\n\r\n"),
6362 MockRead(SYNCHRONOUS
, OK
),
6365 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6366 data_writes
, arraysize(data_writes
));
6367 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6369 TestCompletionCallback callback
;
6371 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6372 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6374 rv
= callback
.WaitForResult();
6378 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
6379 HttpRequestInfo request
;
6380 request
.method
= "POST";
6381 request
.url
= GURL("http://www.google.com/");
6383 scoped_ptr
<HttpTransaction
> trans(
6384 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6385 CreateSession(&session_deps_
)));
6387 MockWrite data_writes
[] = {
6388 MockWrite("POST / HTTP/1.1\r\n"
6389 "Host: www.google.com\r\n"
6390 "Connection: keep-alive\r\n"
6391 "Content-Length: 0\r\n\r\n"),
6394 // Lastly, the server responds with the actual content.
6395 MockRead data_reads
[] = {
6396 MockRead("HTTP/1.0 200 OK\r\n"),
6397 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6398 MockRead("Content-Length: 100\r\n\r\n"),
6399 MockRead(SYNCHRONOUS
, OK
),
6402 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6403 data_writes
, arraysize(data_writes
));
6404 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6406 TestCompletionCallback callback
;
6408 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6409 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6411 rv
= callback
.WaitForResult();
6415 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
6416 HttpRequestInfo request
;
6417 request
.method
= "PUT";
6418 request
.url
= GURL("http://www.google.com/");
6420 scoped_ptr
<HttpTransaction
> trans(
6421 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6422 CreateSession(&session_deps_
)));
6424 MockWrite data_writes
[] = {
6425 MockWrite("PUT / HTTP/1.1\r\n"
6426 "Host: www.google.com\r\n"
6427 "Connection: keep-alive\r\n"
6428 "Content-Length: 0\r\n\r\n"),
6431 // Lastly, the server responds with the actual content.
6432 MockRead data_reads
[] = {
6433 MockRead("HTTP/1.0 200 OK\r\n"),
6434 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6435 MockRead("Content-Length: 100\r\n\r\n"),
6436 MockRead(SYNCHRONOUS
, OK
),
6439 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6440 data_writes
, arraysize(data_writes
));
6441 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6443 TestCompletionCallback callback
;
6445 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6446 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6448 rv
= callback
.WaitForResult();
6452 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
6453 HttpRequestInfo request
;
6454 request
.method
= "HEAD";
6455 request
.url
= GURL("http://www.google.com/");
6457 scoped_ptr
<HttpTransaction
> trans(
6458 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6459 CreateSession(&session_deps_
)));
6461 MockWrite data_writes
[] = {
6462 MockWrite("HEAD / HTTP/1.1\r\n"
6463 "Host: www.google.com\r\n"
6464 "Connection: keep-alive\r\n"
6465 "Content-Length: 0\r\n\r\n"),
6468 // Lastly, the server responds with the actual content.
6469 MockRead data_reads
[] = {
6470 MockRead("HTTP/1.0 200 OK\r\n"),
6471 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6472 MockRead("Content-Length: 100\r\n\r\n"),
6473 MockRead(SYNCHRONOUS
, OK
),
6476 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6477 data_writes
, arraysize(data_writes
));
6478 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6480 TestCompletionCallback callback
;
6482 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6483 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6485 rv
= callback
.WaitForResult();
6489 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
6490 HttpRequestInfo request
;
6491 request
.method
= "GET";
6492 request
.url
= GURL("http://www.google.com/");
6493 request
.load_flags
= LOAD_BYPASS_CACHE
;
6495 scoped_ptr
<HttpTransaction
> trans(
6496 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6497 CreateSession(&session_deps_
)));
6499 MockWrite data_writes
[] = {
6500 MockWrite("GET / HTTP/1.1\r\n"
6501 "Host: www.google.com\r\n"
6502 "Connection: keep-alive\r\n"
6503 "Pragma: no-cache\r\n"
6504 "Cache-Control: no-cache\r\n\r\n"),
6507 // Lastly, the server responds with the actual content.
6508 MockRead data_reads
[] = {
6509 MockRead("HTTP/1.0 200 OK\r\n"),
6510 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6511 MockRead("Content-Length: 100\r\n\r\n"),
6512 MockRead(SYNCHRONOUS
, OK
),
6515 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6516 data_writes
, arraysize(data_writes
));
6517 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6519 TestCompletionCallback callback
;
6521 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6522 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6524 rv
= callback
.WaitForResult();
6528 TEST_P(HttpNetworkTransactionTest
,
6529 BuildRequest_CacheControlValidateCache
) {
6530 HttpRequestInfo request
;
6531 request
.method
= "GET";
6532 request
.url
= GURL("http://www.google.com/");
6533 request
.load_flags
= LOAD_VALIDATE_CACHE
;
6535 scoped_ptr
<HttpTransaction
> trans(
6536 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6537 CreateSession(&session_deps_
)));
6539 MockWrite data_writes
[] = {
6540 MockWrite("GET / HTTP/1.1\r\n"
6541 "Host: www.google.com\r\n"
6542 "Connection: keep-alive\r\n"
6543 "Cache-Control: max-age=0\r\n\r\n"),
6546 // Lastly, the server responds with the actual content.
6547 MockRead data_reads
[] = {
6548 MockRead("HTTP/1.0 200 OK\r\n"),
6549 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6550 MockRead("Content-Length: 100\r\n\r\n"),
6551 MockRead(SYNCHRONOUS
, OK
),
6554 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6555 data_writes
, arraysize(data_writes
));
6556 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6558 TestCompletionCallback callback
;
6560 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6561 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6563 rv
= callback
.WaitForResult();
6567 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
6568 HttpRequestInfo request
;
6569 request
.method
= "GET";
6570 request
.url
= GURL("http://www.google.com/");
6571 request
.extra_headers
.SetHeader("FooHeader", "Bar");
6573 scoped_ptr
<HttpTransaction
> trans(
6574 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6575 CreateSession(&session_deps_
)));
6577 MockWrite data_writes
[] = {
6578 MockWrite("GET / HTTP/1.1\r\n"
6579 "Host: www.google.com\r\n"
6580 "Connection: keep-alive\r\n"
6581 "FooHeader: Bar\r\n\r\n"),
6584 // Lastly, the server responds with the actual content.
6585 MockRead data_reads
[] = {
6586 MockRead("HTTP/1.0 200 OK\r\n"),
6587 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6588 MockRead("Content-Length: 100\r\n\r\n"),
6589 MockRead(SYNCHRONOUS
, OK
),
6592 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6593 data_writes
, arraysize(data_writes
));
6594 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6596 TestCompletionCallback callback
;
6598 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6599 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6601 rv
= callback
.WaitForResult();
6605 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
6606 HttpRequestInfo request
;
6607 request
.method
= "GET";
6608 request
.url
= GURL("http://www.google.com/");
6609 request
.extra_headers
.SetHeader("referer", "www.foo.com");
6610 request
.extra_headers
.SetHeader("hEllo", "Kitty");
6611 request
.extra_headers
.SetHeader("FoO", "bar");
6613 scoped_ptr
<HttpTransaction
> trans(
6614 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6615 CreateSession(&session_deps_
)));
6617 MockWrite data_writes
[] = {
6618 MockWrite("GET / HTTP/1.1\r\n"
6619 "Host: www.google.com\r\n"
6620 "Connection: keep-alive\r\n"
6621 "referer: www.foo.com\r\n"
6623 "FoO: bar\r\n\r\n"),
6626 // Lastly, the server responds with the actual content.
6627 MockRead data_reads
[] = {
6628 MockRead("HTTP/1.0 200 OK\r\n"),
6629 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6630 MockRead("Content-Length: 100\r\n\r\n"),
6631 MockRead(SYNCHRONOUS
, OK
),
6634 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6635 data_writes
, arraysize(data_writes
));
6636 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6638 TestCompletionCallback callback
;
6640 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6641 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6643 rv
= callback
.WaitForResult();
6647 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
6648 HttpRequestInfo request
;
6649 request
.method
= "GET";
6650 request
.url
= GURL("http://www.google.com/");
6651 request
.load_flags
= 0;
6653 session_deps_
.proxy_service
.reset(
6654 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6655 CapturingNetLog net_log
;
6656 session_deps_
.net_log
= &net_log
;
6658 scoped_ptr
<HttpTransaction
> trans(
6659 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6660 CreateSession(&session_deps_
)));
6662 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6663 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6665 MockWrite data_writes
[] = {
6666 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
6667 MockWrite("GET / HTTP/1.1\r\n"
6668 "Host: www.google.com\r\n"
6669 "Connection: keep-alive\r\n\r\n")
6672 MockRead data_reads
[] = {
6673 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
6674 MockRead("HTTP/1.0 200 OK\r\n"),
6675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6676 MockRead("Payload"),
6677 MockRead(SYNCHRONOUS
, OK
)
6680 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6681 data_writes
, arraysize(data_writes
));
6682 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6684 TestCompletionCallback callback
;
6686 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6687 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6689 rv
= callback
.WaitForResult();
6692 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6693 ASSERT_TRUE(response
!= NULL
);
6695 LoadTimingInfo load_timing_info
;
6696 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6697 TestLoadTimingNotReusedWithPac(load_timing_info
,
6698 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6700 std::string response_text
;
6701 rv
= ReadTransaction(trans
.get(), &response_text
);
6703 EXPECT_EQ("Payload", response_text
);
6706 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
6707 HttpRequestInfo request
;
6708 request
.method
= "GET";
6709 request
.url
= GURL("https://www.google.com/");
6710 request
.load_flags
= 0;
6712 session_deps_
.proxy_service
.reset(
6713 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6714 CapturingNetLog net_log
;
6715 session_deps_
.net_log
= &net_log
;
6717 scoped_ptr
<HttpTransaction
> trans(
6718 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6719 CreateSession(&session_deps_
)));
6721 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
6722 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6724 MockWrite data_writes
[] = {
6725 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
6726 arraysize(write_buffer
)),
6727 MockWrite("GET / HTTP/1.1\r\n"
6728 "Host: www.google.com\r\n"
6729 "Connection: keep-alive\r\n\r\n")
6732 MockRead data_reads
[] = {
6733 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
6734 arraysize(read_buffer
)),
6735 MockRead("HTTP/1.0 200 OK\r\n"),
6736 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6737 MockRead("Payload"),
6738 MockRead(SYNCHRONOUS
, OK
)
6741 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6742 data_writes
, arraysize(data_writes
));
6743 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6745 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6746 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6748 TestCompletionCallback callback
;
6750 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6751 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6753 rv
= callback
.WaitForResult();
6756 LoadTimingInfo load_timing_info
;
6757 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6758 TestLoadTimingNotReusedWithPac(load_timing_info
,
6759 CONNECT_TIMING_HAS_SSL_TIMES
);
6761 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6762 ASSERT_TRUE(response
!= NULL
);
6764 std::string response_text
;
6765 rv
= ReadTransaction(trans
.get(), &response_text
);
6767 EXPECT_EQ("Payload", response_text
);
6770 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
6771 HttpRequestInfo request
;
6772 request
.method
= "GET";
6773 request
.url
= GURL("http://www.google.com/");
6774 request
.load_flags
= 0;
6776 session_deps_
.proxy_service
.reset(
6777 ProxyService::CreateFixed("socks4://myproxy:1080"));
6778 CapturingNetLog net_log
;
6779 session_deps_
.net_log
= &net_log
;
6781 scoped_ptr
<HttpTransaction
> trans(
6782 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6783 CreateSession(&session_deps_
)));
6785 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6786 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6788 MockWrite data_writes
[] = {
6789 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
6790 MockWrite("GET / HTTP/1.1\r\n"
6791 "Host: www.google.com\r\n"
6792 "Connection: keep-alive\r\n\r\n")
6795 MockRead data_reads
[] = {
6796 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
6797 MockRead("HTTP/1.0 200 OK\r\n"),
6798 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6799 MockRead("Payload"),
6800 MockRead(SYNCHRONOUS
, OK
)
6803 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6804 data_writes
, arraysize(data_writes
));
6805 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6807 TestCompletionCallback callback
;
6809 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6810 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6812 rv
= callback
.WaitForResult();
6815 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6816 ASSERT_TRUE(response
!= NULL
);
6818 LoadTimingInfo load_timing_info
;
6819 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6820 TestLoadTimingNotReused(load_timing_info
,
6821 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6823 std::string response_text
;
6824 rv
= ReadTransaction(trans
.get(), &response_text
);
6826 EXPECT_EQ("Payload", response_text
);
6829 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
6830 HttpRequestInfo request
;
6831 request
.method
= "GET";
6832 request
.url
= GURL("http://www.google.com/");
6833 request
.load_flags
= 0;
6835 session_deps_
.proxy_service
.reset(
6836 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
6837 CapturingNetLog net_log
;
6838 session_deps_
.net_log
= &net_log
;
6840 scoped_ptr
<HttpTransaction
> trans(
6841 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6842 CreateSession(&session_deps_
)));
6844 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
6845 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
6846 const char kSOCKS5OkRequest
[] = {
6848 0x01, // Command (CONNECT)
6850 0x03, // Address type (DOMAINNAME).
6851 0x0E, // Length of domain (14)
6853 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
6854 0x00, 0x50, // 16-bit port (80)
6856 const char kSOCKS5OkResponse
[] =
6857 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
6859 MockWrite data_writes
[] = {
6860 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
6861 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
6862 MockWrite("GET / HTTP/1.1\r\n"
6863 "Host: www.google.com\r\n"
6864 "Connection: keep-alive\r\n\r\n")
6867 MockRead data_reads
[] = {
6868 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
6869 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
6870 MockRead("HTTP/1.0 200 OK\r\n"),
6871 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6872 MockRead("Payload"),
6873 MockRead(SYNCHRONOUS
, OK
)
6876 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6877 data_writes
, arraysize(data_writes
));
6878 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6880 TestCompletionCallback callback
;
6882 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6883 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6885 rv
= callback
.WaitForResult();
6888 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6889 ASSERT_TRUE(response
!= NULL
);
6891 LoadTimingInfo load_timing_info
;
6892 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6893 TestLoadTimingNotReusedWithPac(load_timing_info
,
6894 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6896 std::string response_text
;
6897 rv
= ReadTransaction(trans
.get(), &response_text
);
6899 EXPECT_EQ("Payload", response_text
);
6902 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
6903 HttpRequestInfo request
;
6904 request
.method
= "GET";
6905 request
.url
= GURL("https://www.google.com/");
6906 request
.load_flags
= 0;
6908 session_deps_
.proxy_service
.reset(
6909 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
6910 CapturingNetLog net_log
;
6911 session_deps_
.net_log
= &net_log
;
6913 scoped_ptr
<HttpTransaction
> trans(
6914 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
6915 CreateSession(&session_deps_
)));
6917 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
6918 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
6919 const unsigned char kSOCKS5OkRequest
[] = {
6921 0x01, // Command (CONNECT)
6923 0x03, // Address type (DOMAINNAME).
6924 0x0E, // Length of domain (14)
6926 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
6927 0x01, 0xBB, // 16-bit port (443)
6930 const char kSOCKS5OkResponse
[] =
6931 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
6933 MockWrite data_writes
[] = {
6934 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
6935 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
6936 arraysize(kSOCKS5OkRequest
)),
6937 MockWrite("GET / HTTP/1.1\r\n"
6938 "Host: www.google.com\r\n"
6939 "Connection: keep-alive\r\n\r\n")
6942 MockRead data_reads
[] = {
6943 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
6944 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
6945 MockRead("HTTP/1.0 200 OK\r\n"),
6946 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6947 MockRead("Payload"),
6948 MockRead(SYNCHRONOUS
, OK
)
6951 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6952 data_writes
, arraysize(data_writes
));
6953 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6955 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6956 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6958 TestCompletionCallback callback
;
6960 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6961 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6963 rv
= callback
.WaitForResult();
6966 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6967 ASSERT_TRUE(response
!= NULL
);
6969 LoadTimingInfo load_timing_info
;
6970 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6971 TestLoadTimingNotReusedWithPac(load_timing_info
,
6972 CONNECT_TIMING_HAS_SSL_TIMES
);
6974 std::string response_text
;
6975 rv
= ReadTransaction(trans
.get(), &response_text
);
6977 EXPECT_EQ("Payload", response_text
);
6982 // Tests that for connection endpoints the group names are correctly set.
6984 struct GroupNameTest
{
6985 std::string proxy_server
;
6987 std::string expected_group_name
;
6991 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
6992 NextProto next_proto
,
6993 SpdySessionDependencies
* session_deps_
) {
6994 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
6996 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
6997 session
->http_server_properties();
6998 http_server_properties
->SetAlternateProtocol(
6999 HostPortPair("host.with.alternate", 80), 443,
7000 AlternateProtocolFromNextProto(next_proto
));
7005 int GroupNameTransactionHelper(
7006 const std::string
& url
,
7007 const scoped_refptr
<HttpNetworkSession
>& session
) {
7008 HttpRequestInfo request
;
7009 request
.method
= "GET";
7010 request
.url
= GURL(url
);
7011 request
.load_flags
= 0;
7013 scoped_ptr
<HttpTransaction
> trans(
7014 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7016 TestCompletionCallback callback
;
7018 // We do not complete this request, the dtor will clean the transaction up.
7019 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7024 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7025 const GroupNameTest tests
[] = {
7028 "http://www.google.com/direct",
7029 "www.google.com:80",
7034 "http://[2001:1418:13:1::25]/direct",
7035 "[2001:1418:13:1::25]:80",
7042 "https://www.google.com/direct_ssl",
7043 "ssl/www.google.com:443",
7048 "https://[2001:1418:13:1::25]/direct",
7049 "ssl/[2001:1418:13:1::25]:443",
7054 "http://host.with.alternate/direct",
7055 "ssl/host.with.alternate:443",
7060 HttpStreamFactory::set_use_alternate_protocols(true);
7062 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7063 session_deps_
.proxy_service
.reset(
7064 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7065 scoped_refptr
<HttpNetworkSession
> session(
7066 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7068 HttpNetworkSessionPeer
peer(session
);
7069 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7070 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7071 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7072 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7073 MockClientSocketPoolManager
* mock_pool_manager
=
7074 new MockClientSocketPoolManager
;
7075 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7076 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7077 peer
.SetClientSocketPoolManager(mock_pool_manager
);
7079 EXPECT_EQ(ERR_IO_PENDING
,
7080 GroupNameTransactionHelper(tests
[i
].url
, session
));
7082 EXPECT_EQ(tests
[i
].expected_group_name
,
7083 ssl_conn_pool
->last_group_name_received());
7085 EXPECT_EQ(tests
[i
].expected_group_name
,
7086 transport_conn_pool
->last_group_name_received());
7091 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7092 const GroupNameTest tests
[] = {
7095 "http://www.google.com/http_proxy_normal",
7096 "www.google.com:80",
7103 "https://www.google.com/http_connect_ssl",
7104 "ssl/www.google.com:443",
7110 "http://host.with.alternate/direct",
7111 "ssl/host.with.alternate:443",
7117 "ftp://ftp.google.com/http_proxy_normal",
7118 "ftp/ftp.google.com:21",
7123 HttpStreamFactory::set_use_alternate_protocols(true);
7125 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7126 session_deps_
.proxy_service
.reset(
7127 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7128 scoped_refptr
<HttpNetworkSession
> session(
7129 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7131 HttpNetworkSessionPeer
peer(session
);
7133 HostPortPair
proxy_host("http_proxy", 80);
7134 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
7135 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
7136 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7137 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7139 MockClientSocketPoolManager
* mock_pool_manager
=
7140 new MockClientSocketPoolManager
;
7141 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
7142 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7143 peer
.SetClientSocketPoolManager(mock_pool_manager
);
7145 EXPECT_EQ(ERR_IO_PENDING
,
7146 GroupNameTransactionHelper(tests
[i
].url
, session
));
7148 EXPECT_EQ(tests
[i
].expected_group_name
,
7149 ssl_conn_pool
->last_group_name_received());
7151 EXPECT_EQ(tests
[i
].expected_group_name
,
7152 http_proxy_pool
->last_group_name_received());
7156 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
7157 const GroupNameTest tests
[] = {
7159 "socks4://socks_proxy:1080",
7160 "http://www.google.com/socks4_direct",
7161 "socks4/www.google.com:80",
7165 "socks5://socks_proxy:1080",
7166 "http://www.google.com/socks5_direct",
7167 "socks5/www.google.com:80",
7173 "socks4://socks_proxy:1080",
7174 "https://www.google.com/socks4_ssl",
7175 "socks4/ssl/www.google.com:443",
7179 "socks5://socks_proxy:1080",
7180 "https://www.google.com/socks5_ssl",
7181 "socks5/ssl/www.google.com:443",
7186 "socks4://socks_proxy:1080",
7187 "http://host.with.alternate/direct",
7188 "socks4/ssl/host.with.alternate:443",
7193 HttpStreamFactory::set_use_alternate_protocols(true);
7195 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7196 session_deps_
.proxy_service
.reset(
7197 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7198 scoped_refptr
<HttpNetworkSession
> session(
7199 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7201 HttpNetworkSessionPeer
peer(session
);
7203 HostPortPair
proxy_host("socks_proxy", 1080);
7204 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
7205 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
7206 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7207 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7209 MockClientSocketPoolManager
* mock_pool_manager
=
7210 new MockClientSocketPoolManager
;
7211 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
7212 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7213 peer
.SetClientSocketPoolManager(mock_pool_manager
);
7215 scoped_ptr
<HttpTransaction
> trans(
7216 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7218 EXPECT_EQ(ERR_IO_PENDING
,
7219 GroupNameTransactionHelper(tests
[i
].url
, session
));
7221 EXPECT_EQ(tests
[i
].expected_group_name
,
7222 ssl_conn_pool
->last_group_name_received());
7224 EXPECT_EQ(tests
[i
].expected_group_name
,
7225 socks_conn_pool
->last_group_name_received());
7229 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
7230 HttpRequestInfo request
;
7231 request
.method
= "GET";
7232 request
.url
= GURL("http://www.google.com/");
7234 session_deps_
.proxy_service
.reset(
7235 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7237 // This simulates failure resolving all hostnames; that means we will fail
7238 // connecting to both proxies (myproxy:70 and foobar:80).
7239 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
7241 scoped_ptr
<HttpTransaction
> trans(
7242 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7243 CreateSession(&session_deps_
)));
7245 TestCompletionCallback callback
;
7247 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7248 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7250 rv
= callback
.WaitForResult();
7251 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
7254 // Base test to make sure that when the load flags for a request specify to
7255 // bypass the cache, the DNS cache is not used.
7256 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7258 // Issue a request, asking to bypass the cache(s).
7259 HttpRequestInfo request
;
7260 request
.method
= "GET";
7261 request
.load_flags
= load_flags
;
7262 request
.url
= GURL("http://www.google.com/");
7264 // Select a host resolver that does caching.
7265 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
7267 scoped_ptr
<HttpTransaction
> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7268 CreateSession(&session_deps_
)));
7270 // Warm up the host cache so it has an entry for "www.google.com".
7271 AddressList addrlist
;
7272 TestCompletionCallback callback
;
7273 int rv
= session_deps_
.host_resolver
->Resolve(
7274 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist
,
7275 callback
.callback(), NULL
, BoundNetLog());
7276 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7277 rv
= callback
.WaitForResult();
7280 // Verify that it was added to host cache, by doing a subsequent async lookup
7281 // and confirming it completes synchronously.
7282 rv
= session_deps_
.host_resolver
->Resolve(
7283 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist
,
7284 callback
.callback(), NULL
, BoundNetLog());
7287 // Inject a failure the next time that "www.google.com" is resolved. This way
7288 // we can tell if the next lookup hit the cache, or the "network".
7289 // (cache --> success, "network" --> failure).
7290 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.google.com");
7292 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7293 // first read -- this won't be reached as the host resolution will fail first.
7294 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
7295 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7296 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7299 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7300 ASSERT_EQ(ERR_IO_PENDING
, rv
);
7301 rv
= callback
.WaitForResult();
7303 // If we bypassed the cache, we would have gotten a failure while resolving
7304 // "www.google.com".
7305 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
7308 // There are multiple load flags that should trigger the host cache bypass.
7309 // Test each in isolation:
7310 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
7311 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
7314 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
7315 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
7318 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
7319 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
7322 // Make sure we can handle an error when writing the request.
7323 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
7324 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7326 HttpRequestInfo request
;
7327 request
.method
= "GET";
7328 request
.url
= GURL("http://www.foo.com/");
7329 request
.load_flags
= 0;
7331 MockWrite write_failure
[] = {
7332 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
7334 StaticSocketDataProvider
data(NULL
, 0,
7335 write_failure
, arraysize(write_failure
));
7336 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7338 TestCompletionCallback callback
;
7340 scoped_ptr
<HttpTransaction
> trans(
7341 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7342 CreateSession(&session_deps_
)));
7344 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7345 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7347 rv
= callback
.WaitForResult();
7348 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
7351 // Check that a connection closed after the start of the headers finishes ok.
7352 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
7353 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7355 HttpRequestInfo request
;
7356 request
.method
= "GET";
7357 request
.url
= GURL("http://www.foo.com/");
7358 request
.load_flags
= 0;
7360 MockRead data_reads
[] = {
7361 MockRead("HTTP/1."),
7362 MockRead(SYNCHRONOUS
, OK
),
7365 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7366 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7368 TestCompletionCallback callback
;
7370 scoped_ptr
<HttpTransaction
> trans(
7371 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7372 CreateSession(&session_deps_
)));
7374 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7375 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7377 rv
= callback
.WaitForResult();
7380 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7381 ASSERT_TRUE(response
!= NULL
);
7383 EXPECT_TRUE(response
->headers
.get() != NULL
);
7384 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7386 std::string response_data
;
7387 rv
= ReadTransaction(trans
.get(), &response_data
);
7389 EXPECT_EQ("", response_data
);
7392 // Make sure that a dropped connection while draining the body for auth
7393 // restart does the right thing.
7394 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
7395 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7397 HttpRequestInfo request
;
7398 request
.method
= "GET";
7399 request
.url
= GURL("http://www.google.com/");
7400 request
.load_flags
= 0;
7402 MockWrite data_writes1
[] = {
7403 MockWrite("GET / HTTP/1.1\r\n"
7404 "Host: www.google.com\r\n"
7405 "Connection: keep-alive\r\n\r\n"),
7408 MockRead data_reads1
[] = {
7409 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7410 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7412 MockRead("Content-Length: 14\r\n\r\n"),
7414 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
7417 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
7418 data_writes1
, arraysize(data_writes1
));
7419 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
7421 // After calling trans->RestartWithAuth(), this is the request we should
7422 // be issuing -- the final header line contains the credentials.
7423 MockWrite data_writes2
[] = {
7424 MockWrite("GET / HTTP/1.1\r\n"
7425 "Host: www.google.com\r\n"
7426 "Connection: keep-alive\r\n"
7427 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7430 // Lastly, the server responds with the actual content.
7431 MockRead data_reads2
[] = {
7432 MockRead("HTTP/1.1 200 OK\r\n"),
7433 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7434 MockRead("Content-Length: 100\r\n\r\n"),
7435 MockRead(SYNCHRONOUS
, OK
),
7438 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
7439 data_writes2
, arraysize(data_writes2
));
7440 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
7442 TestCompletionCallback callback1
;
7444 scoped_ptr
<HttpTransaction
> trans(
7445 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7447 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
7448 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7450 rv
= callback1
.WaitForResult();
7453 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7454 ASSERT_TRUE(response
!= NULL
);
7455 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
7457 TestCompletionCallback callback2
;
7459 rv
= trans
->RestartWithAuth(
7460 AuthCredentials(kFoo
, kBar
), callback2
.callback());
7461 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7463 rv
= callback2
.WaitForResult();
7466 response
= trans
->GetResponseInfo();
7467 ASSERT_TRUE(response
!= NULL
);
7468 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
7469 EXPECT_EQ(100, response
->headers
->GetContentLength());
7472 // Test HTTPS connections going through a proxy that sends extra data.
7473 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
7474 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7476 HttpRequestInfo request
;
7477 request
.method
= "GET";
7478 request
.url
= GURL("https://www.google.com/");
7479 request
.load_flags
= 0;
7481 MockRead proxy_reads
[] = {
7482 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7483 MockRead(SYNCHRONOUS
, OK
)
7486 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
7487 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7489 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7490 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7492 TestCompletionCallback callback
;
7494 session_deps_
.socket_factory
->ResetNextMockIndexes();
7496 scoped_ptr
<HttpTransaction
> trans(
7497 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7498 CreateSession(&session_deps_
)));
7500 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7501 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7503 rv
= callback
.WaitForResult();
7504 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
7507 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
7508 HttpRequestInfo request
;
7509 request
.method
= "GET";
7510 request
.url
= GURL("http://www.google.com/");
7511 request
.load_flags
= 0;
7513 scoped_ptr
<HttpTransaction
> trans(
7514 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7515 CreateSession(&session_deps_
)));
7517 MockRead data_reads
[] = {
7518 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7519 MockRead(SYNCHRONOUS
, OK
),
7522 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7523 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7525 TestCompletionCallback callback
;
7527 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7528 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7530 EXPECT_EQ(OK
, callback
.WaitForResult());
7532 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7533 ASSERT_TRUE(response
!= NULL
);
7535 EXPECT_TRUE(response
->headers
.get() != NULL
);
7536 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7538 std::string response_data
;
7539 rv
= ReadTransaction(trans
.get(), &response_data
);
7540 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
7543 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
7544 base::FilePath temp_file_path
;
7545 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path
));
7546 const uint64 kFakeSize
= 100000; // file is actually blank
7547 UploadFileElementReader::ScopedOverridingContentLengthForTests
7548 overriding_content_length(kFakeSize
);
7550 ScopedVector
<UploadElementReader
> element_readers
;
7551 element_readers
.push_back(
7552 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7557 UploadDataStream
upload_data_stream(&element_readers
, 0);
7559 HttpRequestInfo request
;
7560 request
.method
= "POST";
7561 request
.url
= GURL("http://www.google.com/upload");
7562 request
.upload_data_stream
= &upload_data_stream
;
7563 request
.load_flags
= 0;
7565 scoped_ptr
<HttpTransaction
> trans(
7566 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7567 CreateSession(&session_deps_
)));
7569 MockRead data_reads
[] = {
7570 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7571 MockRead("hello world"),
7572 MockRead(SYNCHRONOUS
, OK
),
7574 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7575 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7577 TestCompletionCallback callback
;
7579 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7580 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7582 rv
= callback
.WaitForResult();
7585 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7586 ASSERT_TRUE(response
!= NULL
);
7588 EXPECT_TRUE(response
->headers
.get() != NULL
);
7589 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7591 std::string response_data
;
7592 rv
= ReadTransaction(trans
.get(), &response_data
);
7594 EXPECT_EQ("hello world", response_data
);
7596 base::DeleteFile(temp_file_path
, false);
7599 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
7600 base::FilePath temp_file
;
7601 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file
));
7602 std::string
temp_file_content("Unreadable file.");
7603 ASSERT_TRUE(file_util::WriteFile(temp_file
, temp_file_content
.c_str(),
7604 temp_file_content
.length()));
7605 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file
));
7607 ScopedVector
<UploadElementReader
> element_readers
;
7608 element_readers
.push_back(
7609 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7614 UploadDataStream
upload_data_stream(&element_readers
, 0);
7616 HttpRequestInfo request
;
7617 request
.method
= "POST";
7618 request
.url
= GURL("http://www.google.com/upload");
7619 request
.upload_data_stream
= &upload_data_stream
;
7620 request
.load_flags
= 0;
7622 // If we try to upload an unreadable file, the network stack should report
7623 // the file size as zero and upload zero bytes for that file.
7624 scoped_ptr
<HttpTransaction
> trans(
7625 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7626 CreateSession(&session_deps_
)));
7628 MockRead data_reads
[] = {
7629 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7630 MockRead(SYNCHRONOUS
, OK
),
7632 MockWrite data_writes
[] = {
7633 MockWrite("POST /upload HTTP/1.1\r\n"
7634 "Host: www.google.com\r\n"
7635 "Connection: keep-alive\r\n"
7636 "Content-Length: 0\r\n\r\n"),
7637 MockWrite(SYNCHRONOUS
, OK
),
7639 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
7640 arraysize(data_writes
));
7641 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7643 TestCompletionCallback callback
;
7645 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7646 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7648 rv
= callback
.WaitForResult();
7651 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7652 ASSERT_TRUE(response
!= NULL
);
7653 EXPECT_TRUE(response
->headers
.get() != NULL
);
7654 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7656 base::DeleteFile(temp_file
, false);
7659 TEST_P(HttpNetworkTransactionTest
, UnreadableUploadFileAfterAuthRestart
) {
7660 base::FilePath temp_file
;
7661 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file
));
7662 std::string
temp_file_contents("Unreadable file.");
7663 std::string
unreadable_contents(temp_file_contents
.length(), '\0');
7664 ASSERT_TRUE(file_util::WriteFile(temp_file
, temp_file_contents
.c_str(),
7665 temp_file_contents
.length()));
7667 ScopedVector
<UploadElementReader
> element_readers
;
7668 element_readers
.push_back(
7669 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7674 UploadDataStream
upload_data_stream(&element_readers
, 0);
7676 HttpRequestInfo request
;
7677 request
.method
= "POST";
7678 request
.url
= GURL("http://www.google.com/upload");
7679 request
.upload_data_stream
= &upload_data_stream
;
7680 request
.load_flags
= 0;
7682 scoped_ptr
<HttpTransaction
> trans(
7683 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7684 CreateSession(&session_deps_
)));
7686 MockRead data_reads
[] = {
7687 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7688 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7689 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
7691 MockRead("HTTP/1.1 200 OK\r\n"),
7692 MockRead("Content-Length: 0\r\n\r\n"),
7693 MockRead(SYNCHRONOUS
, OK
),
7695 MockWrite data_writes
[] = {
7696 MockWrite("POST /upload HTTP/1.1\r\n"
7697 "Host: www.google.com\r\n"
7698 "Connection: keep-alive\r\n"
7699 "Content-Length: 16\r\n\r\n"),
7700 MockWrite(SYNCHRONOUS
, temp_file_contents
.c_str()),
7702 MockWrite("POST /upload HTTP/1.1\r\n"
7703 "Host: www.google.com\r\n"
7704 "Connection: keep-alive\r\n"
7705 "Content-Length: 0\r\n"
7706 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7707 MockWrite(SYNCHRONOUS
, unreadable_contents
.c_str(),
7708 temp_file_contents
.length()),
7709 MockWrite(SYNCHRONOUS
, OK
),
7711 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
7712 arraysize(data_writes
));
7713 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7715 TestCompletionCallback callback1
;
7717 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
7718 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7720 rv
= callback1
.WaitForResult();
7723 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7724 ASSERT_TRUE(response
!= NULL
);
7725 ASSERT_TRUE(response
->headers
.get() != NULL
);
7726 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response
->headers
->GetStatusLine());
7727 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
7729 // Now make the file unreadable and try again.
7730 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file
));
7732 TestCompletionCallback callback2
;
7734 rv
= trans
->RestartWithAuth(
7735 AuthCredentials(kFoo
, kBar
), callback2
.callback());
7736 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7738 rv
= callback2
.WaitForResult();
7741 response
= trans
->GetResponseInfo();
7742 ASSERT_TRUE(response
!= NULL
);
7743 EXPECT_TRUE(response
->headers
.get() != NULL
);
7744 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
7745 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
7747 base::DeleteFile(temp_file
, false);
7750 // Tests that changes to Auth realms are treated like auth rejections.
7751 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
7753 HttpRequestInfo request
;
7754 request
.method
= "GET";
7755 request
.url
= GURL("http://www.google.com/");
7756 request
.load_flags
= 0;
7758 // First transaction will request a resource and receive a Basic challenge
7759 // with realm="first_realm".
7760 MockWrite data_writes1
[] = {
7761 MockWrite("GET / HTTP/1.1\r\n"
7762 "Host: www.google.com\r\n"
7763 "Connection: keep-alive\r\n"
7766 MockRead data_reads1
[] = {
7767 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7768 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7772 // After calling trans->RestartWithAuth(), provide an Authentication header
7773 // for first_realm. The server will reject and provide a challenge with
7775 MockWrite data_writes2
[] = {
7776 MockWrite("GET / HTTP/1.1\r\n"
7777 "Host: www.google.com\r\n"
7778 "Connection: keep-alive\r\n"
7779 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
7782 MockRead data_reads2
[] = {
7783 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7784 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
7788 // This again fails, and goes back to first_realm. Make sure that the
7789 // entry is removed from cache.
7790 MockWrite data_writes3
[] = {
7791 MockWrite("GET / HTTP/1.1\r\n"
7792 "Host: www.google.com\r\n"
7793 "Connection: keep-alive\r\n"
7794 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
7797 MockRead data_reads3
[] = {
7798 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7799 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7803 // Try one last time (with the correct password) and get the resource.
7804 MockWrite data_writes4
[] = {
7805 MockWrite("GET / HTTP/1.1\r\n"
7806 "Host: www.google.com\r\n"
7807 "Connection: keep-alive\r\n"
7808 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
7811 MockRead data_reads4
[] = {
7812 MockRead("HTTP/1.1 200 OK\r\n"
7813 "Content-Type: text/html; charset=iso-8859-1\r\n"
7814 "Content-Length: 5\r\n"
7819 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
7820 data_writes1
, arraysize(data_writes1
));
7821 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
7822 data_writes2
, arraysize(data_writes2
));
7823 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
7824 data_writes3
, arraysize(data_writes3
));
7825 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
7826 data_writes4
, arraysize(data_writes4
));
7827 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
7828 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
7829 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
7830 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
7832 TestCompletionCallback callback1
;
7834 scoped_ptr
<HttpTransaction
> trans(
7835 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
7836 CreateSession(&session_deps_
)));
7838 // Issue the first request with Authorize headers. There should be a
7839 // password prompt for first_realm waiting to be filled in after the
7840 // transaction completes.
7841 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
7842 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7843 rv
= callback1
.WaitForResult();
7845 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7846 ASSERT_TRUE(response
!= NULL
);
7847 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
7848 ASSERT_FALSE(challenge
== NULL
);
7849 EXPECT_FALSE(challenge
->is_proxy
);
7850 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
7851 EXPECT_EQ("first_realm", challenge
->realm
);
7852 EXPECT_EQ("basic", challenge
->scheme
);
7854 // Issue the second request with an incorrect password. There should be a
7855 // password prompt for second_realm waiting to be filled in after the
7856 // transaction completes.
7857 TestCompletionCallback callback2
;
7858 rv
= trans
->RestartWithAuth(
7859 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
7860 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7861 rv
= callback2
.WaitForResult();
7863 response
= trans
->GetResponseInfo();
7864 ASSERT_TRUE(response
!= NULL
);
7865 challenge
= response
->auth_challenge
.get();
7866 ASSERT_FALSE(challenge
== NULL
);
7867 EXPECT_FALSE(challenge
->is_proxy
);
7868 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
7869 EXPECT_EQ("second_realm", challenge
->realm
);
7870 EXPECT_EQ("basic", challenge
->scheme
);
7872 // Issue the third request with another incorrect password. There should be
7873 // a password prompt for first_realm waiting to be filled in. If the password
7874 // prompt is not present, it indicates that the HttpAuthCacheEntry for
7875 // first_realm was not correctly removed.
7876 TestCompletionCallback callback3
;
7877 rv
= trans
->RestartWithAuth(
7878 AuthCredentials(kSecond
, kFou
), callback3
.callback());
7879 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7880 rv
= callback3
.WaitForResult();
7882 response
= trans
->GetResponseInfo();
7883 ASSERT_TRUE(response
!= NULL
);
7884 challenge
= response
->auth_challenge
.get();
7885 ASSERT_FALSE(challenge
== NULL
);
7886 EXPECT_FALSE(challenge
->is_proxy
);
7887 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
7888 EXPECT_EQ("first_realm", challenge
->realm
);
7889 EXPECT_EQ("basic", challenge
->scheme
);
7891 // Issue the fourth request with the correct password and username.
7892 TestCompletionCallback callback4
;
7893 rv
= trans
->RestartWithAuth(
7894 AuthCredentials(kFirst
, kBar
), callback4
.callback());
7895 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7896 rv
= callback4
.WaitForResult();
7898 response
= trans
->GetResponseInfo();
7899 ASSERT_TRUE(response
!= NULL
);
7900 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
7903 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
7904 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
7905 HttpStreamFactory::set_use_alternate_protocols(true);
7907 std::string alternate_protocol_http_header
=
7908 GetAlternateProtocolHttpHeader();
7910 MockRead data_reads
[] = {
7911 MockRead("HTTP/1.1 200 OK\r\n"),
7912 MockRead(alternate_protocol_http_header
.c_str()),
7913 MockRead("hello world"),
7914 MockRead(SYNCHRONOUS
, OK
),
7917 HttpRequestInfo request
;
7918 request
.method
= "GET";
7919 request
.url
= GURL("http://www.google.com/");
7920 request
.load_flags
= 0;
7922 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7924 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7926 TestCompletionCallback callback
;
7928 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7929 scoped_ptr
<HttpTransaction
> trans(
7930 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7932 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7933 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7935 HostPortPair
http_host_port_pair("www.google.com", 80);
7936 const HttpServerProperties
& http_server_properties
=
7937 *session
->http_server_properties();
7939 http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
7941 EXPECT_EQ(OK
, callback
.WaitForResult());
7943 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7944 ASSERT_TRUE(response
!= NULL
);
7945 ASSERT_TRUE(response
->headers
.get() != NULL
);
7946 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
7947 EXPECT_FALSE(response
->was_fetched_via_spdy
);
7948 EXPECT_FALSE(response
->was_npn_negotiated
);
7950 std::string response_data
;
7951 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
7952 EXPECT_EQ("hello world", response_data
);
7954 ASSERT_TRUE(http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
7955 const PortAlternateProtocolPair alternate
=
7956 http_server_properties
.GetAlternateProtocol(http_host_port_pair
);
7957 PortAlternateProtocolPair expected_alternate
;
7958 expected_alternate
.port
= 443;
7959 expected_alternate
.protocol
= AlternateProtocolFromNextProto(GetParam());
7960 EXPECT_TRUE(expected_alternate
.Equals(alternate
));
7963 TEST_P(HttpNetworkTransactionTest
,
7964 MarkBrokenAlternateProtocolAndFallback
) {
7965 HttpStreamFactory::set_use_alternate_protocols(true);
7967 HttpRequestInfo request
;
7968 request
.method
= "GET";
7969 request
.url
= GURL("http://www.google.com/");
7970 request
.load_flags
= 0;
7972 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
7973 StaticSocketDataProvider first_data
;
7974 first_data
.set_connect_data(mock_connect
);
7975 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
7977 MockRead data_reads
[] = {
7978 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
7979 MockRead("hello world"),
7980 MockRead(ASYNC
, OK
),
7982 StaticSocketDataProvider
second_data(
7983 data_reads
, arraysize(data_reads
), NULL
, 0);
7984 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
7986 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7988 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7989 session
->http_server_properties();
7990 // Port must be < 1024, or the header will be ignored (since initial port was
7991 // port 80 (another restricted port).
7992 http_server_properties
->SetAlternateProtocol(
7993 HostPortPair::FromURL(request
.url
),
7994 666 /* port is ignored by MockConnect anyway */,
7995 AlternateProtocolFromNextProto(GetParam()));
7997 scoped_ptr
<HttpTransaction
> trans(
7998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7999 TestCompletionCallback callback
;
8001 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8002 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8003 EXPECT_EQ(OK
, callback
.WaitForResult());
8005 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8006 ASSERT_TRUE(response
!= NULL
);
8007 ASSERT_TRUE(response
->headers
.get() != NULL
);
8008 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8010 std::string response_data
;
8011 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8012 EXPECT_EQ("hello world", response_data
);
8014 ASSERT_TRUE(http_server_properties
->HasAlternateProtocol(
8015 HostPortPair::FromURL(request
.url
)));
8016 const PortAlternateProtocolPair alternate
=
8017 http_server_properties
->GetAlternateProtocol(
8018 HostPortPair::FromURL(request
.url
));
8019 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN
, alternate
.protocol
);
8022 TEST_P(HttpNetworkTransactionTest
,
8023 AlternateProtocolPortRestrictedBlocked
) {
8024 // Ensure that we're not allowed to redirect traffic via an alternate
8025 // protocol to an unrestricted (port >= 1024) when the original traffic was
8026 // on a restricted port (port < 1024). Ensure that we can redirect in all
8028 HttpStreamFactory::set_use_alternate_protocols(true);
8030 HttpRequestInfo restricted_port_request
;
8031 restricted_port_request
.method
= "GET";
8032 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8033 restricted_port_request
.load_flags
= 0;
8035 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8036 StaticSocketDataProvider first_data
;
8037 first_data
.set_connect_data(mock_connect
);
8038 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8040 MockRead data_reads
[] = {
8041 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8042 MockRead("hello world"),
8043 MockRead(ASYNC
, OK
),
8045 StaticSocketDataProvider
second_data(
8046 data_reads
, arraysize(data_reads
), NULL
, 0);
8047 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8049 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8051 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8052 session
->http_server_properties();
8053 const int kUnrestrictedAlternatePort
= 1024;
8054 http_server_properties
->SetAlternateProtocol(
8055 HostPortPair::FromURL(restricted_port_request
.url
),
8056 kUnrestrictedAlternatePort
,
8057 AlternateProtocolFromNextProto(GetParam()));
8059 scoped_ptr
<HttpTransaction
> trans(
8060 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8061 TestCompletionCallback callback
;
8063 int rv
= trans
->Start(
8064 &restricted_port_request
,
8065 callback
.callback(), BoundNetLog());
8066 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8067 // Invalid change to unrestricted port should fail.
8068 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8071 TEST_P(HttpNetworkTransactionTest
,
8072 AlternateProtocolPortRestrictedPermitted
) {
8073 // Ensure that we're allowed to redirect traffic via an alternate
8074 // protocol to an unrestricted (port >= 1024) when the original traffic was
8075 // on a restricted port (port < 1024) if we set
8076 // enable_user_alternate_protocol_ports.
8078 HttpStreamFactory::set_use_alternate_protocols(true);
8079 session_deps_
.enable_user_alternate_protocol_ports
= true;
8081 HttpRequestInfo restricted_port_request
;
8082 restricted_port_request
.method
= "GET";
8083 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8084 restricted_port_request
.load_flags
= 0;
8086 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8087 StaticSocketDataProvider first_data
;
8088 first_data
.set_connect_data(mock_connect
);
8089 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8091 MockRead data_reads
[] = {
8092 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8093 MockRead("hello world"),
8094 MockRead(ASYNC
, OK
),
8096 StaticSocketDataProvider
second_data(
8097 data_reads
, arraysize(data_reads
), NULL
, 0);
8098 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8100 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8102 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8103 session
->http_server_properties();
8104 const int kUnrestrictedAlternatePort
= 1024;
8105 http_server_properties
->SetAlternateProtocol(
8106 HostPortPair::FromURL(restricted_port_request
.url
),
8107 kUnrestrictedAlternatePort
,
8108 AlternateProtocolFromNextProto(GetParam()));
8110 scoped_ptr
<HttpTransaction
> trans(
8111 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8112 TestCompletionCallback callback
;
8114 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
8115 &restricted_port_request
,
8116 callback
.callback(), BoundNetLog()));
8117 // Change to unrestricted port should succeed.
8118 EXPECT_EQ(OK
, callback
.WaitForResult());
8121 TEST_P(HttpNetworkTransactionTest
,
8122 AlternateProtocolPortRestrictedAllowed
) {
8123 // Ensure that we're not allowed to redirect traffic via an alternate
8124 // protocol to an unrestricted (port >= 1024) when the original traffic was
8125 // on a restricted port (port < 1024). Ensure that we can redirect in all
8127 HttpStreamFactory::set_use_alternate_protocols(true);
8129 HttpRequestInfo restricted_port_request
;
8130 restricted_port_request
.method
= "GET";
8131 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8132 restricted_port_request
.load_flags
= 0;
8134 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8135 StaticSocketDataProvider first_data
;
8136 first_data
.set_connect_data(mock_connect
);
8137 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8139 MockRead data_reads
[] = {
8140 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8141 MockRead("hello world"),
8142 MockRead(ASYNC
, OK
),
8144 StaticSocketDataProvider
second_data(
8145 data_reads
, arraysize(data_reads
), NULL
, 0);
8146 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8148 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8150 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8151 session
->http_server_properties();
8152 const int kRestrictedAlternatePort
= 80;
8153 http_server_properties
->SetAlternateProtocol(
8154 HostPortPair::FromURL(restricted_port_request
.url
),
8155 kRestrictedAlternatePort
,
8156 AlternateProtocolFromNextProto(GetParam()));
8158 scoped_ptr
<HttpTransaction
> trans(
8159 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8160 TestCompletionCallback callback
;
8162 int rv
= trans
->Start(
8163 &restricted_port_request
,
8164 callback
.callback(), BoundNetLog());
8165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8166 // Valid change to restricted port should pass.
8167 EXPECT_EQ(OK
, callback
.WaitForResult());
8170 TEST_P(HttpNetworkTransactionTest
,
8171 AlternateProtocolPortUnrestrictedAllowed1
) {
8172 // Ensure that we're not allowed to redirect traffic via an alternate
8173 // protocol to an unrestricted (port >= 1024) when the original traffic was
8174 // on a restricted port (port < 1024). Ensure that we can redirect in all
8176 HttpStreamFactory::set_use_alternate_protocols(true);
8178 HttpRequestInfo unrestricted_port_request
;
8179 unrestricted_port_request
.method
= "GET";
8180 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8181 unrestricted_port_request
.load_flags
= 0;
8183 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8184 StaticSocketDataProvider first_data
;
8185 first_data
.set_connect_data(mock_connect
);
8186 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8188 MockRead data_reads
[] = {
8189 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8190 MockRead("hello world"),
8191 MockRead(ASYNC
, OK
),
8193 StaticSocketDataProvider
second_data(
8194 data_reads
, arraysize(data_reads
), NULL
, 0);
8195 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8197 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8199 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8200 session
->http_server_properties();
8201 const int kRestrictedAlternatePort
= 80;
8202 http_server_properties
->SetAlternateProtocol(
8203 HostPortPair::FromURL(unrestricted_port_request
.url
),
8204 kRestrictedAlternatePort
,
8205 AlternateProtocolFromNextProto(GetParam()));
8207 scoped_ptr
<HttpTransaction
> trans(
8208 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8209 TestCompletionCallback callback
;
8211 int rv
= trans
->Start(
8212 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8213 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8214 // Valid change to restricted port should pass.
8215 EXPECT_EQ(OK
, callback
.WaitForResult());
8218 TEST_P(HttpNetworkTransactionTest
,
8219 AlternateProtocolPortUnrestrictedAllowed2
) {
8220 // Ensure that we're not allowed to redirect traffic via an alternate
8221 // protocol to an unrestricted (port >= 1024) when the original traffic was
8222 // on a restricted port (port < 1024). Ensure that we can redirect in all
8224 HttpStreamFactory::set_use_alternate_protocols(true);
8226 HttpRequestInfo unrestricted_port_request
;
8227 unrestricted_port_request
.method
= "GET";
8228 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8229 unrestricted_port_request
.load_flags
= 0;
8231 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8232 StaticSocketDataProvider first_data
;
8233 first_data
.set_connect_data(mock_connect
);
8234 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8236 MockRead data_reads
[] = {
8237 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8238 MockRead("hello world"),
8239 MockRead(ASYNC
, OK
),
8241 StaticSocketDataProvider
second_data(
8242 data_reads
, arraysize(data_reads
), NULL
, 0);
8243 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8245 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8247 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8248 session
->http_server_properties();
8249 const int kUnrestrictedAlternatePort
= 1024;
8250 http_server_properties
->SetAlternateProtocol(
8251 HostPortPair::FromURL(unrestricted_port_request
.url
),
8252 kUnrestrictedAlternatePort
,
8253 AlternateProtocolFromNextProto(GetParam()));
8255 scoped_ptr
<HttpTransaction
> trans(
8256 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8257 TestCompletionCallback callback
;
8259 int rv
= trans
->Start(
8260 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8261 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8262 // Valid change to an unrestricted port should pass.
8263 EXPECT_EQ(OK
, callback
.WaitForResult());
8266 TEST_P(HttpNetworkTransactionTest
,
8267 AlternateProtocolUnsafeBlocked
) {
8268 // Ensure that we're not allowed to redirect traffic via an alternate
8269 // protocol to an unsafe port, and that we resume the second
8270 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8271 HttpStreamFactory::set_use_alternate_protocols(true);
8273 HttpRequestInfo request
;
8274 request
.method
= "GET";
8275 request
.url
= GURL("http://www.google.com/");
8276 request
.load_flags
= 0;
8278 // The alternate protocol request will error out before we attempt to connect,
8279 // so only the standard HTTP request will try to connect.
8280 MockRead data_reads
[] = {
8281 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8282 MockRead("hello world"),
8283 MockRead(ASYNC
, OK
),
8285 StaticSocketDataProvider
data(
8286 data_reads
, arraysize(data_reads
), NULL
, 0);
8287 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8289 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8291 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8292 session
->http_server_properties();
8293 const int kUnsafePort
= 7;
8294 http_server_properties
->SetAlternateProtocol(
8295 HostPortPair::FromURL(request
.url
),
8297 AlternateProtocolFromNextProto(GetParam()));
8299 scoped_ptr
<HttpTransaction
> trans(
8300 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8301 TestCompletionCallback callback
;
8303 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8304 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8305 // The HTTP request should succeed.
8306 EXPECT_EQ(OK
, callback
.WaitForResult());
8308 // Disable alternate protocol before the asserts.
8309 HttpStreamFactory::set_use_alternate_protocols(false);
8311 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8312 ASSERT_TRUE(response
!= NULL
);
8313 ASSERT_TRUE(response
->headers
.get() != NULL
);
8314 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8316 std::string response_data
;
8317 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8318 EXPECT_EQ("hello world", response_data
);
8321 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
8322 HttpStreamFactory::set_use_alternate_protocols(true);
8323 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8325 HttpRequestInfo request
;
8326 request
.method
= "GET";
8327 request
.url
= GURL("http://www.google.com/");
8328 request
.load_flags
= 0;
8330 std::string alternate_protocol_http_header
=
8331 GetAlternateProtocolHttpHeader();
8333 MockRead data_reads
[] = {
8334 MockRead("HTTP/1.1 200 OK\r\n"),
8335 MockRead(alternate_protocol_http_header
.c_str()),
8336 MockRead("hello world"),
8337 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8341 StaticSocketDataProvider
first_transaction(
8342 data_reads
, arraysize(data_reads
), NULL
, 0);
8343 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8345 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8346 ssl
.SetNextProto(GetParam());
8347 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8349 scoped_ptr
<SpdyFrame
> req(
8350 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8351 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
8353 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8354 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8355 MockRead spdy_reads
[] = {
8356 CreateMockRead(*resp
),
8357 CreateMockRead(*data
),
8358 MockRead(ASYNC
, 0, 0),
8361 DelayedSocketData
spdy_data(
8362 1, // wait for one write to finish before reading.
8363 spdy_reads
, arraysize(spdy_reads
),
8364 spdy_writes
, arraysize(spdy_writes
));
8365 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8367 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8368 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
8370 hanging_non_alternate_protocol_socket
.set_connect_data(
8371 never_finishing_connect
);
8372 session_deps_
.socket_factory
->AddSocketDataProvider(
8373 &hanging_non_alternate_protocol_socket
);
8375 TestCompletionCallback callback
;
8377 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8378 scoped_ptr
<HttpTransaction
> trans(
8379 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8381 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8382 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8383 EXPECT_EQ(OK
, callback
.WaitForResult());
8385 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8386 ASSERT_TRUE(response
!= NULL
);
8387 ASSERT_TRUE(response
->headers
.get() != NULL
);
8388 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8390 std::string response_data
;
8391 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8392 EXPECT_EQ("hello world", response_data
);
8394 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8396 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8397 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8398 EXPECT_EQ(OK
, callback
.WaitForResult());
8400 response
= trans
->GetResponseInfo();
8401 ASSERT_TRUE(response
!= NULL
);
8402 ASSERT_TRUE(response
->headers
.get() != NULL
);
8403 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8404 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8405 EXPECT_TRUE(response
->was_npn_negotiated
);
8407 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8408 EXPECT_EQ("hello!", response_data
);
8411 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
8412 HttpStreamFactory::set_use_alternate_protocols(true);
8413 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8415 HttpRequestInfo request
;
8416 request
.method
= "GET";
8417 request
.url
= GURL("http://www.google.com/");
8418 request
.load_flags
= 0;
8420 std::string alternate_protocol_http_header
=
8421 GetAlternateProtocolHttpHeader();
8423 MockRead data_reads
[] = {
8424 MockRead("HTTP/1.1 200 OK\r\n"),
8425 MockRead(alternate_protocol_http_header
.c_str()),
8426 MockRead("hello world"),
8427 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8428 MockRead(ASYNC
, OK
),
8431 StaticSocketDataProvider
first_transaction(
8432 data_reads
, arraysize(data_reads
), NULL
, 0);
8433 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8434 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8436 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8437 StaticSocketDataProvider
hanging_socket(
8439 hanging_socket
.set_connect_data(never_finishing_connect
);
8440 // Socket 2 and 3 are the hanging Alternate-Protocol and
8441 // non-Alternate-Protocol jobs from the 2nd transaction.
8442 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8443 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8445 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8446 ssl
.SetNextProto(GetParam());
8447 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8449 scoped_ptr
<SpdyFrame
> req1(
8450 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8451 scoped_ptr
<SpdyFrame
> req2(
8452 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
8453 MockWrite spdy_writes
[] = {
8454 CreateMockWrite(*req1
),
8455 CreateMockWrite(*req2
),
8457 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8458 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8459 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
8460 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
8461 MockRead spdy_reads
[] = {
8462 CreateMockRead(*resp1
),
8463 CreateMockRead(*data1
),
8464 CreateMockRead(*resp2
),
8465 CreateMockRead(*data2
),
8466 MockRead(ASYNC
, 0, 0),
8469 DelayedSocketData
spdy_data(
8470 2, // wait for writes to finish before reading.
8471 spdy_reads
, arraysize(spdy_reads
),
8472 spdy_writes
, arraysize(spdy_writes
));
8473 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8474 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8476 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8477 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8479 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8480 TestCompletionCallback callback1
;
8481 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
8483 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
8484 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8485 EXPECT_EQ(OK
, callback1
.WaitForResult());
8487 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
8488 ASSERT_TRUE(response
!= NULL
);
8489 ASSERT_TRUE(response
->headers
.get() != NULL
);
8490 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8492 std::string response_data
;
8493 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
8494 EXPECT_EQ("hello world", response_data
);
8496 TestCompletionCallback callback2
;
8497 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
8498 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
8499 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8501 TestCompletionCallback callback3
;
8502 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
8503 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
8504 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8506 EXPECT_EQ(OK
, callback2
.WaitForResult());
8507 EXPECT_EQ(OK
, callback3
.WaitForResult());
8509 response
= trans2
.GetResponseInfo();
8510 ASSERT_TRUE(response
!= NULL
);
8511 ASSERT_TRUE(response
->headers
.get() != NULL
);
8512 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8513 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8514 EXPECT_TRUE(response
->was_npn_negotiated
);
8515 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
8516 EXPECT_EQ("hello!", response_data
);
8518 response
= trans3
.GetResponseInfo();
8519 ASSERT_TRUE(response
!= NULL
);
8520 ASSERT_TRUE(response
->headers
.get() != NULL
);
8521 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8522 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8523 EXPECT_TRUE(response
->was_npn_negotiated
);
8524 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
8525 EXPECT_EQ("hello!", response_data
);
8528 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
8529 HttpStreamFactory::set_use_alternate_protocols(true);
8530 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8532 HttpRequestInfo request
;
8533 request
.method
= "GET";
8534 request
.url
= GURL("http://www.google.com/");
8535 request
.load_flags
= 0;
8537 std::string alternate_protocol_http_header
=
8538 GetAlternateProtocolHttpHeader();
8540 MockRead data_reads
[] = {
8541 MockRead("HTTP/1.1 200 OK\r\n"),
8542 MockRead(alternate_protocol_http_header
.c_str()),
8543 MockRead("hello world"),
8544 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8545 MockRead(ASYNC
, OK
),
8548 StaticSocketDataProvider
first_transaction(
8549 data_reads
, arraysize(data_reads
), NULL
, 0);
8550 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8552 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8553 ssl
.SetNextProto(GetParam());
8554 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8556 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8557 StaticSocketDataProvider
hanging_alternate_protocol_socket(
8559 hanging_alternate_protocol_socket
.set_connect_data(
8560 never_finishing_connect
);
8561 session_deps_
.socket_factory
->AddSocketDataProvider(
8562 &hanging_alternate_protocol_socket
);
8564 // 2nd request is just a copy of the first one, over HTTP again.
8565 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8567 TestCompletionCallback callback
;
8569 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8570 scoped_ptr
<HttpTransaction
> trans(
8571 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8573 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8574 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8575 EXPECT_EQ(OK
, callback
.WaitForResult());
8577 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8578 ASSERT_TRUE(response
!= NULL
);
8579 ASSERT_TRUE(response
->headers
.get() != NULL
);
8580 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8582 std::string response_data
;
8583 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8584 EXPECT_EQ("hello world", response_data
);
8586 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8588 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8589 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8590 EXPECT_EQ(OK
, callback
.WaitForResult());
8592 response
= trans
->GetResponseInfo();
8593 ASSERT_TRUE(response
!= NULL
);
8594 ASSERT_TRUE(response
->headers
.get() != NULL
);
8595 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8596 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8597 EXPECT_FALSE(response
->was_npn_negotiated
);
8599 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8600 EXPECT_EQ("hello world", response_data
);
8603 class CapturingProxyResolver
: public ProxyResolver
{
8605 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8606 virtual ~CapturingProxyResolver() {}
8608 virtual int GetProxyForURL(const GURL
& url
,
8610 const CompletionCallback
& callback
,
8611 RequestHandle
* request
,
8612 const BoundNetLog
& net_log
) OVERRIDE
{
8613 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
8614 HostPortPair("myproxy", 80));
8615 results
->UseProxyServer(proxy_server
);
8616 resolved_
.push_back(url
);
8620 virtual void CancelRequest(RequestHandle request
) OVERRIDE
{
8624 virtual LoadState
GetLoadState(RequestHandle request
) const OVERRIDE
{
8626 return LOAD_STATE_IDLE
;
8629 virtual void CancelSetPacScript() OVERRIDE
{
8633 virtual int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
8634 const CompletionCallback
& /*callback*/) OVERRIDE
{
8638 const std::vector
<GURL
>& resolved() const { return resolved_
; }
8641 std::vector
<GURL
> resolved_
;
8643 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
8646 TEST_P(HttpNetworkTransactionTest
,
8647 UseAlternateProtocolForTunneledNpnSpdy
) {
8648 HttpStreamFactory::set_use_alternate_protocols(true);
8649 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8651 ProxyConfig proxy_config
;
8652 proxy_config
.set_auto_detect(true);
8653 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
8655 CapturingProxyResolver
* capturing_proxy_resolver
=
8656 new CapturingProxyResolver();
8657 session_deps_
.proxy_service
.reset(new ProxyService(
8658 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
8660 CapturingNetLog net_log
;
8661 session_deps_
.net_log
= &net_log
;
8663 HttpRequestInfo request
;
8664 request
.method
= "GET";
8665 request
.url
= GURL("http://www.google.com/");
8666 request
.load_flags
= 0;
8668 std::string alternate_protocol_http_header
=
8669 GetAlternateProtocolHttpHeader();
8671 MockRead data_reads
[] = {
8672 MockRead("HTTP/1.1 200 OK\r\n"),
8673 MockRead(alternate_protocol_http_header
.c_str()),
8674 MockRead("hello world"),
8675 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8676 MockRead(ASYNC
, OK
),
8679 StaticSocketDataProvider
first_transaction(
8680 data_reads
, arraysize(data_reads
), NULL
, 0);
8681 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8683 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8684 ssl
.SetNextProto(GetParam());
8685 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8687 scoped_ptr
<SpdyFrame
> req(
8688 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8689 MockWrite spdy_writes
[] = {
8690 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8691 "Host: www.google.com\r\n"
8692 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
8693 CreateMockWrite(*req
), // 3
8696 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
8698 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8699 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8700 MockRead spdy_reads
[] = {
8701 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
8702 CreateMockRead(*resp
.get(), 4), // 2, 4
8703 CreateMockRead(*data
.get(), 4), // 5
8704 MockRead(ASYNC
, 0, 0, 4), // 6
8707 OrderedSocketData
spdy_data(
8708 spdy_reads
, arraysize(spdy_reads
),
8709 spdy_writes
, arraysize(spdy_writes
));
8710 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8712 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8713 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
8715 hanging_non_alternate_protocol_socket
.set_connect_data(
8716 never_finishing_connect
);
8717 session_deps_
.socket_factory
->AddSocketDataProvider(
8718 &hanging_non_alternate_protocol_socket
);
8720 TestCompletionCallback callback
;
8722 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8723 scoped_ptr
<HttpTransaction
> trans(
8724 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8726 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8727 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8728 EXPECT_EQ(OK
, callback
.WaitForResult());
8730 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8731 ASSERT_TRUE(response
!= NULL
);
8732 ASSERT_TRUE(response
->headers
.get() != NULL
);
8733 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8734 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8735 EXPECT_FALSE(response
->was_npn_negotiated
);
8737 std::string response_data
;
8738 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8739 EXPECT_EQ("hello world", response_data
);
8741 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8743 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8744 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8745 EXPECT_EQ(OK
, callback
.WaitForResult());
8747 response
= trans
->GetResponseInfo();
8748 ASSERT_TRUE(response
!= NULL
);
8749 ASSERT_TRUE(response
->headers
.get() != NULL
);
8750 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8751 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8752 EXPECT_TRUE(response
->was_npn_negotiated
);
8754 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8755 EXPECT_EQ("hello!", response_data
);
8756 ASSERT_EQ(3u, capturing_proxy_resolver
->resolved().size());
8757 EXPECT_EQ("http://www.google.com/",
8758 capturing_proxy_resolver
->resolved()[0].spec());
8759 EXPECT_EQ("https://www.google.com/",
8760 capturing_proxy_resolver
->resolved()[1].spec());
8762 LoadTimingInfo load_timing_info
;
8763 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
8764 TestLoadTimingNotReusedWithPac(load_timing_info
,
8765 CONNECT_TIMING_HAS_SSL_TIMES
);
8768 TEST_P(HttpNetworkTransactionTest
,
8769 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
8770 HttpStreamFactory::set_use_alternate_protocols(true);
8771 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8773 HttpRequestInfo request
;
8774 request
.method
= "GET";
8775 request
.url
= GURL("http://www.google.com/");
8776 request
.load_flags
= 0;
8778 std::string alternate_protocol_http_header
=
8779 GetAlternateProtocolHttpHeader();
8781 MockRead data_reads
[] = {
8782 MockRead("HTTP/1.1 200 OK\r\n"),
8783 MockRead(alternate_protocol_http_header
.c_str()),
8784 MockRead("hello world"),
8785 MockRead(ASYNC
, OK
),
8788 StaticSocketDataProvider
first_transaction(
8789 data_reads
, arraysize(data_reads
), NULL
, 0);
8790 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8792 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8793 ssl
.SetNextProto(GetParam());
8794 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8796 scoped_ptr
<SpdyFrame
> req(
8797 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8798 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
8800 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8801 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8802 MockRead spdy_reads
[] = {
8803 CreateMockRead(*resp
),
8804 CreateMockRead(*data
),
8805 MockRead(ASYNC
, 0, 0),
8808 DelayedSocketData
spdy_data(
8809 1, // wait for one write to finish before reading.
8810 spdy_reads
, arraysize(spdy_reads
),
8811 spdy_writes
, arraysize(spdy_writes
));
8812 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8814 TestCompletionCallback callback
;
8816 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8818 scoped_ptr
<HttpTransaction
> trans(
8819 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8821 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8822 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8823 EXPECT_EQ(OK
, callback
.WaitForResult());
8825 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8826 ASSERT_TRUE(response
!= NULL
);
8827 ASSERT_TRUE(response
->headers
.get() != NULL
);
8828 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8830 std::string response_data
;
8831 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8832 EXPECT_EQ("hello world", response_data
);
8834 // Set up an initial SpdySession in the pool to reuse.
8835 HostPortPair
host_port_pair("www.google.com", 443);
8836 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
8837 kPrivacyModeDisabled
);
8838 base::WeakPtr
<SpdySession
> spdy_session
=
8839 CreateSecureSpdySession(session
, key
, BoundNetLog());
8841 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8843 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8844 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8845 EXPECT_EQ(OK
, callback
.WaitForResult());
8847 response
= trans
->GetResponseInfo();
8848 ASSERT_TRUE(response
!= NULL
);
8849 ASSERT_TRUE(response
->headers
.get() != NULL
);
8850 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8851 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8852 EXPECT_TRUE(response
->was_npn_negotiated
);
8854 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8855 EXPECT_EQ("hello!", response_data
);
8858 // GenerateAuthToken is a mighty big test.
8859 // It tests all permutation of GenerateAuthToken behavior:
8860 // - Synchronous and Asynchronous completion.
8861 // - OK or error on completion.
8862 // - Direct connection, non-authenticating proxy, and authenticating proxy.
8863 // - HTTP or HTTPS backend (to include proxy tunneling).
8864 // - Non-authenticating and authenticating backend.
8866 // In all, there are 44 reasonable permuations (for example, if there are
8867 // problems generating an auth token for an authenticating proxy, we don't
8868 // need to test all permutations of the backend server).
8870 // The test proceeds by going over each of the configuration cases, and
8871 // potentially running up to three rounds in each of the tests. The TestConfig
8872 // specifies both the configuration for the test as well as the expectations
8874 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
8875 static const char kServer
[] = "http://www.example.com";
8876 static const char kSecureServer
[] = "https://www.example.com";
8877 static const char kProxy
[] = "myproxy:70";
8878 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
8886 const MockWrite
kGet(
8887 "GET / HTTP/1.1\r\n"
8888 "Host: www.example.com\r\n"
8889 "Connection: keep-alive\r\n\r\n");
8890 const MockWrite
kGetProxy(
8891 "GET http://www.example.com/ HTTP/1.1\r\n"
8892 "Host: www.example.com\r\n"
8893 "Proxy-Connection: keep-alive\r\n\r\n");
8894 const MockWrite
kGetAuth(
8895 "GET / HTTP/1.1\r\n"
8896 "Host: www.example.com\r\n"
8897 "Connection: keep-alive\r\n"
8898 "Authorization: auth_token\r\n\r\n");
8899 const MockWrite
kGetProxyAuth(
8900 "GET http://www.example.com/ HTTP/1.1\r\n"
8901 "Host: www.example.com\r\n"
8902 "Proxy-Connection: keep-alive\r\n"
8903 "Proxy-Authorization: auth_token\r\n\r\n");
8904 const MockWrite
kGetAuthThroughProxy(
8905 "GET http://www.example.com/ HTTP/1.1\r\n"
8906 "Host: www.example.com\r\n"
8907 "Proxy-Connection: keep-alive\r\n"
8908 "Authorization: auth_token\r\n\r\n");
8909 const MockWrite
kGetAuthWithProxyAuth(
8910 "GET http://www.example.com/ HTTP/1.1\r\n"
8911 "Host: www.example.com\r\n"
8912 "Proxy-Connection: keep-alive\r\n"
8913 "Proxy-Authorization: auth_token\r\n"
8914 "Authorization: auth_token\r\n\r\n");
8915 const MockWrite
kConnect(
8916 "CONNECT www.example.com:443 HTTP/1.1\r\n"
8917 "Host: www.example.com\r\n"
8918 "Proxy-Connection: keep-alive\r\n\r\n");
8919 const MockWrite
kConnectProxyAuth(
8920 "CONNECT www.example.com:443 HTTP/1.1\r\n"
8921 "Host: www.example.com\r\n"
8922 "Proxy-Connection: keep-alive\r\n"
8923 "Proxy-Authorization: auth_token\r\n\r\n");
8925 const MockRead
kSuccess(
8926 "HTTP/1.1 200 OK\r\n"
8927 "Content-Type: text/html; charset=iso-8859-1\r\n"
8928 "Content-Length: 3\r\n\r\n"
8930 const MockRead
kFailure(
8931 "Should not be called.");
8932 const MockRead
kServerChallenge(
8933 "HTTP/1.1 401 Unauthorized\r\n"
8934 "WWW-Authenticate: Mock realm=server\r\n"
8935 "Content-Type: text/html; charset=iso-8859-1\r\n"
8936 "Content-Length: 14\r\n\r\n"
8937 "Unauthorized\r\n");
8938 const MockRead
kProxyChallenge(
8939 "HTTP/1.1 407 Unauthorized\r\n"
8940 "Proxy-Authenticate: Mock realm=proxy\r\n"
8941 "Proxy-Connection: close\r\n"
8942 "Content-Type: text/html; charset=iso-8859-1\r\n"
8943 "Content-Length: 14\r\n\r\n"
8944 "Unauthorized\r\n");
8945 const MockRead
kProxyConnected(
8946 "HTTP/1.1 200 Connection Established\r\n\r\n");
8948 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
8949 // no constructors, but the C++ compiler on Windows warns about
8950 // unspecified data in compound literals. So, moved to using constructors,
8951 // and TestRound's created with the default constructor should not be used.
8954 : expected_rv(ERR_UNEXPECTED
),
8958 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
8959 int expected_rv_arg
)
8962 expected_rv(expected_rv_arg
),
8966 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
8967 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
8968 const MockRead
* extra_read_arg
)
8971 expected_rv(expected_rv_arg
),
8972 extra_write(extra_write_arg
),
8973 extra_read(extra_read_arg
) {
8978 const MockWrite
* extra_write
;
8979 const MockRead
* extra_read
;
8982 static const int kNoSSL
= 500;
8985 const char* proxy_url
;
8986 AuthTiming proxy_auth_timing
;
8988 const char* server_url
;
8989 AuthTiming server_auth_timing
;
8991 int num_auth_rounds
;
8992 int first_ssl_round
;
8993 TestRound rounds
[3];
8994 } test_configs
[] = {
8995 // Non-authenticating HTTP server with a direct connection.
8996 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
8997 { TestRound(kGet
, kSuccess
, OK
)}},
8998 // Authenticating HTTP server with a direct connection.
8999 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9000 { TestRound(kGet
, kServerChallenge
, OK
),
9001 TestRound(kGetAuth
, kSuccess
, OK
)}},
9002 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9003 { TestRound(kGet
, kServerChallenge
, OK
),
9004 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9005 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9006 { TestRound(kGet
, kServerChallenge
, OK
),
9007 TestRound(kGetAuth
, kSuccess
, OK
)}},
9008 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9009 { TestRound(kGet
, kServerChallenge
, OK
),
9010 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9011 // Non-authenticating HTTP server through a non-authenticating proxy.
9012 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9013 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9014 // Authenticating HTTP server through a non-authenticating proxy.
9015 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9016 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9017 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9018 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9019 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9020 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9021 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9022 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9023 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9024 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9025 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9026 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9027 // Non-authenticating HTTP server through an authenticating proxy.
9028 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9029 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9030 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9031 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9032 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9033 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9034 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9035 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9036 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9037 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9038 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9039 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9040 // Authenticating HTTP server through an authenticating proxy.
9041 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9042 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9043 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9044 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9045 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9046 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9047 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9048 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9049 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9050 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9051 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9052 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9053 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9054 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9055 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9056 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9057 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9058 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9059 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9060 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9061 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9062 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9063 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9064 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9065 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9066 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9067 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9068 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9069 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9070 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9071 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9072 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9073 // Non-authenticating HTTPS server with a direct connection.
9074 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9075 { TestRound(kGet
, kSuccess
, OK
)}},
9076 // Authenticating HTTPS server with a direct connection.
9077 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9078 { TestRound(kGet
, kServerChallenge
, OK
),
9079 TestRound(kGetAuth
, kSuccess
, OK
)}},
9080 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9081 { TestRound(kGet
, kServerChallenge
, OK
),
9082 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9083 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9084 { TestRound(kGet
, kServerChallenge
, OK
),
9085 TestRound(kGetAuth
, kSuccess
, OK
)}},
9086 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9087 { TestRound(kGet
, kServerChallenge
, OK
),
9088 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9089 // Non-authenticating HTTPS server with a non-authenticating proxy.
9090 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9091 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9092 // Authenticating HTTPS server through a non-authenticating proxy.
9093 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9094 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9095 TestRound(kGetAuth
, kSuccess
, OK
)}},
9096 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9097 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9098 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9099 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9100 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9101 TestRound(kGetAuth
, kSuccess
, OK
)}},
9102 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9103 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9104 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9105 // Non-Authenticating HTTPS server through an authenticating proxy.
9106 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9107 { TestRound(kConnect
, kProxyChallenge
, OK
),
9108 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9109 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9110 { TestRound(kConnect
, kProxyChallenge
, OK
),
9111 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9112 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9113 { TestRound(kConnect
, kProxyChallenge
, OK
),
9114 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9115 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9116 { TestRound(kConnect
, kProxyChallenge
, OK
),
9117 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9118 // Authenticating HTTPS server through an authenticating proxy.
9119 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9120 { TestRound(kConnect
, kProxyChallenge
, OK
),
9121 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9122 &kGet
, &kServerChallenge
),
9123 TestRound(kGetAuth
, kSuccess
, OK
)}},
9124 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9125 { TestRound(kConnect
, kProxyChallenge
, OK
),
9126 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9127 &kGet
, &kServerChallenge
),
9128 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9129 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9130 { TestRound(kConnect
, kProxyChallenge
, OK
),
9131 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9132 &kGet
, &kServerChallenge
),
9133 TestRound(kGetAuth
, kSuccess
, OK
)}},
9134 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9135 { TestRound(kConnect
, kProxyChallenge
, OK
),
9136 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9137 &kGet
, &kServerChallenge
),
9138 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9139 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9140 { TestRound(kConnect
, kProxyChallenge
, OK
),
9141 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9142 &kGet
, &kServerChallenge
),
9143 TestRound(kGetAuth
, kSuccess
, OK
)}},
9144 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9145 { TestRound(kConnect
, kProxyChallenge
, OK
),
9146 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9147 &kGet
, &kServerChallenge
),
9148 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9149 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9150 { TestRound(kConnect
, kProxyChallenge
, OK
),
9151 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9152 &kGet
, &kServerChallenge
),
9153 TestRound(kGetAuth
, kSuccess
, OK
)}},
9154 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9155 { TestRound(kConnect
, kProxyChallenge
, OK
),
9156 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9157 &kGet
, &kServerChallenge
),
9158 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9161 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_configs
); ++i
) {
9162 HttpAuthHandlerMock::Factory
* auth_factory(
9163 new HttpAuthHandlerMock::Factory());
9164 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9165 const TestConfig
& test_config
= test_configs
[i
];
9167 // Set up authentication handlers as necessary.
9168 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
9169 for (int n
= 0; n
< 2; n
++) {
9170 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9171 std::string auth_challenge
= "Mock realm=proxy";
9172 GURL
origin(test_config
.proxy_url
);
9173 HttpAuth::ChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9174 auth_challenge
.end());
9175 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
9176 origin
, BoundNetLog());
9177 auth_handler
->SetGenerateExpectation(
9178 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
9179 test_config
.proxy_auth_rv
);
9180 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9183 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
9184 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9185 std::string auth_challenge
= "Mock realm=server";
9186 GURL
origin(test_config
.server_url
);
9187 HttpAuth::ChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9188 auth_challenge
.end());
9189 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9190 origin
, BoundNetLog());
9191 auth_handler
->SetGenerateExpectation(
9192 test_config
.server_auth_timing
== AUTH_ASYNC
,
9193 test_config
.server_auth_rv
);
9194 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9196 if (test_config
.proxy_url
) {
9197 session_deps_
.proxy_service
.reset(
9198 ProxyService::CreateFixed(test_config
.proxy_url
));
9200 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9203 HttpRequestInfo request
;
9204 request
.method
= "GET";
9205 request
.url
= GURL(test_config
.server_url
);
9206 request
.load_flags
= 0;
9208 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9209 HttpNetworkTransaction
trans(
9210 DEFAULT_PRIORITY
, CreateSession(&session_deps_
));
9212 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
9213 const TestRound
& read_write_round
= test_config
.rounds
[round
];
9215 // Set up expected reads and writes.
9217 reads
[0] = read_write_round
.read
;
9218 size_t length_reads
= 1;
9219 if (read_write_round
.extra_read
) {
9220 reads
[1] = *read_write_round
.extra_read
;
9224 MockWrite writes
[2];
9225 writes
[0] = read_write_round
.write
;
9226 size_t length_writes
= 1;
9227 if (read_write_round
.extra_write
) {
9228 writes
[1] = *read_write_round
.extra_write
;
9231 StaticSocketDataProvider
data_provider(
9232 reads
, length_reads
, writes
, length_writes
);
9233 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9235 // Add an SSL sequence if necessary.
9236 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
9237 if (round
>= test_config
.first_ssl_round
)
9238 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
9239 &ssl_socket_data_provider
);
9241 // Start or restart the transaction.
9242 TestCompletionCallback callback
;
9245 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
9247 rv
= trans
.RestartWithAuth(
9248 AuthCredentials(kFoo
, kBar
), callback
.callback());
9250 if (rv
== ERR_IO_PENDING
)
9251 rv
= callback
.WaitForResult();
9253 // Compare results with expected data.
9254 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
9255 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
9256 if (read_write_round
.expected_rv
== OK
) {
9257 ASSERT_TRUE(response
!= NULL
);
9259 EXPECT_TRUE(response
== NULL
);
9260 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
9263 if (round
+ 1 < test_config
.num_auth_rounds
) {
9264 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9266 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9272 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
9273 // Do multi-round authentication and make sure it works correctly.
9274 HttpAuthHandlerMock::Factory
* auth_factory(
9275 new HttpAuthHandlerMock::Factory());
9276 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9277 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9278 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
9279 session_deps_
.host_resolver
->set_synchronous_mode(true);
9281 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9282 auth_handler
->set_connection_based(true);
9283 std::string auth_challenge
= "Mock realm=server";
9284 GURL
origin("http://www.example.com");
9285 HttpAuth::ChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9286 auth_challenge
.end());
9287 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9288 origin
, BoundNetLog());
9289 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9292 const HttpResponseInfo
* response
= NULL
;
9293 HttpRequestInfo request
;
9294 request
.method
= "GET";
9295 request
.url
= origin
;
9296 request
.load_flags
= 0;
9298 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9300 // Use a TCP Socket Pool with only one connection per group. This is used
9301 // to validate that the TCP socket is not released to the pool between
9302 // each round of multi-round authentication.
9303 HttpNetworkSessionPeer
session_peer(session
);
9304 ClientSocketPoolHistograms
transport_pool_histograms("SmallTCP");
9305 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
9306 50, // Max sockets for pool
9307 1, // Max sockets per group
9308 &transport_pool_histograms
,
9309 session_deps_
.host_resolver
.get(),
9310 session_deps_
.socket_factory
.get(),
9311 session_deps_
.net_log
);
9312 MockClientSocketPoolManager
* mock_pool_manager
=
9313 new MockClientSocketPoolManager
;
9314 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
9315 session_peer
.SetClientSocketPoolManager(mock_pool_manager
);
9317 scoped_ptr
<HttpTransaction
> trans(
9318 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9319 TestCompletionCallback callback
;
9321 const MockWrite
kGet(
9322 "GET / HTTP/1.1\r\n"
9323 "Host: www.example.com\r\n"
9324 "Connection: keep-alive\r\n\r\n");
9325 const MockWrite
kGetAuth(
9326 "GET / HTTP/1.1\r\n"
9327 "Host: www.example.com\r\n"
9328 "Connection: keep-alive\r\n"
9329 "Authorization: auth_token\r\n\r\n");
9331 const MockRead
kServerChallenge(
9332 "HTTP/1.1 401 Unauthorized\r\n"
9333 "WWW-Authenticate: Mock realm=server\r\n"
9334 "Content-Type: text/html; charset=iso-8859-1\r\n"
9335 "Content-Length: 14\r\n\r\n"
9336 "Unauthorized\r\n");
9337 const MockRead
kSuccess(
9338 "HTTP/1.1 200 OK\r\n"
9339 "Content-Type: text/html; charset=iso-8859-1\r\n"
9340 "Content-Length: 3\r\n\r\n"
9343 MockWrite writes
[] = {
9352 // Competing request
9355 MockRead reads
[] = {
9364 // Competing response
9367 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
9368 writes
, arraysize(writes
));
9369 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9371 const char* const kSocketGroup
= "www.example.com:80";
9373 // First round of authentication.
9374 auth_handler
->SetGenerateExpectation(false, OK
);
9375 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9376 if (rv
== ERR_IO_PENDING
)
9377 rv
= callback
.WaitForResult();
9379 response
= trans
->GetResponseInfo();
9380 ASSERT_TRUE(response
!= NULL
);
9381 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9382 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9384 // In between rounds, another request comes in for the same domain.
9385 // It should not be able to grab the TCP socket that trans has already
9387 scoped_ptr
<HttpTransaction
> trans_compete(
9388 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9389 TestCompletionCallback callback_compete
;
9390 rv
= trans_compete
->Start(
9391 &request
, callback_compete
.callback(), BoundNetLog());
9392 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9393 // callback_compete.WaitForResult at this point would stall forever,
9394 // since the HttpNetworkTransaction does not release the request back to
9395 // the pool until after authentication completes.
9397 // Second round of authentication.
9398 auth_handler
->SetGenerateExpectation(false, OK
);
9399 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
9400 if (rv
== ERR_IO_PENDING
)
9401 rv
= callback
.WaitForResult();
9403 response
= trans
->GetResponseInfo();
9404 ASSERT_TRUE(response
!= NULL
);
9405 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9406 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9408 // Third round of authentication.
9409 auth_handler
->SetGenerateExpectation(false, OK
);
9410 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9411 if (rv
== ERR_IO_PENDING
)
9412 rv
= callback
.WaitForResult();
9414 response
= trans
->GetResponseInfo();
9415 ASSERT_TRUE(response
!= NULL
);
9416 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9417 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9419 // Fourth round of authentication, which completes successfully.
9420 auth_handler
->SetGenerateExpectation(false, OK
);
9421 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9422 if (rv
== ERR_IO_PENDING
)
9423 rv
= callback
.WaitForResult();
9425 response
= trans
->GetResponseInfo();
9426 ASSERT_TRUE(response
!= NULL
);
9427 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9428 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9430 // Read the body since the fourth round was successful. This will also
9431 // release the socket back to the pool.
9432 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
9433 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9434 if (rv
== ERR_IO_PENDING
)
9435 rv
= callback
.WaitForResult();
9437 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9439 // There are still 0 idle sockets, since the trans_compete transaction
9440 // will be handed it immediately after trans releases it to the group.
9441 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9443 // The competing request can now finish. Wait for the headers and then
9445 rv
= callback_compete
.WaitForResult();
9447 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9448 if (rv
== ERR_IO_PENDING
)
9449 rv
= callback
.WaitForResult();
9451 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9454 // Finally, the socket is released to the group.
9455 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9458 // This tests the case that a request is issued via http instead of spdy after
9459 // npn is negotiated.
9460 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
9461 HttpStreamFactory::set_use_alternate_protocols(true);
9462 std::vector
<NextProto
> next_protos
;
9463 next_protos
.push_back(kProtoHTTP11
);
9464 HttpStreamFactory::SetNextProtos(next_protos
);
9465 HttpRequestInfo request
;
9466 request
.method
= "GET";
9467 request
.url
= GURL("https://www.google.com/");
9468 request
.load_flags
= 0;
9470 MockWrite data_writes
[] = {
9471 MockWrite("GET / HTTP/1.1\r\n"
9472 "Host: www.google.com\r\n"
9473 "Connection: keep-alive\r\n\r\n"),
9476 std::string alternate_protocol_http_header
=
9477 GetAlternateProtocolHttpHeader();
9479 MockRead data_reads
[] = {
9480 MockRead("HTTP/1.1 200 OK\r\n"),
9481 MockRead(alternate_protocol_http_header
.c_str()),
9482 MockRead("hello world"),
9483 MockRead(SYNCHRONOUS
, OK
),
9486 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9487 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
9488 ssl
.next_proto
= "http/1.1";
9489 ssl
.protocol_negotiated
= kProtoHTTP11
;
9491 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9493 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
9494 data_writes
, arraysize(data_writes
));
9495 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9497 TestCompletionCallback callback
;
9499 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9500 scoped_ptr
<HttpTransaction
> trans(
9501 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9503 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9505 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9506 EXPECT_EQ(OK
, callback
.WaitForResult());
9508 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9509 ASSERT_TRUE(response
!= NULL
);
9510 ASSERT_TRUE(response
->headers
.get() != NULL
);
9511 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9513 std::string response_data
;
9514 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9515 EXPECT_EQ("hello world", response_data
);
9517 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9518 EXPECT_TRUE(response
->was_npn_negotiated
);
9521 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
9522 // Simulate the SSL handshake completing with an NPN negotiation
9523 // followed by an immediate server closing of the socket.
9524 // Fix crash: http://crbug.com/46369
9525 HttpStreamFactory::set_use_alternate_protocols(true);
9526 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9528 HttpRequestInfo request
;
9529 request
.method
= "GET";
9530 request
.url
= GURL("https://www.google.com/");
9531 request
.load_flags
= 0;
9533 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9534 ssl
.SetNextProto(GetParam());
9535 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9537 scoped_ptr
<SpdyFrame
> req(
9538 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9539 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9541 MockRead spdy_reads
[] = {
9542 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
9545 DelayedSocketData
spdy_data(
9546 0, // don't wait in this case, immediate hangup.
9547 spdy_reads
, arraysize(spdy_reads
),
9548 spdy_writes
, arraysize(spdy_writes
));
9549 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9551 TestCompletionCallback callback
;
9553 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9554 scoped_ptr
<HttpTransaction
> trans(
9555 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9557 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9558 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9559 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
9562 // A subclass of HttpAuthHandlerMock that records the request URL when
9563 // it gets it. This is needed since the auth handler may get destroyed
9564 // before we get a chance to query it.
9565 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
9567 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
9569 virtual ~UrlRecordingHttpAuthHandlerMock() {}
9572 virtual int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
9573 const HttpRequestInfo
* request
,
9574 const CompletionCallback
& callback
,
9575 std::string
* auth_token
) OVERRIDE
{
9576 *url_
= request
->url
;
9577 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9578 credentials
, request
, callback
, auth_token
);
9585 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
9586 // This test ensures that the URL passed into the proxy is upgraded
9587 // to https when doing an Alternate Protocol upgrade.
9588 HttpStreamFactory::set_use_alternate_protocols(true);
9589 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9591 session_deps_
.proxy_service
.reset(
9592 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9593 CapturingNetLog net_log
;
9594 session_deps_
.net_log
= &net_log
;
9597 HttpAuthHandlerMock::Factory
* auth_factory
=
9598 new HttpAuthHandlerMock::Factory();
9599 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
9600 new UrlRecordingHttpAuthHandlerMock(&request_url
);
9601 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9602 auth_factory
->set_do_init_from_challenge(true);
9603 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9606 HttpRequestInfo request
;
9607 request
.method
= "GET";
9608 request
.url
= GURL("http://www.google.com");
9609 request
.load_flags
= 0;
9611 // First round goes unauthenticated through the proxy.
9612 MockWrite data_writes_1
[] = {
9613 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9614 "Host: www.google.com\r\n"
9615 "Proxy-Connection: keep-alive\r\n"
9618 MockRead data_reads_1
[] = {
9619 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9620 MockRead("HTTP/1.1 200 OK\r\n"
9621 "Alternate-Protocol: 443:npn-spdy/2\r\n"
9622 "Proxy-Connection: close\r\n"
9625 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
9626 data_writes_1
, arraysize(data_writes_1
));
9628 // Second round tries to tunnel to www.google.com due to the
9629 // Alternate-Protocol announcement in the first round. It fails due
9630 // to a proxy authentication challenge.
9631 // After the failure, a tunnel is established to www.google.com using
9632 // Proxy-Authorization headers. There is then a SPDY request round.
9634 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
9635 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
9636 // does a Disconnect and Connect on the same socket, rather than trying
9637 // to obtain a new one.
9639 // NOTE: Originally, the proxy response to the second CONNECT request
9640 // simply returned another 407 so the unit test could skip the SSL connection
9641 // establishment and SPDY framing issues. Alas, the
9642 // retry-http-when-alternate-protocol fails logic kicks in, which was more
9643 // complicated to set up expectations for than the SPDY session.
9645 scoped_ptr
<SpdyFrame
> req(
9646 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9647 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9648 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9650 MockWrite data_writes_2
[] = {
9651 // First connection attempt without Proxy-Authorization.
9652 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9653 "Host: www.google.com\r\n"
9654 "Proxy-Connection: keep-alive\r\n"
9657 // Second connection attempt with Proxy-Authorization.
9658 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9659 "Host: www.google.com\r\n"
9660 "Proxy-Connection: keep-alive\r\n"
9661 "Proxy-Authorization: auth_token\r\n"
9665 CreateMockWrite(*req
),
9667 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
9668 "Proxy-Authenticate: Mock\r\n"
9669 "Proxy-Connection: close\r\n"
9671 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9672 MockRead data_reads_2
[] = {
9673 // First connection attempt fails
9674 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
9675 MockRead(ASYNC
, kRejectConnectResponse
,
9676 arraysize(kRejectConnectResponse
) - 1, 1),
9678 // Second connection attempt passes
9679 MockRead(ASYNC
, kAcceptConnectResponse
,
9680 arraysize(kAcceptConnectResponse
) -1, 4),
9683 CreateMockRead(*resp
.get(), 6),
9684 CreateMockRead(*data
.get(), 6),
9685 MockRead(ASYNC
, 0, 0, 6),
9687 OrderedSocketData
data_2(
9688 data_reads_2
, arraysize(data_reads_2
),
9689 data_writes_2
, arraysize(data_writes_2
));
9691 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9692 ssl
.SetNextProto(GetParam());
9694 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9695 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9697 hanging_non_alternate_protocol_socket
.set_connect_data(
9698 never_finishing_connect
);
9700 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
9701 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
9702 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9703 session_deps_
.socket_factory
->AddSocketDataProvider(
9704 &hanging_non_alternate_protocol_socket
);
9705 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9707 // First round should work and provide the Alternate-Protocol state.
9708 TestCompletionCallback callback_1
;
9709 scoped_ptr
<HttpTransaction
> trans_1(
9710 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9711 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
9712 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9713 EXPECT_EQ(OK
, callback_1
.WaitForResult());
9715 // Second round should attempt a tunnel connect and get an auth challenge.
9716 TestCompletionCallback callback_2
;
9717 scoped_ptr
<HttpTransaction
> trans_2(
9718 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9719 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
9720 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9721 EXPECT_EQ(OK
, callback_2
.WaitForResult());
9722 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
9723 ASSERT_TRUE(response
!= NULL
);
9724 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
9726 // Restart with auth. Tunnel should work and response received.
9727 TestCompletionCallback callback_3
;
9728 rv
= trans_2
->RestartWithAuth(
9729 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
9730 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9731 EXPECT_EQ(OK
, callback_3
.WaitForResult());
9733 // After all that work, these two lines (or actually, just the scheme) are
9734 // what this test is all about. Make sure it happens correctly.
9735 EXPECT_EQ("https", request_url
.scheme());
9736 EXPECT_EQ("www.google.com", request_url
.host());
9738 LoadTimingInfo load_timing_info
;
9739 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
9740 TestLoadTimingNotReusedWithPac(load_timing_info
,
9741 CONNECT_TIMING_HAS_SSL_TIMES
);
9744 // Test that if we cancel the transaction as the connection is completing, that
9745 // everything tears down correctly.
9746 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
9747 // Setup everything about the connection to complete synchronously, so that
9748 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
9749 // for is the callback from the HttpStreamRequest.
9750 // Then cancel the transaction.
9751 // Verify that we don't crash.
9752 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
9753 MockRead data_reads
[] = {
9754 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
9755 MockRead(SYNCHRONOUS
, "hello world"),
9756 MockRead(SYNCHRONOUS
, OK
),
9759 HttpRequestInfo request
;
9760 request
.method
= "GET";
9761 request
.url
= GURL("http://www.google.com/");
9762 request
.load_flags
= 0;
9764 session_deps_
.host_resolver
->set_synchronous_mode(true);
9765 scoped_ptr
<HttpTransaction
> trans(
9766 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
9767 CreateSession(&session_deps_
)));
9769 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9770 data
.set_connect_data(mock_connect
);
9771 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9773 TestCompletionCallback callback
;
9775 CapturingBoundNetLog log
;
9776 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
9777 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9778 trans
.reset(); // Cancel the transaction here.
9780 base::MessageLoop::current()->RunUntilIdle();
9783 // Test a basic GET request through a proxy.
9784 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
9785 session_deps_
.proxy_service
.reset(
9786 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9787 CapturingBoundNetLog log
;
9788 session_deps_
.net_log
= log
.bound().net_log();
9789 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9791 HttpRequestInfo request
;
9792 request
.method
= "GET";
9793 request
.url
= GURL("http://www.google.com/");
9795 MockWrite data_writes1
[] = {
9796 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9797 "Host: www.google.com\r\n"
9798 "Proxy-Connection: keep-alive\r\n\r\n"),
9801 MockRead data_reads1
[] = {
9802 MockRead("HTTP/1.1 200 OK\r\n"),
9803 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9804 MockRead("Content-Length: 100\r\n\r\n"),
9805 MockRead(SYNCHRONOUS
, OK
),
9808 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
9809 data_writes1
, arraysize(data_writes1
));
9810 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
9812 TestCompletionCallback callback1
;
9814 scoped_ptr
<HttpTransaction
> trans(
9815 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9817 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
9818 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9820 rv
= callback1
.WaitForResult();
9823 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9824 ASSERT_TRUE(response
!= NULL
);
9826 EXPECT_TRUE(response
->headers
->IsKeepAlive());
9827 EXPECT_EQ(200, response
->headers
->response_code());
9828 EXPECT_EQ(100, response
->headers
->GetContentLength());
9829 EXPECT_TRUE(response
->was_fetched_via_proxy
);
9830 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
9832 LoadTimingInfo load_timing_info
;
9833 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9834 TestLoadTimingNotReusedWithPac(load_timing_info
,
9835 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
9838 // Test a basic HTTPS GET request through a proxy.
9839 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
9840 session_deps_
.proxy_service
.reset(
9841 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9842 CapturingBoundNetLog log
;
9843 session_deps_
.net_log
= log
.bound().net_log();
9844 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9846 HttpRequestInfo request
;
9847 request
.method
= "GET";
9848 request
.url
= GURL("https://www.google.com/");
9850 // Since we have proxy, should try to establish tunnel.
9851 MockWrite data_writes1
[] = {
9852 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9853 "Host: www.google.com\r\n"
9854 "Proxy-Connection: keep-alive\r\n\r\n"),
9856 MockWrite("GET / HTTP/1.1\r\n"
9857 "Host: www.google.com\r\n"
9858 "Connection: keep-alive\r\n\r\n"),
9861 MockRead data_reads1
[] = {
9862 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
9864 MockRead("HTTP/1.1 200 OK\r\n"),
9865 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9866 MockRead("Content-Length: 100\r\n\r\n"),
9867 MockRead(SYNCHRONOUS
, OK
),
9870 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
9871 data_writes1
, arraysize(data_writes1
));
9872 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
9873 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9874 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9876 TestCompletionCallback callback1
;
9878 scoped_ptr
<HttpTransaction
> trans(
9879 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9881 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
9882 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9884 rv
= callback1
.WaitForResult();
9886 net::CapturingNetLog::CapturedEntryList entries
;
9887 log
.GetEntries(&entries
);
9888 size_t pos
= ExpectLogContainsSomewhere(
9889 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
9890 NetLog::PHASE_NONE
);
9891 ExpectLogContainsSomewhere(
9893 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
9894 NetLog::PHASE_NONE
);
9896 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9897 ASSERT_TRUE(response
!= NULL
);
9899 EXPECT_TRUE(response
->headers
->IsKeepAlive());
9900 EXPECT_EQ(200, response
->headers
->response_code());
9901 EXPECT_EQ(100, response
->headers
->GetContentLength());
9902 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
9903 EXPECT_TRUE(response
->was_fetched_via_proxy
);
9905 LoadTimingInfo load_timing_info
;
9906 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9907 TestLoadTimingNotReusedWithPac(load_timing_info
,
9908 CONNECT_TIMING_HAS_SSL_TIMES
);
9911 // Test a basic HTTPS GET request through a proxy, but the server hangs up
9912 // while establishing the tunnel.
9913 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
9914 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
9915 CapturingBoundNetLog log
;
9916 session_deps_
.net_log
= log
.bound().net_log();
9917 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9919 HttpRequestInfo request
;
9920 request
.method
= "GET";
9921 request
.url
= GURL("https://www.google.com/");
9923 // Since we have proxy, should try to establish tunnel.
9924 MockWrite data_writes1
[] = {
9925 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9926 "Host: www.google.com\r\n"
9927 "Proxy-Connection: keep-alive\r\n\r\n"),
9929 MockWrite("GET / HTTP/1.1\r\n"
9930 "Host: www.google.com\r\n"
9931 "Connection: keep-alive\r\n\r\n"),
9934 MockRead data_reads1
[] = {
9935 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9936 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
9937 MockRead(ASYNC
, 0, 0), // EOF
9940 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
9941 data_writes1
, arraysize(data_writes1
));
9942 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
9943 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9944 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9946 TestCompletionCallback callback1
;
9948 scoped_ptr
<HttpTransaction
> trans(
9949 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9951 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
9952 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9954 rv
= callback1
.WaitForResult();
9955 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
9956 net::CapturingNetLog::CapturedEntryList entries
;
9957 log
.GetEntries(&entries
);
9958 size_t pos
= ExpectLogContainsSomewhere(
9959 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
9960 NetLog::PHASE_NONE
);
9961 ExpectLogContainsSomewhere(
9963 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
9964 NetLog::PHASE_NONE
);
9967 // Test for crbug.com/55424.
9968 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
9969 scoped_ptr
<SpdyFrame
> req(
9970 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
9971 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9973 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9974 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9975 MockRead spdy_reads
[] = {
9976 CreateMockRead(*resp
),
9977 CreateMockRead(*data
),
9978 MockRead(ASYNC
, 0, 0),
9981 DelayedSocketData
spdy_data(
9982 1, // wait for one write to finish before reading.
9983 spdy_reads
, arraysize(spdy_reads
),
9984 spdy_writes
, arraysize(spdy_writes
));
9985 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9987 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9988 ssl
.SetNextProto(GetParam());
9989 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9991 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9993 // Set up an initial SpdySession in the pool to reuse.
9994 HostPortPair
host_port_pair("www.google.com", 443);
9995 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9996 kPrivacyModeDisabled
);
9997 base::WeakPtr
<SpdySession
> spdy_session
=
9998 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10000 HttpRequestInfo request
;
10001 request
.method
= "GET";
10002 request
.url
= GURL("https://www.google.com/");
10003 request
.load_flags
= 0;
10005 // This is the important line that marks this as a preconnect.
10006 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10008 scoped_ptr
<HttpTransaction
> trans(
10009 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10011 TestCompletionCallback callback
;
10012 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10013 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10014 EXPECT_EQ(OK
, callback
.WaitForResult());
10017 // Given a net error, cause that error to be returned from the first Write()
10018 // call and verify that the HttpTransaction fails with that error.
10019 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10020 int error
, IoMode mode
) {
10021 net::HttpRequestInfo request_info
;
10022 request_info
.url
= GURL("https://www.example.com/");
10023 request_info
.method
= "GET";
10024 request_info
.load_flags
= net::LOAD_NORMAL
;
10026 SSLSocketDataProvider
ssl_data(mode
, OK
);
10027 net::MockWrite data_writes
[] = {
10028 net::MockWrite(mode
, error
),
10030 net::StaticSocketDataProvider
data(NULL
, 0,
10031 data_writes
, arraysize(data_writes
));
10032 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10033 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10035 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10036 scoped_ptr
<HttpTransaction
> trans(
10037 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10039 TestCompletionCallback callback
;
10040 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10041 if (rv
== net::ERR_IO_PENDING
)
10042 rv
= callback
.WaitForResult();
10043 ASSERT_EQ(error
, rv
);
10046 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
10047 // Just check a grab bag of cert errors.
10048 static const int kErrors
[] = {
10049 ERR_CERT_COMMON_NAME_INVALID
,
10050 ERR_CERT_AUTHORITY_INVALID
,
10051 ERR_CERT_DATE_INVALID
,
10053 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
10054 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
10055 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
10059 // Ensure that a client certificate is removed from the SSL client auth
10061 // 1) No proxy is involved.
10062 // 2) TLS False Start is disabled.
10063 // 3) The initial TLS handshake requests a client certificate.
10064 // 4) The client supplies an invalid/unacceptable certificate.
10065 TEST_P(HttpNetworkTransactionTest
,
10066 ClientAuthCertCache_Direct_NoFalseStart
) {
10067 net::HttpRequestInfo request_info
;
10068 request_info
.url
= GURL("https://www.example.com/");
10069 request_info
.method
= "GET";
10070 request_info
.load_flags
= net::LOAD_NORMAL
;
10072 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10073 cert_request
->host_and_port
= "www.example.com:443";
10075 // [ssl_]data1 contains the data for the first SSL handshake. When a
10076 // CertificateRequest is received for the first time, the handshake will
10077 // be aborted to allow the caller to provide a certificate.
10078 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10079 ssl_data1
.cert_request_info
= cert_request
.get();
10080 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10081 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10082 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10084 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10085 // False Start is not being used, the result of the SSL handshake will be
10086 // returned as part of the SSLClientSocket::Connect() call. This test
10087 // matches the result of a server sending a handshake_failure alert,
10088 // rather than a Finished message, because it requires a client
10089 // certificate and none was supplied.
10090 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10091 ssl_data2
.cert_request_info
= cert_request
.get();
10092 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10093 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10094 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10096 // [ssl_]data3 contains the data for the third SSL handshake. When a
10097 // connection to a server fails during an SSL handshake,
10098 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10099 // connection was attempted with TLSv1.1. This is transparent to the caller
10100 // of the HttpNetworkTransaction. Because this test failure is due to
10101 // requiring a client certificate, this fallback handshake should also
10103 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10104 ssl_data3
.cert_request_info
= cert_request
.get();
10105 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10106 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10107 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10109 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10110 // connection to a server fails during an SSL handshake,
10111 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10112 // connection was attempted with TLSv1. This is transparent to the caller
10113 // of the HttpNetworkTransaction. Because this test failure is due to
10114 // requiring a client certificate, this fallback handshake should also
10116 SSLSocketDataProvider
ssl_data4(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10117 ssl_data4
.cert_request_info
= cert_request
.get();
10118 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10119 net::StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
10120 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10122 // Need one more if TLSv1.2 is enabled.
10123 SSLSocketDataProvider
ssl_data5(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10124 ssl_data5
.cert_request_info
= cert_request
.get();
10125 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10126 net::StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
10127 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10129 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10130 scoped_ptr
<HttpTransaction
> trans(
10131 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10133 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10134 TestCompletionCallback callback
;
10135 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10136 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10138 // Complete the SSL handshake, which should abort due to requiring a
10139 // client certificate.
10140 rv
= callback
.WaitForResult();
10141 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10143 // Indicate that no certificate should be supplied. From the perspective
10144 // of SSLClientCertCache, NULL is just as meaningful as a real
10145 // certificate, so this is the same as supply a
10146 // legitimate-but-unacceptable certificate.
10147 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10148 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10150 // Ensure the certificate was added to the client auth cache before
10151 // allowing the connection to continue restarting.
10152 scoped_refptr
<X509Certificate
> client_cert
;
10153 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup("www.example.com:443",
10155 ASSERT_EQ(NULL
, client_cert
.get());
10157 // Restart the handshake. This will consume ssl_data2, which fails, and
10158 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10159 // The result code is checked against what ssl_data4 should return.
10160 rv
= callback
.WaitForResult();
10161 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10163 // Ensure that the client certificate is removed from the cache on a
10164 // handshake failure.
10165 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup("www.example.com:443",
10169 // Ensure that a client certificate is removed from the SSL client auth
10171 // 1) No proxy is involved.
10172 // 2) TLS False Start is enabled.
10173 // 3) The initial TLS handshake requests a client certificate.
10174 // 4) The client supplies an invalid/unacceptable certificate.
10175 TEST_P(HttpNetworkTransactionTest
,
10176 ClientAuthCertCache_Direct_FalseStart
) {
10177 net::HttpRequestInfo request_info
;
10178 request_info
.url
= GURL("https://www.example.com/");
10179 request_info
.method
= "GET";
10180 request_info
.load_flags
= net::LOAD_NORMAL
;
10182 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10183 cert_request
->host_and_port
= "www.example.com:443";
10185 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10186 // return successfully after reading up to the peer's Certificate message.
10187 // This is to allow the caller to call SSLClientSocket::Write(), which can
10188 // enqueue application data to be sent in the same packet as the
10189 // ChangeCipherSpec and Finished messages.
10190 // The actual handshake will be finished when SSLClientSocket::Read() is
10191 // called, which expects to process the peer's ChangeCipherSpec and
10192 // Finished messages. If there was an error negotiating with the peer,
10193 // such as due to the peer requiring a client certificate when none was
10194 // supplied, the alert sent by the peer won't be processed until Read() is
10197 // Like the non-False Start case, when a client certificate is requested by
10198 // the peer, the handshake is aborted during the Connect() call.
10199 // [ssl_]data1 represents the initial SSL handshake with the peer.
10200 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10201 ssl_data1
.cert_request_info
= cert_request
.get();
10202 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10203 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10204 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10206 // When a client certificate is supplied, Connect() will not be aborted
10207 // when the peer requests the certificate. Instead, the handshake will
10208 // artificially succeed, allowing the caller to write the HTTP request to
10209 // the socket. The handshake messages are not processed until Read() is
10210 // called, which then detects that the handshake was aborted, due to the
10211 // peer sending a handshake_failure because it requires a client
10213 SSLSocketDataProvider
ssl_data2(ASYNC
, net::OK
);
10214 ssl_data2
.cert_request_info
= cert_request
.get();
10215 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10216 net::MockRead data2_reads
[] = {
10217 net::MockRead(ASYNC
/* async */, net::ERR_SSL_PROTOCOL_ERROR
),
10219 net::StaticSocketDataProvider
data2(
10220 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10221 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10223 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10224 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10225 // TLSv1. It has the same behaviour as [ssl_]data2.
10226 SSLSocketDataProvider
ssl_data3(ASYNC
, net::OK
);
10227 ssl_data3
.cert_request_info
= cert_request
.get();
10228 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10229 net::StaticSocketDataProvider
data3(
10230 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10231 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10233 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10234 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10235 SSLSocketDataProvider
ssl_data4(ASYNC
, net::OK
);
10236 ssl_data4
.cert_request_info
= cert_request
.get();
10237 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10238 net::StaticSocketDataProvider
data4(
10239 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10240 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10242 // Need one more if TLSv1.2 is enabled.
10243 SSLSocketDataProvider
ssl_data5(ASYNC
, net::OK
);
10244 ssl_data5
.cert_request_info
= cert_request
.get();
10245 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10246 net::StaticSocketDataProvider
data5(
10247 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10248 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10250 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10251 scoped_ptr
<HttpTransaction
> trans(
10252 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10254 // Begin the initial SSL handshake.
10255 TestCompletionCallback callback
;
10256 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10257 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10259 // Complete the SSL handshake, which should abort due to requiring a
10260 // client certificate.
10261 rv
= callback
.WaitForResult();
10262 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10264 // Indicate that no certificate should be supplied. From the perspective
10265 // of SSLClientCertCache, NULL is just as meaningful as a real
10266 // certificate, so this is the same as supply a
10267 // legitimate-but-unacceptable certificate.
10268 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10269 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10271 // Ensure the certificate was added to the client auth cache before
10272 // allowing the connection to continue restarting.
10273 scoped_refptr
<X509Certificate
> client_cert
;
10274 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup("www.example.com:443",
10276 ASSERT_EQ(NULL
, client_cert
.get());
10278 // Restart the handshake. This will consume ssl_data2, which fails, and
10279 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10280 // The result code is checked against what ssl_data4 should return.
10281 rv
= callback
.WaitForResult();
10282 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10284 // Ensure that the client certificate is removed from the cache on a
10285 // handshake failure.
10286 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup("www.example.com:443",
10290 // Ensure that a client certificate is removed from the SSL client auth
10292 // 1) An HTTPS proxy is involved.
10293 // 3) The HTTPS proxy requests a client certificate.
10294 // 4) The client supplies an invalid/unacceptable certificate for the
10296 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10297 // then for connecting to an HTTP endpoint.
10298 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
10299 session_deps_
.proxy_service
.reset(
10300 ProxyService::CreateFixed("https://proxy:70"));
10301 CapturingBoundNetLog log
;
10302 session_deps_
.net_log
= log
.bound().net_log();
10304 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10305 cert_request
->host_and_port
= "proxy:70";
10307 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10308 // [ssl_]data[1-3]. Rather than represending the endpoint
10309 // (www.example.com:443), they represent failures with the HTTPS proxy
10311 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10312 ssl_data1
.cert_request_info
= cert_request
.get();
10313 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10314 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10315 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10317 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10318 ssl_data2
.cert_request_info
= cert_request
.get();
10319 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10320 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10321 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10323 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10325 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10326 ssl_data3
.cert_request_info
= cert_request
.get();
10327 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10328 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10329 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10332 net::HttpRequestInfo requests
[2];
10333 requests
[0].url
= GURL("https://www.example.com/");
10334 requests
[0].method
= "GET";
10335 requests
[0].load_flags
= net::LOAD_NORMAL
;
10337 requests
[1].url
= GURL("http://www.example.com/");
10338 requests
[1].method
= "GET";
10339 requests
[1].load_flags
= net::LOAD_NORMAL
;
10341 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
10342 session_deps_
.socket_factory
->ResetNextMockIndexes();
10343 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10344 scoped_ptr
<HttpNetworkTransaction
> trans(
10345 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10347 // Begin the SSL handshake with the proxy.
10348 TestCompletionCallback callback
;
10349 int rv
= trans
->Start(
10350 &requests
[i
], callback
.callback(), net::BoundNetLog());
10351 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10353 // Complete the SSL handshake, which should abort due to requiring a
10354 // client certificate.
10355 rv
= callback
.WaitForResult();
10356 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10358 // Indicate that no certificate should be supplied. From the perspective
10359 // of SSLClientCertCache, NULL is just as meaningful as a real
10360 // certificate, so this is the same as supply a
10361 // legitimate-but-unacceptable certificate.
10362 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10363 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10365 // Ensure the certificate was added to the client auth cache before
10366 // allowing the connection to continue restarting.
10367 scoped_refptr
<X509Certificate
> client_cert
;
10368 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup("proxy:70",
10370 ASSERT_EQ(NULL
, client_cert
.get());
10371 // Ensure the certificate was NOT cached for the endpoint. This only
10372 // applies to HTTPS requests, but is fine to check for HTTP requests.
10373 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup("www.example.com:443",
10376 // Restart the handshake. This will consume ssl_data2, which fails, and
10377 // then consume ssl_data3, which should also fail. The result code is
10378 // checked against what ssl_data3 should return.
10379 rv
= callback
.WaitForResult();
10380 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED
, rv
);
10382 // Now that the new handshake has failed, ensure that the client
10383 // certificate was removed from the client auth cache.
10384 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup("proxy:70",
10386 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup("www.example.com:443",
10391 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10392 // TEST_P is a macro that expands directly to code that stringizes the
10393 // arguments. As a result, macros passed as parameters (such as prefix
10394 // or test_case_name) will not be expanded by the preprocessor. To
10395 // work around this, indirect the macro for TEST_P, so that the
10396 // pre-processor will expand macros such as MAYBE_test_name before
10397 // instantiating the test.
10398 #define WRAPPED_TEST_P(test_case_name, test_name) \
10399 TEST_P(test_case_name, test_name)
10401 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10402 #if defined(OS_WIN)
10403 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10405 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10407 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
10408 HttpStreamFactory::set_use_alternate_protocols(true);
10409 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10411 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10412 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10413 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10414 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10415 pool_peer
.DisableDomainAuthenticationVerification();
10417 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10418 ssl
.SetNextProto(GetParam());
10419 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10421 scoped_ptr
<SpdyFrame
> host1_req(
10422 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10423 scoped_ptr
<SpdyFrame
> host2_req(
10424 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10425 MockWrite spdy_writes
[] = {
10426 CreateMockWrite(*host1_req
, 1),
10427 CreateMockWrite(*host2_req
, 4),
10429 scoped_ptr
<SpdyFrame
> host1_resp(
10430 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10431 scoped_ptr
<SpdyFrame
> host1_resp_body(
10432 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10433 scoped_ptr
<SpdyFrame
> host2_resp(
10434 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10435 scoped_ptr
<SpdyFrame
> host2_resp_body(
10436 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10437 MockRead spdy_reads
[] = {
10438 CreateMockRead(*host1_resp
, 2),
10439 CreateMockRead(*host1_resp_body
, 3),
10440 CreateMockRead(*host2_resp
, 5),
10441 CreateMockRead(*host2_resp_body
, 6),
10442 MockRead(ASYNC
, 0, 7),
10445 IPAddressNumber ip
;
10446 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
10447 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
10448 MockConnect
connect(ASYNC
, OK
, peer_addr
);
10449 OrderedSocketData
spdy_data(
10451 spdy_reads
, arraysize(spdy_reads
),
10452 spdy_writes
, arraysize(spdy_writes
));
10453 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10455 TestCompletionCallback callback
;
10456 HttpRequestInfo request1
;
10457 request1
.method
= "GET";
10458 request1
.url
= GURL("https://www.google.com/");
10459 request1
.load_flags
= 0;
10460 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
10462 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
10463 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10464 EXPECT_EQ(OK
, callback
.WaitForResult());
10466 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
10467 ASSERT_TRUE(response
!= NULL
);
10468 ASSERT_TRUE(response
->headers
.get() != NULL
);
10469 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10471 std::string response_data
;
10472 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
10473 EXPECT_EQ("hello!", response_data
);
10475 // Preload www.gmail.com into HostCache.
10476 HostPortPair
host_port("www.gmail.com", 443);
10477 HostResolver::RequestInfo
resolve_info(host_port
);
10478 AddressList ignored
;
10479 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
, &ignored
,
10480 callback
.callback(), NULL
,
10482 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10483 rv
= callback
.WaitForResult();
10486 HttpRequestInfo request2
;
10487 request2
.method
= "GET";
10488 request2
.url
= GURL("https://www.gmail.com/");
10489 request2
.load_flags
= 0;
10490 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
10492 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
10493 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10494 EXPECT_EQ(OK
, callback
.WaitForResult());
10496 response
= trans2
.GetResponseInfo();
10497 ASSERT_TRUE(response
!= NULL
);
10498 ASSERT_TRUE(response
->headers
.get() != NULL
);
10499 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10500 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10501 EXPECT_TRUE(response
->was_npn_negotiated
);
10502 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
10503 EXPECT_EQ("hello!", response_data
);
10505 #undef MAYBE_UseIPConnectionPooling
10507 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
10508 HttpStreamFactory::set_use_alternate_protocols(true);
10509 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10511 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10512 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10513 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10514 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10515 pool_peer
.DisableDomainAuthenticationVerification();
10517 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10518 ssl
.SetNextProto(GetParam());
10519 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10521 scoped_ptr
<SpdyFrame
> host1_req(
10522 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10523 scoped_ptr
<SpdyFrame
> host2_req(
10524 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10525 MockWrite spdy_writes
[] = {
10526 CreateMockWrite(*host1_req
, 1),
10527 CreateMockWrite(*host2_req
, 4),
10529 scoped_ptr
<SpdyFrame
> host1_resp(
10530 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10531 scoped_ptr
<SpdyFrame
> host1_resp_body(
10532 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10533 scoped_ptr
<SpdyFrame
> host2_resp(
10534 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10535 scoped_ptr
<SpdyFrame
> host2_resp_body(
10536 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10537 MockRead spdy_reads
[] = {
10538 CreateMockRead(*host1_resp
, 2),
10539 CreateMockRead(*host1_resp_body
, 3),
10540 CreateMockRead(*host2_resp
, 5),
10541 CreateMockRead(*host2_resp_body
, 6),
10542 MockRead(ASYNC
, 0, 7),
10545 IPAddressNumber ip
;
10546 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
10547 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
10548 MockConnect
connect(ASYNC
, OK
, peer_addr
);
10549 OrderedSocketData
spdy_data(
10551 spdy_reads
, arraysize(spdy_reads
),
10552 spdy_writes
, arraysize(spdy_writes
));
10553 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10555 TestCompletionCallback callback
;
10556 HttpRequestInfo request1
;
10557 request1
.method
= "GET";
10558 request1
.url
= GURL("https://www.google.com/");
10559 request1
.load_flags
= 0;
10560 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
10562 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
10563 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10564 EXPECT_EQ(OK
, callback
.WaitForResult());
10566 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
10567 ASSERT_TRUE(response
!= NULL
);
10568 ASSERT_TRUE(response
->headers
.get() != NULL
);
10569 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10571 std::string response_data
;
10572 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
10573 EXPECT_EQ("hello!", response_data
);
10575 HttpRequestInfo request2
;
10576 request2
.method
= "GET";
10577 request2
.url
= GURL("https://www.gmail.com/");
10578 request2
.load_flags
= 0;
10579 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
10581 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
10582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10583 EXPECT_EQ(OK
, callback
.WaitForResult());
10585 response
= trans2
.GetResponseInfo();
10586 ASSERT_TRUE(response
!= NULL
);
10587 ASSERT_TRUE(response
->headers
.get() != NULL
);
10588 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10589 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10590 EXPECT_TRUE(response
->was_npn_negotiated
);
10591 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
10592 EXPECT_EQ("hello!", response_data
);
10595 class OneTimeCachingHostResolver
: public net::HostResolver
{
10597 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
10598 : host_port_(host_port
) {}
10599 virtual ~OneTimeCachingHostResolver() {}
10601 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
10603 // HostResolver methods:
10604 virtual int Resolve(const RequestInfo
& info
,
10605 AddressList
* addresses
,
10606 const CompletionCallback
& callback
,
10607 RequestHandle
* out_req
,
10608 const BoundNetLog
& net_log
) OVERRIDE
{
10609 return host_resolver_
.Resolve(
10610 info
, addresses
, callback
, out_req
, net_log
);
10613 virtual int ResolveFromCache(const RequestInfo
& info
,
10614 AddressList
* addresses
,
10615 const BoundNetLog
& net_log
) OVERRIDE
{
10616 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
10617 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
10618 host_resolver_
.GetHostCache()->clear();
10622 virtual void CancelRequest(RequestHandle req
) OVERRIDE
{
10623 host_resolver_
.CancelRequest(req
);
10626 MockCachingHostResolver
* GetMockHostResolver() {
10627 return &host_resolver_
;
10631 MockCachingHostResolver host_resolver_
;
10632 const HostPortPair host_port_
;
10635 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10636 #if defined(OS_WIN)
10637 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10638 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
10640 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10641 UseIPConnectionPoolingWithHostCacheExpiration
10643 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
10644 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
10645 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
10646 // prefix doesn't work with parametrized tests).
10647 #if defined(OS_WIN)
10651 HttpStreamFactory::set_use_alternate_protocols(true);
10652 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10654 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
10655 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
10656 HttpNetworkSession::Params params
=
10657 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
10658 params
.host_resolver
= &host_resolver
;
10659 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10660 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10661 pool_peer
.DisableDomainAuthenticationVerification();
10663 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10664 ssl
.SetNextProto(GetParam());
10665 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10667 scoped_ptr
<SpdyFrame
> host1_req(
10668 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10669 scoped_ptr
<SpdyFrame
> host2_req(
10670 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10671 MockWrite spdy_writes
[] = {
10672 CreateMockWrite(*host1_req
, 1),
10673 CreateMockWrite(*host2_req
, 4),
10675 scoped_ptr
<SpdyFrame
> host1_resp(
10676 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10677 scoped_ptr
<SpdyFrame
> host1_resp_body(
10678 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10679 scoped_ptr
<SpdyFrame
> host2_resp(
10680 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10681 scoped_ptr
<SpdyFrame
> host2_resp_body(
10682 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10683 MockRead spdy_reads
[] = {
10684 CreateMockRead(*host1_resp
, 2),
10685 CreateMockRead(*host1_resp_body
, 3),
10686 CreateMockRead(*host2_resp
, 5),
10687 CreateMockRead(*host2_resp_body
, 6),
10688 MockRead(ASYNC
, 0, 7),
10691 IPAddressNumber ip
;
10692 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
10693 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
10694 MockConnect
connect(ASYNC
, OK
, peer_addr
);
10695 OrderedSocketData
spdy_data(
10697 spdy_reads
, arraysize(spdy_reads
),
10698 spdy_writes
, arraysize(spdy_writes
));
10699 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10701 TestCompletionCallback callback
;
10702 HttpRequestInfo request1
;
10703 request1
.method
= "GET";
10704 request1
.url
= GURL("https://www.google.com/");
10705 request1
.load_flags
= 0;
10706 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
10708 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
10709 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10710 EXPECT_EQ(OK
, callback
.WaitForResult());
10712 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
10713 ASSERT_TRUE(response
!= NULL
);
10714 ASSERT_TRUE(response
->headers
.get() != NULL
);
10715 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10717 std::string response_data
;
10718 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
10719 EXPECT_EQ("hello!", response_data
);
10721 // Preload cache entries into HostCache.
10722 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
10723 AddressList ignored
;
10724 rv
= host_resolver
.Resolve(resolve_info
, &ignored
, callback
.callback(),
10725 NULL
, BoundNetLog());
10726 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10727 rv
= callback
.WaitForResult();
10730 HttpRequestInfo request2
;
10731 request2
.method
= "GET";
10732 request2
.url
= GURL("https://www.gmail.com/");
10733 request2
.load_flags
= 0;
10734 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
10736 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
10737 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10738 EXPECT_EQ(OK
, callback
.WaitForResult());
10740 response
= trans2
.GetResponseInfo();
10741 ASSERT_TRUE(response
!= NULL
);
10742 ASSERT_TRUE(response
->headers
.get() != NULL
);
10743 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10744 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10745 EXPECT_TRUE(response
->was_npn_negotiated
);
10746 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
10747 EXPECT_EQ("hello!", response_data
);
10749 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
10751 TEST_P(HttpNetworkTransactionTest
, ReadPipelineEvictionFallback
) {
10752 MockRead data_reads1
[] = {
10753 MockRead(SYNCHRONOUS
, ERR_PIPELINE_EVICTION
),
10755 MockRead data_reads2
[] = {
10756 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10757 MockRead("hello world"),
10758 MockRead(SYNCHRONOUS
, OK
),
10760 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
), NULL
, 0);
10761 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
), NULL
, 0);
10762 StaticSocketDataProvider
* data
[] = { &data1
, &data2
};
10764 SimpleGetHelperResult out
= SimpleGetHelperForData(data
, arraysize(data
));
10766 EXPECT_EQ(OK
, out
.rv
);
10767 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
10768 EXPECT_EQ("hello world", out
.response_data
);
10771 TEST_P(HttpNetworkTransactionTest
, SendPipelineEvictionFallback
) {
10772 MockWrite data_writes1
[] = {
10773 MockWrite(SYNCHRONOUS
, ERR_PIPELINE_EVICTION
),
10775 MockWrite data_writes2
[] = {
10776 MockWrite("GET / HTTP/1.1\r\n"
10777 "Host: www.google.com\r\n"
10778 "Connection: keep-alive\r\n\r\n"),
10780 MockRead data_reads2
[] = {
10781 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10782 MockRead("hello world"),
10783 MockRead(SYNCHRONOUS
, OK
),
10785 StaticSocketDataProvider
data1(NULL
, 0,
10786 data_writes1
, arraysize(data_writes1
));
10787 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
10788 data_writes2
, arraysize(data_writes2
));
10789 StaticSocketDataProvider
* data
[] = { &data1
, &data2
};
10791 SimpleGetHelperResult out
= SimpleGetHelperForData(data
, arraysize(data
));
10793 EXPECT_EQ(OK
, out
.rv
);
10794 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
10795 EXPECT_EQ("hello world", out
.response_data
);
10798 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
10799 const std::string https_url
= "https://www.google.com/";
10800 const std::string http_url
= "http://www.google.com:443/";
10802 // SPDY GET for HTTPS URL
10803 scoped_ptr
<SpdyFrame
> req1(
10804 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
10806 MockWrite writes1
[] = {
10807 CreateMockWrite(*req1
, 0),
10810 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10811 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10812 MockRead reads1
[] = {
10813 CreateMockRead(*resp1
, 1),
10814 CreateMockRead(*body1
, 2),
10815 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
10818 DelayedSocketData
data1(
10819 1, reads1
, arraysize(reads1
),
10820 writes1
, arraysize(writes1
));
10821 MockConnect
connect_data1(ASYNC
, OK
);
10822 data1
.set_connect_data(connect_data1
);
10824 // HTTP GET for the HTTP URL
10825 MockWrite writes2
[] = {
10826 MockWrite(ASYNC
, 4,
10827 "GET / HTTP/1.1\r\n"
10828 "Host: www.google.com:443\r\n"
10829 "Connection: keep-alive\r\n\r\n"),
10832 MockRead reads2
[] = {
10833 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
10834 MockRead(ASYNC
, 6, "hello"),
10835 MockRead(ASYNC
, 7, OK
),
10838 DelayedSocketData
data2(
10839 1, reads2
, arraysize(reads2
),
10840 writes2
, arraysize(writes2
));
10842 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10843 ssl
.SetNextProto(GetParam());
10844 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10845 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10846 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10848 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10850 // Start the first transaction to set up the SpdySession
10851 HttpRequestInfo request1
;
10852 request1
.method
= "GET";
10853 request1
.url
= GURL(https_url
);
10854 request1
.load_flags
= 0;
10855 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
10856 TestCompletionCallback callback1
;
10857 EXPECT_EQ(ERR_IO_PENDING
,
10858 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
10859 base::MessageLoop::current()->RunUntilIdle();
10861 EXPECT_EQ(OK
, callback1
.WaitForResult());
10862 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
10864 // Now, start the HTTP request
10865 HttpRequestInfo request2
;
10866 request2
.method
= "GET";
10867 request2
.url
= GURL(http_url
);
10868 request2
.load_flags
= 0;
10869 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
10870 TestCompletionCallback callback2
;
10871 EXPECT_EQ(ERR_IO_PENDING
,
10872 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
10873 base::MessageLoop::current()->RunUntilIdle();
10875 EXPECT_EQ(OK
, callback2
.WaitForResult());
10876 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
10879 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
10880 const std::string https_url
= "https://www.google.com/";
10881 const std::string http_url
= "http://www.google.com:443/";
10883 // SPDY GET for HTTPS URL (through CONNECT tunnel)
10884 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1));
10885 scoped_ptr
<SpdyFrame
> req1(
10886 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
10888 // SPDY GET for HTTP URL (through the proxy, but not the tunnel)
10889 scoped_ptr
<SpdyFrame
> wrapped_req1(
10890 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
10891 const char* const headers
[] = {
10892 spdy_util_
.GetMethodKey(), "GET",
10893 spdy_util_
.GetPathKey(), spdy_util_
.is_spdy2() ? http_url
.c_str() : "/",
10894 spdy_util_
.GetHostKey(), "www.google.com:443",
10895 spdy_util_
.GetSchemeKey(), "http",
10896 spdy_util_
.GetVersionKey(), "HTTP/1.1"
10898 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyControlFrame(
10899 NULL
, 0, false, 3, MEDIUM
, SYN_STREAM
, CONTROL_FLAG_FIN
,
10900 headers
, arraysize(headers
), 0));
10902 MockWrite writes1
[] = {
10903 CreateMockWrite(*connect
, 0),
10904 CreateMockWrite(*wrapped_req1
, 2),
10905 CreateMockWrite(*req2
, 5),
10908 scoped_ptr
<SpdyFrame
> conn_resp(
10909 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10910 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10911 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10912 scoped_ptr
<SpdyFrame
> wrapped_resp1(
10913 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
10914 scoped_ptr
<SpdyFrame
> wrapped_body1(
10915 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
10916 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10917 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
10918 MockRead reads1
[] = {
10919 CreateMockRead(*conn_resp
, 1),
10920 CreateMockRead(*wrapped_resp1
, 3),
10921 CreateMockRead(*wrapped_body1
, 4),
10922 CreateMockRead(*resp2
, 6),
10923 CreateMockRead(*body2
, 7),
10924 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
10927 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
10928 writes1
, arraysize(writes1
));
10929 MockConnect
connect_data1(ASYNC
, OK
);
10930 data1
.set_connect_data(connect_data1
);
10932 session_deps_
.proxy_service
.reset(
10933 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
10934 CapturingNetLog log
;
10935 session_deps_
.net_log
= &log
;
10936 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
10937 ssl1
.SetNextProto(GetParam());
10938 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
10939 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
10940 ssl2
.SetNextProto(GetParam());
10941 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
10942 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
10944 scoped_refptr
<HttpNetworkSession
> session(
10945 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
10947 // Start the first transaction to set up the SpdySession
10948 HttpRequestInfo request1
;
10949 request1
.method
= "GET";
10950 request1
.url
= GURL(https_url
);
10951 request1
.load_flags
= 0;
10952 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
10953 TestCompletionCallback callback1
;
10954 EXPECT_EQ(ERR_IO_PENDING
,
10955 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
10956 base::MessageLoop::current()->RunUntilIdle();
10959 EXPECT_EQ(OK
, callback1
.WaitForResult());
10960 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
10962 LoadTimingInfo load_timing_info1
;
10963 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
10964 TestLoadTimingNotReusedWithPac(load_timing_info1
,
10965 CONNECT_TIMING_HAS_SSL_TIMES
);
10967 // Now, start the HTTP request
10968 HttpRequestInfo request2
;
10969 request2
.method
= "GET";
10970 request2
.url
= GURL(http_url
);
10971 request2
.load_flags
= 0;
10972 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
10973 TestCompletionCallback callback2
;
10974 EXPECT_EQ(ERR_IO_PENDING
,
10975 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
10976 base::MessageLoop::current()->RunUntilIdle();
10979 EXPECT_EQ(OK
, callback2
.WaitForResult());
10980 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
10982 LoadTimingInfo load_timing_info2
;
10983 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
10984 // The established SPDY sessions is considered reused by the HTTP request.
10985 TestLoadTimingReusedWithPac(load_timing_info2
);
10986 // HTTP requests over a SPDY session should have a different connection
10987 // socket_log_id than requests over a tunnel.
10988 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
10991 TEST_P(HttpNetworkTransactionTest
, UseSpdySessionForHttpWhenForced
) {
10992 HttpStreamFactory::set_force_spdy_always(true);
10993 const std::string https_url
= "https://www.google.com/";
10994 const std::string http_url
= "http://www.google.com:443/";
10996 // SPDY GET for HTTPS URL
10997 scoped_ptr
<SpdyFrame
> req1(
10998 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
10999 // SPDY GET for the HTTP URL
11000 scoped_ptr
<SpdyFrame
> req2(
11001 spdy_util_
.ConstructSpdyGet(http_url
.c_str(), false, 3, MEDIUM
));
11003 MockWrite writes
[] = {
11004 CreateMockWrite(*req1
, 1),
11005 CreateMockWrite(*req2
, 4),
11008 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11009 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11010 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11011 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11012 MockRead reads
[] = {
11013 CreateMockRead(*resp1
, 2),
11014 CreateMockRead(*body1
, 3),
11015 CreateMockRead(*resp2
, 5),
11016 CreateMockRead(*body2
, 6),
11017 MockRead(ASYNC
, ERR_IO_PENDING
, 7)
11020 OrderedSocketData
data(reads
, arraysize(reads
),
11021 writes
, arraysize(writes
));
11023 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11024 ssl
.SetNextProto(GetParam());
11025 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11026 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11028 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11030 // Start the first transaction to set up the SpdySession
11031 HttpRequestInfo request1
;
11032 request1
.method
= "GET";
11033 request1
.url
= GURL(https_url
);
11034 request1
.load_flags
= 0;
11035 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11036 TestCompletionCallback callback1
;
11037 EXPECT_EQ(ERR_IO_PENDING
,
11038 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11039 base::MessageLoop::current()->RunUntilIdle();
11041 EXPECT_EQ(OK
, callback1
.WaitForResult());
11042 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11044 // Now, start the HTTP request
11045 HttpRequestInfo request2
;
11046 request2
.method
= "GET";
11047 request2
.url
= GURL(http_url
);
11048 request2
.load_flags
= 0;
11049 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11050 TestCompletionCallback callback2
;
11051 EXPECT_EQ(ERR_IO_PENDING
,
11052 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11053 base::MessageLoop::current()->RunUntilIdle();
11055 EXPECT_EQ(OK
, callback2
.WaitForResult());
11056 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11059 // Test that in the case where we have a SPDY session to a SPDY proxy
11060 // that we do not pool other origins that resolve to the same IP when
11061 // the certificate does not match the new origin.
11062 // http://crbug.com/134690
11063 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11064 const std::string url1
= "http://www.google.com/";
11065 const std::string url2
= "https://mail.google.com/";
11066 const std::string ip_addr
= "1.2.3.4";
11068 // SPDY GET for HTTP URL (through SPDY proxy)
11069 scoped_ptr
<SpdyHeaderBlock
> headers(
11070 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11071 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyControlFrame(
11072 headers
.Pass(), false, 1, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
11074 MockWrite writes1
[] = {
11075 CreateMockWrite(*req1
, 0),
11078 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11079 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11080 MockRead reads1
[] = {
11081 CreateMockRead(*resp1
, 1),
11082 CreateMockRead(*body1
, 2),
11083 MockRead(ASYNC
, OK
, 3) // EOF
11086 scoped_ptr
<DeterministicSocketData
> data1(
11087 new DeterministicSocketData(reads1
, arraysize(reads1
),
11088 writes1
, arraysize(writes1
)));
11089 IPAddressNumber ip
;
11090 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
11091 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11092 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
11093 data1
->set_connect_data(connect_data1
);
11095 // SPDY GET for HTTPS URL (direct)
11096 scoped_ptr
<SpdyFrame
> req2(
11097 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
11099 MockWrite writes2
[] = {
11100 CreateMockWrite(*req2
, 0),
11103 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11104 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11105 MockRead reads2
[] = {
11106 CreateMockRead(*resp2
, 1),
11107 CreateMockRead(*body2
, 2),
11108 MockRead(ASYNC
, OK
, 3) // EOF
11111 scoped_ptr
<DeterministicSocketData
> data2(
11112 new DeterministicSocketData(reads2
, arraysize(reads2
),
11113 writes2
, arraysize(writes2
)));
11114 MockConnect
connect_data2(ASYNC
, OK
);
11115 data2
->set_connect_data(connect_data2
);
11117 // Set up a proxy config that sends HTTP requests to a proxy, and
11118 // all others direct.
11119 ProxyConfig proxy_config
;
11120 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
11121 CapturingProxyResolver
* capturing_proxy_resolver
=
11122 new CapturingProxyResolver();
11123 session_deps_
.proxy_service
.reset(new ProxyService(
11124 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
11127 // Load a valid cert. Note, that this does not need to
11128 // be valid for proxy because the MockSSLClientSocket does
11129 // not actually verify it. But SpdySession will use this
11130 // to see if it is valid for the new origin
11131 base::FilePath certs_dir
= GetTestCertsDirectory();
11132 scoped_refptr
<X509Certificate
> server_cert(
11133 ImportCertFromFile(certs_dir
, "ok_cert.pem"));
11134 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), server_cert
);
11136 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11137 ssl1
.SetNextProto(GetParam());
11138 ssl1
.cert
= server_cert
;
11139 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11140 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11143 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11144 ssl2
.SetNextProto(GetParam());
11145 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11146 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11149 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11150 session_deps_
.host_resolver
->rules()->AddRule("mail.google.com", ip_addr
);
11151 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
11153 scoped_refptr
<HttpNetworkSession
> session(
11154 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11156 // Start the first transaction to set up the SpdySession
11157 HttpRequestInfo request1
;
11158 request1
.method
= "GET";
11159 request1
.url
= GURL(url1
);
11160 request1
.load_flags
= 0;
11161 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11162 TestCompletionCallback callback1
;
11163 ASSERT_EQ(ERR_IO_PENDING
,
11164 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11167 ASSERT_TRUE(callback1
.have_result());
11168 EXPECT_EQ(OK
, callback1
.WaitForResult());
11169 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11171 // Now, start the HTTP request
11172 HttpRequestInfo request2
;
11173 request2
.method
= "GET";
11174 request2
.url
= GURL(url2
);
11175 request2
.load_flags
= 0;
11176 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11177 TestCompletionCallback callback2
;
11178 EXPECT_EQ(ERR_IO_PENDING
,
11179 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11180 base::MessageLoop::current()->RunUntilIdle();
11183 ASSERT_TRUE(callback2
.have_result());
11184 EXPECT_EQ(OK
, callback2
.WaitForResult());
11185 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11188 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11189 // error) in SPDY session, removes the socket from pool and closes the SPDY
11190 // session. Verify that new url's from the same HttpNetworkSession (and a new
11191 // SpdySession) do work. http://crbug.com/224701
11192 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
11193 const std::string https_url
= "https://www.google.com/";
11195 MockRead reads1
[] = {
11196 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
11199 scoped_ptr
<DeterministicSocketData
> data1(
11200 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
11203 scoped_ptr
<SpdyFrame
> req2(
11204 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
11205 MockWrite writes2
[] = {
11206 CreateMockWrite(*req2
, 0),
11209 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11210 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11211 MockRead reads2
[] = {
11212 CreateMockRead(*resp2
, 1),
11213 CreateMockRead(*body2
, 2),
11214 MockRead(ASYNC
, OK
, 3) // EOF
11217 scoped_ptr
<DeterministicSocketData
> data2(
11218 new DeterministicSocketData(reads2
, arraysize(reads2
),
11219 writes2
, arraysize(writes2
)));
11221 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11222 ssl1
.SetNextProto(GetParam());
11223 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11224 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11227 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11228 ssl2
.SetNextProto(GetParam());
11229 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11230 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11233 scoped_refptr
<HttpNetworkSession
> session(
11234 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11236 // Start the first transaction to set up the SpdySession and verify that
11237 // connection was closed.
11238 HttpRequestInfo request1
;
11239 request1
.method
= "GET";
11240 request1
.url
= GURL(https_url
);
11241 request1
.load_flags
= 0;
11242 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
11243 TestCompletionCallback callback1
;
11244 EXPECT_EQ(ERR_IO_PENDING
,
11245 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11246 base::MessageLoop::current()->RunUntilIdle();
11247 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
11249 // Now, start the second request and make sure it succeeds.
11250 HttpRequestInfo request2
;
11251 request2
.method
= "GET";
11252 request2
.url
= GURL(https_url
);
11253 request2
.load_flags
= 0;
11254 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11255 TestCompletionCallback callback2
;
11256 EXPECT_EQ(ERR_IO_PENDING
,
11257 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11258 base::MessageLoop::current()->RunUntilIdle();
11261 ASSERT_TRUE(callback2
.have_result());
11262 EXPECT_EQ(OK
, callback2
.WaitForResult());
11263 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11266 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
11267 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11268 ClientSocketPoolManager::set_max_sockets_per_group(
11269 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11270 ClientSocketPoolManager::set_max_sockets_per_pool(
11271 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11273 // Use two different hosts with different IPs so they don't get pooled.
11274 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
11275 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
11276 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11278 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11279 ssl1
.SetNextProto(GetParam());
11280 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11281 ssl2
.SetNextProto(GetParam());
11282 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11283 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11285 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
11286 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
11287 MockWrite spdy1_writes
[] = {
11288 CreateMockWrite(*host1_req
, 1),
11290 scoped_ptr
<SpdyFrame
> host1_resp(
11291 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11292 scoped_ptr
<SpdyFrame
> host1_resp_body(
11293 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11294 MockRead spdy1_reads
[] = {
11295 CreateMockRead(*host1_resp
, 2),
11296 CreateMockRead(*host1_resp_body
, 3),
11297 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11300 scoped_ptr
<OrderedSocketData
> spdy1_data(
11301 new OrderedSocketData(
11302 spdy1_reads
, arraysize(spdy1_reads
),
11303 spdy1_writes
, arraysize(spdy1_writes
)));
11304 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
11306 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
11307 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
11308 MockWrite spdy2_writes
[] = {
11309 CreateMockWrite(*host2_req
, 1),
11311 scoped_ptr
<SpdyFrame
> host2_resp(
11312 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11313 scoped_ptr
<SpdyFrame
> host2_resp_body(
11314 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11315 MockRead spdy2_reads
[] = {
11316 CreateMockRead(*host2_resp
, 2),
11317 CreateMockRead(*host2_resp_body
, 3),
11318 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11321 scoped_ptr
<OrderedSocketData
> spdy2_data(
11322 new OrderedSocketData(
11323 spdy2_reads
, arraysize(spdy2_reads
),
11324 spdy2_writes
, arraysize(spdy2_writes
)));
11325 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
11327 MockWrite http_write
[] = {
11328 MockWrite("GET / HTTP/1.1\r\n"
11329 "Host: www.a.com\r\n"
11330 "Connection: keep-alive\r\n\r\n"),
11333 MockRead http_read
[] = {
11334 MockRead("HTTP/1.1 200 OK\r\n"),
11335 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11336 MockRead("Content-Length: 6\r\n\r\n"),
11337 MockRead("hello!"),
11339 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
11340 http_write
, arraysize(http_write
));
11341 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
11343 HostPortPair
host_port_pair_a("www.a.com", 443);
11344 SpdySessionKey
spdy_session_key_a(
11345 host_port_pair_a
, ProxyServer::Direct(), kPrivacyModeDisabled
);
11347 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11349 TestCompletionCallback callback
;
11350 HttpRequestInfo request1
;
11351 request1
.method
= "GET";
11352 request1
.url
= GURL("https://www.a.com/");
11353 request1
.load_flags
= 0;
11354 scoped_ptr
<HttpNetworkTransaction
> trans(
11355 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11357 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
11358 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11359 EXPECT_EQ(OK
, callback
.WaitForResult());
11361 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11362 ASSERT_TRUE(response
!= NULL
);
11363 ASSERT_TRUE(response
->headers
.get() != NULL
);
11364 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11365 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11366 EXPECT_TRUE(response
->was_npn_negotiated
);
11368 std::string response_data
;
11369 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11370 EXPECT_EQ("hello!", response_data
);
11373 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11375 HostPortPair
host_port_pair_b("www.b.com", 443);
11376 SpdySessionKey
spdy_session_key_b(
11377 host_port_pair_b
, ProxyServer::Direct(), kPrivacyModeDisabled
);
11379 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11380 HttpRequestInfo request2
;
11381 request2
.method
= "GET";
11382 request2
.url
= GURL("https://www.b.com/");
11383 request2
.load_flags
= 0;
11384 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11386 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
11387 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11388 EXPECT_EQ(OK
, callback
.WaitForResult());
11390 response
= trans
->GetResponseInfo();
11391 ASSERT_TRUE(response
!= NULL
);
11392 ASSERT_TRUE(response
->headers
.get() != NULL
);
11393 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11394 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11395 EXPECT_TRUE(response
->was_npn_negotiated
);
11396 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11397 EXPECT_EQ("hello!", response_data
);
11399 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11401 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11403 HostPortPair
host_port_pair_a1("www.a.com", 80);
11404 SpdySessionKey
spdy_session_key_a1(
11405 host_port_pair_a1
, ProxyServer::Direct(), kPrivacyModeDisabled
);
11407 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
11408 HttpRequestInfo request3
;
11409 request3
.method
= "GET";
11410 request3
.url
= GURL("http://www.a.com/");
11411 request3
.load_flags
= 0;
11412 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11414 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
11415 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11416 EXPECT_EQ(OK
, callback
.WaitForResult());
11418 response
= trans
->GetResponseInfo();
11419 ASSERT_TRUE(response
!= NULL
);
11420 ASSERT_TRUE(response
->headers
.get() != NULL
);
11421 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11422 EXPECT_FALSE(response
->was_fetched_via_spdy
);
11423 EXPECT_FALSE(response
->was_npn_negotiated
);
11424 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11425 EXPECT_EQ("hello!", response_data
);
11427 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11429 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11432 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
11433 HttpRequestInfo request
;
11434 request
.method
= "GET";
11435 request
.url
= GURL("http://www.google.com/");
11436 request
.load_flags
= 0;
11438 scoped_ptr
<HttpTransaction
> trans(
11439 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
11440 CreateSession(&session_deps_
)));
11442 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
11443 StaticSocketDataProvider data
;
11444 data
.set_connect_data(mock_connect
);
11445 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11447 TestCompletionCallback callback
;
11449 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11450 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11452 rv
= callback
.WaitForResult();
11453 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11455 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11457 // We don't care whether this succeeds or fails, but it shouldn't crash.
11458 HttpRequestHeaders request_headers
;
11459 trans
->GetFullRequestHeaders(&request_headers
);
11462 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
11463 HttpRequestInfo request
;
11464 request
.method
= "GET";
11465 request
.url
= GURL("http://www.google.com/");
11466 request
.load_flags
= 0;
11468 scoped_ptr
<HttpTransaction
> trans(
11469 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
11470 CreateSession(&session_deps_
)));
11472 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11473 StaticSocketDataProvider data
;
11474 data
.set_connect_data(mock_connect
);
11475 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11477 TestCompletionCallback callback
;
11479 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11480 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11482 rv
= callback
.WaitForResult();
11483 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11485 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11487 // We don't care whether this succeeds or fails, but it shouldn't crash.
11488 HttpRequestHeaders request_headers
;
11489 trans
->GetFullRequestHeaders(&request_headers
);
11492 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
11493 HttpRequestInfo request
;
11494 request
.method
= "GET";
11495 request
.url
= GURL("http://www.google.com/");
11496 request
.load_flags
= 0;
11498 scoped_ptr
<HttpTransaction
> trans(
11499 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
11500 CreateSession(&session_deps_
)));
11502 MockWrite data_writes
[] = {
11503 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
11505 MockRead data_reads
[] = {
11506 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
11509 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11510 data_writes
, arraysize(data_writes
));
11511 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11513 TestCompletionCallback callback
;
11515 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11516 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11518 rv
= callback
.WaitForResult();
11519 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11521 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11523 HttpRequestHeaders request_headers
;
11524 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11525 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11528 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
11529 HttpRequestInfo request
;
11530 request
.method
= "GET";
11531 request
.url
= GURL("http://www.google.com/");
11532 request
.load_flags
= 0;
11534 scoped_ptr
<HttpTransaction
> trans(
11535 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
11536 CreateSession(&session_deps_
)));
11538 MockWrite data_writes
[] = {
11539 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
11541 MockRead data_reads
[] = {
11542 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
11545 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11546 data_writes
, arraysize(data_writes
));
11547 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11549 TestCompletionCallback callback
;
11551 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11552 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11554 rv
= callback
.WaitForResult();
11555 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11557 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11559 HttpRequestHeaders request_headers
;
11560 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11561 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11564 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
11565 HttpRequestInfo request
;
11566 request
.method
= "GET";
11567 request
.url
= GURL("http://www.google.com/");
11568 request
.load_flags
= 0;
11570 scoped_ptr
<HttpTransaction
> trans(
11571 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
11572 CreateSession(&session_deps_
)));
11574 MockWrite data_writes
[] = {
11575 MockWrite("GET / HTTP/1.1\r\n"
11576 "Host: www.google.com\r\n"
11577 "Connection: keep-alive\r\n\r\n"),
11579 MockRead data_reads
[] = {
11580 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
11583 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11584 data_writes
, arraysize(data_writes
));
11585 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11587 TestCompletionCallback callback
;
11589 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11590 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11592 rv
= callback
.WaitForResult();
11593 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11595 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11597 HttpRequestHeaders request_headers
;
11598 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11599 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11602 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
11603 HttpRequestInfo request
;
11604 request
.method
= "GET";
11605 request
.url
= GURL("http://www.google.com/");
11606 request
.load_flags
= 0;
11608 scoped_ptr
<HttpTransaction
> trans(
11609 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
11610 CreateSession(&session_deps_
)));
11612 MockWrite data_writes
[] = {
11613 MockWrite("GET / HTTP/1.1\r\n"
11614 "Host: www.google.com\r\n"
11615 "Connection: keep-alive\r\n\r\n"),
11617 MockRead data_reads
[] = {
11618 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
11621 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11622 data_writes
, arraysize(data_writes
));
11623 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11625 TestCompletionCallback callback
;
11627 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11628 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11630 rv
= callback
.WaitForResult();
11631 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11633 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11635 HttpRequestHeaders request_headers
;
11636 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11637 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11640 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
11641 HttpRequestInfo request
;
11642 request
.method
= "GET";
11643 request
.url
= GURL("http://www.google.com/");
11644 request
.load_flags
= 0;
11645 request
.extra_headers
.SetHeader("X-Foo", "bar");
11647 scoped_ptr
<HttpTransaction
> trans(
11648 new HttpNetworkTransaction(DEFAULT_PRIORITY
,
11649 CreateSession(&session_deps_
)));
11651 MockWrite data_writes
[] = {
11652 MockWrite("GET / HTTP/1.1\r\n"
11653 "Host: www.google.com\r\n"
11654 "Connection: keep-alive\r\n"
11655 "X-Foo: bar\r\n\r\n"),
11657 MockRead data_reads
[] = {
11658 MockRead("HTTP/1.1 200 OK\r\n"
11659 "Content-Length: 5\r\n\r\n"
11661 MockRead(ASYNC
, ERR_UNEXPECTED
),
11664 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11665 data_writes
, arraysize(data_writes
));
11666 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11668 TestCompletionCallback callback
;
11670 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11671 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11673 rv
= callback
.WaitForResult();
11676 HttpRequestHeaders request_headers
;
11677 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11679 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
11680 EXPECT_EQ("bar", foo
);