ServiceWorker: Rename 'current' to 'controller'
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blobab64040df1ab4b3619e28f2bb584e17c1abd9688
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
8 #include <stdarg.h>
9 #include <string>
10 #include <vector>
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/memory/weak_ptr.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/test/test_file_util.h"
23 #include "net/base/auth.h"
24 #include "net/base/capturing_net_log.h"
25 #include "net/base/completion_callback.h"
26 #include "net/base/load_timing_info.h"
27 #include "net/base/load_timing_info_test_util.h"
28 #include "net/base/net_log.h"
29 #include "net/base/net_log_unittest.h"
30 #include "net/base/request_priority.h"
31 #include "net/base/test_completion_callback.h"
32 #include "net/base/test_data_directory.h"
33 #include "net/base/upload_bytes_element_reader.h"
34 #include "net/base/upload_data_stream.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_stream.h"
44 #include "net/http/http_network_session.h"
45 #include "net/http/http_network_session_peer.h"
46 #include "net/http/http_server_properties_impl.h"
47 #include "net/http/http_stream.h"
48 #include "net/http/http_stream_factory.h"
49 #include "net/http/http_transaction_test_util.h"
50 #include "net/proxy/proxy_config_service_fixed.h"
51 #include "net/proxy/proxy_info.h"
52 #include "net/proxy/proxy_resolver.h"
53 #include "net/proxy/proxy_service.h"
54 #include "net/socket/client_socket_factory.h"
55 #include "net/socket/client_socket_pool_manager.h"
56 #include "net/socket/mock_client_socket_pool_manager.h"
57 #include "net/socket/next_proto.h"
58 #include "net/socket/socket_test_util.h"
59 #include "net/socket/ssl_client_socket.h"
60 #include "net/spdy/spdy_framer.h"
61 #include "net/spdy/spdy_session.h"
62 #include "net/spdy/spdy_session_pool.h"
63 #include "net/spdy/spdy_test_util_common.h"
64 #include "net/ssl/ssl_cert_request_info.h"
65 #include "net/ssl/ssl_config_service.h"
66 #include "net/ssl/ssl_config_service_defaults.h"
67 #include "net/ssl/ssl_info.h"
68 #include "net/test/cert_test_util.h"
69 #include "net/websockets/websocket_handshake_stream_base.h"
70 #include "testing/gtest/include/gtest/gtest.h"
71 #include "testing/platform_test.h"
72 #include "url/gurl.h"
74 using base::ASCIIToUTF16;
76 //-----------------------------------------------------------------------------
78 namespace {
80 const base::string16 kBar(ASCIIToUTF16("bar"));
81 const base::string16 kBar2(ASCIIToUTF16("bar2"));
82 const base::string16 kBar3(ASCIIToUTF16("bar3"));
83 const base::string16 kBaz(ASCIIToUTF16("baz"));
84 const base::string16 kFirst(ASCIIToUTF16("first"));
85 const base::string16 kFoo(ASCIIToUTF16("foo"));
86 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
87 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
88 const base::string16 kFou(ASCIIToUTF16("fou"));
89 const base::string16 kSecond(ASCIIToUTF16("second"));
90 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
91 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
93 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
94 return session->GetTransportSocketPool(
95 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
98 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
99 return session->GetSSLSocketPool(
100 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
103 bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) {
104 return session->GetTransportSocketPool(
105 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled();
108 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
109 // a JSONified list of headers as a single string. Uses single quotes instead
110 // of double quotes for easier comparison. Returns false on failure.
111 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
112 if (!params)
113 return false;
114 base::ListValue* header_list;
115 if (!params->GetList("headers", &header_list))
116 return false;
117 std::string double_quote_headers;
118 base::JSONWriter::Write(header_list, &double_quote_headers);
119 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
120 return true;
123 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
124 // used.
125 void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
126 EXPECT_TRUE(load_timing_info.socket_reused);
127 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
129 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
130 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
132 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
133 EXPECT_FALSE(load_timing_info.send_start.is_null());
135 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
137 // Set at a higher level.
138 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
139 EXPECT_TRUE(load_timing_info.request_start.is_null());
140 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
143 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
144 // used.
145 void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
146 int connect_timing_flags) {
147 EXPECT_FALSE(load_timing_info.socket_reused);
148 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
150 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
151 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
153 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
154 connect_timing_flags);
155 EXPECT_LE(load_timing_info.connect_timing.connect_end,
156 load_timing_info.send_start);
158 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
160 // Set at a higher level.
161 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
162 EXPECT_TRUE(load_timing_info.request_start.is_null());
163 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
166 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
167 // used.
168 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
169 EXPECT_TRUE(load_timing_info.socket_reused);
170 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
172 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
174 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
175 EXPECT_LE(load_timing_info.proxy_resolve_start,
176 load_timing_info.proxy_resolve_end);
177 EXPECT_LE(load_timing_info.proxy_resolve_end,
178 load_timing_info.send_start);
179 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
181 // Set at a higher level.
182 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
183 EXPECT_TRUE(load_timing_info.request_start.is_null());
184 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
187 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
188 // used.
189 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
190 int connect_timing_flags) {
191 EXPECT_FALSE(load_timing_info.socket_reused);
192 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
194 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
195 EXPECT_LE(load_timing_info.proxy_resolve_start,
196 load_timing_info.proxy_resolve_end);
197 EXPECT_LE(load_timing_info.proxy_resolve_end,
198 load_timing_info.connect_timing.connect_start);
199 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
200 connect_timing_flags);
201 EXPECT_LE(load_timing_info.connect_timing.connect_end,
202 load_timing_info.send_start);
204 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
206 // Set at a higher level.
207 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
208 EXPECT_TRUE(load_timing_info.request_start.is_null());
209 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
212 } // namespace
214 namespace net {
216 namespace {
218 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
219 return SpdySessionDependencies::SpdyCreateSession(session_deps);
222 } // namespace
224 class HttpNetworkTransactionTest
225 : public PlatformTest,
226 public ::testing::WithParamInterface<NextProto> {
227 public:
228 virtual ~HttpNetworkTransactionTest() {
229 // Important to restore the per-pool limit first, since the pool limit must
230 // always be greater than group limit, and the tests reduce both limits.
231 ClientSocketPoolManager::set_max_sockets_per_pool(
232 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
233 ClientSocketPoolManager::set_max_sockets_per_group(
234 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
237 protected:
238 HttpNetworkTransactionTest()
239 : spdy_util_(GetParam()),
240 session_deps_(GetParam()),
241 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
242 HttpNetworkSession::NORMAL_SOCKET_POOL)),
243 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
244 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
247 struct SimpleGetHelperResult {
248 int rv;
249 std::string status_line;
250 std::string response_data;
251 int64 totalReceivedBytes;
252 LoadTimingInfo load_timing_info;
255 virtual void SetUp() {
256 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
257 base::MessageLoop::current()->RunUntilIdle();
260 virtual void TearDown() {
261 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
262 base::MessageLoop::current()->RunUntilIdle();
263 // Empty the current queue.
264 base::MessageLoop::current()->RunUntilIdle();
265 PlatformTest::TearDown();
266 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
267 base::MessageLoop::current()->RunUntilIdle();
270 // This is the expected return from a current server advertising SPDY.
271 std::string GetAlternateProtocolHttpHeader() {
272 return
273 std::string("Alternate-Protocol: 443:") +
274 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
275 "\r\n\r\n";
278 // Either |write_failure| specifies a write failure or |read_failure|
279 // specifies a read failure when using a reused socket. In either case, the
280 // failure should cause the network transaction to resend the request, and the
281 // other argument should be NULL.
282 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
283 const MockRead* read_failure);
285 // Either |write_failure| specifies a write failure or |read_failure|
286 // specifies a read failure when using a reused socket. In either case, the
287 // failure should cause the network transaction to resend the request, and the
288 // other argument should be NULL.
289 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
290 const MockRead* read_failure,
291 bool use_spdy);
293 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
294 size_t data_count) {
295 SimpleGetHelperResult out;
297 HttpRequestInfo request;
298 request.method = "GET";
299 request.url = GURL("http://www.google.com/");
300 request.load_flags = 0;
302 CapturingBoundNetLog log;
303 session_deps_.net_log = log.bound().net_log();
304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
305 scoped_ptr<HttpTransaction> trans(
306 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
308 for (size_t i = 0; i < data_count; ++i) {
309 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
312 TestCompletionCallback callback;
314 EXPECT_TRUE(log.bound().IsLogging());
315 int rv = trans->Start(&request, callback.callback(), log.bound());
316 EXPECT_EQ(ERR_IO_PENDING, rv);
318 out.rv = callback.WaitForResult();
320 // Even in the failure cases that use this function, connections are always
321 // successfully established before the error.
322 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
323 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
325 if (out.rv != OK)
326 return out;
328 const HttpResponseInfo* response = trans->GetResponseInfo();
329 // Can't use ASSERT_* inside helper functions like this, so
330 // return an error.
331 if (response == NULL || response->headers.get() == NULL) {
332 out.rv = ERR_UNEXPECTED;
333 return out;
335 out.status_line = response->headers->GetStatusLine();
337 EXPECT_EQ("127.0.0.1", response->socket_address.host());
338 EXPECT_EQ(80, response->socket_address.port());
340 rv = ReadTransaction(trans.get(), &out.response_data);
341 EXPECT_EQ(OK, rv);
343 net::CapturingNetLog::CapturedEntryList entries;
344 log.GetEntries(&entries);
345 size_t pos = ExpectLogContainsSomewhere(
346 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
347 NetLog::PHASE_NONE);
348 ExpectLogContainsSomewhere(
349 entries, pos,
350 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
351 NetLog::PHASE_NONE);
353 std::string line;
354 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
355 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
357 HttpRequestHeaders request_headers;
358 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
359 std::string value;
360 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
361 EXPECT_EQ("www.google.com", value);
362 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
363 EXPECT_EQ("keep-alive", value);
365 std::string response_headers;
366 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
367 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
368 response_headers);
370 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
371 return out;
374 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
375 size_t reads_count) {
376 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
377 StaticSocketDataProvider* data[] = { &reads };
378 return SimpleGetHelperForData(data, 1);
381 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
382 int64 size = 0;
383 for (size_t i = 0; i < reads_count; ++i)
384 size += data_reads[i].data_len;
385 return size;
388 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
389 int expected_status);
391 void ConnectStatusHelper(const MockRead& status);
393 void BypassHostCacheOnRefreshHelper(int load_flags);
395 void CheckErrorIsPassedBack(int error, IoMode mode);
397 SpdyTestUtil spdy_util_;
398 SpdySessionDependencies session_deps_;
400 // Original socket limits. Some tests set these. Safest to always restore
401 // them once each test has been run.
402 int old_max_group_sockets_;
403 int old_max_pool_sockets_;
406 INSTANTIATE_TEST_CASE_P(
407 NextProto,
408 HttpNetworkTransactionTest,
409 testing::Values(kProtoDeprecatedSPDY2,
410 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
412 namespace {
414 class BeforeNetworkStartHandler {
415 public:
416 explicit BeforeNetworkStartHandler(bool defer)
417 : defer_on_before_network_start_(defer),
418 observed_before_network_start_(false) {}
420 void OnBeforeNetworkStart(bool* defer) {
421 *defer = defer_on_before_network_start_;
422 observed_before_network_start_ = true;
425 bool observed_before_network_start() const {
426 return observed_before_network_start_;
429 private:
430 const bool defer_on_before_network_start_;
431 bool observed_before_network_start_;
433 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
436 class BeforeProxyHeadersSentHandler {
437 public:
438 BeforeProxyHeadersSentHandler()
439 : observed_before_proxy_headers_sent_(false) {}
441 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
442 HttpRequestHeaders* request_headers) {
443 observed_before_proxy_headers_sent_ = true;
444 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
447 bool observed_before_proxy_headers_sent() const {
448 return observed_before_proxy_headers_sent_;
451 std::string observed_proxy_server_uri() const {
452 return observed_proxy_server_uri_;
455 private:
456 bool observed_before_proxy_headers_sent_;
457 std::string observed_proxy_server_uri_;
459 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
462 // Fill |str| with a long header list that consumes >= |size| bytes.
463 void FillLargeHeadersString(std::string* str, int size) {
464 const char* row =
465 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
466 const int sizeof_row = strlen(row);
467 const int num_rows = static_cast<int>(
468 ceil(static_cast<float>(size) / sizeof_row));
469 const int sizeof_data = num_rows * sizeof_row;
470 DCHECK(sizeof_data >= size);
471 str->reserve(sizeof_data);
473 for (int i = 0; i < num_rows; ++i)
474 str->append(row, sizeof_row);
477 // Alternative functions that eliminate randomness and dependency on the local
478 // host name so that the generated NTLM messages are reproducible.
479 void MockGenerateRandom1(uint8* output, size_t n) {
480 static const uint8 bytes[] = {
481 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
483 static size_t current_byte = 0;
484 for (size_t i = 0; i < n; ++i) {
485 output[i] = bytes[current_byte++];
486 current_byte %= arraysize(bytes);
490 void MockGenerateRandom2(uint8* output, size_t n) {
491 static const uint8 bytes[] = {
492 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
493 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
495 static size_t current_byte = 0;
496 for (size_t i = 0; i < n; ++i) {
497 output[i] = bytes[current_byte++];
498 current_byte %= arraysize(bytes);
502 std::string MockGetHostName() {
503 return "WTC-WIN7";
506 template<typename ParentPool>
507 class CaptureGroupNameSocketPool : public ParentPool {
508 public:
509 CaptureGroupNameSocketPool(HostResolver* host_resolver,
510 CertVerifier* cert_verifier);
512 const std::string last_group_name_received() const {
513 return last_group_name_;
516 virtual int RequestSocket(const std::string& group_name,
517 const void* socket_params,
518 RequestPriority priority,
519 ClientSocketHandle* handle,
520 const CompletionCallback& callback,
521 const BoundNetLog& net_log) {
522 last_group_name_ = group_name;
523 return ERR_IO_PENDING;
525 virtual void CancelRequest(const std::string& group_name,
526 ClientSocketHandle* handle) {}
527 virtual void ReleaseSocket(const std::string& group_name,
528 scoped_ptr<StreamSocket> socket,
529 int id) {}
530 virtual void CloseIdleSockets() {}
531 virtual int IdleSocketCount() const {
532 return 0;
534 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
535 return 0;
537 virtual LoadState GetLoadState(const std::string& group_name,
538 const ClientSocketHandle* handle) const {
539 return LOAD_STATE_IDLE;
541 virtual base::TimeDelta ConnectionTimeout() const {
542 return base::TimeDelta();
545 private:
546 std::string last_group_name_;
549 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
550 CaptureGroupNameTransportSocketPool;
551 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
552 CaptureGroupNameHttpProxySocketPool;
553 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
554 CaptureGroupNameSOCKSSocketPool;
555 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
556 CaptureGroupNameSSLSocketPool;
558 template<typename ParentPool>
559 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
560 HostResolver* host_resolver,
561 CertVerifier* /* cert_verifier */)
562 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
564 template<>
565 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
566 HostResolver* host_resolver,
567 CertVerifier* /* cert_verifier */)
568 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
570 template <>
571 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
572 HostResolver* host_resolver,
573 CertVerifier* cert_verifier)
574 : SSLClientSocketPool(0,
576 NULL,
577 host_resolver,
578 cert_verifier,
579 NULL,
580 NULL,
581 NULL,
582 std::string(),
583 NULL,
584 NULL,
585 NULL,
586 NULL,
587 NULL,
588 NULL) {}
590 //-----------------------------------------------------------------------------
592 // Helper functions for validating that AuthChallengeInfo's are correctly
593 // configured for common cases.
594 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
595 if (!auth_challenge)
596 return false;
597 EXPECT_FALSE(auth_challenge->is_proxy);
598 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
599 EXPECT_EQ("MyRealm1", auth_challenge->realm);
600 EXPECT_EQ("basic", auth_challenge->scheme);
601 return true;
604 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
605 if (!auth_challenge)
606 return false;
607 EXPECT_TRUE(auth_challenge->is_proxy);
608 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
609 EXPECT_EQ("MyRealm1", auth_challenge->realm);
610 EXPECT_EQ("basic", auth_challenge->scheme);
611 return true;
614 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
615 if (!auth_challenge)
616 return false;
617 EXPECT_FALSE(auth_challenge->is_proxy);
618 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
619 EXPECT_EQ("digestive", auth_challenge->realm);
620 EXPECT_EQ("digest", auth_challenge->scheme);
621 return true;
624 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
625 if (!auth_challenge)
626 return false;
627 EXPECT_FALSE(auth_challenge->is_proxy);
628 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
629 EXPECT_EQ(std::string(), auth_challenge->realm);
630 EXPECT_EQ("ntlm", auth_challenge->scheme);
631 return true;
634 } // namespace
636 TEST_P(HttpNetworkTransactionTest, Basic) {
637 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
638 scoped_ptr<HttpTransaction> trans(
639 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
642 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
643 MockRead data_reads[] = {
644 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
645 MockRead("hello world"),
646 MockRead(SYNCHRONOUS, OK),
648 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
649 arraysize(data_reads));
650 EXPECT_EQ(OK, out.rv);
651 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
652 EXPECT_EQ("hello world", out.response_data);
653 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
654 EXPECT_EQ(reads_size, out.totalReceivedBytes);
657 // Response with no status line.
658 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
659 MockRead data_reads[] = {
660 MockRead("hello world"),
661 MockRead(SYNCHRONOUS, OK),
663 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
664 arraysize(data_reads));
665 EXPECT_EQ(OK, out.rv);
666 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
667 EXPECT_EQ("hello world", out.response_data);
668 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
669 EXPECT_EQ(reads_size, out.totalReceivedBytes);
672 // Allow up to 4 bytes of junk to precede status line.
673 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
674 MockRead data_reads[] = {
675 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
676 MockRead(SYNCHRONOUS, OK),
678 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
679 arraysize(data_reads));
680 EXPECT_EQ(OK, out.rv);
681 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
682 EXPECT_EQ("DATA", out.response_data);
683 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
684 EXPECT_EQ(reads_size, out.totalReceivedBytes);
687 // Allow up to 4 bytes of junk to precede status line.
688 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
689 MockRead data_reads[] = {
690 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
691 MockRead(SYNCHRONOUS, OK),
693 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
694 arraysize(data_reads));
695 EXPECT_EQ(OK, out.rv);
696 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
697 EXPECT_EQ("DATA", out.response_data);
698 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
699 EXPECT_EQ(reads_size, out.totalReceivedBytes);
702 // Beyond 4 bytes of slop and it should fail to find a status line.
703 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
704 MockRead data_reads[] = {
705 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
706 MockRead(SYNCHRONOUS, OK),
708 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
709 arraysize(data_reads));
710 EXPECT_EQ(OK, out.rv);
711 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
712 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
713 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
714 EXPECT_EQ(reads_size, out.totalReceivedBytes);
717 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
718 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
719 MockRead data_reads[] = {
720 MockRead("\n"),
721 MockRead("\n"),
722 MockRead("Q"),
723 MockRead("J"),
724 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
725 MockRead(SYNCHRONOUS, OK),
727 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
728 arraysize(data_reads));
729 EXPECT_EQ(OK, out.rv);
730 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
731 EXPECT_EQ("DATA", out.response_data);
732 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
733 EXPECT_EQ(reads_size, out.totalReceivedBytes);
736 // Close the connection before enough bytes to have a status line.
737 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
738 MockRead data_reads[] = {
739 MockRead("HTT"),
740 MockRead(SYNCHRONOUS, OK),
742 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
743 arraysize(data_reads));
744 EXPECT_EQ(OK, out.rv);
745 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
746 EXPECT_EQ("HTT", out.response_data);
747 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
748 EXPECT_EQ(reads_size, out.totalReceivedBytes);
751 // Simulate a 204 response, lacking a Content-Length header, sent over a
752 // persistent connection. The response should still terminate since a 204
753 // cannot have a response body.
754 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
755 char junk[] = "junk";
756 MockRead data_reads[] = {
757 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
758 MockRead(junk), // Should not be read!!
759 MockRead(SYNCHRONOUS, OK),
761 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
762 arraysize(data_reads));
763 EXPECT_EQ(OK, out.rv);
764 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
765 EXPECT_EQ("", out.response_data);
766 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
767 int64 response_size = reads_size - strlen(junk);
768 EXPECT_EQ(response_size, out.totalReceivedBytes);
771 // A simple request using chunked encoding with some extra data after.
772 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
773 std::string final_chunk = "0\r\n\r\n";
774 std::string extra_data = "HTTP/1.1 200 OK\r\n";
775 std::string last_read = final_chunk + extra_data;
776 MockRead data_reads[] = {
777 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
778 MockRead("5\r\nHello\r\n"),
779 MockRead("1\r\n"),
780 MockRead(" \r\n"),
781 MockRead("5\r\nworld\r\n"),
782 MockRead(last_read.data()),
783 MockRead(SYNCHRONOUS, OK),
785 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
786 arraysize(data_reads));
787 EXPECT_EQ(OK, out.rv);
788 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
789 EXPECT_EQ("Hello world", out.response_data);
790 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
791 int64 response_size = reads_size - extra_data.size();
792 EXPECT_EQ(response_size, out.totalReceivedBytes);
795 // Next tests deal with http://crbug.com/56344.
797 TEST_P(HttpNetworkTransactionTest,
798 MultipleContentLengthHeadersNoTransferEncoding) {
799 MockRead data_reads[] = {
800 MockRead("HTTP/1.1 200 OK\r\n"),
801 MockRead("Content-Length: 10\r\n"),
802 MockRead("Content-Length: 5\r\n\r\n"),
804 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
805 arraysize(data_reads));
806 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
809 TEST_P(HttpNetworkTransactionTest,
810 DuplicateContentLengthHeadersNoTransferEncoding) {
811 MockRead data_reads[] = {
812 MockRead("HTTP/1.1 200 OK\r\n"),
813 MockRead("Content-Length: 5\r\n"),
814 MockRead("Content-Length: 5\r\n\r\n"),
815 MockRead("Hello"),
817 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
818 arraysize(data_reads));
819 EXPECT_EQ(OK, out.rv);
820 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
821 EXPECT_EQ("Hello", out.response_data);
824 TEST_P(HttpNetworkTransactionTest,
825 ComplexContentLengthHeadersNoTransferEncoding) {
826 // More than 2 dupes.
828 MockRead data_reads[] = {
829 MockRead("HTTP/1.1 200 OK\r\n"),
830 MockRead("Content-Length: 5\r\n"),
831 MockRead("Content-Length: 5\r\n"),
832 MockRead("Content-Length: 5\r\n\r\n"),
833 MockRead("Hello"),
835 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
836 arraysize(data_reads));
837 EXPECT_EQ(OK, out.rv);
838 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
839 EXPECT_EQ("Hello", out.response_data);
841 // HTTP/1.0
843 MockRead data_reads[] = {
844 MockRead("HTTP/1.0 200 OK\r\n"),
845 MockRead("Content-Length: 5\r\n"),
846 MockRead("Content-Length: 5\r\n"),
847 MockRead("Content-Length: 5\r\n\r\n"),
848 MockRead("Hello"),
850 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
851 arraysize(data_reads));
852 EXPECT_EQ(OK, out.rv);
853 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
854 EXPECT_EQ("Hello", out.response_data);
856 // 2 dupes and one mismatched.
858 MockRead data_reads[] = {
859 MockRead("HTTP/1.1 200 OK\r\n"),
860 MockRead("Content-Length: 10\r\n"),
861 MockRead("Content-Length: 10\r\n"),
862 MockRead("Content-Length: 5\r\n\r\n"),
864 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
865 arraysize(data_reads));
866 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
870 TEST_P(HttpNetworkTransactionTest,
871 MultipleContentLengthHeadersTransferEncoding) {
872 MockRead data_reads[] = {
873 MockRead("HTTP/1.1 200 OK\r\n"),
874 MockRead("Content-Length: 666\r\n"),
875 MockRead("Content-Length: 1337\r\n"),
876 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
877 MockRead("5\r\nHello\r\n"),
878 MockRead("1\r\n"),
879 MockRead(" \r\n"),
880 MockRead("5\r\nworld\r\n"),
881 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
882 MockRead(SYNCHRONOUS, OK),
884 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
885 arraysize(data_reads));
886 EXPECT_EQ(OK, out.rv);
887 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
888 EXPECT_EQ("Hello world", out.response_data);
891 // Next tests deal with http://crbug.com/98895.
893 // Checks that a single Content-Disposition header results in no error.
894 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
895 MockRead data_reads[] = {
896 MockRead("HTTP/1.1 200 OK\r\n"),
897 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
898 MockRead("Content-Length: 5\r\n\r\n"),
899 MockRead("Hello"),
901 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
902 arraysize(data_reads));
903 EXPECT_EQ(OK, out.rv);
904 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
905 EXPECT_EQ("Hello", out.response_data);
908 // Checks that two identical Content-Disposition headers result in no error.
909 TEST_P(HttpNetworkTransactionTest,
910 TwoIdenticalContentDispositionHeaders) {
911 MockRead data_reads[] = {
912 MockRead("HTTP/1.1 200 OK\r\n"),
913 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
914 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
915 MockRead("Content-Length: 5\r\n\r\n"),
916 MockRead("Hello"),
918 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
919 arraysize(data_reads));
920 EXPECT_EQ(OK, out.rv);
921 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
922 EXPECT_EQ("Hello", out.response_data);
925 // Checks that two distinct Content-Disposition headers result in an error.
926 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
927 MockRead data_reads[] = {
928 MockRead("HTTP/1.1 200 OK\r\n"),
929 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
930 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
931 MockRead("Content-Length: 5\r\n\r\n"),
932 MockRead("Hello"),
934 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
935 arraysize(data_reads));
936 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
939 // Checks that two identical Location headers result in no error.
940 // Also tests Location header behavior.
941 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
942 MockRead data_reads[] = {
943 MockRead("HTTP/1.1 302 Redirect\r\n"),
944 MockRead("Location: http://good.com/\r\n"),
945 MockRead("Location: http://good.com/\r\n"),
946 MockRead("Content-Length: 0\r\n\r\n"),
947 MockRead(SYNCHRONOUS, OK),
950 HttpRequestInfo request;
951 request.method = "GET";
952 request.url = GURL("http://redirect.com/");
953 request.load_flags = 0;
955 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
956 scoped_ptr<HttpTransaction> trans(
957 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
959 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
960 session_deps_.socket_factory->AddSocketDataProvider(&data);
962 TestCompletionCallback callback;
964 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
965 EXPECT_EQ(ERR_IO_PENDING, rv);
967 EXPECT_EQ(OK, callback.WaitForResult());
969 const HttpResponseInfo* response = trans->GetResponseInfo();
970 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
971 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
972 std::string url;
973 EXPECT_TRUE(response->headers->IsRedirect(&url));
974 EXPECT_EQ("http://good.com/", url);
975 EXPECT_TRUE(response->proxy_server.IsEmpty());
978 // Checks that two distinct Location headers result in an error.
979 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
980 MockRead data_reads[] = {
981 MockRead("HTTP/1.1 302 Redirect\r\n"),
982 MockRead("Location: http://good.com/\r\n"),
983 MockRead("Location: http://evil.com/\r\n"),
984 MockRead("Content-Length: 0\r\n\r\n"),
985 MockRead(SYNCHRONOUS, OK),
987 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
988 arraysize(data_reads));
989 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
992 // Do a request using the HEAD method. Verify that we don't try to read the
993 // message body (since HEAD has none).
994 TEST_P(HttpNetworkTransactionTest, Head) {
995 HttpRequestInfo request;
996 request.method = "HEAD";
997 request.url = GURL("http://www.google.com/");
998 request.load_flags = 0;
1000 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1001 scoped_ptr<HttpTransaction> trans(
1002 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1003 BeforeProxyHeadersSentHandler proxy_headers_handler;
1004 trans->SetBeforeProxyHeadersSentCallback(
1005 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1006 base::Unretained(&proxy_headers_handler)));
1008 MockWrite data_writes1[] = {
1009 MockWrite("HEAD / HTTP/1.1\r\n"
1010 "Host: www.google.com\r\n"
1011 "Connection: keep-alive\r\n"
1012 "Content-Length: 0\r\n\r\n"),
1014 MockRead data_reads1[] = {
1015 MockRead("HTTP/1.1 404 Not Found\r\n"),
1016 MockRead("Server: Blah\r\n"),
1017 MockRead("Content-Length: 1234\r\n\r\n"),
1019 // No response body because the test stops reading here.
1020 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1023 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1024 data_writes1, arraysize(data_writes1));
1025 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1027 TestCompletionCallback callback1;
1029 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1030 EXPECT_EQ(ERR_IO_PENDING, rv);
1032 rv = callback1.WaitForResult();
1033 EXPECT_EQ(OK, rv);
1035 const HttpResponseInfo* response = trans->GetResponseInfo();
1036 ASSERT_TRUE(response != NULL);
1038 // Check that the headers got parsed.
1039 EXPECT_TRUE(response->headers.get() != NULL);
1040 EXPECT_EQ(1234, response->headers->GetContentLength());
1041 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1042 EXPECT_TRUE(response->proxy_server.IsEmpty());
1043 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1045 std::string server_header;
1046 void* iter = NULL;
1047 bool has_server_header = response->headers->EnumerateHeader(
1048 &iter, "Server", &server_header);
1049 EXPECT_TRUE(has_server_header);
1050 EXPECT_EQ("Blah", server_header);
1052 // Reading should give EOF right away, since there is no message body
1053 // (despite non-zero content-length).
1054 std::string response_data;
1055 rv = ReadTransaction(trans.get(), &response_data);
1056 EXPECT_EQ(OK, rv);
1057 EXPECT_EQ("", response_data);
1060 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1061 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1063 MockRead data_reads[] = {
1064 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1065 MockRead("hello"),
1066 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1067 MockRead("world"),
1068 MockRead(SYNCHRONOUS, OK),
1070 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1071 session_deps_.socket_factory->AddSocketDataProvider(&data);
1073 const char* const kExpectedResponseData[] = {
1074 "hello", "world"
1077 for (int i = 0; i < 2; ++i) {
1078 HttpRequestInfo request;
1079 request.method = "GET";
1080 request.url = GURL("http://www.google.com/");
1081 request.load_flags = 0;
1083 scoped_ptr<HttpTransaction> trans(
1084 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1086 TestCompletionCallback callback;
1088 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1089 EXPECT_EQ(ERR_IO_PENDING, rv);
1091 rv = callback.WaitForResult();
1092 EXPECT_EQ(OK, rv);
1094 const HttpResponseInfo* response = trans->GetResponseInfo();
1095 ASSERT_TRUE(response != NULL);
1097 EXPECT_TRUE(response->headers.get() != NULL);
1098 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1099 EXPECT_TRUE(response->proxy_server.IsEmpty());
1101 std::string response_data;
1102 rv = ReadTransaction(trans.get(), &response_data);
1103 EXPECT_EQ(OK, rv);
1104 EXPECT_EQ(kExpectedResponseData[i], response_data);
1108 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1109 ScopedVector<UploadElementReader> element_readers;
1110 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1111 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1113 HttpRequestInfo request;
1114 request.method = "POST";
1115 request.url = GURL("http://www.foo.com/");
1116 request.upload_data_stream = &upload_data_stream;
1117 request.load_flags = 0;
1119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1120 scoped_ptr<HttpTransaction> trans(
1121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1123 MockRead data_reads[] = {
1124 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1125 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1126 MockRead("hello world"),
1127 MockRead(SYNCHRONOUS, OK),
1129 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1130 session_deps_.socket_factory->AddSocketDataProvider(&data);
1132 TestCompletionCallback callback;
1134 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1135 EXPECT_EQ(ERR_IO_PENDING, rv);
1137 rv = callback.WaitForResult();
1138 EXPECT_EQ(OK, rv);
1140 const HttpResponseInfo* response = trans->GetResponseInfo();
1141 ASSERT_TRUE(response != NULL);
1143 EXPECT_TRUE(response->headers.get() != NULL);
1144 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1146 std::string response_data;
1147 rv = ReadTransaction(trans.get(), &response_data);
1148 EXPECT_EQ(OK, rv);
1149 EXPECT_EQ("hello world", response_data);
1152 // This test is almost the same as Ignores100 above, but the response contains
1153 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1154 // HTTP/1.1 and the two status headers are read in one read.
1155 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1156 HttpRequestInfo request;
1157 request.method = "GET";
1158 request.url = GURL("http://www.foo.com/");
1159 request.load_flags = 0;
1161 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1162 scoped_ptr<HttpTransaction> trans(
1163 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1165 MockRead data_reads[] = {
1166 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1167 "HTTP/1.1 200 OK\r\n\r\n"),
1168 MockRead("hello world"),
1169 MockRead(SYNCHRONOUS, OK),
1171 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1172 session_deps_.socket_factory->AddSocketDataProvider(&data);
1174 TestCompletionCallback callback;
1176 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1177 EXPECT_EQ(ERR_IO_PENDING, rv);
1179 rv = callback.WaitForResult();
1180 EXPECT_EQ(OK, rv);
1182 const HttpResponseInfo* response = trans->GetResponseInfo();
1183 ASSERT_TRUE(response != NULL);
1185 EXPECT_TRUE(response->headers.get() != NULL);
1186 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1188 std::string response_data;
1189 rv = ReadTransaction(trans.get(), &response_data);
1190 EXPECT_EQ(OK, rv);
1191 EXPECT_EQ("hello world", response_data);
1194 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1195 HttpRequestInfo request;
1196 request.method = "POST";
1197 request.url = GURL("http://www.foo.com/");
1198 request.load_flags = 0;
1200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1201 scoped_ptr<HttpTransaction> trans(
1202 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1204 MockRead data_reads[] = {
1205 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1206 MockRead(ASYNC, 0),
1208 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1209 session_deps_.socket_factory->AddSocketDataProvider(&data);
1211 TestCompletionCallback callback;
1213 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1214 EXPECT_EQ(ERR_IO_PENDING, rv);
1216 rv = callback.WaitForResult();
1217 EXPECT_EQ(OK, rv);
1219 std::string response_data;
1220 rv = ReadTransaction(trans.get(), &response_data);
1221 EXPECT_EQ(OK, rv);
1222 EXPECT_EQ("", response_data);
1225 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1226 HttpRequestInfo request;
1227 request.method = "POST";
1228 request.url = GURL("http://www.foo.com/");
1229 request.load_flags = 0;
1231 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1232 scoped_ptr<HttpTransaction> trans(
1233 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1236 MockRead data_reads[] = {
1237 MockRead(ASYNC, 0),
1239 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1240 session_deps_.socket_factory->AddSocketDataProvider(&data);
1242 TestCompletionCallback callback;
1244 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1245 EXPECT_EQ(ERR_IO_PENDING, rv);
1247 rv = callback.WaitForResult();
1248 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1251 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1252 const MockWrite* write_failure,
1253 const MockRead* read_failure) {
1254 HttpRequestInfo request;
1255 request.method = "GET";
1256 request.url = GURL("http://www.foo.com/");
1257 request.load_flags = 0;
1259 CapturingNetLog net_log;
1260 session_deps_.net_log = &net_log;
1261 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1263 // Written data for successfully sending both requests.
1264 MockWrite data1_writes[] = {
1265 MockWrite("GET / HTTP/1.1\r\n"
1266 "Host: www.foo.com\r\n"
1267 "Connection: keep-alive\r\n\r\n"),
1268 MockWrite("GET / HTTP/1.1\r\n"
1269 "Host: www.foo.com\r\n"
1270 "Connection: keep-alive\r\n\r\n")
1273 // Read results for the first request.
1274 MockRead data1_reads[] = {
1275 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1276 MockRead("hello"),
1277 MockRead(ASYNC, OK),
1280 if (write_failure) {
1281 ASSERT_FALSE(read_failure);
1282 data1_writes[1] = *write_failure;
1283 } else {
1284 ASSERT_TRUE(read_failure);
1285 data1_reads[2] = *read_failure;
1288 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1289 data1_writes, arraysize(data1_writes));
1290 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1292 MockRead data2_reads[] = {
1293 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1294 MockRead("world"),
1295 MockRead(ASYNC, OK),
1297 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1298 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1300 const char* kExpectedResponseData[] = {
1301 "hello", "world"
1304 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1305 for (int i = 0; i < 2; ++i) {
1306 TestCompletionCallback callback;
1308 scoped_ptr<HttpTransaction> trans(
1309 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1311 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1312 EXPECT_EQ(ERR_IO_PENDING, rv);
1314 rv = callback.WaitForResult();
1315 EXPECT_EQ(OK, rv);
1317 LoadTimingInfo load_timing_info;
1318 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1319 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1320 if (i == 0) {
1321 first_socket_log_id = load_timing_info.socket_log_id;
1322 } else {
1323 // The second request should be using a new socket.
1324 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1327 const HttpResponseInfo* response = trans->GetResponseInfo();
1328 ASSERT_TRUE(response != NULL);
1330 EXPECT_TRUE(response->headers.get() != NULL);
1331 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1333 std::string response_data;
1334 rv = ReadTransaction(trans.get(), &response_data);
1335 EXPECT_EQ(OK, rv);
1336 EXPECT_EQ(kExpectedResponseData[i], response_data);
1340 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1341 const MockWrite* write_failure,
1342 const MockRead* read_failure,
1343 bool use_spdy) {
1344 HttpRequestInfo request;
1345 request.method = "GET";
1346 request.url = GURL("https://www.foo.com/");
1347 request.load_flags = 0;
1349 CapturingNetLog net_log;
1350 session_deps_.net_log = &net_log;
1351 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1353 SSLSocketDataProvider ssl1(ASYNC, OK);
1354 SSLSocketDataProvider ssl2(ASYNC, OK);
1355 if (use_spdy) {
1356 ssl1.SetNextProto(GetParam());
1357 ssl2.SetNextProto(GetParam());
1359 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1360 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1362 // SPDY versions of the request and response.
1363 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1364 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1365 scoped_ptr<SpdyFrame> spdy_response(
1366 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1367 scoped_ptr<SpdyFrame> spdy_data(
1368 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1370 // HTTP/1.1 versions of the request and response.
1371 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1372 "Host: www.foo.com\r\n"
1373 "Connection: keep-alive\r\n\r\n";
1374 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1375 const char kHttpData[] = "hello";
1377 std::vector<MockRead> data1_reads;
1378 std::vector<MockWrite> data1_writes;
1379 if (write_failure) {
1380 ASSERT_FALSE(read_failure);
1381 data1_writes.push_back(*write_failure);
1382 data1_reads.push_back(MockRead(ASYNC, OK));
1383 } else {
1384 ASSERT_TRUE(read_failure);
1385 if (use_spdy) {
1386 data1_writes.push_back(CreateMockWrite(*spdy_request));
1387 } else {
1388 data1_writes.push_back(MockWrite(kHttpRequest));
1390 data1_reads.push_back(*read_failure);
1393 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1394 &data1_writes[0], data1_writes.size());
1395 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1397 std::vector<MockRead> data2_reads;
1398 std::vector<MockWrite> data2_writes;
1400 if (use_spdy) {
1401 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1403 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1404 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1405 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1406 } else {
1407 data2_writes.push_back(
1408 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1410 data2_reads.push_back(
1411 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1412 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1413 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1415 OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
1416 &data2_writes[0], data2_writes.size());
1417 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1419 // Preconnect a socket.
1420 net::SSLConfig ssl_config;
1421 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1422 session->GetNextProtos(&ssl_config.next_protos);
1423 session->http_stream_factory()->PreconnectStreams(
1424 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1425 // Wait for the preconnect to complete.
1426 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1427 base::RunLoop().RunUntilIdle();
1428 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1430 // Make the request.
1431 TestCompletionCallback callback;
1433 scoped_ptr<HttpTransaction> trans(
1434 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1436 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1437 EXPECT_EQ(ERR_IO_PENDING, rv);
1439 rv = callback.WaitForResult();
1440 EXPECT_EQ(OK, rv);
1442 LoadTimingInfo load_timing_info;
1443 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1444 TestLoadTimingNotReused(
1445 load_timing_info,
1446 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1448 const HttpResponseInfo* response = trans->GetResponseInfo();
1449 ASSERT_TRUE(response != NULL);
1451 EXPECT_TRUE(response->headers.get() != NULL);
1452 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1454 std::string response_data;
1455 rv = ReadTransaction(trans.get(), &response_data);
1456 EXPECT_EQ(OK, rv);
1457 EXPECT_EQ(kHttpData, response_data);
1460 TEST_P(HttpNetworkTransactionTest,
1461 KeepAliveConnectionNotConnectedOnWrite) {
1462 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1463 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1466 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1467 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1468 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1471 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1472 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1473 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1476 // Make sure that on a 408 response (Request Timeout), the request is retried,
1477 // if the socket was a reused keep alive socket.
1478 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1479 MockRead read_failure(SYNCHRONOUS,
1480 "HTTP/1.1 408 Request Timeout\r\n"
1481 "Connection: Keep-Alive\r\n"
1482 "Content-Length: 6\r\n\r\n"
1483 "Pickle");
1484 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1487 TEST_P(HttpNetworkTransactionTest,
1488 PreconnectErrorNotConnectedOnWrite) {
1489 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1490 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1493 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1494 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1495 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1498 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1499 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1500 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1503 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1504 MockRead read_failure(ASYNC, OK); // EOF
1505 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1508 // Make sure that on a 408 response (Request Timeout), the request is retried,
1509 // if the socket was a preconnected (UNUSED_IDLE) socket.
1510 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1511 MockRead read_failure(SYNCHRONOUS,
1512 "HTTP/1.1 408 Request Timeout\r\n"
1513 "Connection: Keep-Alive\r\n"
1514 "Content-Length: 6\r\n\r\n"
1515 "Pickle");
1516 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1517 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1520 TEST_P(HttpNetworkTransactionTest,
1521 SpdyPreconnectErrorNotConnectedOnWrite) {
1522 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1523 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1526 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1527 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1528 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1531 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1532 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1533 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1536 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1537 MockRead read_failure(ASYNC, OK); // EOF
1538 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1541 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1542 HttpRequestInfo request;
1543 request.method = "GET";
1544 request.url = GURL("http://www.google.com/");
1545 request.load_flags = 0;
1547 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1548 scoped_ptr<HttpTransaction> trans(
1549 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1551 MockRead data_reads[] = {
1552 MockRead(ASYNC, ERR_CONNECTION_RESET),
1553 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1554 MockRead("hello world"),
1555 MockRead(SYNCHRONOUS, OK),
1557 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1558 session_deps_.socket_factory->AddSocketDataProvider(&data);
1560 TestCompletionCallback callback;
1562 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1563 EXPECT_EQ(ERR_IO_PENDING, rv);
1565 rv = callback.WaitForResult();
1566 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1568 const HttpResponseInfo* response = trans->GetResponseInfo();
1569 EXPECT_TRUE(response == NULL);
1572 // What do various browsers do when the server closes a non-keepalive
1573 // connection without sending any response header or body?
1575 // IE7: error page
1576 // Safari 3.1.2 (Windows): error page
1577 // Firefox 3.0.1: blank page
1578 // Opera 9.52: after five attempts, blank page
1579 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1580 // Us: error page (EMPTY_RESPONSE)
1581 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1582 MockRead data_reads[] = {
1583 MockRead(SYNCHRONOUS, OK), // EOF
1584 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1585 MockRead("hello world"),
1586 MockRead(SYNCHRONOUS, OK),
1588 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1589 arraysize(data_reads));
1590 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1593 // Test that network access can be deferred and resumed.
1594 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1595 HttpRequestInfo request;
1596 request.method = "GET";
1597 request.url = GURL("http://www.google.com/");
1598 request.load_flags = 0;
1600 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1601 scoped_ptr<HttpTransaction> trans(
1602 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1604 // Defer on OnBeforeNetworkStart.
1605 BeforeNetworkStartHandler net_start_handler(true); // defer
1606 trans->SetBeforeNetworkStartCallback(
1607 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1608 base::Unretained(&net_start_handler)));
1610 MockRead data_reads[] = {
1611 MockRead("HTTP/1.0 200 OK\r\n"),
1612 MockRead("Content-Length: 5\r\n\r\n"),
1613 MockRead("hello"),
1614 MockRead(SYNCHRONOUS, 0),
1616 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1617 session_deps_.socket_factory->AddSocketDataProvider(&data);
1619 TestCompletionCallback callback;
1621 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1622 EXPECT_EQ(ERR_IO_PENDING, rv);
1623 base::MessageLoop::current()->RunUntilIdle();
1625 // Should have deferred for network start.
1626 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1627 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1628 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1630 trans->ResumeNetworkStart();
1631 rv = callback.WaitForResult();
1632 EXPECT_EQ(OK, rv);
1633 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1635 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1636 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1637 if (rv == ERR_IO_PENDING)
1638 rv = callback.WaitForResult();
1639 EXPECT_EQ(5, rv);
1640 trans.reset();
1643 // Test that network use can be deferred and canceled.
1644 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1645 HttpRequestInfo request;
1646 request.method = "GET";
1647 request.url = GURL("http://www.google.com/");
1648 request.load_flags = 0;
1650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1651 scoped_ptr<HttpTransaction> trans(
1652 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1654 // Defer on OnBeforeNetworkStart.
1655 BeforeNetworkStartHandler net_start_handler(true); // defer
1656 trans->SetBeforeNetworkStartCallback(
1657 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1658 base::Unretained(&net_start_handler)));
1660 TestCompletionCallback callback;
1662 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1663 EXPECT_EQ(ERR_IO_PENDING, rv);
1664 base::MessageLoop::current()->RunUntilIdle();
1666 // Should have deferred for network start.
1667 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1668 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1669 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1672 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1673 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1674 // destructor in such situations.
1675 // See http://crbug.com/154712 and http://crbug.com/156609.
1676 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1677 HttpRequestInfo request;
1678 request.method = "GET";
1679 request.url = GURL("http://www.google.com/");
1680 request.load_flags = 0;
1682 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1683 scoped_ptr<HttpTransaction> trans(
1684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1686 MockRead data_reads[] = {
1687 MockRead("HTTP/1.0 200 OK\r\n"),
1688 MockRead("Connection: keep-alive\r\n"),
1689 MockRead("Content-Length: 100\r\n\r\n"),
1690 MockRead("hello"),
1691 MockRead(SYNCHRONOUS, 0),
1693 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1694 session_deps_.socket_factory->AddSocketDataProvider(&data);
1696 TestCompletionCallback callback;
1698 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1699 EXPECT_EQ(ERR_IO_PENDING, rv);
1701 rv = callback.WaitForResult();
1702 EXPECT_EQ(OK, rv);
1704 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1705 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1706 if (rv == ERR_IO_PENDING)
1707 rv = callback.WaitForResult();
1708 EXPECT_EQ(5, rv);
1709 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1710 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1712 trans.reset();
1713 base::MessageLoop::current()->RunUntilIdle();
1714 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1717 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1718 HttpRequestInfo request;
1719 request.method = "GET";
1720 request.url = GURL("http://www.google.com/");
1721 request.load_flags = 0;
1723 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1724 scoped_ptr<HttpTransaction> trans(
1725 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1727 MockRead data_reads[] = {
1728 MockRead("HTTP/1.0 200 OK\r\n"),
1729 MockRead("Connection: keep-alive\r\n"),
1730 MockRead("Content-Length: 100\r\n\r\n"),
1731 MockRead(SYNCHRONOUS, 0),
1733 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1734 session_deps_.socket_factory->AddSocketDataProvider(&data);
1736 TestCompletionCallback callback;
1738 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1739 EXPECT_EQ(ERR_IO_PENDING, rv);
1741 rv = callback.WaitForResult();
1742 EXPECT_EQ(OK, rv);
1744 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1745 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1746 if (rv == ERR_IO_PENDING)
1747 rv = callback.WaitForResult();
1748 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1750 trans.reset();
1751 base::MessageLoop::current()->RunUntilIdle();
1752 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1755 // Test that we correctly reuse a keep-alive connection after not explicitly
1756 // reading the body.
1757 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1758 HttpRequestInfo request;
1759 request.method = "GET";
1760 request.url = GURL("http://www.foo.com/");
1761 request.load_flags = 0;
1763 CapturingNetLog net_log;
1764 session_deps_.net_log = &net_log;
1765 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1767 // Note that because all these reads happen in the same
1768 // StaticSocketDataProvider, it shows that the same socket is being reused for
1769 // all transactions.
1770 MockRead data1_reads[] = {
1771 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1772 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1773 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1774 MockRead("HTTP/1.1 302 Found\r\n"
1775 "Content-Length: 0\r\n\r\n"),
1776 MockRead("HTTP/1.1 302 Found\r\n"
1777 "Content-Length: 5\r\n\r\n"
1778 "hello"),
1779 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1780 "Content-Length: 0\r\n\r\n"),
1781 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1782 "Content-Length: 5\r\n\r\n"
1783 "hello"),
1784 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1785 MockRead("hello"),
1787 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1788 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1790 MockRead data2_reads[] = {
1791 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1793 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1794 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1796 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1797 std::string response_lines[kNumUnreadBodies];
1799 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1800 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1801 TestCompletionCallback callback;
1803 scoped_ptr<HttpTransaction> trans(
1804 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1806 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1807 EXPECT_EQ(ERR_IO_PENDING, rv);
1809 rv = callback.WaitForResult();
1810 EXPECT_EQ(OK, rv);
1812 LoadTimingInfo load_timing_info;
1813 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1814 if (i == 0) {
1815 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1816 first_socket_log_id = load_timing_info.socket_log_id;
1817 } else {
1818 TestLoadTimingReused(load_timing_info);
1819 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1822 const HttpResponseInfo* response = trans->GetResponseInfo();
1823 ASSERT_TRUE(response != NULL);
1825 ASSERT_TRUE(response->headers.get() != NULL);
1826 response_lines[i] = response->headers->GetStatusLine();
1828 // We intentionally don't read the response bodies.
1831 const char* const kStatusLines[] = {
1832 "HTTP/1.1 204 No Content",
1833 "HTTP/1.1 205 Reset Content",
1834 "HTTP/1.1 304 Not Modified",
1835 "HTTP/1.1 302 Found",
1836 "HTTP/1.1 302 Found",
1837 "HTTP/1.1 301 Moved Permanently",
1838 "HTTP/1.1 301 Moved Permanently",
1841 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1842 forgot_to_update_kStatusLines);
1844 for (int i = 0; i < kNumUnreadBodies; ++i)
1845 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1847 TestCompletionCallback callback;
1848 scoped_ptr<HttpTransaction> trans(
1849 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1850 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1851 EXPECT_EQ(ERR_IO_PENDING, rv);
1852 rv = callback.WaitForResult();
1853 EXPECT_EQ(OK, rv);
1854 const HttpResponseInfo* response = trans->GetResponseInfo();
1855 ASSERT_TRUE(response != NULL);
1856 ASSERT_TRUE(response->headers.get() != NULL);
1857 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1858 std::string response_data;
1859 rv = ReadTransaction(trans.get(), &response_data);
1860 EXPECT_EQ(OK, rv);
1861 EXPECT_EQ("hello", response_data);
1864 // Test the request-challenge-retry sequence for basic auth.
1865 // (basic auth is the easiest to mock, because it has no randomness).
1866 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1867 HttpRequestInfo request;
1868 request.method = "GET";
1869 request.url = GURL("http://www.google.com/");
1870 request.load_flags = 0;
1872 CapturingNetLog log;
1873 session_deps_.net_log = &log;
1874 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1875 scoped_ptr<HttpTransaction> trans(
1876 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1878 MockWrite data_writes1[] = {
1879 MockWrite("GET / HTTP/1.1\r\n"
1880 "Host: www.google.com\r\n"
1881 "Connection: keep-alive\r\n\r\n"),
1884 MockRead data_reads1[] = {
1885 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1886 // Give a couple authenticate options (only the middle one is actually
1887 // supported).
1888 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1889 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1890 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1891 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1892 // Large content-length -- won't matter, as connection will be reset.
1893 MockRead("Content-Length: 10000\r\n\r\n"),
1894 MockRead(SYNCHRONOUS, ERR_FAILED),
1897 // After calling trans->RestartWithAuth(), this is the request we should
1898 // be issuing -- the final header line contains the credentials.
1899 MockWrite data_writes2[] = {
1900 MockWrite("GET / HTTP/1.1\r\n"
1901 "Host: www.google.com\r\n"
1902 "Connection: keep-alive\r\n"
1903 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1906 // Lastly, the server responds with the actual content.
1907 MockRead data_reads2[] = {
1908 MockRead("HTTP/1.0 200 OK\r\n"),
1909 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1910 MockRead("Content-Length: 100\r\n\r\n"),
1911 MockRead(SYNCHRONOUS, OK),
1914 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1915 data_writes1, arraysize(data_writes1));
1916 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1917 data_writes2, arraysize(data_writes2));
1918 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1919 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1921 TestCompletionCallback callback1;
1923 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1924 EXPECT_EQ(ERR_IO_PENDING, rv);
1926 rv = callback1.WaitForResult();
1927 EXPECT_EQ(OK, rv);
1929 LoadTimingInfo load_timing_info1;
1930 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1931 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1933 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1934 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1936 const HttpResponseInfo* response = trans->GetResponseInfo();
1937 ASSERT_TRUE(response != NULL);
1938 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1940 TestCompletionCallback callback2;
1942 rv = trans->RestartWithAuth(
1943 AuthCredentials(kFoo, kBar), callback2.callback());
1944 EXPECT_EQ(ERR_IO_PENDING, rv);
1946 rv = callback2.WaitForResult();
1947 EXPECT_EQ(OK, rv);
1949 LoadTimingInfo load_timing_info2;
1950 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1951 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1952 // The load timing after restart should have a new socket ID, and times after
1953 // those of the first load timing.
1954 EXPECT_LE(load_timing_info1.receive_headers_end,
1955 load_timing_info2.connect_timing.connect_start);
1956 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1958 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1959 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1961 response = trans->GetResponseInfo();
1962 ASSERT_TRUE(response != NULL);
1963 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1964 EXPECT_EQ(100, response->headers->GetContentLength());
1967 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1968 HttpRequestInfo request;
1969 request.method = "GET";
1970 request.url = GURL("http://www.google.com/");
1971 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1973 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1974 scoped_ptr<HttpTransaction> trans(
1975 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1977 MockWrite data_writes[] = {
1978 MockWrite("GET / HTTP/1.1\r\n"
1979 "Host: www.google.com\r\n"
1980 "Connection: keep-alive\r\n\r\n"),
1983 MockRead data_reads[] = {
1984 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1985 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1986 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1987 // Large content-length -- won't matter, as connection will be reset.
1988 MockRead("Content-Length: 10000\r\n\r\n"),
1989 MockRead(SYNCHRONOUS, ERR_FAILED),
1992 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1993 data_writes, arraysize(data_writes));
1994 session_deps_.socket_factory->AddSocketDataProvider(&data);
1995 TestCompletionCallback callback;
1997 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1998 EXPECT_EQ(ERR_IO_PENDING, rv);
2000 rv = callback.WaitForResult();
2001 EXPECT_EQ(0, rv);
2003 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2004 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2006 const HttpResponseInfo* response = trans->GetResponseInfo();
2007 ASSERT_TRUE(response != NULL);
2008 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2011 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2012 // connection.
2013 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2014 HttpRequestInfo request;
2015 request.method = "GET";
2016 request.url = GURL("http://www.google.com/");
2017 request.load_flags = 0;
2019 CapturingNetLog log;
2020 session_deps_.net_log = &log;
2021 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2023 MockWrite data_writes1[] = {
2024 MockWrite("GET / HTTP/1.1\r\n"
2025 "Host: www.google.com\r\n"
2026 "Connection: keep-alive\r\n\r\n"),
2028 // After calling trans->RestartWithAuth(), this is the request we should
2029 // be issuing -- the final header line contains the credentials.
2030 MockWrite("GET / HTTP/1.1\r\n"
2031 "Host: www.google.com\r\n"
2032 "Connection: keep-alive\r\n"
2033 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2036 MockRead data_reads1[] = {
2037 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2038 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2039 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2040 MockRead("Content-Length: 14\r\n\r\n"),
2041 MockRead("Unauthorized\r\n"),
2043 // Lastly, the server responds with the actual content.
2044 MockRead("HTTP/1.1 200 OK\r\n"),
2045 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2046 MockRead("Content-Length: 5\r\n\r\n"),
2047 MockRead("Hello"),
2050 // If there is a regression where we disconnect a Keep-Alive
2051 // connection during an auth roundtrip, we'll end up reading this.
2052 MockRead data_reads2[] = {
2053 MockRead(SYNCHRONOUS, ERR_FAILED),
2056 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2057 data_writes1, arraysize(data_writes1));
2058 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2059 NULL, 0);
2060 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2061 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2063 TestCompletionCallback callback1;
2065 scoped_ptr<HttpTransaction> trans(
2066 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2067 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2068 EXPECT_EQ(ERR_IO_PENDING, rv);
2070 rv = callback1.WaitForResult();
2071 EXPECT_EQ(OK, rv);
2073 LoadTimingInfo load_timing_info1;
2074 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2075 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2077 const HttpResponseInfo* response = trans->GetResponseInfo();
2078 ASSERT_TRUE(response != NULL);
2079 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2081 TestCompletionCallback callback2;
2083 rv = trans->RestartWithAuth(
2084 AuthCredentials(kFoo, kBar), callback2.callback());
2085 EXPECT_EQ(ERR_IO_PENDING, rv);
2087 rv = callback2.WaitForResult();
2088 EXPECT_EQ(OK, rv);
2090 LoadTimingInfo load_timing_info2;
2091 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2092 TestLoadTimingReused(load_timing_info2);
2093 // The load timing after restart should have the same socket ID, and times
2094 // those of the first load timing.
2095 EXPECT_LE(load_timing_info1.receive_headers_end,
2096 load_timing_info2.send_start);
2097 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2099 response = trans->GetResponseInfo();
2100 ASSERT_TRUE(response != NULL);
2101 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2102 EXPECT_EQ(5, response->headers->GetContentLength());
2104 std::string response_data;
2105 rv = ReadTransaction(trans.get(), &response_data);
2106 EXPECT_EQ(OK, rv);
2107 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2108 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2111 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2112 // connection and with no response body to drain.
2113 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2114 HttpRequestInfo request;
2115 request.method = "GET";
2116 request.url = GURL("http://www.google.com/");
2117 request.load_flags = 0;
2119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2121 MockWrite data_writes1[] = {
2122 MockWrite("GET / HTTP/1.1\r\n"
2123 "Host: www.google.com\r\n"
2124 "Connection: keep-alive\r\n\r\n"),
2126 // After calling trans->RestartWithAuth(), this is the request we should
2127 // be issuing -- the final header line contains the credentials.
2128 MockWrite("GET / HTTP/1.1\r\n"
2129 "Host: www.google.com\r\n"
2130 "Connection: keep-alive\r\n"
2131 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2134 MockRead data_reads1[] = {
2135 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2136 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2137 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2139 // Lastly, the server responds with the actual content.
2140 MockRead("HTTP/1.1 200 OK\r\n"),
2141 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2142 MockRead("Content-Length: 5\r\n\r\n"),
2143 MockRead("hello"),
2146 // An incorrect reconnect would cause this to be read.
2147 MockRead data_reads2[] = {
2148 MockRead(SYNCHRONOUS, ERR_FAILED),
2151 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2152 data_writes1, arraysize(data_writes1));
2153 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2154 NULL, 0);
2155 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2156 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2158 TestCompletionCallback callback1;
2160 scoped_ptr<HttpTransaction> trans(
2161 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2162 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2163 EXPECT_EQ(ERR_IO_PENDING, rv);
2165 rv = callback1.WaitForResult();
2166 EXPECT_EQ(OK, rv);
2168 const HttpResponseInfo* response = trans->GetResponseInfo();
2169 ASSERT_TRUE(response != NULL);
2170 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2172 TestCompletionCallback callback2;
2174 rv = trans->RestartWithAuth(
2175 AuthCredentials(kFoo, kBar), callback2.callback());
2176 EXPECT_EQ(ERR_IO_PENDING, rv);
2178 rv = callback2.WaitForResult();
2179 EXPECT_EQ(OK, rv);
2181 response = trans->GetResponseInfo();
2182 ASSERT_TRUE(response != NULL);
2183 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2184 EXPECT_EQ(5, response->headers->GetContentLength());
2187 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2188 // connection and with a large response body to drain.
2189 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2190 HttpRequestInfo request;
2191 request.method = "GET";
2192 request.url = GURL("http://www.google.com/");
2193 request.load_flags = 0;
2195 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2197 MockWrite data_writes1[] = {
2198 MockWrite("GET / HTTP/1.1\r\n"
2199 "Host: www.google.com\r\n"
2200 "Connection: keep-alive\r\n\r\n"),
2202 // After calling trans->RestartWithAuth(), this is the request we should
2203 // be issuing -- the final header line contains the credentials.
2204 MockWrite("GET / HTTP/1.1\r\n"
2205 "Host: www.google.com\r\n"
2206 "Connection: keep-alive\r\n"
2207 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2210 // Respond with 5 kb of response body.
2211 std::string large_body_string("Unauthorized");
2212 large_body_string.append(5 * 1024, ' ');
2213 large_body_string.append("\r\n");
2215 MockRead data_reads1[] = {
2216 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2217 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2218 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2219 // 5134 = 12 + 5 * 1024 + 2
2220 MockRead("Content-Length: 5134\r\n\r\n"),
2221 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2223 // Lastly, the server responds with the actual content.
2224 MockRead("HTTP/1.1 200 OK\r\n"),
2225 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2226 MockRead("Content-Length: 5\r\n\r\n"),
2227 MockRead("hello"),
2230 // An incorrect reconnect would cause this to be read.
2231 MockRead data_reads2[] = {
2232 MockRead(SYNCHRONOUS, ERR_FAILED),
2235 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2236 data_writes1, arraysize(data_writes1));
2237 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2238 NULL, 0);
2239 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2240 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2242 TestCompletionCallback callback1;
2244 scoped_ptr<HttpTransaction> trans(
2245 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2246 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2247 EXPECT_EQ(ERR_IO_PENDING, rv);
2249 rv = callback1.WaitForResult();
2250 EXPECT_EQ(OK, rv);
2252 const HttpResponseInfo* response = trans->GetResponseInfo();
2253 ASSERT_TRUE(response != NULL);
2254 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2256 TestCompletionCallback callback2;
2258 rv = trans->RestartWithAuth(
2259 AuthCredentials(kFoo, kBar), callback2.callback());
2260 EXPECT_EQ(ERR_IO_PENDING, rv);
2262 rv = callback2.WaitForResult();
2263 EXPECT_EQ(OK, rv);
2265 response = trans->GetResponseInfo();
2266 ASSERT_TRUE(response != NULL);
2267 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2268 EXPECT_EQ(5, response->headers->GetContentLength());
2271 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2272 // connection, but the server gets impatient and closes the connection.
2273 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2274 HttpRequestInfo request;
2275 request.method = "GET";
2276 request.url = GURL("http://www.google.com/");
2277 request.load_flags = 0;
2279 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2281 MockWrite data_writes1[] = {
2282 MockWrite("GET / HTTP/1.1\r\n"
2283 "Host: www.google.com\r\n"
2284 "Connection: keep-alive\r\n\r\n"),
2285 // This simulates the seemingly successful write to a closed connection
2286 // if the bug is not fixed.
2287 MockWrite("GET / HTTP/1.1\r\n"
2288 "Host: www.google.com\r\n"
2289 "Connection: keep-alive\r\n"
2290 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2293 MockRead data_reads1[] = {
2294 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2295 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2296 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2297 MockRead("Content-Length: 14\r\n\r\n"),
2298 // Tell MockTCPClientSocket to simulate the server closing the connection.
2299 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2300 MockRead("Unauthorized\r\n"),
2301 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2304 // After calling trans->RestartWithAuth(), this is the request we should
2305 // be issuing -- the final header line contains the credentials.
2306 MockWrite data_writes2[] = {
2307 MockWrite("GET / HTTP/1.1\r\n"
2308 "Host: www.google.com\r\n"
2309 "Connection: keep-alive\r\n"
2310 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2313 // Lastly, the server responds with the actual content.
2314 MockRead data_reads2[] = {
2315 MockRead("HTTP/1.1 200 OK\r\n"),
2316 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2317 MockRead("Content-Length: 5\r\n\r\n"),
2318 MockRead("hello"),
2321 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2322 data_writes1, arraysize(data_writes1));
2323 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2324 data_writes2, arraysize(data_writes2));
2325 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2326 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2328 TestCompletionCallback callback1;
2330 scoped_ptr<HttpTransaction> trans(
2331 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2332 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2333 EXPECT_EQ(ERR_IO_PENDING, rv);
2335 rv = callback1.WaitForResult();
2336 EXPECT_EQ(OK, rv);
2338 const HttpResponseInfo* response = trans->GetResponseInfo();
2339 ASSERT_TRUE(response != NULL);
2340 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2342 TestCompletionCallback callback2;
2344 rv = trans->RestartWithAuth(
2345 AuthCredentials(kFoo, kBar), callback2.callback());
2346 EXPECT_EQ(ERR_IO_PENDING, rv);
2348 rv = callback2.WaitForResult();
2349 EXPECT_EQ(OK, rv);
2351 response = trans->GetResponseInfo();
2352 ASSERT_TRUE(response != NULL);
2353 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2354 EXPECT_EQ(5, response->headers->GetContentLength());
2357 // Test the request-challenge-retry sequence for basic auth, over a connection
2358 // that requires a restart when setting up an SSL tunnel.
2359 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
2360 HttpRequestInfo request;
2361 request.method = "GET";
2362 request.url = GURL("https://www.google.com/");
2363 // when the no authentication data flag is set.
2364 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2366 // Configure against proxy server "myproxy:70".
2367 session_deps_.proxy_service.reset(
2368 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2369 CapturingBoundNetLog log;
2370 session_deps_.net_log = log.bound().net_log();
2371 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2373 // Since we have proxy, should try to establish tunnel.
2374 MockWrite data_writes1[] = {
2375 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2376 "Host: www.google.com\r\n"
2377 "Proxy-Connection: keep-alive\r\n\r\n"),
2379 // After calling trans->RestartWithAuth(), this is the request we should
2380 // be issuing -- the final header line contains the credentials.
2381 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2382 "Host: www.google.com\r\n"
2383 "Proxy-Connection: keep-alive\r\n"
2384 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2386 MockWrite("GET / HTTP/1.1\r\n"
2387 "Host: www.google.com\r\n"
2388 "Connection: keep-alive\r\n\r\n"),
2391 // The proxy responds to the connect with a 407, using a persistent
2392 // connection.
2393 MockRead data_reads1[] = {
2394 // No credentials.
2395 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2396 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2397 MockRead("Proxy-Connection: close\r\n\r\n"),
2399 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2401 MockRead("HTTP/1.1 200 OK\r\n"),
2402 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2403 MockRead("Content-Length: 5\r\n\r\n"),
2404 MockRead(SYNCHRONOUS, "hello"),
2407 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2408 data_writes1, arraysize(data_writes1));
2409 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2410 SSLSocketDataProvider ssl(ASYNC, OK);
2411 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2413 TestCompletionCallback callback1;
2415 scoped_ptr<HttpTransaction> trans(
2416 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2418 int rv = trans->Start(&request, callback1.callback(), log.bound());
2419 EXPECT_EQ(ERR_IO_PENDING, rv);
2421 rv = callback1.WaitForResult();
2422 EXPECT_EQ(OK, rv);
2423 net::CapturingNetLog::CapturedEntryList entries;
2424 log.GetEntries(&entries);
2425 size_t pos = ExpectLogContainsSomewhere(
2426 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2427 NetLog::PHASE_NONE);
2428 ExpectLogContainsSomewhere(
2429 entries, pos,
2430 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2431 NetLog::PHASE_NONE);
2433 const HttpResponseInfo* response = trans->GetResponseInfo();
2434 ASSERT_TRUE(response != NULL);
2435 ASSERT_FALSE(response->headers.get() == NULL);
2436 EXPECT_EQ(407, response->headers->response_code());
2437 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2438 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2440 LoadTimingInfo load_timing_info;
2441 // CONNECT requests and responses are handled at the connect job level, so
2442 // the transaction does not yet have a connection.
2443 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2445 TestCompletionCallback callback2;
2447 rv = trans->RestartWithAuth(
2448 AuthCredentials(kFoo, kBar), callback2.callback());
2449 EXPECT_EQ(ERR_IO_PENDING, rv);
2451 rv = callback2.WaitForResult();
2452 EXPECT_EQ(OK, rv);
2454 response = trans->GetResponseInfo();
2455 ASSERT_TRUE(response != NULL);
2457 EXPECT_TRUE(response->headers->IsKeepAlive());
2458 EXPECT_EQ(200, response->headers->response_code());
2459 EXPECT_EQ(5, response->headers->GetContentLength());
2460 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2462 // The password prompt info should not be set.
2463 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2465 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2466 TestLoadTimingNotReusedWithPac(load_timing_info,
2467 CONNECT_TIMING_HAS_SSL_TIMES);
2469 trans.reset();
2470 session->CloseAllConnections();
2473 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2474 // proxy connection, when setting up an SSL tunnel.
2475 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2476 HttpRequestInfo request;
2477 request.method = "GET";
2478 request.url = GURL("https://www.google.com/");
2479 // Ensure that proxy authentication is attempted even
2480 // when the no authentication data flag is set.
2481 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2483 // Configure against proxy server "myproxy:70".
2484 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2485 CapturingBoundNetLog log;
2486 session_deps_.net_log = log.bound().net_log();
2487 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2489 scoped_ptr<HttpTransaction> trans(
2490 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2492 // Since we have proxy, should try to establish tunnel.
2493 MockWrite data_writes1[] = {
2494 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2495 "Host: www.google.com\r\n"
2496 "Proxy-Connection: keep-alive\r\n\r\n"),
2498 // After calling trans->RestartWithAuth(), this is the request we should
2499 // be issuing -- the final header line contains the credentials.
2500 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2501 "Host: www.google.com\r\n"
2502 "Proxy-Connection: keep-alive\r\n"
2503 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2506 // The proxy responds to the connect with a 407, using a persistent
2507 // connection.
2508 MockRead data_reads1[] = {
2509 // No credentials.
2510 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2511 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2512 MockRead("Content-Length: 10\r\n\r\n"),
2513 MockRead("0123456789"),
2515 // Wrong credentials (wrong password).
2516 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2517 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2518 MockRead("Content-Length: 10\r\n\r\n"),
2519 // No response body because the test stops reading here.
2520 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2523 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2524 data_writes1, arraysize(data_writes1));
2525 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2527 TestCompletionCallback callback1;
2529 int rv = trans->Start(&request, callback1.callback(), log.bound());
2530 EXPECT_EQ(ERR_IO_PENDING, rv);
2532 rv = callback1.WaitForResult();
2533 EXPECT_EQ(OK, rv);
2534 net::CapturingNetLog::CapturedEntryList entries;
2535 log.GetEntries(&entries);
2536 size_t pos = ExpectLogContainsSomewhere(
2537 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2538 NetLog::PHASE_NONE);
2539 ExpectLogContainsSomewhere(
2540 entries, pos,
2541 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2542 NetLog::PHASE_NONE);
2544 const HttpResponseInfo* response = trans->GetResponseInfo();
2545 ASSERT_TRUE(response != NULL);
2546 ASSERT_FALSE(response->headers.get() == NULL);
2547 EXPECT_TRUE(response->headers->IsKeepAlive());
2548 EXPECT_EQ(407, response->headers->response_code());
2549 EXPECT_EQ(10, response->headers->GetContentLength());
2550 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2551 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2553 TestCompletionCallback callback2;
2555 // Wrong password (should be "bar").
2556 rv = trans->RestartWithAuth(
2557 AuthCredentials(kFoo, kBaz), callback2.callback());
2558 EXPECT_EQ(ERR_IO_PENDING, rv);
2560 rv = callback2.WaitForResult();
2561 EXPECT_EQ(OK, rv);
2563 response = trans->GetResponseInfo();
2564 ASSERT_TRUE(response != NULL);
2565 ASSERT_FALSE(response->headers.get() == NULL);
2566 EXPECT_TRUE(response->headers->IsKeepAlive());
2567 EXPECT_EQ(407, response->headers->response_code());
2568 EXPECT_EQ(10, response->headers->GetContentLength());
2569 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2570 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2572 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2573 // out of scope.
2574 session->CloseAllConnections();
2577 // Test that we don't read the response body when we fail to establish a tunnel,
2578 // even if the user cancels the proxy's auth attempt.
2579 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2580 HttpRequestInfo request;
2581 request.method = "GET";
2582 request.url = GURL("https://www.google.com/");
2583 request.load_flags = 0;
2585 // Configure against proxy server "myproxy:70".
2586 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2588 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2590 scoped_ptr<HttpTransaction> trans(
2591 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2593 // Since we have proxy, should try to establish tunnel.
2594 MockWrite data_writes[] = {
2595 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2596 "Host: www.google.com\r\n"
2597 "Proxy-Connection: keep-alive\r\n\r\n"),
2600 // The proxy responds to the connect with a 407.
2601 MockRead data_reads[] = {
2602 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2603 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2604 MockRead("Content-Length: 10\r\n\r\n"),
2605 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2608 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2609 data_writes, arraysize(data_writes));
2610 session_deps_.socket_factory->AddSocketDataProvider(&data);
2612 TestCompletionCallback callback;
2614 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2615 EXPECT_EQ(ERR_IO_PENDING, rv);
2617 rv = callback.WaitForResult();
2618 EXPECT_EQ(OK, rv);
2620 const HttpResponseInfo* response = trans->GetResponseInfo();
2621 ASSERT_TRUE(response != NULL);
2623 EXPECT_TRUE(response->headers->IsKeepAlive());
2624 EXPECT_EQ(407, response->headers->response_code());
2625 EXPECT_EQ(10, response->headers->GetContentLength());
2626 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2628 std::string response_data;
2629 rv = ReadTransaction(trans.get(), &response_data);
2630 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2632 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2633 session->CloseAllConnections();
2636 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2637 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2638 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2639 HttpRequestInfo request;
2640 request.method = "GET";
2641 request.url = GURL("http://www.google.com/");
2642 request.load_flags = 0;
2644 // We are using a DIRECT connection (i.e. no proxy) for this session.
2645 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2646 scoped_ptr<HttpTransaction> trans(
2647 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
2649 MockWrite data_writes1[] = {
2650 MockWrite("GET / HTTP/1.1\r\n"
2651 "Host: www.google.com\r\n"
2652 "Connection: keep-alive\r\n\r\n"),
2655 MockRead data_reads1[] = {
2656 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2657 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2658 // Large content-length -- won't matter, as connection will be reset.
2659 MockRead("Content-Length: 10000\r\n\r\n"),
2660 MockRead(SYNCHRONOUS, ERR_FAILED),
2663 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2664 data_writes1, arraysize(data_writes1));
2665 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2667 TestCompletionCallback callback;
2669 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2670 EXPECT_EQ(ERR_IO_PENDING, rv);
2672 rv = callback.WaitForResult();
2673 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2676 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2677 // through a non-authenticating proxy. The request should fail with
2678 // ERR_UNEXPECTED_PROXY_AUTH.
2679 // Note that it is impossible to detect if an HTTP server returns a 407 through
2680 // a non-authenticating proxy - there is nothing to indicate whether the
2681 // response came from the proxy or the server, so it is treated as if the proxy
2682 // issued the challenge.
2683 TEST_P(HttpNetworkTransactionTest,
2684 HttpsServerRequestsProxyAuthThroughProxy) {
2685 HttpRequestInfo request;
2686 request.method = "GET";
2687 request.url = GURL("https://www.google.com/");
2689 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2690 CapturingBoundNetLog log;
2691 session_deps_.net_log = log.bound().net_log();
2692 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2694 // Since we have proxy, should try to establish tunnel.
2695 MockWrite data_writes1[] = {
2696 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2697 "Host: www.google.com\r\n"
2698 "Proxy-Connection: keep-alive\r\n\r\n"),
2700 MockWrite("GET / HTTP/1.1\r\n"
2701 "Host: www.google.com\r\n"
2702 "Connection: keep-alive\r\n\r\n"),
2705 MockRead data_reads1[] = {
2706 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2708 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2709 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2710 MockRead("\r\n"),
2711 MockRead(SYNCHRONOUS, OK),
2714 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2715 data_writes1, arraysize(data_writes1));
2716 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2717 SSLSocketDataProvider ssl(ASYNC, OK);
2718 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2720 TestCompletionCallback callback1;
2722 scoped_ptr<HttpTransaction> trans(
2723 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2725 int rv = trans->Start(&request, callback1.callback(), log.bound());
2726 EXPECT_EQ(ERR_IO_PENDING, rv);
2728 rv = callback1.WaitForResult();
2729 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2730 net::CapturingNetLog::CapturedEntryList entries;
2731 log.GetEntries(&entries);
2732 size_t pos = ExpectLogContainsSomewhere(
2733 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2734 NetLog::PHASE_NONE);
2735 ExpectLogContainsSomewhere(
2736 entries, pos,
2737 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2738 NetLog::PHASE_NONE);
2741 // Test the load timing for HTTPS requests with an HTTP proxy.
2742 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2743 HttpRequestInfo request1;
2744 request1.method = "GET";
2745 request1.url = GURL("https://www.google.com/1");
2747 HttpRequestInfo request2;
2748 request2.method = "GET";
2749 request2.url = GURL("https://www.google.com/2");
2751 // Configure against proxy server "myproxy:70".
2752 session_deps_.proxy_service.reset(
2753 ProxyService::CreateFixed("PROXY myproxy:70"));
2754 CapturingBoundNetLog log;
2755 session_deps_.net_log = log.bound().net_log();
2756 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2758 // Since we have proxy, should try to establish tunnel.
2759 MockWrite data_writes1[] = {
2760 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2761 "Host: www.google.com\r\n"
2762 "Proxy-Connection: keep-alive\r\n\r\n"),
2764 MockWrite("GET /1 HTTP/1.1\r\n"
2765 "Host: www.google.com\r\n"
2766 "Connection: keep-alive\r\n\r\n"),
2768 MockWrite("GET /2 HTTP/1.1\r\n"
2769 "Host: www.google.com\r\n"
2770 "Connection: keep-alive\r\n\r\n"),
2773 // The proxy responds to the connect with a 407, using a persistent
2774 // connection.
2775 MockRead data_reads1[] = {
2776 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2778 MockRead("HTTP/1.1 200 OK\r\n"),
2779 MockRead("Content-Length: 1\r\n\r\n"),
2780 MockRead(SYNCHRONOUS, "1"),
2782 MockRead("HTTP/1.1 200 OK\r\n"),
2783 MockRead("Content-Length: 2\r\n\r\n"),
2784 MockRead(SYNCHRONOUS, "22"),
2787 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2788 data_writes1, arraysize(data_writes1));
2789 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2790 SSLSocketDataProvider ssl(ASYNC, OK);
2791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2793 TestCompletionCallback callback1;
2794 scoped_ptr<HttpTransaction> trans1(
2795 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2797 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2798 EXPECT_EQ(ERR_IO_PENDING, rv);
2800 rv = callback1.WaitForResult();
2801 EXPECT_EQ(OK, rv);
2803 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2804 ASSERT_TRUE(response1 != NULL);
2805 ASSERT_TRUE(response1->headers.get() != NULL);
2806 EXPECT_EQ(1, response1->headers->GetContentLength());
2808 LoadTimingInfo load_timing_info1;
2809 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2810 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2812 trans1.reset();
2814 TestCompletionCallback callback2;
2815 scoped_ptr<HttpTransaction> trans2(
2816 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2818 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2819 EXPECT_EQ(ERR_IO_PENDING, rv);
2821 rv = callback2.WaitForResult();
2822 EXPECT_EQ(OK, rv);
2824 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2825 ASSERT_TRUE(response2 != NULL);
2826 ASSERT_TRUE(response2->headers.get() != NULL);
2827 EXPECT_EQ(2, response2->headers->GetContentLength());
2829 LoadTimingInfo load_timing_info2;
2830 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2831 TestLoadTimingReused(load_timing_info2);
2833 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2835 trans2.reset();
2836 session->CloseAllConnections();
2839 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2840 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2841 HttpRequestInfo request1;
2842 request1.method = "GET";
2843 request1.url = GURL("https://www.google.com/1");
2845 HttpRequestInfo request2;
2846 request2.method = "GET";
2847 request2.url = GURL("https://www.google.com/2");
2849 // Configure against proxy server "myproxy:70".
2850 session_deps_.proxy_service.reset(
2851 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2852 CapturingBoundNetLog log;
2853 session_deps_.net_log = log.bound().net_log();
2854 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2856 // Since we have proxy, should try to establish tunnel.
2857 MockWrite data_writes1[] = {
2858 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2859 "Host: www.google.com\r\n"
2860 "Proxy-Connection: keep-alive\r\n\r\n"),
2862 MockWrite("GET /1 HTTP/1.1\r\n"
2863 "Host: www.google.com\r\n"
2864 "Connection: keep-alive\r\n\r\n"),
2866 MockWrite("GET /2 HTTP/1.1\r\n"
2867 "Host: www.google.com\r\n"
2868 "Connection: keep-alive\r\n\r\n"),
2871 // The proxy responds to the connect with a 407, using a persistent
2872 // connection.
2873 MockRead data_reads1[] = {
2874 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2876 MockRead("HTTP/1.1 200 OK\r\n"),
2877 MockRead("Content-Length: 1\r\n\r\n"),
2878 MockRead(SYNCHRONOUS, "1"),
2880 MockRead("HTTP/1.1 200 OK\r\n"),
2881 MockRead("Content-Length: 2\r\n\r\n"),
2882 MockRead(SYNCHRONOUS, "22"),
2885 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2886 data_writes1, arraysize(data_writes1));
2887 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2888 SSLSocketDataProvider ssl(ASYNC, OK);
2889 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2891 TestCompletionCallback callback1;
2892 scoped_ptr<HttpTransaction> trans1(
2893 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2895 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2896 EXPECT_EQ(ERR_IO_PENDING, rv);
2898 rv = callback1.WaitForResult();
2899 EXPECT_EQ(OK, rv);
2901 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2902 ASSERT_TRUE(response1 != NULL);
2903 ASSERT_TRUE(response1->headers.get() != NULL);
2904 EXPECT_EQ(1, response1->headers->GetContentLength());
2906 LoadTimingInfo load_timing_info1;
2907 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2908 TestLoadTimingNotReusedWithPac(load_timing_info1,
2909 CONNECT_TIMING_HAS_SSL_TIMES);
2911 trans1.reset();
2913 TestCompletionCallback callback2;
2914 scoped_ptr<HttpTransaction> trans2(
2915 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2917 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2918 EXPECT_EQ(ERR_IO_PENDING, rv);
2920 rv = callback2.WaitForResult();
2921 EXPECT_EQ(OK, rv);
2923 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2924 ASSERT_TRUE(response2 != NULL);
2925 ASSERT_TRUE(response2->headers.get() != NULL);
2926 EXPECT_EQ(2, response2->headers->GetContentLength());
2928 LoadTimingInfo load_timing_info2;
2929 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2930 TestLoadTimingReusedWithPac(load_timing_info2);
2932 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2934 trans2.reset();
2935 session->CloseAllConnections();
2938 // Test a simple get through an HTTPS Proxy.
2939 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2940 HttpRequestInfo request;
2941 request.method = "GET";
2942 request.url = GURL("http://www.google.com/");
2944 // Configure against https proxy server "proxy:70".
2945 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2946 "https://proxy:70"));
2947 CapturingBoundNetLog log;
2948 session_deps_.net_log = log.bound().net_log();
2949 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2951 // Since we have proxy, should use full url
2952 MockWrite data_writes1[] = {
2953 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2954 "Host: www.google.com\r\n"
2955 "Proxy-Connection: keep-alive\r\n\r\n"),
2958 MockRead data_reads1[] = {
2959 MockRead("HTTP/1.1 200 OK\r\n"),
2960 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2961 MockRead("Content-Length: 100\r\n\r\n"),
2962 MockRead(SYNCHRONOUS, OK),
2965 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2966 data_writes1, arraysize(data_writes1));
2967 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2968 SSLSocketDataProvider ssl(ASYNC, OK);
2969 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2971 TestCompletionCallback callback1;
2973 scoped_ptr<HttpTransaction> trans(
2974 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2976 int rv = trans->Start(&request, callback1.callback(), log.bound());
2977 EXPECT_EQ(ERR_IO_PENDING, rv);
2979 rv = callback1.WaitForResult();
2980 EXPECT_EQ(OK, rv);
2982 LoadTimingInfo load_timing_info;
2983 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2984 TestLoadTimingNotReused(load_timing_info,
2985 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2987 const HttpResponseInfo* response = trans->GetResponseInfo();
2988 ASSERT_TRUE(response != NULL);
2990 EXPECT_TRUE(response->headers->IsKeepAlive());
2991 EXPECT_EQ(200, response->headers->response_code());
2992 EXPECT_EQ(100, response->headers->GetContentLength());
2993 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2995 // The password prompt info should not be set.
2996 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2999 // Test a SPDY get through an HTTPS Proxy.
3000 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3001 HttpRequestInfo request;
3002 request.method = "GET";
3003 request.url = GURL("http://www.google.com/");
3004 request.load_flags = 0;
3006 // Configure against https proxy server "proxy:70".
3007 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3008 "https://proxy:70"));
3009 CapturingBoundNetLog log;
3010 session_deps_.net_log = log.bound().net_log();
3011 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3013 // fetch http://www.google.com/ via SPDY
3014 scoped_ptr<SpdyFrame> req(
3015 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3016 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
3018 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3019 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3020 MockRead spdy_reads[] = {
3021 CreateMockRead(*resp),
3022 CreateMockRead(*data),
3023 MockRead(ASYNC, 0, 0),
3026 DelayedSocketData spdy_data(
3027 1, // wait for one write to finish before reading.
3028 spdy_reads, arraysize(spdy_reads),
3029 spdy_writes, arraysize(spdy_writes));
3030 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3032 SSLSocketDataProvider ssl(ASYNC, OK);
3033 ssl.SetNextProto(GetParam());
3034 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3036 TestCompletionCallback callback1;
3038 scoped_ptr<HttpTransaction> trans(
3039 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3041 int rv = trans->Start(&request, callback1.callback(), log.bound());
3042 EXPECT_EQ(ERR_IO_PENDING, rv);
3044 rv = callback1.WaitForResult();
3045 EXPECT_EQ(OK, rv);
3047 LoadTimingInfo load_timing_info;
3048 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3049 TestLoadTimingNotReused(load_timing_info,
3050 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3052 const HttpResponseInfo* response = trans->GetResponseInfo();
3053 ASSERT_TRUE(response != NULL);
3054 ASSERT_TRUE(response->headers.get() != NULL);
3055 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3057 std::string response_data;
3058 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3059 EXPECT_EQ(kUploadData, response_data);
3062 // Verifies that a session which races and wins against the owning transaction
3063 // (completing prior to host resolution), doesn't fail the transaction.
3064 // Regression test for crbug.com/334413.
3065 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3066 HttpRequestInfo request;
3067 request.method = "GET";
3068 request.url = GURL("http://www.google.com/");
3069 request.load_flags = 0;
3071 // Configure SPDY proxy server "proxy:70".
3072 session_deps_.proxy_service.reset(
3073 ProxyService::CreateFixed("https://proxy:70"));
3074 CapturingBoundNetLog log;
3075 session_deps_.net_log = log.bound().net_log();
3076 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3078 // Fetch http://www.google.com/ through the SPDY proxy.
3079 scoped_ptr<SpdyFrame> req(
3080 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3081 MockWrite spdy_writes[] = {CreateMockWrite(*req)};
3083 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3084 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3085 MockRead spdy_reads[] = {
3086 CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0),
3089 DelayedSocketData spdy_data(
3090 1, // wait for one write to finish before reading.
3091 spdy_reads,
3092 arraysize(spdy_reads),
3093 spdy_writes,
3094 arraysize(spdy_writes));
3095 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3097 SSLSocketDataProvider ssl(ASYNC, OK);
3098 ssl.SetNextProto(GetParam());
3099 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3101 TestCompletionCallback callback1;
3103 scoped_ptr<HttpTransaction> trans(
3104 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3106 // Stall the hostname resolution begun by the transaction.
3107 session_deps_.host_resolver->set_synchronous_mode(false);
3108 session_deps_.host_resolver->set_ondemand_mode(true);
3110 int rv = trans->Start(&request, callback1.callback(), log.bound());
3111 EXPECT_EQ(ERR_IO_PENDING, rv);
3113 // Race a session to the proxy, which completes first.
3114 session_deps_.host_resolver->set_ondemand_mode(false);
3115 SpdySessionKey key(
3116 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3117 base::WeakPtr<SpdySession> spdy_session =
3118 CreateSecureSpdySession(session, key, log.bound());
3120 // Unstall the resolution begun by the transaction.
3121 session_deps_.host_resolver->set_ondemand_mode(true);
3122 session_deps_.host_resolver->ResolveAllPending();
3124 EXPECT_FALSE(callback1.have_result());
3125 rv = callback1.WaitForResult();
3126 EXPECT_EQ(OK, rv);
3128 const HttpResponseInfo* response = trans->GetResponseInfo();
3129 ASSERT_TRUE(response != NULL);
3130 ASSERT_TRUE(response->headers.get() != NULL);
3131 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3133 std::string response_data;
3134 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3135 EXPECT_EQ(kUploadData, response_data);
3138 // Test a SPDY get through an HTTPS Proxy.
3139 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3140 HttpRequestInfo request;
3141 request.method = "GET";
3142 request.url = GURL("http://www.google.com/");
3143 request.load_flags = 0;
3145 // Configure against https proxy server "myproxy:70".
3146 session_deps_.proxy_service.reset(
3147 ProxyService::CreateFixed("https://myproxy:70"));
3148 CapturingBoundNetLog log;
3149 session_deps_.net_log = log.bound().net_log();
3150 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3152 // The first request will be a bare GET, the second request will be a
3153 // GET with a Proxy-Authorization header.
3154 scoped_ptr<SpdyFrame> req_get(
3155 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3156 const char* const kExtraAuthorizationHeaders[] = {
3157 "proxy-authorization", "Basic Zm9vOmJhcg=="
3159 scoped_ptr<SpdyFrame> req_get_authorization(
3160 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3161 arraysize(kExtraAuthorizationHeaders) / 2,
3162 false,
3164 LOWEST,
3165 false));
3166 MockWrite spdy_writes[] = {
3167 CreateMockWrite(*req_get, 1),
3168 CreateMockWrite(*req_get_authorization, 4),
3171 // The first response is a 407 proxy authentication challenge, and the second
3172 // response will be a 200 response since the second request includes a valid
3173 // Authorization header.
3174 const char* const kExtraAuthenticationHeaders[] = {
3175 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3177 scoped_ptr<SpdyFrame> resp_authentication(
3178 spdy_util_.ConstructSpdySynReplyError(
3179 "407 Proxy Authentication Required",
3180 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3181 1));
3182 scoped_ptr<SpdyFrame> body_authentication(
3183 spdy_util_.ConstructSpdyBodyFrame(1, true));
3184 scoped_ptr<SpdyFrame> resp_data(
3185 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3186 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3187 MockRead spdy_reads[] = {
3188 CreateMockRead(*resp_authentication, 2),
3189 CreateMockRead(*body_authentication, 3),
3190 CreateMockRead(*resp_data, 5),
3191 CreateMockRead(*body_data, 6),
3192 MockRead(ASYNC, 0, 7),
3195 OrderedSocketData data(
3196 spdy_reads, arraysize(spdy_reads),
3197 spdy_writes, arraysize(spdy_writes));
3198 session_deps_.socket_factory->AddSocketDataProvider(&data);
3200 SSLSocketDataProvider ssl(ASYNC, OK);
3201 ssl.SetNextProto(GetParam());
3202 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3204 TestCompletionCallback callback1;
3206 scoped_ptr<HttpTransaction> trans(
3207 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3209 int rv = trans->Start(&request, callback1.callback(), log.bound());
3210 EXPECT_EQ(ERR_IO_PENDING, rv);
3212 rv = callback1.WaitForResult();
3213 EXPECT_EQ(OK, rv);
3215 const HttpResponseInfo* const response = trans->GetResponseInfo();
3217 ASSERT_TRUE(response != NULL);
3218 ASSERT_TRUE(response->headers.get() != NULL);
3219 EXPECT_EQ(407, response->headers->response_code());
3220 EXPECT_TRUE(response->was_fetched_via_spdy);
3221 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3223 TestCompletionCallback callback2;
3225 rv = trans->RestartWithAuth(
3226 AuthCredentials(kFoo, kBar), callback2.callback());
3227 EXPECT_EQ(ERR_IO_PENDING, rv);
3229 rv = callback2.WaitForResult();
3230 EXPECT_EQ(OK, rv);
3232 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3234 ASSERT_TRUE(response_restart != NULL);
3235 ASSERT_TRUE(response_restart->headers.get() != NULL);
3236 EXPECT_EQ(200, response_restart->headers->response_code());
3237 // The password prompt info should not be set.
3238 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3241 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3242 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3243 HttpRequestInfo request;
3244 request.method = "GET";
3245 request.url = GURL("https://www.google.com/");
3246 request.load_flags = 0;
3248 // Configure against https proxy server "proxy:70".
3249 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3250 "https://proxy:70"));
3251 CapturingBoundNetLog log;
3252 session_deps_.net_log = log.bound().net_log();
3253 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3255 scoped_ptr<HttpTransaction> trans(
3256 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3258 // CONNECT to www.google.com:443 via SPDY
3259 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3260 LOWEST));
3261 // fetch https://www.google.com/ via HTTP
3263 const char get[] = "GET / HTTP/1.1\r\n"
3264 "Host: www.google.com\r\n"
3265 "Connection: keep-alive\r\n\r\n";
3266 scoped_ptr<SpdyFrame> wrapped_get(
3267 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3268 scoped_ptr<SpdyFrame> conn_resp(
3269 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3270 const char resp[] = "HTTP/1.1 200 OK\r\n"
3271 "Content-Length: 10\r\n\r\n";
3272 scoped_ptr<SpdyFrame> wrapped_get_resp(
3273 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3274 scoped_ptr<SpdyFrame> wrapped_body(
3275 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3276 scoped_ptr<SpdyFrame> window_update(
3277 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3279 MockWrite spdy_writes[] = {
3280 CreateMockWrite(*connect, 1),
3281 CreateMockWrite(*wrapped_get, 3),
3282 CreateMockWrite(*window_update, 5),
3285 MockRead spdy_reads[] = {
3286 CreateMockRead(*conn_resp, 2, ASYNC),
3287 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3288 CreateMockRead(*wrapped_body, 6, ASYNC),
3289 CreateMockRead(*wrapped_body, 7, ASYNC),
3290 MockRead(ASYNC, 0, 8),
3293 OrderedSocketData spdy_data(
3294 spdy_reads, arraysize(spdy_reads),
3295 spdy_writes, arraysize(spdy_writes));
3296 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3298 SSLSocketDataProvider ssl(ASYNC, OK);
3299 ssl.SetNextProto(GetParam());
3300 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3301 SSLSocketDataProvider ssl2(ASYNC, OK);
3302 ssl2.was_npn_negotiated = false;
3303 ssl2.protocol_negotiated = kProtoUnknown;
3304 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3306 TestCompletionCallback callback1;
3308 int rv = trans->Start(&request, callback1.callback(), log.bound());
3309 EXPECT_EQ(ERR_IO_PENDING, rv);
3311 rv = callback1.WaitForResult();
3312 EXPECT_EQ(OK, rv);
3314 LoadTimingInfo load_timing_info;
3315 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3316 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3318 const HttpResponseInfo* response = trans->GetResponseInfo();
3319 ASSERT_TRUE(response != NULL);
3320 ASSERT_TRUE(response->headers.get() != NULL);
3321 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3323 std::string response_data;
3324 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3325 EXPECT_EQ("1234567890", response_data);
3328 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3329 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3330 HttpRequestInfo request;
3331 request.method = "GET";
3332 request.url = GURL("https://www.google.com/");
3333 request.load_flags = 0;
3335 // Configure against https proxy server "proxy:70".
3336 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3337 "https://proxy:70"));
3338 CapturingBoundNetLog log;
3339 session_deps_.net_log = log.bound().net_log();
3340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3342 scoped_ptr<HttpTransaction> trans(
3343 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3345 // CONNECT to www.google.com:443 via SPDY
3346 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3347 LOWEST));
3348 // fetch https://www.google.com/ via SPDY
3349 const char* const kMyUrl = "https://www.google.com/";
3350 scoped_ptr<SpdyFrame> get(
3351 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3352 scoped_ptr<SpdyFrame> wrapped_get(
3353 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3354 scoped_ptr<SpdyFrame> conn_resp(
3355 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3356 scoped_ptr<SpdyFrame> get_resp(
3357 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3358 scoped_ptr<SpdyFrame> wrapped_get_resp(
3359 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3360 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3361 scoped_ptr<SpdyFrame> wrapped_body(
3362 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3363 scoped_ptr<SpdyFrame> window_update_get_resp(
3364 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3365 scoped_ptr<SpdyFrame> window_update_body(
3366 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3368 MockWrite spdy_writes[] = {
3369 CreateMockWrite(*connect, 1),
3370 CreateMockWrite(*wrapped_get, 3),
3371 CreateMockWrite(*window_update_get_resp, 5),
3372 CreateMockWrite(*window_update_body, 7),
3375 MockRead spdy_reads[] = {
3376 CreateMockRead(*conn_resp, 2, ASYNC),
3377 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3378 CreateMockRead(*wrapped_body, 6, ASYNC),
3379 MockRead(ASYNC, 0, 8),
3382 OrderedSocketData spdy_data(
3383 spdy_reads, arraysize(spdy_reads),
3384 spdy_writes, arraysize(spdy_writes));
3385 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3387 SSLSocketDataProvider ssl(ASYNC, OK);
3388 ssl.SetNextProto(GetParam());
3389 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3390 SSLSocketDataProvider ssl2(ASYNC, OK);
3391 ssl2.SetNextProto(GetParam());
3392 ssl2.protocol_negotiated = GetParam();
3393 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3395 TestCompletionCallback callback1;
3397 int rv = trans->Start(&request, callback1.callback(), log.bound());
3398 EXPECT_EQ(ERR_IO_PENDING, rv);
3400 rv = callback1.WaitForResult();
3401 EXPECT_EQ(OK, rv);
3403 LoadTimingInfo load_timing_info;
3404 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3405 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3407 const HttpResponseInfo* response = trans->GetResponseInfo();
3408 ASSERT_TRUE(response != NULL);
3409 ASSERT_TRUE(response->headers.get() != NULL);
3410 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3412 std::string response_data;
3413 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3414 EXPECT_EQ(kUploadData, response_data);
3417 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3418 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3419 HttpRequestInfo request;
3420 request.method = "GET";
3421 request.url = GURL("https://www.google.com/");
3422 request.load_flags = 0;
3424 // Configure against https proxy server "proxy:70".
3425 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3426 "https://proxy:70"));
3427 CapturingBoundNetLog log;
3428 session_deps_.net_log = log.bound().net_log();
3429 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3431 scoped_ptr<HttpTransaction> trans(
3432 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3434 // CONNECT to www.google.com:443 via SPDY
3435 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3436 LOWEST));
3437 scoped_ptr<SpdyFrame> get(
3438 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3440 MockWrite spdy_writes[] = {
3441 CreateMockWrite(*connect, 1),
3442 CreateMockWrite(*get, 3),
3445 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3446 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3447 MockRead spdy_reads[] = {
3448 CreateMockRead(*resp, 2, ASYNC),
3449 MockRead(ASYNC, 0, 4),
3452 OrderedSocketData spdy_data(
3453 spdy_reads, arraysize(spdy_reads),
3454 spdy_writes, arraysize(spdy_writes));
3455 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3457 SSLSocketDataProvider ssl(ASYNC, OK);
3458 ssl.SetNextProto(GetParam());
3459 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3460 SSLSocketDataProvider ssl2(ASYNC, OK);
3461 ssl2.SetNextProto(GetParam());
3462 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3464 TestCompletionCallback callback1;
3466 int rv = trans->Start(&request, callback1.callback(), log.bound());
3467 EXPECT_EQ(ERR_IO_PENDING, rv);
3469 rv = callback1.WaitForResult();
3470 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3472 // TODO(ttuttle): Anything else to check here?
3475 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3476 // HTTPS Proxy to different servers.
3477 TEST_P(HttpNetworkTransactionTest,
3478 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3479 // Configure against https proxy server "proxy:70".
3480 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3481 "https://proxy:70"));
3482 CapturingBoundNetLog log;
3483 session_deps_.net_log = log.bound().net_log();
3484 scoped_refptr<HttpNetworkSession> session(
3485 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3487 HttpRequestInfo request1;
3488 request1.method = "GET";
3489 request1.url = GURL("https://www.google.com/");
3490 request1.load_flags = 0;
3492 HttpRequestInfo request2;
3493 request2.method = "GET";
3494 request2.url = GURL("https://news.google.com/");
3495 request2.load_flags = 0;
3497 // CONNECT to www.google.com:443 via SPDY.
3498 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3499 LOWEST));
3500 scoped_ptr<SpdyFrame> conn_resp1(
3501 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3503 // Fetch https://www.google.com/ via HTTP.
3504 const char get1[] = "GET / HTTP/1.1\r\n"
3505 "Host: www.google.com\r\n"
3506 "Connection: keep-alive\r\n\r\n";
3507 scoped_ptr<SpdyFrame> wrapped_get1(
3508 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3509 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3510 "Content-Length: 1\r\n\r\n";
3511 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3512 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3513 scoped_ptr<SpdyFrame> wrapped_body1(
3514 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3515 scoped_ptr<SpdyFrame> window_update(
3516 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3518 // CONNECT to news.google.com:443 via SPDY.
3519 SpdyHeaderBlock connect2_block;
3520 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3521 connect2_block[spdy_util_.GetPathKey()] = "news.google.com:443";
3522 connect2_block[spdy_util_.GetHostKey()] = "news.google.com";
3523 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3524 scoped_ptr<SpdyFrame> connect2(
3525 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3527 scoped_ptr<SpdyFrame> conn_resp2(
3528 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3530 // Fetch https://news.google.com/ via HTTP.
3531 const char get2[] = "GET / HTTP/1.1\r\n"
3532 "Host: news.google.com\r\n"
3533 "Connection: keep-alive\r\n\r\n";
3534 scoped_ptr<SpdyFrame> wrapped_get2(
3535 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3536 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3537 "Content-Length: 2\r\n\r\n";
3538 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3539 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3540 scoped_ptr<SpdyFrame> wrapped_body2(
3541 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3543 MockWrite spdy_writes[] = {
3544 CreateMockWrite(*connect1, 0),
3545 CreateMockWrite(*wrapped_get1, 2),
3546 CreateMockWrite(*connect2, 5),
3547 CreateMockWrite(*wrapped_get2, 7),
3550 MockRead spdy_reads[] = {
3551 CreateMockRead(*conn_resp1, 1, ASYNC),
3552 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3553 CreateMockRead(*wrapped_body1, 4, ASYNC),
3554 CreateMockRead(*conn_resp2, 6, ASYNC),
3555 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3556 CreateMockRead(*wrapped_body2, 9, ASYNC),
3557 MockRead(ASYNC, 0, 10),
3560 DeterministicSocketData spdy_data(
3561 spdy_reads, arraysize(spdy_reads),
3562 spdy_writes, arraysize(spdy_writes));
3563 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3565 SSLSocketDataProvider ssl(ASYNC, OK);
3566 ssl.SetNextProto(GetParam());
3567 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3568 SSLSocketDataProvider ssl2(ASYNC, OK);
3569 ssl2.was_npn_negotiated = false;
3570 ssl2.protocol_negotiated = kProtoUnknown;
3571 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3572 SSLSocketDataProvider ssl3(ASYNC, OK);
3573 ssl3.was_npn_negotiated = false;
3574 ssl3.protocol_negotiated = kProtoUnknown;
3575 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3577 TestCompletionCallback callback;
3579 scoped_ptr<HttpTransaction> trans(
3580 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3581 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3582 EXPECT_EQ(ERR_IO_PENDING, rv);
3583 // The first connect and request, each of their responses, and the body.
3584 spdy_data.RunFor(5);
3586 rv = callback.WaitForResult();
3587 EXPECT_EQ(OK, rv);
3589 LoadTimingInfo load_timing_info;
3590 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3591 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3593 const HttpResponseInfo* response = trans->GetResponseInfo();
3594 ASSERT_TRUE(response != NULL);
3595 ASSERT_TRUE(response->headers.get() != NULL);
3596 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3598 std::string response_data;
3599 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3600 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3602 scoped_ptr<HttpTransaction> trans2(
3603 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3604 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3605 EXPECT_EQ(ERR_IO_PENDING, rv);
3607 // The second connect and request, each of their responses, and the body.
3608 spdy_data.RunFor(5);
3609 rv = callback.WaitForResult();
3610 EXPECT_EQ(OK, rv);
3612 LoadTimingInfo load_timing_info2;
3613 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3614 // Even though the SPDY connection is reused, a new tunnelled connection has
3615 // to be created, so the socket's load timing looks like a fresh connection.
3616 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3618 // The requests should have different IDs, since they each are using their own
3619 // separate stream.
3620 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3622 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3625 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3626 // HTTPS Proxy to the same server.
3627 TEST_P(HttpNetworkTransactionTest,
3628 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3629 // Configure against https proxy server "proxy:70".
3630 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3631 "https://proxy:70"));
3632 CapturingBoundNetLog log;
3633 session_deps_.net_log = log.bound().net_log();
3634 scoped_refptr<HttpNetworkSession> session(
3635 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3637 HttpRequestInfo request1;
3638 request1.method = "GET";
3639 request1.url = GURL("https://www.google.com/");
3640 request1.load_flags = 0;
3642 HttpRequestInfo request2;
3643 request2.method = "GET";
3644 request2.url = GURL("https://www.google.com/2");
3645 request2.load_flags = 0;
3647 // CONNECT to www.google.com:443 via SPDY.
3648 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3649 LOWEST));
3650 scoped_ptr<SpdyFrame> conn_resp1(
3651 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3653 // Fetch https://www.google.com/ via HTTP.
3654 const char get1[] = "GET / HTTP/1.1\r\n"
3655 "Host: www.google.com\r\n"
3656 "Connection: keep-alive\r\n\r\n";
3657 scoped_ptr<SpdyFrame> wrapped_get1(
3658 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3659 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3660 "Content-Length: 1\r\n\r\n";
3661 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3662 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3663 scoped_ptr<SpdyFrame> wrapped_body1(
3664 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3665 scoped_ptr<SpdyFrame> window_update(
3666 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3668 // Fetch https://www.google.com/2 via HTTP.
3669 const char get2[] = "GET /2 HTTP/1.1\r\n"
3670 "Host: www.google.com\r\n"
3671 "Connection: keep-alive\r\n\r\n";
3672 scoped_ptr<SpdyFrame> wrapped_get2(
3673 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3674 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3675 "Content-Length: 2\r\n\r\n";
3676 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3677 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3678 scoped_ptr<SpdyFrame> wrapped_body2(
3679 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3681 MockWrite spdy_writes[] = {
3682 CreateMockWrite(*connect1, 0),
3683 CreateMockWrite(*wrapped_get1, 2),
3684 CreateMockWrite(*wrapped_get2, 5),
3687 MockRead spdy_reads[] = {
3688 CreateMockRead(*conn_resp1, 1, ASYNC),
3689 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3690 CreateMockRead(*wrapped_body1, 4, ASYNC),
3691 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3692 CreateMockRead(*wrapped_body2, 7, ASYNC),
3693 MockRead(ASYNC, 0, 8),
3696 DeterministicSocketData spdy_data(
3697 spdy_reads, arraysize(spdy_reads),
3698 spdy_writes, arraysize(spdy_writes));
3699 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3701 SSLSocketDataProvider ssl(ASYNC, OK);
3702 ssl.SetNextProto(GetParam());
3703 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3704 SSLSocketDataProvider ssl2(ASYNC, OK);
3705 ssl2.was_npn_negotiated = false;
3706 ssl2.protocol_negotiated = kProtoUnknown;
3707 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3709 TestCompletionCallback callback;
3711 scoped_ptr<HttpTransaction> trans(
3712 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3713 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3714 EXPECT_EQ(ERR_IO_PENDING, rv);
3715 // The first connect and request, each of their responses, and the body.
3716 spdy_data.RunFor(5);
3718 rv = callback.WaitForResult();
3719 EXPECT_EQ(OK, rv);
3721 LoadTimingInfo load_timing_info;
3722 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3723 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3725 const HttpResponseInfo* response = trans->GetResponseInfo();
3726 ASSERT_TRUE(response != NULL);
3727 ASSERT_TRUE(response->headers.get() != NULL);
3728 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3730 std::string response_data;
3731 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3732 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3733 trans.reset();
3735 scoped_ptr<HttpTransaction> trans2(
3736 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3737 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3738 EXPECT_EQ(ERR_IO_PENDING, rv);
3740 // The second request, response, and body. There should not be a second
3741 // connect.
3742 spdy_data.RunFor(3);
3743 rv = callback.WaitForResult();
3744 EXPECT_EQ(OK, rv);
3746 LoadTimingInfo load_timing_info2;
3747 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3748 TestLoadTimingReused(load_timing_info2);
3750 // The requests should have the same ID.
3751 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3753 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3756 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3757 // Proxy to different servers.
3758 TEST_P(HttpNetworkTransactionTest,
3759 HttpsProxySpdyLoadTimingTwoHttpRequests) {
3760 // Configure against https proxy server "proxy:70".
3761 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3762 "https://proxy:70"));
3763 CapturingBoundNetLog log;
3764 session_deps_.net_log = log.bound().net_log();
3765 scoped_refptr<HttpNetworkSession> session(
3766 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3768 HttpRequestInfo request1;
3769 request1.method = "GET";
3770 request1.url = GURL("http://www.google.com/");
3771 request1.load_flags = 0;
3773 HttpRequestInfo request2;
3774 request2.method = "GET";
3775 request2.url = GURL("http://news.google.com/");
3776 request2.load_flags = 0;
3778 // http://www.google.com/
3779 scoped_ptr<SpdyHeaderBlock> headers(
3780 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3781 scoped_ptr<SpdyFrame> get1(
3782 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
3783 scoped_ptr<SpdyFrame> get_resp1(
3784 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3785 scoped_ptr<SpdyFrame> body1(
3786 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3788 // http://news.google.com/
3789 scoped_ptr<SpdyHeaderBlock> headers2(
3790 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3791 scoped_ptr<SpdyFrame> get2(
3792 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
3793 scoped_ptr<SpdyFrame> get_resp2(
3794 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3795 scoped_ptr<SpdyFrame> body2(
3796 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3798 MockWrite spdy_writes[] = {
3799 CreateMockWrite(*get1, 0),
3800 CreateMockWrite(*get2, 3),
3803 MockRead spdy_reads[] = {
3804 CreateMockRead(*get_resp1, 1, ASYNC),
3805 CreateMockRead(*body1, 2, ASYNC),
3806 CreateMockRead(*get_resp2, 4, ASYNC),
3807 CreateMockRead(*body2, 5, ASYNC),
3808 MockRead(ASYNC, 0, 6),
3811 DeterministicSocketData spdy_data(
3812 spdy_reads, arraysize(spdy_reads),
3813 spdy_writes, arraysize(spdy_writes));
3814 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3816 SSLSocketDataProvider ssl(ASYNC, OK);
3817 ssl.SetNextProto(GetParam());
3818 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3820 TestCompletionCallback callback;
3822 scoped_ptr<HttpTransaction> trans(
3823 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3824 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3825 EXPECT_EQ(ERR_IO_PENDING, rv);
3826 spdy_data.RunFor(2);
3828 rv = callback.WaitForResult();
3829 EXPECT_EQ(OK, rv);
3831 LoadTimingInfo load_timing_info;
3832 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3833 TestLoadTimingNotReused(load_timing_info,
3834 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3836 const HttpResponseInfo* response = trans->GetResponseInfo();
3837 ASSERT_TRUE(response != NULL);
3838 ASSERT_TRUE(response->headers.get() != NULL);
3839 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3841 std::string response_data;
3842 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3843 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3844 spdy_data.RunFor(1);
3845 EXPECT_EQ(1, callback.WaitForResult());
3846 // Delete the first request, so the second one can reuse the socket.
3847 trans.reset();
3849 scoped_ptr<HttpTransaction> trans2(
3850 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3851 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3852 EXPECT_EQ(ERR_IO_PENDING, rv);
3854 spdy_data.RunFor(2);
3855 rv = callback.WaitForResult();
3856 EXPECT_EQ(OK, rv);
3858 LoadTimingInfo load_timing_info2;
3859 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3860 TestLoadTimingReused(load_timing_info2);
3862 // The requests should have the same ID.
3863 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3865 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3866 spdy_data.RunFor(1);
3867 EXPECT_EQ(2, callback.WaitForResult());
3870 // Test the challenge-response-retry sequence through an HTTPS Proxy
3871 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3872 HttpRequestInfo request;
3873 request.method = "GET";
3874 request.url = GURL("http://www.google.com/");
3875 // when the no authentication data flag is set.
3876 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3878 // Configure against https proxy server "myproxy:70".
3879 session_deps_.proxy_service.reset(
3880 ProxyService::CreateFixed("https://myproxy:70"));
3881 CapturingBoundNetLog log;
3882 session_deps_.net_log = log.bound().net_log();
3883 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3885 // Since we have proxy, should use full url
3886 MockWrite data_writes1[] = {
3887 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3888 "Host: www.google.com\r\n"
3889 "Proxy-Connection: keep-alive\r\n\r\n"),
3891 // After calling trans->RestartWithAuth(), this is the request we should
3892 // be issuing -- the final header line contains the credentials.
3893 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3894 "Host: www.google.com\r\n"
3895 "Proxy-Connection: keep-alive\r\n"
3896 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3899 // The proxy responds to the GET with a 407, using a persistent
3900 // connection.
3901 MockRead data_reads1[] = {
3902 // No credentials.
3903 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3904 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3905 MockRead("Proxy-Connection: keep-alive\r\n"),
3906 MockRead("Content-Length: 0\r\n\r\n"),
3908 MockRead("HTTP/1.1 200 OK\r\n"),
3909 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3910 MockRead("Content-Length: 100\r\n\r\n"),
3911 MockRead(SYNCHRONOUS, OK),
3914 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3915 data_writes1, arraysize(data_writes1));
3916 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3917 SSLSocketDataProvider ssl(ASYNC, OK);
3918 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3920 TestCompletionCallback callback1;
3922 scoped_ptr<HttpTransaction> trans(
3923 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3925 int rv = trans->Start(&request, callback1.callback(), log.bound());
3926 EXPECT_EQ(ERR_IO_PENDING, rv);
3928 rv = callback1.WaitForResult();
3929 EXPECT_EQ(OK, rv);
3931 LoadTimingInfo load_timing_info;
3932 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3933 TestLoadTimingNotReused(load_timing_info,
3934 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3936 const HttpResponseInfo* response = trans->GetResponseInfo();
3937 ASSERT_TRUE(response != NULL);
3938 ASSERT_FALSE(response->headers.get() == NULL);
3939 EXPECT_EQ(407, response->headers->response_code());
3940 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3941 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3943 TestCompletionCallback callback2;
3945 rv = trans->RestartWithAuth(
3946 AuthCredentials(kFoo, kBar), callback2.callback());
3947 EXPECT_EQ(ERR_IO_PENDING, rv);
3949 rv = callback2.WaitForResult();
3950 EXPECT_EQ(OK, rv);
3952 load_timing_info = LoadTimingInfo();
3953 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3954 // Retrying with HTTP AUTH is considered to be reusing a socket.
3955 TestLoadTimingReused(load_timing_info);
3957 response = trans->GetResponseInfo();
3958 ASSERT_TRUE(response != NULL);
3960 EXPECT_TRUE(response->headers->IsKeepAlive());
3961 EXPECT_EQ(200, response->headers->response_code());
3962 EXPECT_EQ(100, response->headers->GetContentLength());
3963 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3965 // The password prompt info should not be set.
3966 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3969 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3970 const MockRead& status, int expected_status) {
3971 HttpRequestInfo request;
3972 request.method = "GET";
3973 request.url = GURL("https://www.google.com/");
3974 request.load_flags = 0;
3976 // Configure against proxy server "myproxy:70".
3977 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3978 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3980 // Since we have proxy, should try to establish tunnel.
3981 MockWrite data_writes[] = {
3982 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3983 "Host: www.google.com\r\n"
3984 "Proxy-Connection: keep-alive\r\n\r\n"),
3987 MockRead data_reads[] = {
3988 status,
3989 MockRead("Content-Length: 10\r\n\r\n"),
3990 // No response body because the test stops reading here.
3991 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3994 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3995 data_writes, arraysize(data_writes));
3996 session_deps_.socket_factory->AddSocketDataProvider(&data);
3998 TestCompletionCallback callback;
4000 scoped_ptr<HttpTransaction> trans(
4001 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4003 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4004 EXPECT_EQ(ERR_IO_PENDING, rv);
4006 rv = callback.WaitForResult();
4007 EXPECT_EQ(expected_status, rv);
4010 void HttpNetworkTransactionTest::ConnectStatusHelper(
4011 const MockRead& status) {
4012 ConnectStatusHelperWithExpectedStatus(
4013 status, ERR_TUNNEL_CONNECTION_FAILED);
4016 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4017 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4020 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4021 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4024 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4025 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4028 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4029 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4032 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4033 ConnectStatusHelper(
4034 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4037 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4038 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4041 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4042 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4045 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4046 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4049 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4050 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4053 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4054 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4057 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4058 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4061 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4062 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4065 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4066 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4069 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4070 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4073 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4074 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4077 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4078 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4081 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4082 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4085 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4086 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4089 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4090 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4093 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4094 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4097 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4098 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4101 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4102 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4105 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4106 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4109 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4110 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4113 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4114 ConnectStatusHelperWithExpectedStatus(
4115 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4116 ERR_PROXY_AUTH_UNSUPPORTED);
4119 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4120 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4123 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4124 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4127 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4128 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4131 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4132 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4135 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4136 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4139 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4140 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4143 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4144 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4147 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4148 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4151 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4152 ConnectStatusHelper(
4153 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4156 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4157 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4160 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4161 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4164 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4165 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4168 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4169 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4172 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4173 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4176 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4177 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4180 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4181 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4184 // Test the flow when both the proxy server AND origin server require
4185 // authentication. Again, this uses basic auth for both since that is
4186 // the simplest to mock.
4187 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4188 HttpRequestInfo request;
4189 request.method = "GET";
4190 request.url = GURL("http://www.google.com/");
4191 request.load_flags = 0;
4193 // Configure against proxy server "myproxy:70".
4194 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4195 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4197 scoped_ptr<HttpTransaction> trans(
4198 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4200 MockWrite data_writes1[] = {
4201 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4202 "Host: www.google.com\r\n"
4203 "Proxy-Connection: keep-alive\r\n\r\n"),
4206 MockRead data_reads1[] = {
4207 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4208 // Give a couple authenticate options (only the middle one is actually
4209 // supported).
4210 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4211 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4212 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4214 // Large content-length -- won't matter, as connection will be reset.
4215 MockRead("Content-Length: 10000\r\n\r\n"),
4216 MockRead(SYNCHRONOUS, ERR_FAILED),
4219 // After calling trans->RestartWithAuth() the first time, this is the
4220 // request we should be issuing -- the final header line contains the
4221 // proxy's credentials.
4222 MockWrite data_writes2[] = {
4223 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4224 "Host: www.google.com\r\n"
4225 "Proxy-Connection: keep-alive\r\n"
4226 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4229 // Now the proxy server lets the request pass through to origin server.
4230 // The origin server responds with a 401.
4231 MockRead data_reads2[] = {
4232 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4233 // Note: We are using the same realm-name as the proxy server. This is
4234 // completely valid, as realms are unique across hosts.
4235 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4236 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4237 MockRead("Content-Length: 2000\r\n\r\n"),
4238 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4241 // After calling trans->RestartWithAuth() the second time, we should send
4242 // the credentials for both the proxy and origin server.
4243 MockWrite data_writes3[] = {
4244 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4245 "Host: www.google.com\r\n"
4246 "Proxy-Connection: keep-alive\r\n"
4247 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4248 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4251 // Lastly we get the desired content.
4252 MockRead data_reads3[] = {
4253 MockRead("HTTP/1.0 200 OK\r\n"),
4254 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4255 MockRead("Content-Length: 100\r\n\r\n"),
4256 MockRead(SYNCHRONOUS, OK),
4259 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4260 data_writes1, arraysize(data_writes1));
4261 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4262 data_writes2, arraysize(data_writes2));
4263 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4264 data_writes3, arraysize(data_writes3));
4265 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4266 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4267 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4269 TestCompletionCallback callback1;
4271 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4272 EXPECT_EQ(ERR_IO_PENDING, rv);
4274 rv = callback1.WaitForResult();
4275 EXPECT_EQ(OK, rv);
4277 const HttpResponseInfo* response = trans->GetResponseInfo();
4278 ASSERT_TRUE(response != NULL);
4279 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4281 TestCompletionCallback callback2;
4283 rv = trans->RestartWithAuth(
4284 AuthCredentials(kFoo, kBar), callback2.callback());
4285 EXPECT_EQ(ERR_IO_PENDING, rv);
4287 rv = callback2.WaitForResult();
4288 EXPECT_EQ(OK, rv);
4290 response = trans->GetResponseInfo();
4291 ASSERT_TRUE(response != NULL);
4292 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4294 TestCompletionCallback callback3;
4296 rv = trans->RestartWithAuth(
4297 AuthCredentials(kFoo2, kBar2), callback3.callback());
4298 EXPECT_EQ(ERR_IO_PENDING, rv);
4300 rv = callback3.WaitForResult();
4301 EXPECT_EQ(OK, rv);
4303 response = trans->GetResponseInfo();
4304 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4305 EXPECT_EQ(100, response->headers->GetContentLength());
4308 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4309 // can't hook into its internals to cause it to generate predictable NTLM
4310 // authorization headers.
4311 #if defined(NTLM_PORTABLE)
4312 // The NTLM authentication unit tests were generated by capturing the HTTP
4313 // requests and responses using Fiddler 2 and inspecting the generated random
4314 // bytes in the debugger.
4316 // Enter the correct password and authenticate successfully.
4317 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4318 HttpRequestInfo request;
4319 request.method = "GET";
4320 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4322 // Ensure load is not disrupted by flags which suppress behaviour specific
4323 // to other auth schemes.
4324 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4326 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4327 MockGetHostName);
4328 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4330 MockWrite data_writes1[] = {
4331 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4332 "Host: 172.22.68.17\r\n"
4333 "Connection: keep-alive\r\n\r\n"),
4336 MockRead data_reads1[] = {
4337 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4338 // Negotiate and NTLM are often requested together. However, we only want
4339 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4340 // the header that requests Negotiate for this test.
4341 MockRead("WWW-Authenticate: NTLM\r\n"),
4342 MockRead("Connection: close\r\n"),
4343 MockRead("Content-Length: 42\r\n"),
4344 MockRead("Content-Type: text/html\r\n\r\n"),
4345 // Missing content -- won't matter, as connection will be reset.
4346 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4349 MockWrite data_writes2[] = {
4350 // After restarting with a null identity, this is the
4351 // request we should be issuing -- the final header line contains a Type
4352 // 1 message.
4353 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4354 "Host: 172.22.68.17\r\n"
4355 "Connection: keep-alive\r\n"
4356 "Authorization: NTLM "
4357 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4359 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4360 // (the credentials for the origin server). The second request continues
4361 // on the same connection.
4362 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4363 "Host: 172.22.68.17\r\n"
4364 "Connection: keep-alive\r\n"
4365 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4366 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4367 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4368 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4369 "ahlhx5I=\r\n\r\n"),
4372 MockRead data_reads2[] = {
4373 // The origin server responds with a Type 2 message.
4374 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4375 MockRead("WWW-Authenticate: NTLM "
4376 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4377 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4378 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4379 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4380 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4381 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4382 "BtAAAAAAA=\r\n"),
4383 MockRead("Content-Length: 42\r\n"),
4384 MockRead("Content-Type: text/html\r\n\r\n"),
4385 MockRead("You are not authorized to view this page\r\n"),
4387 // Lastly we get the desired content.
4388 MockRead("HTTP/1.1 200 OK\r\n"),
4389 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4390 MockRead("Content-Length: 13\r\n\r\n"),
4391 MockRead("Please Login\r\n"),
4392 MockRead(SYNCHRONOUS, OK),
4395 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4396 data_writes1, arraysize(data_writes1));
4397 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4398 data_writes2, arraysize(data_writes2));
4399 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4400 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4402 TestCompletionCallback callback1;
4404 scoped_ptr<HttpTransaction> trans(
4405 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4407 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4408 EXPECT_EQ(ERR_IO_PENDING, rv);
4410 rv = callback1.WaitForResult();
4411 EXPECT_EQ(OK, rv);
4413 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4415 const HttpResponseInfo* response = trans->GetResponseInfo();
4416 ASSERT_FALSE(response == NULL);
4417 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4419 TestCompletionCallback callback2;
4421 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4422 callback2.callback());
4423 EXPECT_EQ(ERR_IO_PENDING, rv);
4425 rv = callback2.WaitForResult();
4426 EXPECT_EQ(OK, rv);
4428 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4430 response = trans->GetResponseInfo();
4431 ASSERT_TRUE(response != NULL);
4432 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4434 TestCompletionCallback callback3;
4436 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4437 EXPECT_EQ(ERR_IO_PENDING, rv);
4439 rv = callback3.WaitForResult();
4440 EXPECT_EQ(OK, rv);
4442 response = trans->GetResponseInfo();
4443 ASSERT_TRUE(response != NULL);
4444 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4445 EXPECT_EQ(13, response->headers->GetContentLength());
4448 // Enter a wrong password, and then the correct one.
4449 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4450 HttpRequestInfo request;
4451 request.method = "GET";
4452 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4453 request.load_flags = 0;
4455 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4456 MockGetHostName);
4457 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4459 MockWrite data_writes1[] = {
4460 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4461 "Host: 172.22.68.17\r\n"
4462 "Connection: keep-alive\r\n\r\n"),
4465 MockRead data_reads1[] = {
4466 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4467 // Negotiate and NTLM are often requested together. However, we only want
4468 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4469 // the header that requests Negotiate for this test.
4470 MockRead("WWW-Authenticate: NTLM\r\n"),
4471 MockRead("Connection: close\r\n"),
4472 MockRead("Content-Length: 42\r\n"),
4473 MockRead("Content-Type: text/html\r\n\r\n"),
4474 // Missing content -- won't matter, as connection will be reset.
4475 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4478 MockWrite data_writes2[] = {
4479 // After restarting with a null identity, this is the
4480 // request we should be issuing -- the final header line contains a Type
4481 // 1 message.
4482 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4483 "Host: 172.22.68.17\r\n"
4484 "Connection: keep-alive\r\n"
4485 "Authorization: NTLM "
4486 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4488 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4489 // (the credentials for the origin server). The second request continues
4490 // on the same connection.
4491 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4492 "Host: 172.22.68.17\r\n"
4493 "Connection: keep-alive\r\n"
4494 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4495 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4496 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4497 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4498 "4Ww7b7E=\r\n\r\n"),
4501 MockRead data_reads2[] = {
4502 // The origin server responds with a Type 2 message.
4503 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4504 MockRead("WWW-Authenticate: NTLM "
4505 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4506 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4507 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4508 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4509 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4510 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4511 "BtAAAAAAA=\r\n"),
4512 MockRead("Content-Length: 42\r\n"),
4513 MockRead("Content-Type: text/html\r\n\r\n"),
4514 MockRead("You are not authorized to view this page\r\n"),
4516 // Wrong password.
4517 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4518 MockRead("WWW-Authenticate: NTLM\r\n"),
4519 MockRead("Connection: close\r\n"),
4520 MockRead("Content-Length: 42\r\n"),
4521 MockRead("Content-Type: text/html\r\n\r\n"),
4522 // Missing content -- won't matter, as connection will be reset.
4523 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4526 MockWrite data_writes3[] = {
4527 // After restarting with a null identity, this is the
4528 // request we should be issuing -- the final header line contains a Type
4529 // 1 message.
4530 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4531 "Host: 172.22.68.17\r\n"
4532 "Connection: keep-alive\r\n"
4533 "Authorization: NTLM "
4534 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4536 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4537 // (the credentials for the origin server). The second request continues
4538 // on the same connection.
4539 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4540 "Host: 172.22.68.17\r\n"
4541 "Connection: keep-alive\r\n"
4542 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4543 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4544 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4545 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4546 "+4MUm7c=\r\n\r\n"),
4549 MockRead data_reads3[] = {
4550 // The origin server responds with a Type 2 message.
4551 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4552 MockRead("WWW-Authenticate: NTLM "
4553 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4554 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4555 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4556 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4557 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4558 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4559 "BtAAAAAAA=\r\n"),
4560 MockRead("Content-Length: 42\r\n"),
4561 MockRead("Content-Type: text/html\r\n\r\n"),
4562 MockRead("You are not authorized to view this page\r\n"),
4564 // Lastly we get the desired content.
4565 MockRead("HTTP/1.1 200 OK\r\n"),
4566 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4567 MockRead("Content-Length: 13\r\n\r\n"),
4568 MockRead("Please Login\r\n"),
4569 MockRead(SYNCHRONOUS, OK),
4572 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4573 data_writes1, arraysize(data_writes1));
4574 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4575 data_writes2, arraysize(data_writes2));
4576 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4577 data_writes3, arraysize(data_writes3));
4578 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4579 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4580 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4582 TestCompletionCallback callback1;
4584 scoped_ptr<HttpTransaction> trans(
4585 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4587 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4588 EXPECT_EQ(ERR_IO_PENDING, rv);
4590 rv = callback1.WaitForResult();
4591 EXPECT_EQ(OK, rv);
4593 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4595 const HttpResponseInfo* response = trans->GetResponseInfo();
4596 ASSERT_TRUE(response != NULL);
4597 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4599 TestCompletionCallback callback2;
4601 // Enter the wrong password.
4602 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4603 callback2.callback());
4604 EXPECT_EQ(ERR_IO_PENDING, rv);
4606 rv = callback2.WaitForResult();
4607 EXPECT_EQ(OK, rv);
4609 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4610 TestCompletionCallback callback3;
4611 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4612 EXPECT_EQ(ERR_IO_PENDING, rv);
4613 rv = callback3.WaitForResult();
4614 EXPECT_EQ(OK, rv);
4615 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4617 response = trans->GetResponseInfo();
4618 ASSERT_FALSE(response == NULL);
4619 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4621 TestCompletionCallback callback4;
4623 // Now enter the right password.
4624 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4625 callback4.callback());
4626 EXPECT_EQ(ERR_IO_PENDING, rv);
4628 rv = callback4.WaitForResult();
4629 EXPECT_EQ(OK, rv);
4631 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4633 TestCompletionCallback callback5;
4635 // One more roundtrip
4636 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4637 EXPECT_EQ(ERR_IO_PENDING, rv);
4639 rv = callback5.WaitForResult();
4640 EXPECT_EQ(OK, rv);
4642 response = trans->GetResponseInfo();
4643 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4644 EXPECT_EQ(13, response->headers->GetContentLength());
4646 #endif // NTLM_PORTABLE
4648 // Test reading a server response which has only headers, and no body.
4649 // After some maximum number of bytes is consumed, the transaction should
4650 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4651 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4652 HttpRequestInfo request;
4653 request.method = "GET";
4654 request.url = GURL("http://www.google.com/");
4655 request.load_flags = 0;
4657 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4658 scoped_ptr<HttpTransaction> trans(
4659 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4661 // Respond with 300 kb of headers (we should fail after 256 kb).
4662 std::string large_headers_string;
4663 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4665 MockRead data_reads[] = {
4666 MockRead("HTTP/1.0 200 OK\r\n"),
4667 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4668 MockRead("\r\nBODY"),
4669 MockRead(SYNCHRONOUS, OK),
4671 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4672 session_deps_.socket_factory->AddSocketDataProvider(&data);
4674 TestCompletionCallback callback;
4676 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4677 EXPECT_EQ(ERR_IO_PENDING, rv);
4679 rv = callback.WaitForResult();
4680 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4682 const HttpResponseInfo* response = trans->GetResponseInfo();
4683 EXPECT_TRUE(response == NULL);
4686 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4687 // establish tunnel.
4688 // http://code.google.com/p/chromium/issues/detail?id=3772
4689 TEST_P(HttpNetworkTransactionTest,
4690 DontRecycleTransportSocketForSSLTunnel) {
4691 HttpRequestInfo request;
4692 request.method = "GET";
4693 request.url = GURL("https://www.google.com/");
4694 request.load_flags = 0;
4696 // Configure against proxy server "myproxy:70".
4697 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4699 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4701 scoped_ptr<HttpTransaction> trans(
4702 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4704 // Since we have proxy, should try to establish tunnel.
4705 MockWrite data_writes1[] = {
4706 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4707 "Host: www.google.com\r\n"
4708 "Proxy-Connection: keep-alive\r\n\r\n"),
4711 // The proxy responds to the connect with a 404, using a persistent
4712 // connection. Usually a proxy would return 501 (not implemented),
4713 // or 200 (tunnel established).
4714 MockRead data_reads1[] = {
4715 MockRead("HTTP/1.1 404 Not Found\r\n"),
4716 MockRead("Content-Length: 10\r\n\r\n"),
4717 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4720 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4721 data_writes1, arraysize(data_writes1));
4722 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4724 TestCompletionCallback callback1;
4726 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4727 EXPECT_EQ(ERR_IO_PENDING, rv);
4729 rv = callback1.WaitForResult();
4730 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4732 const HttpResponseInfo* response = trans->GetResponseInfo();
4733 EXPECT_TRUE(response == NULL);
4735 // Empty the current queue. This is necessary because idle sockets are
4736 // added to the connection pool asynchronously with a PostTask.
4737 base::MessageLoop::current()->RunUntilIdle();
4739 // We now check to make sure the TCPClientSocket was not added back to
4740 // the pool.
4741 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4742 trans.reset();
4743 base::MessageLoop::current()->RunUntilIdle();
4744 // Make sure that the socket didn't get recycled after calling the destructor.
4745 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4748 // Make sure that we recycle a socket after reading all of the response body.
4749 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4750 HttpRequestInfo request;
4751 request.method = "GET";
4752 request.url = GURL("http://www.google.com/");
4753 request.load_flags = 0;
4755 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4757 scoped_ptr<HttpTransaction> trans(
4758 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4760 MockRead data_reads[] = {
4761 // A part of the response body is received with the response headers.
4762 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4763 // The rest of the response body is received in two parts.
4764 MockRead("lo"),
4765 MockRead(" world"),
4766 MockRead("junk"), // Should not be read!!
4767 MockRead(SYNCHRONOUS, OK),
4770 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4771 session_deps_.socket_factory->AddSocketDataProvider(&data);
4773 TestCompletionCallback callback;
4775 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4776 EXPECT_EQ(ERR_IO_PENDING, rv);
4778 rv = callback.WaitForResult();
4779 EXPECT_EQ(OK, rv);
4781 const HttpResponseInfo* response = trans->GetResponseInfo();
4782 ASSERT_TRUE(response != NULL);
4784 EXPECT_TRUE(response->headers.get() != NULL);
4785 std::string status_line = response->headers->GetStatusLine();
4786 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4788 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4790 std::string response_data;
4791 rv = ReadTransaction(trans.get(), &response_data);
4792 EXPECT_EQ(OK, rv);
4793 EXPECT_EQ("hello world", response_data);
4795 // Empty the current queue. This is necessary because idle sockets are
4796 // added to the connection pool asynchronously with a PostTask.
4797 base::MessageLoop::current()->RunUntilIdle();
4799 // We now check to make sure the socket was added back to the pool.
4800 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4803 // Make sure that we recycle a SSL socket after reading all of the response
4804 // body.
4805 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4806 HttpRequestInfo request;
4807 request.method = "GET";
4808 request.url = GURL("https://www.google.com/");
4809 request.load_flags = 0;
4811 MockWrite data_writes[] = {
4812 MockWrite("GET / HTTP/1.1\r\n"
4813 "Host: www.google.com\r\n"
4814 "Connection: keep-alive\r\n\r\n"),
4817 MockRead data_reads[] = {
4818 MockRead("HTTP/1.1 200 OK\r\n"),
4819 MockRead("Content-Length: 11\r\n\r\n"),
4820 MockRead("hello world"),
4821 MockRead(SYNCHRONOUS, OK),
4824 SSLSocketDataProvider ssl(ASYNC, OK);
4825 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4827 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4828 data_writes, arraysize(data_writes));
4829 session_deps_.socket_factory->AddSocketDataProvider(&data);
4831 TestCompletionCallback callback;
4833 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4834 scoped_ptr<HttpTransaction> trans(
4835 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4837 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4839 EXPECT_EQ(ERR_IO_PENDING, rv);
4840 EXPECT_EQ(OK, callback.WaitForResult());
4842 const HttpResponseInfo* response = trans->GetResponseInfo();
4843 ASSERT_TRUE(response != NULL);
4844 ASSERT_TRUE(response->headers.get() != NULL);
4845 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4847 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4849 std::string response_data;
4850 rv = ReadTransaction(trans.get(), &response_data);
4851 EXPECT_EQ(OK, rv);
4852 EXPECT_EQ("hello world", response_data);
4854 // Empty the current queue. This is necessary because idle sockets are
4855 // added to the connection pool asynchronously with a PostTask.
4856 base::MessageLoop::current()->RunUntilIdle();
4858 // We now check to make sure the socket was added back to the pool.
4859 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4862 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4863 // from the pool and make sure that we recover okay.
4864 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4865 HttpRequestInfo request;
4866 request.method = "GET";
4867 request.url = GURL("https://www.google.com/");
4868 request.load_flags = 0;
4870 MockWrite data_writes[] = {
4871 MockWrite("GET / HTTP/1.1\r\n"
4872 "Host: www.google.com\r\n"
4873 "Connection: keep-alive\r\n\r\n"),
4874 MockWrite("GET / HTTP/1.1\r\n"
4875 "Host: www.google.com\r\n"
4876 "Connection: keep-alive\r\n\r\n"),
4879 MockRead data_reads[] = {
4880 MockRead("HTTP/1.1 200 OK\r\n"),
4881 MockRead("Content-Length: 11\r\n\r\n"),
4882 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4883 MockRead("hello world"),
4884 MockRead(ASYNC, 0, 0) // EOF
4887 SSLSocketDataProvider ssl(ASYNC, OK);
4888 SSLSocketDataProvider ssl2(ASYNC, OK);
4889 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4890 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4892 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4893 data_writes, arraysize(data_writes));
4894 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4895 data_writes, arraysize(data_writes));
4896 session_deps_.socket_factory->AddSocketDataProvider(&data);
4897 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4899 TestCompletionCallback callback;
4901 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4902 scoped_ptr<HttpTransaction> trans(
4903 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4905 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4907 EXPECT_EQ(ERR_IO_PENDING, rv);
4908 EXPECT_EQ(OK, callback.WaitForResult());
4910 const HttpResponseInfo* response = trans->GetResponseInfo();
4911 ASSERT_TRUE(response != NULL);
4912 ASSERT_TRUE(response->headers.get() != NULL);
4913 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4915 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4917 std::string response_data;
4918 rv = ReadTransaction(trans.get(), &response_data);
4919 EXPECT_EQ(OK, rv);
4920 EXPECT_EQ("hello world", response_data);
4922 // Empty the current queue. This is necessary because idle sockets are
4923 // added to the connection pool asynchronously with a PostTask.
4924 base::MessageLoop::current()->RunUntilIdle();
4926 // We now check to make sure the socket was added back to the pool.
4927 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4929 // Now start the second transaction, which should reuse the previous socket.
4931 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4933 rv = trans->Start(&request, callback.callback(), BoundNetLog());
4935 EXPECT_EQ(ERR_IO_PENDING, rv);
4936 EXPECT_EQ(OK, callback.WaitForResult());
4938 response = trans->GetResponseInfo();
4939 ASSERT_TRUE(response != NULL);
4940 ASSERT_TRUE(response->headers.get() != NULL);
4941 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4943 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4945 rv = ReadTransaction(trans.get(), &response_data);
4946 EXPECT_EQ(OK, rv);
4947 EXPECT_EQ("hello world", response_data);
4949 // Empty the current queue. This is necessary because idle sockets are
4950 // added to the connection pool asynchronously with a PostTask.
4951 base::MessageLoop::current()->RunUntilIdle();
4953 // We now check to make sure the socket was added back to the pool.
4954 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4957 // Make sure that we recycle a socket after a zero-length response.
4958 // http://crbug.com/9880
4959 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4960 HttpRequestInfo request;
4961 request.method = "GET";
4962 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4963 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4964 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4965 "rt=prt.2642,ol.2649,xjs.2951");
4966 request.load_flags = 0;
4968 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4970 scoped_ptr<HttpTransaction> trans(
4971 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4973 MockRead data_reads[] = {
4974 MockRead("HTTP/1.1 204 No Content\r\n"
4975 "Content-Length: 0\r\n"
4976 "Content-Type: text/html\r\n\r\n"),
4977 MockRead("junk"), // Should not be read!!
4978 MockRead(SYNCHRONOUS, OK),
4981 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4982 session_deps_.socket_factory->AddSocketDataProvider(&data);
4984 TestCompletionCallback callback;
4986 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4987 EXPECT_EQ(ERR_IO_PENDING, rv);
4989 rv = callback.WaitForResult();
4990 EXPECT_EQ(OK, rv);
4992 const HttpResponseInfo* response = trans->GetResponseInfo();
4993 ASSERT_TRUE(response != NULL);
4995 EXPECT_TRUE(response->headers.get() != NULL);
4996 std::string status_line = response->headers->GetStatusLine();
4997 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4999 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5001 std::string response_data;
5002 rv = ReadTransaction(trans.get(), &response_data);
5003 EXPECT_EQ(OK, rv);
5004 EXPECT_EQ("", response_data);
5006 // Empty the current queue. This is necessary because idle sockets are
5007 // added to the connection pool asynchronously with a PostTask.
5008 base::MessageLoop::current()->RunUntilIdle();
5010 // We now check to make sure the socket was added back to the pool.
5011 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5014 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5015 ScopedVector<UploadElementReader> element_readers;
5016 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5017 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
5019 HttpRequestInfo request[2];
5020 // Transaction 1: a GET request that succeeds. The socket is recycled
5021 // after use.
5022 request[0].method = "GET";
5023 request[0].url = GURL("http://www.google.com/");
5024 request[0].load_flags = 0;
5025 // Transaction 2: a POST request. Reuses the socket kept alive from
5026 // transaction 1. The first attempts fails when writing the POST data.
5027 // This causes the transaction to retry with a new socket. The second
5028 // attempt succeeds.
5029 request[1].method = "POST";
5030 request[1].url = GURL("http://www.google.com/login.cgi");
5031 request[1].upload_data_stream = &upload_data_stream;
5032 request[1].load_flags = 0;
5034 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5036 // The first socket is used for transaction 1 and the first attempt of
5037 // transaction 2.
5039 // The response of transaction 1.
5040 MockRead data_reads1[] = {
5041 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5042 MockRead("hello world"),
5043 MockRead(SYNCHRONOUS, OK),
5045 // The mock write results of transaction 1 and the first attempt of
5046 // transaction 2.
5047 MockWrite data_writes1[] = {
5048 MockWrite(SYNCHRONOUS, 64), // GET
5049 MockWrite(SYNCHRONOUS, 93), // POST
5050 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5052 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5053 data_writes1, arraysize(data_writes1));
5055 // The second socket is used for the second attempt of transaction 2.
5057 // The response of transaction 2.
5058 MockRead data_reads2[] = {
5059 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5060 MockRead("welcome"),
5061 MockRead(SYNCHRONOUS, OK),
5063 // The mock write results of the second attempt of transaction 2.
5064 MockWrite data_writes2[] = {
5065 MockWrite(SYNCHRONOUS, 93), // POST
5066 MockWrite(SYNCHRONOUS, 3), // POST data
5068 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5069 data_writes2, arraysize(data_writes2));
5071 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5072 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5074 const char* kExpectedResponseData[] = {
5075 "hello world", "welcome"
5078 for (int i = 0; i < 2; ++i) {
5079 scoped_ptr<HttpTransaction> trans(
5080 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5082 TestCompletionCallback callback;
5084 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5085 EXPECT_EQ(ERR_IO_PENDING, rv);
5087 rv = callback.WaitForResult();
5088 EXPECT_EQ(OK, rv);
5090 const HttpResponseInfo* response = trans->GetResponseInfo();
5091 ASSERT_TRUE(response != NULL);
5093 EXPECT_TRUE(response->headers.get() != NULL);
5094 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5096 std::string response_data;
5097 rv = ReadTransaction(trans.get(), &response_data);
5098 EXPECT_EQ(OK, rv);
5099 EXPECT_EQ(kExpectedResponseData[i], response_data);
5103 // Test the request-challenge-retry sequence for basic auth when there is
5104 // an identity in the URL. The request should be sent as normal, but when
5105 // it fails the identity from the URL is used to answer the challenge.
5106 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5107 HttpRequestInfo request;
5108 request.method = "GET";
5109 request.url = GURL("http://foo:b@r@www.google.com/");
5110 request.load_flags = LOAD_NORMAL;
5112 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5113 scoped_ptr<HttpTransaction> trans(
5114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5116 // The password contains an escaped character -- for this test to pass it
5117 // will need to be unescaped by HttpNetworkTransaction.
5118 EXPECT_EQ("b%40r", request.url.password());
5120 MockWrite data_writes1[] = {
5121 MockWrite("GET / HTTP/1.1\r\n"
5122 "Host: www.google.com\r\n"
5123 "Connection: keep-alive\r\n\r\n"),
5126 MockRead data_reads1[] = {
5127 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5128 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5129 MockRead("Content-Length: 10\r\n\r\n"),
5130 MockRead(SYNCHRONOUS, ERR_FAILED),
5133 // After the challenge above, the transaction will be restarted using the
5134 // identity from the url (foo, b@r) to answer the challenge.
5135 MockWrite data_writes2[] = {
5136 MockWrite("GET / HTTP/1.1\r\n"
5137 "Host: www.google.com\r\n"
5138 "Connection: keep-alive\r\n"
5139 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5142 MockRead data_reads2[] = {
5143 MockRead("HTTP/1.0 200 OK\r\n"),
5144 MockRead("Content-Length: 100\r\n\r\n"),
5145 MockRead(SYNCHRONOUS, OK),
5148 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5149 data_writes1, arraysize(data_writes1));
5150 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5151 data_writes2, arraysize(data_writes2));
5152 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5153 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5155 TestCompletionCallback callback1;
5156 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5157 EXPECT_EQ(ERR_IO_PENDING, rv);
5158 rv = callback1.WaitForResult();
5159 EXPECT_EQ(OK, rv);
5160 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5162 TestCompletionCallback callback2;
5163 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5164 EXPECT_EQ(ERR_IO_PENDING, rv);
5165 rv = callback2.WaitForResult();
5166 EXPECT_EQ(OK, rv);
5167 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5169 const HttpResponseInfo* response = trans->GetResponseInfo();
5170 ASSERT_TRUE(response != NULL);
5172 // There is no challenge info, since the identity in URL worked.
5173 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5175 EXPECT_EQ(100, response->headers->GetContentLength());
5177 // Empty the current queue.
5178 base::MessageLoop::current()->RunUntilIdle();
5181 // Test the request-challenge-retry sequence for basic auth when there is an
5182 // incorrect identity in the URL. The identity from the URL should be used only
5183 // once.
5184 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5185 HttpRequestInfo request;
5186 request.method = "GET";
5187 // Note: the URL has a username:password in it. The password "baz" is
5188 // wrong (should be "bar").
5189 request.url = GURL("http://foo:baz@www.google.com/");
5191 request.load_flags = LOAD_NORMAL;
5193 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5194 scoped_ptr<HttpTransaction> trans(
5195 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5197 MockWrite data_writes1[] = {
5198 MockWrite("GET / HTTP/1.1\r\n"
5199 "Host: www.google.com\r\n"
5200 "Connection: keep-alive\r\n\r\n"),
5203 MockRead data_reads1[] = {
5204 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5205 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5206 MockRead("Content-Length: 10\r\n\r\n"),
5207 MockRead(SYNCHRONOUS, ERR_FAILED),
5210 // After the challenge above, the transaction will be restarted using the
5211 // identity from the url (foo, baz) to answer the challenge.
5212 MockWrite data_writes2[] = {
5213 MockWrite("GET / HTTP/1.1\r\n"
5214 "Host: www.google.com\r\n"
5215 "Connection: keep-alive\r\n"
5216 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5219 MockRead data_reads2[] = {
5220 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5221 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5222 MockRead("Content-Length: 10\r\n\r\n"),
5223 MockRead(SYNCHRONOUS, ERR_FAILED),
5226 // After the challenge above, the transaction will be restarted using the
5227 // identity supplied by the user (foo, bar) to answer the challenge.
5228 MockWrite data_writes3[] = {
5229 MockWrite("GET / HTTP/1.1\r\n"
5230 "Host: www.google.com\r\n"
5231 "Connection: keep-alive\r\n"
5232 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5235 MockRead data_reads3[] = {
5236 MockRead("HTTP/1.0 200 OK\r\n"),
5237 MockRead("Content-Length: 100\r\n\r\n"),
5238 MockRead(SYNCHRONOUS, OK),
5241 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5242 data_writes1, arraysize(data_writes1));
5243 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5244 data_writes2, arraysize(data_writes2));
5245 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5246 data_writes3, arraysize(data_writes3));
5247 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5248 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5249 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5251 TestCompletionCallback callback1;
5253 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5254 EXPECT_EQ(ERR_IO_PENDING, rv);
5256 rv = callback1.WaitForResult();
5257 EXPECT_EQ(OK, rv);
5259 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5260 TestCompletionCallback callback2;
5261 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5262 EXPECT_EQ(ERR_IO_PENDING, rv);
5263 rv = callback2.WaitForResult();
5264 EXPECT_EQ(OK, rv);
5265 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5267 const HttpResponseInfo* response = trans->GetResponseInfo();
5268 ASSERT_TRUE(response != NULL);
5269 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5271 TestCompletionCallback callback3;
5272 rv = trans->RestartWithAuth(
5273 AuthCredentials(kFoo, kBar), callback3.callback());
5274 EXPECT_EQ(ERR_IO_PENDING, rv);
5275 rv = callback3.WaitForResult();
5276 EXPECT_EQ(OK, rv);
5277 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5279 response = trans->GetResponseInfo();
5280 ASSERT_TRUE(response != NULL);
5282 // There is no challenge info, since the identity worked.
5283 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5285 EXPECT_EQ(100, response->headers->GetContentLength());
5287 // Empty the current queue.
5288 base::MessageLoop::current()->RunUntilIdle();
5292 // Test the request-challenge-retry sequence for basic auth when there is a
5293 // correct identity in the URL, but its use is being suppressed. The identity
5294 // from the URL should never be used.
5295 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5296 HttpRequestInfo request;
5297 request.method = "GET";
5298 request.url = GURL("http://foo:bar@www.google.com/");
5299 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5301 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5302 scoped_ptr<HttpTransaction> trans(
5303 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5305 MockWrite data_writes1[] = {
5306 MockWrite("GET / HTTP/1.1\r\n"
5307 "Host: www.google.com\r\n"
5308 "Connection: keep-alive\r\n\r\n"),
5311 MockRead data_reads1[] = {
5312 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5313 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5314 MockRead("Content-Length: 10\r\n\r\n"),
5315 MockRead(SYNCHRONOUS, ERR_FAILED),
5318 // After the challenge above, the transaction will be restarted using the
5319 // identity supplied by the user, not the one in the URL, to answer the
5320 // challenge.
5321 MockWrite data_writes3[] = {
5322 MockWrite("GET / HTTP/1.1\r\n"
5323 "Host: www.google.com\r\n"
5324 "Connection: keep-alive\r\n"
5325 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5328 MockRead data_reads3[] = {
5329 MockRead("HTTP/1.0 200 OK\r\n"),
5330 MockRead("Content-Length: 100\r\n\r\n"),
5331 MockRead(SYNCHRONOUS, OK),
5334 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5335 data_writes1, arraysize(data_writes1));
5336 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5337 data_writes3, arraysize(data_writes3));
5338 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5339 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5341 TestCompletionCallback callback1;
5342 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5343 EXPECT_EQ(ERR_IO_PENDING, rv);
5344 rv = callback1.WaitForResult();
5345 EXPECT_EQ(OK, rv);
5346 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5348 const HttpResponseInfo* response = trans->GetResponseInfo();
5349 ASSERT_TRUE(response != NULL);
5350 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5352 TestCompletionCallback callback3;
5353 rv = trans->RestartWithAuth(
5354 AuthCredentials(kFoo, kBar), callback3.callback());
5355 EXPECT_EQ(ERR_IO_PENDING, rv);
5356 rv = callback3.WaitForResult();
5357 EXPECT_EQ(OK, rv);
5358 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5360 response = trans->GetResponseInfo();
5361 ASSERT_TRUE(response != NULL);
5363 // There is no challenge info, since the identity worked.
5364 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5365 EXPECT_EQ(100, response->headers->GetContentLength());
5367 // Empty the current queue.
5368 base::MessageLoop::current()->RunUntilIdle();
5371 // Test that previously tried username/passwords for a realm get re-used.
5372 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5373 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5375 // Transaction 1: authenticate (foo, bar) on MyRealm1
5377 HttpRequestInfo request;
5378 request.method = "GET";
5379 request.url = GURL("http://www.google.com/x/y/z");
5380 request.load_flags = 0;
5382 scoped_ptr<HttpTransaction> trans(
5383 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5385 MockWrite data_writes1[] = {
5386 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5387 "Host: www.google.com\r\n"
5388 "Connection: keep-alive\r\n\r\n"),
5391 MockRead data_reads1[] = {
5392 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5393 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5394 MockRead("Content-Length: 10000\r\n\r\n"),
5395 MockRead(SYNCHRONOUS, ERR_FAILED),
5398 // Resend with authorization (username=foo, password=bar)
5399 MockWrite data_writes2[] = {
5400 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5401 "Host: www.google.com\r\n"
5402 "Connection: keep-alive\r\n"
5403 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5406 // Sever accepts the authorization.
5407 MockRead data_reads2[] = {
5408 MockRead("HTTP/1.0 200 OK\r\n"),
5409 MockRead("Content-Length: 100\r\n\r\n"),
5410 MockRead(SYNCHRONOUS, OK),
5413 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5414 data_writes1, arraysize(data_writes1));
5415 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5416 data_writes2, arraysize(data_writes2));
5417 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5418 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5420 TestCompletionCallback callback1;
5422 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5423 EXPECT_EQ(ERR_IO_PENDING, rv);
5425 rv = callback1.WaitForResult();
5426 EXPECT_EQ(OK, rv);
5428 const HttpResponseInfo* response = trans->GetResponseInfo();
5429 ASSERT_TRUE(response != NULL);
5430 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5432 TestCompletionCallback callback2;
5434 rv = trans->RestartWithAuth(
5435 AuthCredentials(kFoo, kBar), callback2.callback());
5436 EXPECT_EQ(ERR_IO_PENDING, rv);
5438 rv = callback2.WaitForResult();
5439 EXPECT_EQ(OK, rv);
5441 response = trans->GetResponseInfo();
5442 ASSERT_TRUE(response != NULL);
5443 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5444 EXPECT_EQ(100, response->headers->GetContentLength());
5447 // ------------------------------------------------------------------------
5449 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5451 HttpRequestInfo request;
5452 request.method = "GET";
5453 // Note that Transaction 1 was at /x/y/z, so this is in the same
5454 // protection space as MyRealm1.
5455 request.url = GURL("http://www.google.com/x/y/a/b");
5456 request.load_flags = 0;
5458 scoped_ptr<HttpTransaction> trans(
5459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5461 MockWrite data_writes1[] = {
5462 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5463 "Host: www.google.com\r\n"
5464 "Connection: keep-alive\r\n"
5465 // Send preemptive authorization for MyRealm1
5466 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5469 // The server didn't like the preemptive authorization, and
5470 // challenges us for a different realm (MyRealm2).
5471 MockRead data_reads1[] = {
5472 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5473 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5474 MockRead("Content-Length: 10000\r\n\r\n"),
5475 MockRead(SYNCHRONOUS, ERR_FAILED),
5478 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5479 MockWrite data_writes2[] = {
5480 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5481 "Host: www.google.com\r\n"
5482 "Connection: keep-alive\r\n"
5483 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5486 // Sever accepts the authorization.
5487 MockRead data_reads2[] = {
5488 MockRead("HTTP/1.0 200 OK\r\n"),
5489 MockRead("Content-Length: 100\r\n\r\n"),
5490 MockRead(SYNCHRONOUS, OK),
5493 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5494 data_writes1, arraysize(data_writes1));
5495 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5496 data_writes2, arraysize(data_writes2));
5497 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5498 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5500 TestCompletionCallback callback1;
5502 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5503 EXPECT_EQ(ERR_IO_PENDING, rv);
5505 rv = callback1.WaitForResult();
5506 EXPECT_EQ(OK, rv);
5508 const HttpResponseInfo* response = trans->GetResponseInfo();
5509 ASSERT_TRUE(response != NULL);
5510 ASSERT_TRUE(response->auth_challenge.get());
5511 EXPECT_FALSE(response->auth_challenge->is_proxy);
5512 EXPECT_EQ("www.google.com:80",
5513 response->auth_challenge->challenger.ToString());
5514 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5515 EXPECT_EQ("basic", response->auth_challenge->scheme);
5517 TestCompletionCallback callback2;
5519 rv = trans->RestartWithAuth(
5520 AuthCredentials(kFoo2, kBar2), callback2.callback());
5521 EXPECT_EQ(ERR_IO_PENDING, rv);
5523 rv = callback2.WaitForResult();
5524 EXPECT_EQ(OK, rv);
5526 response = trans->GetResponseInfo();
5527 ASSERT_TRUE(response != NULL);
5528 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5529 EXPECT_EQ(100, response->headers->GetContentLength());
5532 // ------------------------------------------------------------------------
5534 // Transaction 3: Resend a request in MyRealm's protection space --
5535 // succeed with preemptive authorization.
5537 HttpRequestInfo request;
5538 request.method = "GET";
5539 request.url = GURL("http://www.google.com/x/y/z2");
5540 request.load_flags = 0;
5542 scoped_ptr<HttpTransaction> trans(
5543 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5545 MockWrite data_writes1[] = {
5546 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5547 "Host: www.google.com\r\n"
5548 "Connection: keep-alive\r\n"
5549 // The authorization for MyRealm1 gets sent preemptively
5550 // (since the url is in the same protection space)
5551 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5554 // Sever accepts the preemptive authorization
5555 MockRead data_reads1[] = {
5556 MockRead("HTTP/1.0 200 OK\r\n"),
5557 MockRead("Content-Length: 100\r\n\r\n"),
5558 MockRead(SYNCHRONOUS, OK),
5561 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5562 data_writes1, arraysize(data_writes1));
5563 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5565 TestCompletionCallback callback1;
5567 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5568 EXPECT_EQ(ERR_IO_PENDING, rv);
5570 rv = callback1.WaitForResult();
5571 EXPECT_EQ(OK, rv);
5573 const HttpResponseInfo* response = trans->GetResponseInfo();
5574 ASSERT_TRUE(response != NULL);
5576 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5577 EXPECT_EQ(100, response->headers->GetContentLength());
5580 // ------------------------------------------------------------------------
5582 // Transaction 4: request another URL in MyRealm (however the
5583 // url is not known to belong to the protection space, so no pre-auth).
5585 HttpRequestInfo request;
5586 request.method = "GET";
5587 request.url = GURL("http://www.google.com/x/1");
5588 request.load_flags = 0;
5590 scoped_ptr<HttpTransaction> trans(
5591 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5593 MockWrite data_writes1[] = {
5594 MockWrite("GET /x/1 HTTP/1.1\r\n"
5595 "Host: www.google.com\r\n"
5596 "Connection: keep-alive\r\n\r\n"),
5599 MockRead data_reads1[] = {
5600 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5601 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5602 MockRead("Content-Length: 10000\r\n\r\n"),
5603 MockRead(SYNCHRONOUS, ERR_FAILED),
5606 // Resend with authorization from MyRealm's cache.
5607 MockWrite data_writes2[] = {
5608 MockWrite("GET /x/1 HTTP/1.1\r\n"
5609 "Host: www.google.com\r\n"
5610 "Connection: keep-alive\r\n"
5611 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5614 // Sever accepts the authorization.
5615 MockRead data_reads2[] = {
5616 MockRead("HTTP/1.0 200 OK\r\n"),
5617 MockRead("Content-Length: 100\r\n\r\n"),
5618 MockRead(SYNCHRONOUS, OK),
5621 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5622 data_writes1, arraysize(data_writes1));
5623 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5624 data_writes2, arraysize(data_writes2));
5625 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5626 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5628 TestCompletionCallback callback1;
5630 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5631 EXPECT_EQ(ERR_IO_PENDING, rv);
5633 rv = callback1.WaitForResult();
5634 EXPECT_EQ(OK, rv);
5636 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5637 TestCompletionCallback callback2;
5638 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5639 EXPECT_EQ(ERR_IO_PENDING, rv);
5640 rv = callback2.WaitForResult();
5641 EXPECT_EQ(OK, rv);
5642 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5644 const HttpResponseInfo* response = trans->GetResponseInfo();
5645 ASSERT_TRUE(response != NULL);
5646 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5647 EXPECT_EQ(100, response->headers->GetContentLength());
5650 // ------------------------------------------------------------------------
5652 // Transaction 5: request a URL in MyRealm, but the server rejects the
5653 // cached identity. Should invalidate and re-prompt.
5655 HttpRequestInfo request;
5656 request.method = "GET";
5657 request.url = GURL("http://www.google.com/p/q/t");
5658 request.load_flags = 0;
5660 scoped_ptr<HttpTransaction> trans(
5661 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5663 MockWrite data_writes1[] = {
5664 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5665 "Host: www.google.com\r\n"
5666 "Connection: keep-alive\r\n\r\n"),
5669 MockRead data_reads1[] = {
5670 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5671 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5672 MockRead("Content-Length: 10000\r\n\r\n"),
5673 MockRead(SYNCHRONOUS, ERR_FAILED),
5676 // Resend with authorization from cache for MyRealm.
5677 MockWrite data_writes2[] = {
5678 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5679 "Host: www.google.com\r\n"
5680 "Connection: keep-alive\r\n"
5681 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5684 // Sever rejects the authorization.
5685 MockRead data_reads2[] = {
5686 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5687 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5688 MockRead("Content-Length: 10000\r\n\r\n"),
5689 MockRead(SYNCHRONOUS, ERR_FAILED),
5692 // At this point we should prompt for new credentials for MyRealm.
5693 // Restart with username=foo3, password=foo4.
5694 MockWrite data_writes3[] = {
5695 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5696 "Host: www.google.com\r\n"
5697 "Connection: keep-alive\r\n"
5698 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5701 // Sever accepts the authorization.
5702 MockRead data_reads3[] = {
5703 MockRead("HTTP/1.0 200 OK\r\n"),
5704 MockRead("Content-Length: 100\r\n\r\n"),
5705 MockRead(SYNCHRONOUS, OK),
5708 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5709 data_writes1, arraysize(data_writes1));
5710 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5711 data_writes2, arraysize(data_writes2));
5712 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5713 data_writes3, arraysize(data_writes3));
5714 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5715 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5716 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5718 TestCompletionCallback callback1;
5720 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5721 EXPECT_EQ(ERR_IO_PENDING, rv);
5723 rv = callback1.WaitForResult();
5724 EXPECT_EQ(OK, rv);
5726 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5727 TestCompletionCallback callback2;
5728 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5729 EXPECT_EQ(ERR_IO_PENDING, rv);
5730 rv = callback2.WaitForResult();
5731 EXPECT_EQ(OK, rv);
5732 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5734 const HttpResponseInfo* response = trans->GetResponseInfo();
5735 ASSERT_TRUE(response != NULL);
5736 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5738 TestCompletionCallback callback3;
5740 rv = trans->RestartWithAuth(
5741 AuthCredentials(kFoo3, kBar3), callback3.callback());
5742 EXPECT_EQ(ERR_IO_PENDING, rv);
5744 rv = callback3.WaitForResult();
5745 EXPECT_EQ(OK, rv);
5747 response = trans->GetResponseInfo();
5748 ASSERT_TRUE(response != NULL);
5749 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5750 EXPECT_EQ(100, response->headers->GetContentLength());
5754 // Tests that nonce count increments when multiple auth attempts
5755 // are started with the same nonce.
5756 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5757 HttpAuthHandlerDigest::Factory* digest_factory =
5758 new HttpAuthHandlerDigest::Factory();
5759 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5760 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5761 digest_factory->set_nonce_generator(nonce_generator);
5762 session_deps_.http_auth_handler_factory.reset(digest_factory);
5763 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5765 // Transaction 1: authenticate (foo, bar) on MyRealm1
5767 HttpRequestInfo request;
5768 request.method = "GET";
5769 request.url = GURL("http://www.google.com/x/y/z");
5770 request.load_flags = 0;
5772 scoped_ptr<HttpTransaction> trans(
5773 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5775 MockWrite data_writes1[] = {
5776 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5777 "Host: www.google.com\r\n"
5778 "Connection: keep-alive\r\n\r\n"),
5781 MockRead data_reads1[] = {
5782 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5783 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5784 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5785 MockRead(SYNCHRONOUS, OK),
5788 // Resend with authorization (username=foo, password=bar)
5789 MockWrite data_writes2[] = {
5790 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5791 "Host: www.google.com\r\n"
5792 "Connection: keep-alive\r\n"
5793 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5794 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5795 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5796 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5799 // Sever accepts the authorization.
5800 MockRead data_reads2[] = {
5801 MockRead("HTTP/1.0 200 OK\r\n"),
5802 MockRead(SYNCHRONOUS, OK),
5805 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5806 data_writes1, arraysize(data_writes1));
5807 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5808 data_writes2, arraysize(data_writes2));
5809 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5810 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5812 TestCompletionCallback callback1;
5814 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5815 EXPECT_EQ(ERR_IO_PENDING, rv);
5817 rv = callback1.WaitForResult();
5818 EXPECT_EQ(OK, rv);
5820 const HttpResponseInfo* response = trans->GetResponseInfo();
5821 ASSERT_TRUE(response != NULL);
5822 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5824 TestCompletionCallback callback2;
5826 rv = trans->RestartWithAuth(
5827 AuthCredentials(kFoo, kBar), callback2.callback());
5828 EXPECT_EQ(ERR_IO_PENDING, rv);
5830 rv = callback2.WaitForResult();
5831 EXPECT_EQ(OK, rv);
5833 response = trans->GetResponseInfo();
5834 ASSERT_TRUE(response != NULL);
5835 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5838 // ------------------------------------------------------------------------
5840 // Transaction 2: Request another resource in digestive's protection space.
5841 // This will preemptively add an Authorization header which should have an
5842 // "nc" value of 2 (as compared to 1 in the first use.
5844 HttpRequestInfo request;
5845 request.method = "GET";
5846 // Note that Transaction 1 was at /x/y/z, so this is in the same
5847 // protection space as digest.
5848 request.url = GURL("http://www.google.com/x/y/a/b");
5849 request.load_flags = 0;
5851 scoped_ptr<HttpTransaction> trans(
5852 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5854 MockWrite data_writes1[] = {
5855 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5856 "Host: www.google.com\r\n"
5857 "Connection: keep-alive\r\n"
5858 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5859 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5860 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5861 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5864 // Sever accepts the authorization.
5865 MockRead data_reads1[] = {
5866 MockRead("HTTP/1.0 200 OK\r\n"),
5867 MockRead("Content-Length: 100\r\n\r\n"),
5868 MockRead(SYNCHRONOUS, OK),
5871 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5872 data_writes1, arraysize(data_writes1));
5873 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5875 TestCompletionCallback callback1;
5877 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5878 EXPECT_EQ(ERR_IO_PENDING, rv);
5880 rv = callback1.WaitForResult();
5881 EXPECT_EQ(OK, rv);
5883 const HttpResponseInfo* response = trans->GetResponseInfo();
5884 ASSERT_TRUE(response != NULL);
5885 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5889 // Test the ResetStateForRestart() private method.
5890 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5891 // Create a transaction (the dependencies aren't important).
5892 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5893 scoped_ptr<HttpNetworkTransaction> trans(
5894 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5896 // Setup some state (which we expect ResetStateForRestart() will clear).
5897 trans->read_buf_ = new IOBuffer(15);
5898 trans->read_buf_len_ = 15;
5899 trans->request_headers_.SetHeader("Authorization", "NTLM");
5901 // Setup state in response_
5902 HttpResponseInfo* response = &trans->response_;
5903 response->auth_challenge = new AuthChallengeInfo();
5904 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
5905 response->response_time = base::Time::Now();
5906 response->was_cached = true; // (Wouldn't ever actually be true...)
5908 { // Setup state for response_.vary_data
5909 HttpRequestInfo request;
5910 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5911 std::replace(temp.begin(), temp.end(), '\n', '\0');
5912 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5913 request.extra_headers.SetHeader("Foo", "1");
5914 request.extra_headers.SetHeader("bar", "23");
5915 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5918 // Cause the above state to be reset.
5919 trans->ResetStateForRestart();
5921 // Verify that the state that needed to be reset, has been reset.
5922 EXPECT_TRUE(trans->read_buf_.get() == NULL);
5923 EXPECT_EQ(0, trans->read_buf_len_);
5924 EXPECT_TRUE(trans->request_headers_.IsEmpty());
5925 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5926 EXPECT_TRUE(response->headers.get() == NULL);
5927 EXPECT_FALSE(response->was_cached);
5928 EXPECT_EQ(0U, response->ssl_info.cert_status);
5929 EXPECT_FALSE(response->vary_data.is_valid());
5932 // Test HTTPS connections to a site with a bad certificate
5933 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5934 HttpRequestInfo request;
5935 request.method = "GET";
5936 request.url = GURL("https://www.google.com/");
5937 request.load_flags = 0;
5939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5940 scoped_ptr<HttpTransaction> trans(
5941 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5943 MockWrite data_writes[] = {
5944 MockWrite("GET / HTTP/1.1\r\n"
5945 "Host: www.google.com\r\n"
5946 "Connection: keep-alive\r\n\r\n"),
5949 MockRead data_reads[] = {
5950 MockRead("HTTP/1.0 200 OK\r\n"),
5951 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5952 MockRead("Content-Length: 100\r\n\r\n"),
5953 MockRead(SYNCHRONOUS, OK),
5956 StaticSocketDataProvider ssl_bad_certificate;
5957 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5958 data_writes, arraysize(data_writes));
5959 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5960 SSLSocketDataProvider ssl(ASYNC, OK);
5962 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5963 session_deps_.socket_factory->AddSocketDataProvider(&data);
5964 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5965 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5967 TestCompletionCallback callback;
5969 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5970 EXPECT_EQ(ERR_IO_PENDING, rv);
5972 rv = callback.WaitForResult();
5973 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5975 rv = trans->RestartIgnoringLastError(callback.callback());
5976 EXPECT_EQ(ERR_IO_PENDING, rv);
5978 rv = callback.WaitForResult();
5979 EXPECT_EQ(OK, rv);
5981 const HttpResponseInfo* response = trans->GetResponseInfo();
5983 ASSERT_TRUE(response != NULL);
5984 EXPECT_EQ(100, response->headers->GetContentLength());
5987 // Test HTTPS connections to a site with a bad certificate, going through a
5988 // proxy
5989 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5990 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5992 HttpRequestInfo request;
5993 request.method = "GET";
5994 request.url = GURL("https://www.google.com/");
5995 request.load_flags = 0;
5997 MockWrite proxy_writes[] = {
5998 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5999 "Host: www.google.com\r\n"
6000 "Proxy-Connection: keep-alive\r\n\r\n"),
6003 MockRead proxy_reads[] = {
6004 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6005 MockRead(SYNCHRONOUS, OK)
6008 MockWrite data_writes[] = {
6009 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6010 "Host: www.google.com\r\n"
6011 "Proxy-Connection: keep-alive\r\n\r\n"),
6012 MockWrite("GET / HTTP/1.1\r\n"
6013 "Host: www.google.com\r\n"
6014 "Connection: keep-alive\r\n\r\n"),
6017 MockRead data_reads[] = {
6018 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6019 MockRead("HTTP/1.0 200 OK\r\n"),
6020 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6021 MockRead("Content-Length: 100\r\n\r\n"),
6022 MockRead(SYNCHRONOUS, OK),
6025 StaticSocketDataProvider ssl_bad_certificate(
6026 proxy_reads, arraysize(proxy_reads),
6027 proxy_writes, arraysize(proxy_writes));
6028 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6029 data_writes, arraysize(data_writes));
6030 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6031 SSLSocketDataProvider ssl(ASYNC, OK);
6033 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6034 session_deps_.socket_factory->AddSocketDataProvider(&data);
6035 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6036 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6038 TestCompletionCallback callback;
6040 for (int i = 0; i < 2; i++) {
6041 session_deps_.socket_factory->ResetNextMockIndexes();
6043 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6044 scoped_ptr<HttpTransaction> trans(
6045 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6047 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6048 EXPECT_EQ(ERR_IO_PENDING, rv);
6050 rv = callback.WaitForResult();
6051 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6053 rv = trans->RestartIgnoringLastError(callback.callback());
6054 EXPECT_EQ(ERR_IO_PENDING, rv);
6056 rv = callback.WaitForResult();
6057 EXPECT_EQ(OK, rv);
6059 const HttpResponseInfo* response = trans->GetResponseInfo();
6061 ASSERT_TRUE(response != NULL);
6062 EXPECT_EQ(100, response->headers->GetContentLength());
6067 // Test HTTPS connections to a site, going through an HTTPS proxy
6068 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6069 session_deps_.proxy_service.reset(
6070 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6071 CapturingNetLog net_log;
6072 session_deps_.net_log = &net_log;
6074 HttpRequestInfo request;
6075 request.method = "GET";
6076 request.url = GURL("https://www.google.com/");
6077 request.load_flags = 0;
6079 MockWrite data_writes[] = {
6080 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6081 "Host: www.google.com\r\n"
6082 "Proxy-Connection: keep-alive\r\n\r\n"),
6083 MockWrite("GET / HTTP/1.1\r\n"
6084 "Host: www.google.com\r\n"
6085 "Connection: keep-alive\r\n\r\n"),
6088 MockRead data_reads[] = {
6089 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6090 MockRead("HTTP/1.1 200 OK\r\n"),
6091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6092 MockRead("Content-Length: 100\r\n\r\n"),
6093 MockRead(SYNCHRONOUS, OK),
6096 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6097 data_writes, arraysize(data_writes));
6098 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6099 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6101 session_deps_.socket_factory->AddSocketDataProvider(&data);
6102 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6103 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6105 TestCompletionCallback callback;
6107 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6108 scoped_ptr<HttpTransaction> trans(
6109 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6111 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6112 EXPECT_EQ(ERR_IO_PENDING, rv);
6114 rv = callback.WaitForResult();
6115 EXPECT_EQ(OK, rv);
6116 const HttpResponseInfo* response = trans->GetResponseInfo();
6118 ASSERT_TRUE(response != NULL);
6120 EXPECT_TRUE(response->headers->IsKeepAlive());
6121 EXPECT_EQ(200, response->headers->response_code());
6122 EXPECT_EQ(100, response->headers->GetContentLength());
6123 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6125 LoadTimingInfo load_timing_info;
6126 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6127 TestLoadTimingNotReusedWithPac(load_timing_info,
6128 CONNECT_TIMING_HAS_SSL_TIMES);
6131 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6132 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6133 session_deps_.proxy_service.reset(
6134 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6135 CapturingNetLog net_log;
6136 session_deps_.net_log = &net_log;
6138 HttpRequestInfo request;
6139 request.method = "GET";
6140 request.url = GURL("https://www.google.com/");
6141 request.load_flags = 0;
6143 MockWrite data_writes[] = {
6144 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6145 "Host: www.google.com\r\n"
6146 "Proxy-Connection: keep-alive\r\n\r\n"),
6149 MockRead data_reads[] = {
6150 MockRead("HTTP/1.1 302 Redirect\r\n"),
6151 MockRead("Location: http://login.example.com/\r\n"),
6152 MockRead("Content-Length: 0\r\n\r\n"),
6153 MockRead(SYNCHRONOUS, OK),
6156 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6157 data_writes, arraysize(data_writes));
6158 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6160 session_deps_.socket_factory->AddSocketDataProvider(&data);
6161 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6163 TestCompletionCallback callback;
6165 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6166 scoped_ptr<HttpTransaction> trans(
6167 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6169 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6170 EXPECT_EQ(ERR_IO_PENDING, rv);
6172 rv = callback.WaitForResult();
6173 EXPECT_EQ(OK, rv);
6174 const HttpResponseInfo* response = trans->GetResponseInfo();
6176 ASSERT_TRUE(response != NULL);
6178 EXPECT_EQ(302, response->headers->response_code());
6179 std::string url;
6180 EXPECT_TRUE(response->headers->IsRedirect(&url));
6181 EXPECT_EQ("http://login.example.com/", url);
6183 // In the case of redirects from proxies, HttpNetworkTransaction returns
6184 // timing for the proxy connection instead of the connection to the host,
6185 // and no send / receive times.
6186 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6187 LoadTimingInfo load_timing_info;
6188 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6190 EXPECT_FALSE(load_timing_info.socket_reused);
6191 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6193 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6194 EXPECT_LE(load_timing_info.proxy_resolve_start,
6195 load_timing_info.proxy_resolve_end);
6196 EXPECT_LE(load_timing_info.proxy_resolve_end,
6197 load_timing_info.connect_timing.connect_start);
6198 ExpectConnectTimingHasTimes(
6199 load_timing_info.connect_timing,
6200 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6202 EXPECT_TRUE(load_timing_info.send_start.is_null());
6203 EXPECT_TRUE(load_timing_info.send_end.is_null());
6204 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6207 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6208 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6209 session_deps_.proxy_service.reset(
6210 ProxyService::CreateFixed("https://proxy:70"));
6212 HttpRequestInfo request;
6213 request.method = "GET";
6214 request.url = GURL("https://www.google.com/");
6215 request.load_flags = 0;
6217 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6218 LOWEST));
6219 scoped_ptr<SpdyFrame> goaway(
6220 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6221 MockWrite data_writes[] = {
6222 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6223 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
6226 static const char* const kExtraHeaders[] = {
6227 "location",
6228 "http://login.example.com/",
6230 scoped_ptr<SpdyFrame> resp(
6231 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6232 arraysize(kExtraHeaders)/2, 1));
6233 MockRead data_reads[] = {
6234 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6235 MockRead(ASYNC, 0, 2), // EOF
6238 DelayedSocketData data(
6239 1, // wait for one write to finish before reading.
6240 data_reads, arraysize(data_reads),
6241 data_writes, arraysize(data_writes));
6242 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6243 proxy_ssl.SetNextProto(GetParam());
6245 session_deps_.socket_factory->AddSocketDataProvider(&data);
6246 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6248 TestCompletionCallback callback;
6250 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6251 scoped_ptr<HttpTransaction> trans(
6252 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6254 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6255 EXPECT_EQ(ERR_IO_PENDING, rv);
6257 rv = callback.WaitForResult();
6258 EXPECT_EQ(OK, rv);
6259 const HttpResponseInfo* response = trans->GetResponseInfo();
6261 ASSERT_TRUE(response != NULL);
6263 EXPECT_EQ(302, response->headers->response_code());
6264 std::string url;
6265 EXPECT_TRUE(response->headers->IsRedirect(&url));
6266 EXPECT_EQ("http://login.example.com/", url);
6269 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6270 TEST_P(HttpNetworkTransactionTest,
6271 ErrorResponseToHttpsConnectViaHttpsProxy) {
6272 session_deps_.proxy_service.reset(
6273 ProxyService::CreateFixed("https://proxy:70"));
6275 HttpRequestInfo request;
6276 request.method = "GET";
6277 request.url = GURL("https://www.google.com/");
6278 request.load_flags = 0;
6280 MockWrite data_writes[] = {
6281 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6282 "Host: www.google.com\r\n"
6283 "Proxy-Connection: keep-alive\r\n\r\n"),
6286 MockRead data_reads[] = {
6287 MockRead("HTTP/1.1 404 Not Found\r\n"),
6288 MockRead("Content-Length: 23\r\n\r\n"),
6289 MockRead("The host does not exist"),
6290 MockRead(SYNCHRONOUS, OK),
6293 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6294 data_writes, arraysize(data_writes));
6295 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6297 session_deps_.socket_factory->AddSocketDataProvider(&data);
6298 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6300 TestCompletionCallback callback;
6302 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6303 scoped_ptr<HttpTransaction> trans(
6304 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6306 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6307 EXPECT_EQ(ERR_IO_PENDING, rv);
6309 rv = callback.WaitForResult();
6310 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6312 // TODO(ttuttle): Anything else to check here?
6315 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6316 TEST_P(HttpNetworkTransactionTest,
6317 ErrorResponseToHttpsConnectViaSpdyProxy) {
6318 session_deps_.proxy_service.reset(
6319 ProxyService::CreateFixed("https://proxy:70"));
6321 HttpRequestInfo request;
6322 request.method = "GET";
6323 request.url = GURL("https://www.google.com/");
6324 request.load_flags = 0;
6326 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6327 LOWEST));
6328 scoped_ptr<SpdyFrame> rst(
6329 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6330 MockWrite data_writes[] = {
6331 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6332 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6335 static const char* const kExtraHeaders[] = {
6336 "location",
6337 "http://login.example.com/",
6339 scoped_ptr<SpdyFrame> resp(
6340 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6341 arraysize(kExtraHeaders)/2, 1));
6342 scoped_ptr<SpdyFrame> body(
6343 spdy_util_.ConstructSpdyBodyFrame(
6344 1, "The host does not exist", 23, true));
6345 MockRead data_reads[] = {
6346 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6347 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6348 MockRead(ASYNC, 0, 4), // EOF
6351 DelayedSocketData data(
6352 1, // wait for one write to finish before reading.
6353 data_reads, arraysize(data_reads),
6354 data_writes, arraysize(data_writes));
6355 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6356 proxy_ssl.SetNextProto(GetParam());
6358 session_deps_.socket_factory->AddSocketDataProvider(&data);
6359 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6361 TestCompletionCallback callback;
6363 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6364 scoped_ptr<HttpTransaction> trans(
6365 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6367 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6368 EXPECT_EQ(ERR_IO_PENDING, rv);
6370 rv = callback.WaitForResult();
6371 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6373 // TODO(ttuttle): Anything else to check here?
6376 // Test the request-challenge-retry sequence for basic auth, through
6377 // a SPDY proxy over a single SPDY session.
6378 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6379 HttpRequestInfo request;
6380 request.method = "GET";
6381 request.url = GURL("https://www.google.com/");
6382 // when the no authentication data flag is set.
6383 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
6385 // Configure against https proxy server "myproxy:70".
6386 session_deps_.proxy_service.reset(
6387 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6388 CapturingBoundNetLog log;
6389 session_deps_.net_log = log.bound().net_log();
6390 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6392 // Since we have proxy, should try to establish tunnel.
6393 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6394 LOWEST));
6395 scoped_ptr<SpdyFrame> rst(
6396 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6398 // After calling trans->RestartWithAuth(), this is the request we should
6399 // be issuing -- the final header line contains the credentials.
6400 const char* const kAuthCredentials[] = {
6401 "proxy-authorization", "Basic Zm9vOmJhcg==",
6403 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6404 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
6405 // fetch https://www.google.com/ via HTTP
6406 const char get[] = "GET / HTTP/1.1\r\n"
6407 "Host: www.google.com\r\n"
6408 "Connection: keep-alive\r\n\r\n";
6409 scoped_ptr<SpdyFrame> wrapped_get(
6410 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6412 MockWrite spdy_writes[] = {
6413 CreateMockWrite(*req, 1, ASYNC),
6414 CreateMockWrite(*rst, 4, ASYNC),
6415 CreateMockWrite(*connect2, 5),
6416 CreateMockWrite(*wrapped_get, 8),
6419 // The proxy responds to the connect with a 407, using a persistent
6420 // connection.
6421 const char* const kAuthStatus = "407";
6422 const char* const kAuthChallenge[] = {
6423 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6425 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6426 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6428 scoped_ptr<SpdyFrame> conn_resp(
6429 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6430 const char resp[] = "HTTP/1.1 200 OK\r\n"
6431 "Content-Length: 5\r\n\r\n";
6433 scoped_ptr<SpdyFrame> wrapped_get_resp(
6434 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6435 scoped_ptr<SpdyFrame> wrapped_body(
6436 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6437 MockRead spdy_reads[] = {
6438 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6439 CreateMockRead(*conn_resp, 6, ASYNC),
6440 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6441 CreateMockRead(*wrapped_body, 10, ASYNC),
6442 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6445 OrderedSocketData spdy_data(
6446 spdy_reads, arraysize(spdy_reads),
6447 spdy_writes, arraysize(spdy_writes));
6448 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6449 // Negotiate SPDY to the proxy
6450 SSLSocketDataProvider proxy(ASYNC, OK);
6451 proxy.SetNextProto(GetParam());
6452 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6453 // Vanilla SSL to the server
6454 SSLSocketDataProvider server(ASYNC, OK);
6455 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6457 TestCompletionCallback callback1;
6459 scoped_ptr<HttpTransaction> trans(
6460 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6462 int rv = trans->Start(&request, callback1.callback(), log.bound());
6463 EXPECT_EQ(ERR_IO_PENDING, rv);
6465 rv = callback1.WaitForResult();
6466 EXPECT_EQ(OK, rv);
6467 net::CapturingNetLog::CapturedEntryList entries;
6468 log.GetEntries(&entries);
6469 size_t pos = ExpectLogContainsSomewhere(
6470 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6471 NetLog::PHASE_NONE);
6472 ExpectLogContainsSomewhere(
6473 entries, pos,
6474 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6475 NetLog::PHASE_NONE);
6477 const HttpResponseInfo* response = trans->GetResponseInfo();
6478 ASSERT_TRUE(response != NULL);
6479 ASSERT_FALSE(response->headers.get() == NULL);
6480 EXPECT_EQ(407, response->headers->response_code());
6481 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6482 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6483 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6485 TestCompletionCallback callback2;
6487 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6488 callback2.callback());
6489 EXPECT_EQ(ERR_IO_PENDING, rv);
6491 rv = callback2.WaitForResult();
6492 EXPECT_EQ(OK, rv);
6494 response = trans->GetResponseInfo();
6495 ASSERT_TRUE(response != NULL);
6497 EXPECT_TRUE(response->headers->IsKeepAlive());
6498 EXPECT_EQ(200, response->headers->response_code());
6499 EXPECT_EQ(5, response->headers->GetContentLength());
6500 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6502 // The password prompt info should not be set.
6503 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6505 LoadTimingInfo load_timing_info;
6506 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6507 TestLoadTimingNotReusedWithPac(load_timing_info,
6508 CONNECT_TIMING_HAS_SSL_TIMES);
6510 trans.reset();
6511 session->CloseAllConnections();
6514 // Test that an explicitly trusted SPDY proxy can push a resource from an
6515 // origin that is different from that of its associated resource.
6516 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6517 HttpRequestInfo request;
6518 HttpRequestInfo push_request;
6520 request.method = "GET";
6521 request.url = GURL("http://www.google.com/");
6522 push_request.method = "GET";
6523 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6525 // Configure against https proxy server "myproxy:70".
6526 session_deps_.proxy_service.reset(
6527 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6528 CapturingBoundNetLog log;
6529 session_deps_.net_log = log.bound().net_log();
6531 // Enable cross-origin push.
6532 session_deps_.trusted_spdy_proxy = "myproxy:70";
6534 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6536 scoped_ptr<SpdyFrame> stream1_syn(
6537 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6539 MockWrite spdy_writes[] = {
6540 CreateMockWrite(*stream1_syn, 1, ASYNC),
6543 scoped_ptr<SpdyFrame>
6544 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6546 scoped_ptr<SpdyFrame>
6547 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6549 scoped_ptr<SpdyFrame>
6550 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6554 "http://www.another-origin.com/foo.dat"));
6555 const char kPushedData[] = "pushed";
6556 scoped_ptr<SpdyFrame> stream2_body(
6557 spdy_util_.ConstructSpdyBodyFrame(
6558 2, kPushedData, strlen(kPushedData), true));
6560 MockRead spdy_reads[] = {
6561 CreateMockRead(*stream1_reply, 2, ASYNC),
6562 CreateMockRead(*stream2_syn, 3, ASYNC),
6563 CreateMockRead(*stream1_body, 4, ASYNC),
6564 CreateMockRead(*stream2_body, 5, ASYNC),
6565 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6568 OrderedSocketData spdy_data(
6569 spdy_reads, arraysize(spdy_reads),
6570 spdy_writes, arraysize(spdy_writes));
6571 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6572 // Negotiate SPDY to the proxy
6573 SSLSocketDataProvider proxy(ASYNC, OK);
6574 proxy.SetNextProto(GetParam());
6575 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6577 scoped_ptr<HttpTransaction> trans(
6578 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6579 TestCompletionCallback callback;
6580 int rv = trans->Start(&request, callback.callback(), log.bound());
6581 EXPECT_EQ(ERR_IO_PENDING, rv);
6583 rv = callback.WaitForResult();
6584 EXPECT_EQ(OK, rv);
6585 const HttpResponseInfo* response = trans->GetResponseInfo();
6587 scoped_ptr<HttpTransaction> push_trans(
6588 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6589 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6590 EXPECT_EQ(ERR_IO_PENDING, rv);
6592 rv = callback.WaitForResult();
6593 EXPECT_EQ(OK, rv);
6594 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6596 ASSERT_TRUE(response != NULL);
6597 EXPECT_TRUE(response->headers->IsKeepAlive());
6599 EXPECT_EQ(200, response->headers->response_code());
6600 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6602 std::string response_data;
6603 rv = ReadTransaction(trans.get(), &response_data);
6604 EXPECT_EQ(OK, rv);
6605 EXPECT_EQ("hello!", response_data);
6607 LoadTimingInfo load_timing_info;
6608 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6609 TestLoadTimingNotReusedWithPac(load_timing_info,
6610 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6612 // Verify the pushed stream.
6613 EXPECT_TRUE(push_response->headers.get() != NULL);
6614 EXPECT_EQ(200, push_response->headers->response_code());
6616 rv = ReadTransaction(push_trans.get(), &response_data);
6617 EXPECT_EQ(OK, rv);
6618 EXPECT_EQ("pushed", response_data);
6620 LoadTimingInfo push_load_timing_info;
6621 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6622 TestLoadTimingReusedWithPac(push_load_timing_info);
6623 // The transactions should share a socket ID, despite being for different
6624 // origins.
6625 EXPECT_EQ(load_timing_info.socket_log_id,
6626 push_load_timing_info.socket_log_id);
6628 trans.reset();
6629 push_trans.reset();
6630 session->CloseAllConnections();
6633 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6634 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6635 HttpRequestInfo request;
6637 request.method = "GET";
6638 request.url = GURL("http://www.google.com/");
6640 // Configure against https proxy server "myproxy:70".
6641 session_deps_.proxy_service.reset(
6642 ProxyService::CreateFixed("https://myproxy:70"));
6643 CapturingBoundNetLog log;
6644 session_deps_.net_log = log.bound().net_log();
6646 // Enable cross-origin push.
6647 session_deps_.trusted_spdy_proxy = "myproxy:70";
6649 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6651 scoped_ptr<SpdyFrame> stream1_syn(
6652 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6654 scoped_ptr<SpdyFrame> push_rst(
6655 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6657 MockWrite spdy_writes[] = {
6658 CreateMockWrite(*stream1_syn, 1, ASYNC),
6659 CreateMockWrite(*push_rst, 4),
6662 scoped_ptr<SpdyFrame>
6663 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6665 scoped_ptr<SpdyFrame>
6666 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6668 scoped_ptr<SpdyFrame>
6669 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6673 "https://www.another-origin.com/foo.dat"));
6675 MockRead spdy_reads[] = {
6676 CreateMockRead(*stream1_reply, 2, ASYNC),
6677 CreateMockRead(*stream2_syn, 3, ASYNC),
6678 CreateMockRead(*stream1_body, 5, ASYNC),
6679 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6682 OrderedSocketData spdy_data(
6683 spdy_reads, arraysize(spdy_reads),
6684 spdy_writes, arraysize(spdy_writes));
6685 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6686 // Negotiate SPDY to the proxy
6687 SSLSocketDataProvider proxy(ASYNC, OK);
6688 proxy.SetNextProto(GetParam());
6689 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6691 scoped_ptr<HttpTransaction> trans(
6692 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6693 TestCompletionCallback callback;
6694 int rv = trans->Start(&request, callback.callback(), log.bound());
6695 EXPECT_EQ(ERR_IO_PENDING, rv);
6697 rv = callback.WaitForResult();
6698 EXPECT_EQ(OK, rv);
6699 const HttpResponseInfo* response = trans->GetResponseInfo();
6701 ASSERT_TRUE(response != NULL);
6702 EXPECT_TRUE(response->headers->IsKeepAlive());
6704 EXPECT_EQ(200, response->headers->response_code());
6705 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6707 std::string response_data;
6708 rv = ReadTransaction(trans.get(), &response_data);
6709 EXPECT_EQ(OK, rv);
6710 EXPECT_EQ("hello!", response_data);
6712 trans.reset();
6713 session->CloseAllConnections();
6716 // Test HTTPS connections to a site with a bad certificate, going through an
6717 // HTTPS proxy
6718 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6719 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6720 "https://proxy:70"));
6722 HttpRequestInfo request;
6723 request.method = "GET";
6724 request.url = GURL("https://www.google.com/");
6725 request.load_flags = 0;
6727 // Attempt to fetch the URL from a server with a bad cert
6728 MockWrite bad_cert_writes[] = {
6729 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6730 "Host: www.google.com\r\n"
6731 "Proxy-Connection: keep-alive\r\n\r\n"),
6734 MockRead bad_cert_reads[] = {
6735 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6736 MockRead(SYNCHRONOUS, OK)
6739 // Attempt to fetch the URL with a good cert
6740 MockWrite good_data_writes[] = {
6741 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6742 "Host: www.google.com\r\n"
6743 "Proxy-Connection: keep-alive\r\n\r\n"),
6744 MockWrite("GET / HTTP/1.1\r\n"
6745 "Host: www.google.com\r\n"
6746 "Connection: keep-alive\r\n\r\n"),
6749 MockRead good_cert_reads[] = {
6750 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6751 MockRead("HTTP/1.0 200 OK\r\n"),
6752 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6753 MockRead("Content-Length: 100\r\n\r\n"),
6754 MockRead(SYNCHRONOUS, OK),
6757 StaticSocketDataProvider ssl_bad_certificate(
6758 bad_cert_reads, arraysize(bad_cert_reads),
6759 bad_cert_writes, arraysize(bad_cert_writes));
6760 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6761 good_data_writes, arraysize(good_data_writes));
6762 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6763 SSLSocketDataProvider ssl(ASYNC, OK);
6765 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6766 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6767 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6768 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6770 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6771 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6772 session_deps_.socket_factory->AddSocketDataProvider(&data);
6773 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6775 TestCompletionCallback callback;
6777 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6778 scoped_ptr<HttpTransaction> trans(
6779 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6781 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6782 EXPECT_EQ(ERR_IO_PENDING, rv);
6784 rv = callback.WaitForResult();
6785 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6787 rv = trans->RestartIgnoringLastError(callback.callback());
6788 EXPECT_EQ(ERR_IO_PENDING, rv);
6790 rv = callback.WaitForResult();
6791 EXPECT_EQ(OK, rv);
6793 const HttpResponseInfo* response = trans->GetResponseInfo();
6795 ASSERT_TRUE(response != NULL);
6796 EXPECT_EQ(100, response->headers->GetContentLength());
6799 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6800 HttpRequestInfo request;
6801 request.method = "GET";
6802 request.url = GURL("http://www.google.com/");
6803 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6804 "Chromium Ultra Awesome X Edition");
6806 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6807 scoped_ptr<HttpTransaction> trans(
6808 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6810 MockWrite data_writes[] = {
6811 MockWrite("GET / HTTP/1.1\r\n"
6812 "Host: www.google.com\r\n"
6813 "Connection: keep-alive\r\n"
6814 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6817 // Lastly, the server responds with the actual content.
6818 MockRead data_reads[] = {
6819 MockRead("HTTP/1.0 200 OK\r\n"),
6820 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6821 MockRead("Content-Length: 100\r\n\r\n"),
6822 MockRead(SYNCHRONOUS, OK),
6825 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6826 data_writes, arraysize(data_writes));
6827 session_deps_.socket_factory->AddSocketDataProvider(&data);
6829 TestCompletionCallback callback;
6831 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6832 EXPECT_EQ(ERR_IO_PENDING, rv);
6834 rv = callback.WaitForResult();
6835 EXPECT_EQ(OK, rv);
6838 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6839 HttpRequestInfo request;
6840 request.method = "GET";
6841 request.url = GURL("https://www.google.com/");
6842 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6843 "Chromium Ultra Awesome X Edition");
6845 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6846 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6847 scoped_ptr<HttpTransaction> trans(
6848 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6850 MockWrite data_writes[] = {
6851 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6852 "Host: www.google.com\r\n"
6853 "Proxy-Connection: keep-alive\r\n"
6854 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6856 MockRead data_reads[] = {
6857 // Return an error, so the transaction stops here (this test isn't
6858 // interested in the rest).
6859 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6860 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6861 MockRead("Proxy-Connection: close\r\n\r\n"),
6864 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6865 data_writes, arraysize(data_writes));
6866 session_deps_.socket_factory->AddSocketDataProvider(&data);
6868 TestCompletionCallback callback;
6870 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6871 EXPECT_EQ(ERR_IO_PENDING, rv);
6873 rv = callback.WaitForResult();
6874 EXPECT_EQ(OK, rv);
6877 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6878 HttpRequestInfo request;
6879 request.method = "GET";
6880 request.url = GURL("http://www.google.com/");
6881 request.load_flags = 0;
6882 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6883 "http://the.previous.site.com/");
6885 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6886 scoped_ptr<HttpTransaction> trans(
6887 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6889 MockWrite data_writes[] = {
6890 MockWrite("GET / HTTP/1.1\r\n"
6891 "Host: www.google.com\r\n"
6892 "Connection: keep-alive\r\n"
6893 "Referer: http://the.previous.site.com/\r\n\r\n"),
6896 // Lastly, the server responds with the actual content.
6897 MockRead data_reads[] = {
6898 MockRead("HTTP/1.0 200 OK\r\n"),
6899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6900 MockRead("Content-Length: 100\r\n\r\n"),
6901 MockRead(SYNCHRONOUS, OK),
6904 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6905 data_writes, arraysize(data_writes));
6906 session_deps_.socket_factory->AddSocketDataProvider(&data);
6908 TestCompletionCallback callback;
6910 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6911 EXPECT_EQ(ERR_IO_PENDING, rv);
6913 rv = callback.WaitForResult();
6914 EXPECT_EQ(OK, rv);
6917 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6918 HttpRequestInfo request;
6919 request.method = "POST";
6920 request.url = GURL("http://www.google.com/");
6922 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6923 scoped_ptr<HttpTransaction> trans(
6924 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6926 MockWrite data_writes[] = {
6927 MockWrite("POST / HTTP/1.1\r\n"
6928 "Host: www.google.com\r\n"
6929 "Connection: keep-alive\r\n"
6930 "Content-Length: 0\r\n\r\n"),
6933 // Lastly, the server responds with the actual content.
6934 MockRead data_reads[] = {
6935 MockRead("HTTP/1.0 200 OK\r\n"),
6936 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6937 MockRead("Content-Length: 100\r\n\r\n"),
6938 MockRead(SYNCHRONOUS, OK),
6941 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6942 data_writes, arraysize(data_writes));
6943 session_deps_.socket_factory->AddSocketDataProvider(&data);
6945 TestCompletionCallback callback;
6947 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6948 EXPECT_EQ(ERR_IO_PENDING, rv);
6950 rv = callback.WaitForResult();
6951 EXPECT_EQ(OK, rv);
6954 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6955 HttpRequestInfo request;
6956 request.method = "PUT";
6957 request.url = GURL("http://www.google.com/");
6959 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6960 scoped_ptr<HttpTransaction> trans(
6961 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6963 MockWrite data_writes[] = {
6964 MockWrite("PUT / HTTP/1.1\r\n"
6965 "Host: www.google.com\r\n"
6966 "Connection: keep-alive\r\n"
6967 "Content-Length: 0\r\n\r\n"),
6970 // Lastly, the server responds with the actual content.
6971 MockRead data_reads[] = {
6972 MockRead("HTTP/1.0 200 OK\r\n"),
6973 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6974 MockRead("Content-Length: 100\r\n\r\n"),
6975 MockRead(SYNCHRONOUS, OK),
6978 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6979 data_writes, arraysize(data_writes));
6980 session_deps_.socket_factory->AddSocketDataProvider(&data);
6982 TestCompletionCallback callback;
6984 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6985 EXPECT_EQ(ERR_IO_PENDING, rv);
6987 rv = callback.WaitForResult();
6988 EXPECT_EQ(OK, rv);
6991 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6992 HttpRequestInfo request;
6993 request.method = "HEAD";
6994 request.url = GURL("http://www.google.com/");
6996 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6997 scoped_ptr<HttpTransaction> trans(
6998 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7000 MockWrite data_writes[] = {
7001 MockWrite("HEAD / HTTP/1.1\r\n"
7002 "Host: www.google.com\r\n"
7003 "Connection: keep-alive\r\n"
7004 "Content-Length: 0\r\n\r\n"),
7007 // Lastly, the server responds with the actual content.
7008 MockRead data_reads[] = {
7009 MockRead("HTTP/1.0 200 OK\r\n"),
7010 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7011 MockRead("Content-Length: 100\r\n\r\n"),
7012 MockRead(SYNCHRONOUS, OK),
7015 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7016 data_writes, arraysize(data_writes));
7017 session_deps_.socket_factory->AddSocketDataProvider(&data);
7019 TestCompletionCallback callback;
7021 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7022 EXPECT_EQ(ERR_IO_PENDING, rv);
7024 rv = callback.WaitForResult();
7025 EXPECT_EQ(OK, rv);
7028 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7029 HttpRequestInfo request;
7030 request.method = "GET";
7031 request.url = GURL("http://www.google.com/");
7032 request.load_flags = LOAD_BYPASS_CACHE;
7034 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7035 scoped_ptr<HttpTransaction> trans(
7036 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7038 MockWrite data_writes[] = {
7039 MockWrite("GET / HTTP/1.1\r\n"
7040 "Host: www.google.com\r\n"
7041 "Connection: keep-alive\r\n"
7042 "Pragma: no-cache\r\n"
7043 "Cache-Control: no-cache\r\n\r\n"),
7046 // Lastly, the server responds with the actual content.
7047 MockRead data_reads[] = {
7048 MockRead("HTTP/1.0 200 OK\r\n"),
7049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7050 MockRead("Content-Length: 100\r\n\r\n"),
7051 MockRead(SYNCHRONOUS, OK),
7054 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7055 data_writes, arraysize(data_writes));
7056 session_deps_.socket_factory->AddSocketDataProvider(&data);
7058 TestCompletionCallback callback;
7060 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7061 EXPECT_EQ(ERR_IO_PENDING, rv);
7063 rv = callback.WaitForResult();
7064 EXPECT_EQ(OK, rv);
7067 TEST_P(HttpNetworkTransactionTest,
7068 BuildRequest_CacheControlValidateCache) {
7069 HttpRequestInfo request;
7070 request.method = "GET";
7071 request.url = GURL("http://www.google.com/");
7072 request.load_flags = LOAD_VALIDATE_CACHE;
7074 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7075 scoped_ptr<HttpTransaction> trans(
7076 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7078 MockWrite data_writes[] = {
7079 MockWrite("GET / HTTP/1.1\r\n"
7080 "Host: www.google.com\r\n"
7081 "Connection: keep-alive\r\n"
7082 "Cache-Control: max-age=0\r\n\r\n"),
7085 // Lastly, the server responds with the actual content.
7086 MockRead data_reads[] = {
7087 MockRead("HTTP/1.0 200 OK\r\n"),
7088 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7089 MockRead("Content-Length: 100\r\n\r\n"),
7090 MockRead(SYNCHRONOUS, OK),
7093 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7094 data_writes, arraysize(data_writes));
7095 session_deps_.socket_factory->AddSocketDataProvider(&data);
7097 TestCompletionCallback callback;
7099 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7100 EXPECT_EQ(ERR_IO_PENDING, rv);
7102 rv = callback.WaitForResult();
7103 EXPECT_EQ(OK, rv);
7106 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7107 HttpRequestInfo request;
7108 request.method = "GET";
7109 request.url = GURL("http://www.google.com/");
7110 request.extra_headers.SetHeader("FooHeader", "Bar");
7112 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7113 scoped_ptr<HttpTransaction> trans(
7114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7116 MockWrite data_writes[] = {
7117 MockWrite("GET / HTTP/1.1\r\n"
7118 "Host: www.google.com\r\n"
7119 "Connection: keep-alive\r\n"
7120 "FooHeader: Bar\r\n\r\n"),
7123 // Lastly, the server responds with the actual content.
7124 MockRead data_reads[] = {
7125 MockRead("HTTP/1.0 200 OK\r\n"),
7126 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7127 MockRead("Content-Length: 100\r\n\r\n"),
7128 MockRead(SYNCHRONOUS, OK),
7131 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7132 data_writes, arraysize(data_writes));
7133 session_deps_.socket_factory->AddSocketDataProvider(&data);
7135 TestCompletionCallback callback;
7137 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7138 EXPECT_EQ(ERR_IO_PENDING, rv);
7140 rv = callback.WaitForResult();
7141 EXPECT_EQ(OK, rv);
7144 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7145 HttpRequestInfo request;
7146 request.method = "GET";
7147 request.url = GURL("http://www.google.com/");
7148 request.extra_headers.SetHeader("referer", "www.foo.com");
7149 request.extra_headers.SetHeader("hEllo", "Kitty");
7150 request.extra_headers.SetHeader("FoO", "bar");
7152 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7153 scoped_ptr<HttpTransaction> trans(
7154 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7156 MockWrite data_writes[] = {
7157 MockWrite("GET / HTTP/1.1\r\n"
7158 "Host: www.google.com\r\n"
7159 "Connection: keep-alive\r\n"
7160 "referer: www.foo.com\r\n"
7161 "hEllo: Kitty\r\n"
7162 "FoO: bar\r\n\r\n"),
7165 // Lastly, the server responds with the actual content.
7166 MockRead data_reads[] = {
7167 MockRead("HTTP/1.0 200 OK\r\n"),
7168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7169 MockRead("Content-Length: 100\r\n\r\n"),
7170 MockRead(SYNCHRONOUS, OK),
7173 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7174 data_writes, arraysize(data_writes));
7175 session_deps_.socket_factory->AddSocketDataProvider(&data);
7177 TestCompletionCallback callback;
7179 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7180 EXPECT_EQ(ERR_IO_PENDING, rv);
7182 rv = callback.WaitForResult();
7183 EXPECT_EQ(OK, rv);
7186 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7187 HttpRequestInfo request;
7188 request.method = "GET";
7189 request.url = GURL("http://www.google.com/");
7190 request.load_flags = 0;
7192 session_deps_.proxy_service.reset(
7193 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7194 CapturingNetLog net_log;
7195 session_deps_.net_log = &net_log;
7197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7198 scoped_ptr<HttpTransaction> trans(
7199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7201 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7202 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7204 MockWrite data_writes[] = {
7205 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7206 MockWrite("GET / HTTP/1.1\r\n"
7207 "Host: www.google.com\r\n"
7208 "Connection: keep-alive\r\n\r\n")
7211 MockRead data_reads[] = {
7212 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7213 MockRead("HTTP/1.0 200 OK\r\n"),
7214 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7215 MockRead("Payload"),
7216 MockRead(SYNCHRONOUS, OK)
7219 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7220 data_writes, arraysize(data_writes));
7221 session_deps_.socket_factory->AddSocketDataProvider(&data);
7223 TestCompletionCallback callback;
7225 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7226 EXPECT_EQ(ERR_IO_PENDING, rv);
7228 rv = callback.WaitForResult();
7229 EXPECT_EQ(OK, rv);
7231 const HttpResponseInfo* response = trans->GetResponseInfo();
7232 ASSERT_TRUE(response != NULL);
7234 LoadTimingInfo load_timing_info;
7235 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7236 TestLoadTimingNotReusedWithPac(load_timing_info,
7237 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7239 std::string response_text;
7240 rv = ReadTransaction(trans.get(), &response_text);
7241 EXPECT_EQ(OK, rv);
7242 EXPECT_EQ("Payload", response_text);
7245 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7246 HttpRequestInfo request;
7247 request.method = "GET";
7248 request.url = GURL("https://www.google.com/");
7249 request.load_flags = 0;
7251 session_deps_.proxy_service.reset(
7252 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7253 CapturingNetLog net_log;
7254 session_deps_.net_log = &net_log;
7256 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7257 scoped_ptr<HttpTransaction> trans(
7258 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7260 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7261 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7263 MockWrite data_writes[] = {
7264 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7265 arraysize(write_buffer)),
7266 MockWrite("GET / HTTP/1.1\r\n"
7267 "Host: www.google.com\r\n"
7268 "Connection: keep-alive\r\n\r\n")
7271 MockRead data_reads[] = {
7272 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7273 arraysize(read_buffer)),
7274 MockRead("HTTP/1.0 200 OK\r\n"),
7275 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7276 MockRead("Payload"),
7277 MockRead(SYNCHRONOUS, OK)
7280 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7281 data_writes, arraysize(data_writes));
7282 session_deps_.socket_factory->AddSocketDataProvider(&data);
7284 SSLSocketDataProvider ssl(ASYNC, OK);
7285 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7287 TestCompletionCallback callback;
7289 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7290 EXPECT_EQ(ERR_IO_PENDING, rv);
7292 rv = callback.WaitForResult();
7293 EXPECT_EQ(OK, rv);
7295 LoadTimingInfo load_timing_info;
7296 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7297 TestLoadTimingNotReusedWithPac(load_timing_info,
7298 CONNECT_TIMING_HAS_SSL_TIMES);
7300 const HttpResponseInfo* response = trans->GetResponseInfo();
7301 ASSERT_TRUE(response != NULL);
7303 std::string response_text;
7304 rv = ReadTransaction(trans.get(), &response_text);
7305 EXPECT_EQ(OK, rv);
7306 EXPECT_EQ("Payload", response_text);
7309 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7310 HttpRequestInfo request;
7311 request.method = "GET";
7312 request.url = GURL("http://www.google.com/");
7313 request.load_flags = 0;
7315 session_deps_.proxy_service.reset(
7316 ProxyService::CreateFixed("socks4://myproxy:1080"));
7317 CapturingNetLog net_log;
7318 session_deps_.net_log = &net_log;
7320 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7321 scoped_ptr<HttpTransaction> trans(
7322 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7324 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7325 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7327 MockWrite data_writes[] = {
7328 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7329 MockWrite("GET / HTTP/1.1\r\n"
7330 "Host: www.google.com\r\n"
7331 "Connection: keep-alive\r\n\r\n")
7334 MockRead data_reads[] = {
7335 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7336 MockRead("HTTP/1.0 200 OK\r\n"),
7337 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7338 MockRead("Payload"),
7339 MockRead(SYNCHRONOUS, OK)
7342 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7343 data_writes, arraysize(data_writes));
7344 session_deps_.socket_factory->AddSocketDataProvider(&data);
7346 TestCompletionCallback callback;
7348 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7349 EXPECT_EQ(ERR_IO_PENDING, rv);
7351 rv = callback.WaitForResult();
7352 EXPECT_EQ(OK, rv);
7354 const HttpResponseInfo* response = trans->GetResponseInfo();
7355 ASSERT_TRUE(response != NULL);
7357 LoadTimingInfo load_timing_info;
7358 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7359 TestLoadTimingNotReused(load_timing_info,
7360 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7362 std::string response_text;
7363 rv = ReadTransaction(trans.get(), &response_text);
7364 EXPECT_EQ(OK, rv);
7365 EXPECT_EQ("Payload", response_text);
7368 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7369 HttpRequestInfo request;
7370 request.method = "GET";
7371 request.url = GURL("http://www.google.com/");
7372 request.load_flags = 0;
7374 session_deps_.proxy_service.reset(
7375 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7376 CapturingNetLog net_log;
7377 session_deps_.net_log = &net_log;
7379 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7380 scoped_ptr<HttpTransaction> trans(
7381 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7383 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7384 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7385 const char kSOCKS5OkRequest[] = {
7386 0x05, // Version
7387 0x01, // Command (CONNECT)
7388 0x00, // Reserved.
7389 0x03, // Address type (DOMAINNAME).
7390 0x0E, // Length of domain (14)
7391 // Domain string:
7392 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7393 0x00, 0x50, // 16-bit port (80)
7395 const char kSOCKS5OkResponse[] =
7396 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7398 MockWrite data_writes[] = {
7399 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7400 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7401 MockWrite("GET / HTTP/1.1\r\n"
7402 "Host: www.google.com\r\n"
7403 "Connection: keep-alive\r\n\r\n")
7406 MockRead data_reads[] = {
7407 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7408 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7409 MockRead("HTTP/1.0 200 OK\r\n"),
7410 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7411 MockRead("Payload"),
7412 MockRead(SYNCHRONOUS, OK)
7415 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7416 data_writes, arraysize(data_writes));
7417 session_deps_.socket_factory->AddSocketDataProvider(&data);
7419 TestCompletionCallback callback;
7421 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7422 EXPECT_EQ(ERR_IO_PENDING, rv);
7424 rv = callback.WaitForResult();
7425 EXPECT_EQ(OK, rv);
7427 const HttpResponseInfo* response = trans->GetResponseInfo();
7428 ASSERT_TRUE(response != NULL);
7430 LoadTimingInfo load_timing_info;
7431 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7432 TestLoadTimingNotReusedWithPac(load_timing_info,
7433 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7435 std::string response_text;
7436 rv = ReadTransaction(trans.get(), &response_text);
7437 EXPECT_EQ(OK, rv);
7438 EXPECT_EQ("Payload", response_text);
7441 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7442 HttpRequestInfo request;
7443 request.method = "GET";
7444 request.url = GURL("https://www.google.com/");
7445 request.load_flags = 0;
7447 session_deps_.proxy_service.reset(
7448 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7449 CapturingNetLog net_log;
7450 session_deps_.net_log = &net_log;
7452 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7453 scoped_ptr<HttpTransaction> trans(
7454 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7456 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7457 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7458 const unsigned char kSOCKS5OkRequest[] = {
7459 0x05, // Version
7460 0x01, // Command (CONNECT)
7461 0x00, // Reserved.
7462 0x03, // Address type (DOMAINNAME).
7463 0x0E, // Length of domain (14)
7464 // Domain string:
7465 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7466 0x01, 0xBB, // 16-bit port (443)
7469 const char kSOCKS5OkResponse[] =
7470 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7472 MockWrite data_writes[] = {
7473 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7474 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7475 arraysize(kSOCKS5OkRequest)),
7476 MockWrite("GET / HTTP/1.1\r\n"
7477 "Host: www.google.com\r\n"
7478 "Connection: keep-alive\r\n\r\n")
7481 MockRead data_reads[] = {
7482 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7483 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7484 MockRead("HTTP/1.0 200 OK\r\n"),
7485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7486 MockRead("Payload"),
7487 MockRead(SYNCHRONOUS, OK)
7490 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7491 data_writes, arraysize(data_writes));
7492 session_deps_.socket_factory->AddSocketDataProvider(&data);
7494 SSLSocketDataProvider ssl(ASYNC, OK);
7495 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7497 TestCompletionCallback callback;
7499 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7500 EXPECT_EQ(ERR_IO_PENDING, rv);
7502 rv = callback.WaitForResult();
7503 EXPECT_EQ(OK, rv);
7505 const HttpResponseInfo* response = trans->GetResponseInfo();
7506 ASSERT_TRUE(response != NULL);
7508 LoadTimingInfo load_timing_info;
7509 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7510 TestLoadTimingNotReusedWithPac(load_timing_info,
7511 CONNECT_TIMING_HAS_SSL_TIMES);
7513 std::string response_text;
7514 rv = ReadTransaction(trans.get(), &response_text);
7515 EXPECT_EQ(OK, rv);
7516 EXPECT_EQ("Payload", response_text);
7519 namespace {
7521 // Tests that for connection endpoints the group names are correctly set.
7523 struct GroupNameTest {
7524 std::string proxy_server;
7525 std::string url;
7526 std::string expected_group_name;
7527 bool ssl;
7530 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7531 NextProto next_proto,
7532 SpdySessionDependencies* session_deps_) {
7533 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7535 base::WeakPtr<HttpServerProperties> http_server_properties =
7536 session->http_server_properties();
7537 http_server_properties->SetAlternateProtocol(
7538 HostPortPair("host.with.alternate", 80), 443,
7539 AlternateProtocolFromNextProto(next_proto));
7541 return session;
7544 int GroupNameTransactionHelper(
7545 const std::string& url,
7546 const scoped_refptr<HttpNetworkSession>& session) {
7547 HttpRequestInfo request;
7548 request.method = "GET";
7549 request.url = GURL(url);
7550 request.load_flags = 0;
7552 scoped_ptr<HttpTransaction> trans(
7553 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7555 TestCompletionCallback callback;
7557 // We do not complete this request, the dtor will clean the transaction up.
7558 return trans->Start(&request, callback.callback(), BoundNetLog());
7561 } // namespace
7563 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7564 const GroupNameTest tests[] = {
7566 "", // unused
7567 "http://www.google.com/direct",
7568 "www.google.com:80",
7569 false,
7572 "", // unused
7573 "http://[2001:1418:13:1::25]/direct",
7574 "[2001:1418:13:1::25]:80",
7575 false,
7578 // SSL Tests
7580 "", // unused
7581 "https://www.google.com/direct_ssl",
7582 "ssl/www.google.com:443",
7583 true,
7586 "", // unused
7587 "https://[2001:1418:13:1::25]/direct",
7588 "ssl/[2001:1418:13:1::25]:443",
7589 true,
7592 "", // unused
7593 "http://host.with.alternate/direct",
7594 "ssl/host.with.alternate:443",
7595 true,
7599 session_deps_.use_alternate_protocols = true;
7601 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7602 session_deps_.proxy_service.reset(
7603 ProxyService::CreateFixed(tests[i].proxy_server));
7604 scoped_refptr<HttpNetworkSession> session(
7605 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7607 HttpNetworkSessionPeer peer(session);
7608 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7609 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7610 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7611 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7612 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7613 new MockClientSocketPoolManager);
7614 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7615 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7616 peer.SetClientSocketPoolManager(
7617 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7619 EXPECT_EQ(ERR_IO_PENDING,
7620 GroupNameTransactionHelper(tests[i].url, session));
7621 if (tests[i].ssl)
7622 EXPECT_EQ(tests[i].expected_group_name,
7623 ssl_conn_pool->last_group_name_received());
7624 else
7625 EXPECT_EQ(tests[i].expected_group_name,
7626 transport_conn_pool->last_group_name_received());
7631 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7632 const GroupNameTest tests[] = {
7634 "http_proxy",
7635 "http://www.google.com/http_proxy_normal",
7636 "www.google.com:80",
7637 false,
7640 // SSL Tests
7642 "http_proxy",
7643 "https://www.google.com/http_connect_ssl",
7644 "ssl/www.google.com:443",
7645 true,
7649 "http_proxy",
7650 "http://host.with.alternate/direct",
7651 "ssl/host.with.alternate:443",
7652 true,
7656 "http_proxy",
7657 "ftp://ftp.google.com/http_proxy_normal",
7658 "ftp/ftp.google.com:21",
7659 false,
7663 session_deps_.use_alternate_protocols = true;
7665 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7666 session_deps_.proxy_service.reset(
7667 ProxyService::CreateFixed(tests[i].proxy_server));
7668 scoped_refptr<HttpNetworkSession> session(
7669 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7671 HttpNetworkSessionPeer peer(session);
7673 HostPortPair proxy_host("http_proxy", 80);
7674 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7675 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7676 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7677 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7679 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7680 new MockClientSocketPoolManager);
7681 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7682 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7683 peer.SetClientSocketPoolManager(
7684 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7686 EXPECT_EQ(ERR_IO_PENDING,
7687 GroupNameTransactionHelper(tests[i].url, session));
7688 if (tests[i].ssl)
7689 EXPECT_EQ(tests[i].expected_group_name,
7690 ssl_conn_pool->last_group_name_received());
7691 else
7692 EXPECT_EQ(tests[i].expected_group_name,
7693 http_proxy_pool->last_group_name_received());
7697 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7698 const GroupNameTest tests[] = {
7700 "socks4://socks_proxy:1080",
7701 "http://www.google.com/socks4_direct",
7702 "socks4/www.google.com:80",
7703 false,
7706 "socks5://socks_proxy:1080",
7707 "http://www.google.com/socks5_direct",
7708 "socks5/www.google.com:80",
7709 false,
7712 // SSL Tests
7714 "socks4://socks_proxy:1080",
7715 "https://www.google.com/socks4_ssl",
7716 "socks4/ssl/www.google.com:443",
7717 true,
7720 "socks5://socks_proxy:1080",
7721 "https://www.google.com/socks5_ssl",
7722 "socks5/ssl/www.google.com:443",
7723 true,
7727 "socks4://socks_proxy:1080",
7728 "http://host.with.alternate/direct",
7729 "socks4/ssl/host.with.alternate:443",
7730 true,
7734 session_deps_.use_alternate_protocols = true;
7736 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7737 session_deps_.proxy_service.reset(
7738 ProxyService::CreateFixed(tests[i].proxy_server));
7739 scoped_refptr<HttpNetworkSession> session(
7740 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7742 HttpNetworkSessionPeer peer(session);
7744 HostPortPair proxy_host("socks_proxy", 1080);
7745 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7746 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7747 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7748 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7750 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7751 new MockClientSocketPoolManager);
7752 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7753 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7754 peer.SetClientSocketPoolManager(
7755 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7757 scoped_ptr<HttpTransaction> trans(
7758 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7760 EXPECT_EQ(ERR_IO_PENDING,
7761 GroupNameTransactionHelper(tests[i].url, session));
7762 if (tests[i].ssl)
7763 EXPECT_EQ(tests[i].expected_group_name,
7764 ssl_conn_pool->last_group_name_received());
7765 else
7766 EXPECT_EQ(tests[i].expected_group_name,
7767 socks_conn_pool->last_group_name_received());
7771 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7772 HttpRequestInfo request;
7773 request.method = "GET";
7774 request.url = GURL("http://www.google.com/");
7776 session_deps_.proxy_service.reset(
7777 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7779 // This simulates failure resolving all hostnames; that means we will fail
7780 // connecting to both proxies (myproxy:70 and foobar:80).
7781 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7783 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7784 scoped_ptr<HttpTransaction> trans(
7785 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7787 TestCompletionCallback callback;
7789 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7790 EXPECT_EQ(ERR_IO_PENDING, rv);
7792 rv = callback.WaitForResult();
7793 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7796 // Base test to make sure that when the load flags for a request specify to
7797 // bypass the cache, the DNS cache is not used.
7798 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7799 int load_flags) {
7800 // Issue a request, asking to bypass the cache(s).
7801 HttpRequestInfo request;
7802 request.method = "GET";
7803 request.load_flags = load_flags;
7804 request.url = GURL("http://www.google.com/");
7806 // Select a host resolver that does caching.
7807 session_deps_.host_resolver.reset(new MockCachingHostResolver);
7809 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7810 scoped_ptr<HttpTransaction> trans(
7811 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7813 // Warm up the host cache so it has an entry for "www.google.com".
7814 AddressList addrlist;
7815 TestCompletionCallback callback;
7816 int rv = session_deps_.host_resolver->Resolve(
7817 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7818 DEFAULT_PRIORITY,
7819 &addrlist,
7820 callback.callback(),
7821 NULL,
7822 BoundNetLog());
7823 EXPECT_EQ(ERR_IO_PENDING, rv);
7824 rv = callback.WaitForResult();
7825 EXPECT_EQ(OK, rv);
7827 // Verify that it was added to host cache, by doing a subsequent async lookup
7828 // and confirming it completes synchronously.
7829 rv = session_deps_.host_resolver->Resolve(
7830 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7831 DEFAULT_PRIORITY,
7832 &addrlist,
7833 callback.callback(),
7834 NULL,
7835 BoundNetLog());
7836 ASSERT_EQ(OK, rv);
7838 // Inject a failure the next time that "www.google.com" is resolved. This way
7839 // we can tell if the next lookup hit the cache, or the "network".
7840 // (cache --> success, "network" --> failure).
7841 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7843 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7844 // first read -- this won't be reached as the host resolution will fail first.
7845 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7846 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7847 session_deps_.socket_factory->AddSocketDataProvider(&data);
7849 // Run the request.
7850 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7851 ASSERT_EQ(ERR_IO_PENDING, rv);
7852 rv = callback.WaitForResult();
7854 // If we bypassed the cache, we would have gotten a failure while resolving
7855 // "www.google.com".
7856 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7859 // There are multiple load flags that should trigger the host cache bypass.
7860 // Test each in isolation:
7861 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7862 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7865 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7866 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7869 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7870 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7873 // Make sure we can handle an error when writing the request.
7874 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7875 HttpRequestInfo request;
7876 request.method = "GET";
7877 request.url = GURL("http://www.foo.com/");
7878 request.load_flags = 0;
7880 MockWrite write_failure[] = {
7881 MockWrite(ASYNC, ERR_CONNECTION_RESET),
7883 StaticSocketDataProvider data(NULL, 0,
7884 write_failure, arraysize(write_failure));
7885 session_deps_.socket_factory->AddSocketDataProvider(&data);
7886 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7888 TestCompletionCallback callback;
7890 scoped_ptr<HttpTransaction> trans(
7891 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7893 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7894 EXPECT_EQ(ERR_IO_PENDING, rv);
7896 rv = callback.WaitForResult();
7897 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7900 // Check that a connection closed after the start of the headers finishes ok.
7901 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7902 HttpRequestInfo request;
7903 request.method = "GET";
7904 request.url = GURL("http://www.foo.com/");
7905 request.load_flags = 0;
7907 MockRead data_reads[] = {
7908 MockRead("HTTP/1."),
7909 MockRead(SYNCHRONOUS, OK),
7912 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7913 session_deps_.socket_factory->AddSocketDataProvider(&data);
7914 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7916 TestCompletionCallback callback;
7918 scoped_ptr<HttpTransaction> trans(
7919 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7921 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7922 EXPECT_EQ(ERR_IO_PENDING, rv);
7924 rv = callback.WaitForResult();
7925 EXPECT_EQ(OK, rv);
7927 const HttpResponseInfo* response = trans->GetResponseInfo();
7928 ASSERT_TRUE(response != NULL);
7930 EXPECT_TRUE(response->headers.get() != NULL);
7931 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7933 std::string response_data;
7934 rv = ReadTransaction(trans.get(), &response_data);
7935 EXPECT_EQ(OK, rv);
7936 EXPECT_EQ("", response_data);
7939 // Make sure that a dropped connection while draining the body for auth
7940 // restart does the right thing.
7941 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7942 HttpRequestInfo request;
7943 request.method = "GET";
7944 request.url = GURL("http://www.google.com/");
7945 request.load_flags = 0;
7947 MockWrite data_writes1[] = {
7948 MockWrite("GET / HTTP/1.1\r\n"
7949 "Host: www.google.com\r\n"
7950 "Connection: keep-alive\r\n\r\n"),
7953 MockRead data_reads1[] = {
7954 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7955 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7956 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7957 MockRead("Content-Length: 14\r\n\r\n"),
7958 MockRead("Unauth"),
7959 MockRead(ASYNC, ERR_CONNECTION_RESET),
7962 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7963 data_writes1, arraysize(data_writes1));
7964 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7966 // After calling trans->RestartWithAuth(), this is the request we should
7967 // be issuing -- the final header line contains the credentials.
7968 MockWrite data_writes2[] = {
7969 MockWrite("GET / HTTP/1.1\r\n"
7970 "Host: www.google.com\r\n"
7971 "Connection: keep-alive\r\n"
7972 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7975 // Lastly, the server responds with the actual content.
7976 MockRead data_reads2[] = {
7977 MockRead("HTTP/1.1 200 OK\r\n"),
7978 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7979 MockRead("Content-Length: 100\r\n\r\n"),
7980 MockRead(SYNCHRONOUS, OK),
7983 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7984 data_writes2, arraysize(data_writes2));
7985 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7986 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7988 TestCompletionCallback callback1;
7990 scoped_ptr<HttpTransaction> trans(
7991 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7993 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7994 EXPECT_EQ(ERR_IO_PENDING, rv);
7996 rv = callback1.WaitForResult();
7997 EXPECT_EQ(OK, rv);
7999 const HttpResponseInfo* response = trans->GetResponseInfo();
8000 ASSERT_TRUE(response != NULL);
8001 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8003 TestCompletionCallback callback2;
8005 rv = trans->RestartWithAuth(
8006 AuthCredentials(kFoo, kBar), callback2.callback());
8007 EXPECT_EQ(ERR_IO_PENDING, rv);
8009 rv = callback2.WaitForResult();
8010 EXPECT_EQ(OK, rv);
8012 response = trans->GetResponseInfo();
8013 ASSERT_TRUE(response != NULL);
8014 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8015 EXPECT_EQ(100, response->headers->GetContentLength());
8018 // Test HTTPS connections going through a proxy that sends extra data.
8019 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8020 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8022 HttpRequestInfo request;
8023 request.method = "GET";
8024 request.url = GURL("https://www.google.com/");
8025 request.load_flags = 0;
8027 MockRead proxy_reads[] = {
8028 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8029 MockRead(SYNCHRONOUS, OK)
8032 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8033 SSLSocketDataProvider ssl(ASYNC, OK);
8035 session_deps_.socket_factory->AddSocketDataProvider(&data);
8036 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8038 TestCompletionCallback callback;
8040 session_deps_.socket_factory->ResetNextMockIndexes();
8042 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8043 scoped_ptr<HttpTransaction> trans(
8044 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8046 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8047 EXPECT_EQ(ERR_IO_PENDING, rv);
8049 rv = callback.WaitForResult();
8050 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8053 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8054 HttpRequestInfo request;
8055 request.method = "GET";
8056 request.url = GURL("http://www.google.com/");
8057 request.load_flags = 0;
8059 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8060 scoped_ptr<HttpTransaction> trans(
8061 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8063 MockRead data_reads[] = {
8064 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8065 MockRead(SYNCHRONOUS, OK),
8068 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8069 session_deps_.socket_factory->AddSocketDataProvider(&data);
8071 TestCompletionCallback callback;
8073 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8074 EXPECT_EQ(ERR_IO_PENDING, rv);
8076 EXPECT_EQ(OK, callback.WaitForResult());
8078 const HttpResponseInfo* response = trans->GetResponseInfo();
8079 ASSERT_TRUE(response != NULL);
8081 EXPECT_TRUE(response->headers.get() != NULL);
8082 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8084 std::string response_data;
8085 rv = ReadTransaction(trans.get(), &response_data);
8086 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8089 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8090 base::FilePath temp_file_path;
8091 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8092 const uint64 kFakeSize = 100000; // file is actually blank
8093 UploadFileElementReader::ScopedOverridingContentLengthForTests
8094 overriding_content_length(kFakeSize);
8096 ScopedVector<UploadElementReader> element_readers;
8097 element_readers.push_back(
8098 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8099 temp_file_path,
8101 kuint64max,
8102 base::Time()));
8103 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8105 HttpRequestInfo request;
8106 request.method = "POST";
8107 request.url = GURL("http://www.google.com/upload");
8108 request.upload_data_stream = &upload_data_stream;
8109 request.load_flags = 0;
8111 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8112 scoped_ptr<HttpTransaction> trans(
8113 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8115 MockRead data_reads[] = {
8116 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8117 MockRead("hello world"),
8118 MockRead(SYNCHRONOUS, OK),
8120 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8121 session_deps_.socket_factory->AddSocketDataProvider(&data);
8123 TestCompletionCallback callback;
8125 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8126 EXPECT_EQ(ERR_IO_PENDING, rv);
8128 rv = callback.WaitForResult();
8129 EXPECT_EQ(OK, rv);
8131 const HttpResponseInfo* response = trans->GetResponseInfo();
8132 ASSERT_TRUE(response != NULL);
8134 EXPECT_TRUE(response->headers.get() != NULL);
8135 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8137 std::string response_data;
8138 rv = ReadTransaction(trans.get(), &response_data);
8139 EXPECT_EQ(OK, rv);
8140 EXPECT_EQ("hello world", response_data);
8142 base::DeleteFile(temp_file_path, false);
8145 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8146 base::FilePath temp_file;
8147 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8148 std::string temp_file_content("Unreadable file.");
8149 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8150 temp_file_content.length()));
8151 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
8153 ScopedVector<UploadElementReader> element_readers;
8154 element_readers.push_back(
8155 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8156 temp_file,
8158 kuint64max,
8159 base::Time()));
8160 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8162 HttpRequestInfo request;
8163 request.method = "POST";
8164 request.url = GURL("http://www.google.com/upload");
8165 request.upload_data_stream = &upload_data_stream;
8166 request.load_flags = 0;
8168 // If we try to upload an unreadable file, the transaction should fail.
8169 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8170 scoped_ptr<HttpTransaction> trans(
8171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8173 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8174 session_deps_.socket_factory->AddSocketDataProvider(&data);
8176 TestCompletionCallback callback;
8178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8179 EXPECT_EQ(ERR_IO_PENDING, rv);
8181 rv = callback.WaitForResult();
8182 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8184 const HttpResponseInfo* response = trans->GetResponseInfo();
8185 EXPECT_FALSE(response);
8187 base::DeleteFile(temp_file, false);
8190 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8191 class FakeUploadElementReader : public UploadElementReader {
8192 public:
8193 FakeUploadElementReader() {}
8194 virtual ~FakeUploadElementReader() {}
8196 const CompletionCallback& callback() const { return callback_; }
8198 // UploadElementReader overrides:
8199 virtual int Init(const CompletionCallback& callback) OVERRIDE {
8200 callback_ = callback;
8201 return ERR_IO_PENDING;
8203 virtual uint64 GetContentLength() const OVERRIDE { return 0; }
8204 virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
8205 virtual int Read(IOBuffer* buf,
8206 int buf_length,
8207 const CompletionCallback& callback) OVERRIDE {
8208 return ERR_FAILED;
8211 private:
8212 CompletionCallback callback_;
8215 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8216 ScopedVector<UploadElementReader> element_readers;
8217 element_readers.push_back(fake_reader);
8218 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8220 HttpRequestInfo request;
8221 request.method = "POST";
8222 request.url = GURL("http://www.google.com/upload");
8223 request.upload_data_stream = &upload_data_stream;
8224 request.load_flags = 0;
8226 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8227 scoped_ptr<HttpTransaction> trans(
8228 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8230 StaticSocketDataProvider data;
8231 session_deps_.socket_factory->AddSocketDataProvider(&data);
8233 TestCompletionCallback callback;
8234 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8235 EXPECT_EQ(ERR_IO_PENDING, rv);
8236 base::MessageLoop::current()->RunUntilIdle();
8238 // Transaction is pending on request body initialization.
8239 ASSERT_FALSE(fake_reader->callback().is_null());
8241 // Return Init()'s result after the transaction gets destroyed.
8242 trans.reset();
8243 fake_reader->callback().Run(OK); // Should not crash.
8246 // Tests that changes to Auth realms are treated like auth rejections.
8247 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8249 HttpRequestInfo request;
8250 request.method = "GET";
8251 request.url = GURL("http://www.google.com/");
8252 request.load_flags = 0;
8254 // First transaction will request a resource and receive a Basic challenge
8255 // with realm="first_realm".
8256 MockWrite data_writes1[] = {
8257 MockWrite("GET / HTTP/1.1\r\n"
8258 "Host: www.google.com\r\n"
8259 "Connection: keep-alive\r\n"
8260 "\r\n"),
8262 MockRead data_reads1[] = {
8263 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8264 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8265 "\r\n"),
8268 // After calling trans->RestartWithAuth(), provide an Authentication header
8269 // for first_realm. The server will reject and provide a challenge with
8270 // second_realm.
8271 MockWrite data_writes2[] = {
8272 MockWrite("GET / HTTP/1.1\r\n"
8273 "Host: www.google.com\r\n"
8274 "Connection: keep-alive\r\n"
8275 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8276 "\r\n"),
8278 MockRead data_reads2[] = {
8279 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8280 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8281 "\r\n"),
8284 // This again fails, and goes back to first_realm. Make sure that the
8285 // entry is removed from cache.
8286 MockWrite data_writes3[] = {
8287 MockWrite("GET / HTTP/1.1\r\n"
8288 "Host: www.google.com\r\n"
8289 "Connection: keep-alive\r\n"
8290 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8291 "\r\n"),
8293 MockRead data_reads3[] = {
8294 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8295 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8296 "\r\n"),
8299 // Try one last time (with the correct password) and get the resource.
8300 MockWrite data_writes4[] = {
8301 MockWrite("GET / HTTP/1.1\r\n"
8302 "Host: www.google.com\r\n"
8303 "Connection: keep-alive\r\n"
8304 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8305 "\r\n"),
8307 MockRead data_reads4[] = {
8308 MockRead("HTTP/1.1 200 OK\r\n"
8309 "Content-Type: text/html; charset=iso-8859-1\r\n"
8310 "Content-Length: 5\r\n"
8311 "\r\n"
8312 "hello"),
8315 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8316 data_writes1, arraysize(data_writes1));
8317 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8318 data_writes2, arraysize(data_writes2));
8319 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8320 data_writes3, arraysize(data_writes3));
8321 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8322 data_writes4, arraysize(data_writes4));
8323 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8324 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8325 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8326 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8328 TestCompletionCallback callback1;
8330 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8331 scoped_ptr<HttpTransaction> trans(
8332 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8334 // Issue the first request with Authorize headers. There should be a
8335 // password prompt for first_realm waiting to be filled in after the
8336 // transaction completes.
8337 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8338 EXPECT_EQ(ERR_IO_PENDING, rv);
8339 rv = callback1.WaitForResult();
8340 EXPECT_EQ(OK, rv);
8341 const HttpResponseInfo* response = trans->GetResponseInfo();
8342 ASSERT_TRUE(response != NULL);
8343 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8344 ASSERT_FALSE(challenge == NULL);
8345 EXPECT_FALSE(challenge->is_proxy);
8346 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8347 EXPECT_EQ("first_realm", challenge->realm);
8348 EXPECT_EQ("basic", challenge->scheme);
8350 // Issue the second request with an incorrect password. There should be a
8351 // password prompt for second_realm waiting to be filled in after the
8352 // transaction completes.
8353 TestCompletionCallback callback2;
8354 rv = trans->RestartWithAuth(
8355 AuthCredentials(kFirst, kBaz), callback2.callback());
8356 EXPECT_EQ(ERR_IO_PENDING, rv);
8357 rv = callback2.WaitForResult();
8358 EXPECT_EQ(OK, rv);
8359 response = trans->GetResponseInfo();
8360 ASSERT_TRUE(response != NULL);
8361 challenge = response->auth_challenge.get();
8362 ASSERT_FALSE(challenge == NULL);
8363 EXPECT_FALSE(challenge->is_proxy);
8364 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8365 EXPECT_EQ("second_realm", challenge->realm);
8366 EXPECT_EQ("basic", challenge->scheme);
8368 // Issue the third request with another incorrect password. There should be
8369 // a password prompt for first_realm waiting to be filled in. If the password
8370 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8371 // first_realm was not correctly removed.
8372 TestCompletionCallback callback3;
8373 rv = trans->RestartWithAuth(
8374 AuthCredentials(kSecond, kFou), callback3.callback());
8375 EXPECT_EQ(ERR_IO_PENDING, rv);
8376 rv = callback3.WaitForResult();
8377 EXPECT_EQ(OK, rv);
8378 response = trans->GetResponseInfo();
8379 ASSERT_TRUE(response != NULL);
8380 challenge = response->auth_challenge.get();
8381 ASSERT_FALSE(challenge == NULL);
8382 EXPECT_FALSE(challenge->is_proxy);
8383 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8384 EXPECT_EQ("first_realm", challenge->realm);
8385 EXPECT_EQ("basic", challenge->scheme);
8387 // Issue the fourth request with the correct password and username.
8388 TestCompletionCallback callback4;
8389 rv = trans->RestartWithAuth(
8390 AuthCredentials(kFirst, kBar), callback4.callback());
8391 EXPECT_EQ(ERR_IO_PENDING, rv);
8392 rv = callback4.WaitForResult();
8393 EXPECT_EQ(OK, rv);
8394 response = trans->GetResponseInfo();
8395 ASSERT_TRUE(response != NULL);
8396 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8399 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8400 session_deps_.next_protos = SpdyNextProtos();
8401 session_deps_.use_alternate_protocols = true;
8403 std::string alternate_protocol_http_header =
8404 GetAlternateProtocolHttpHeader();
8406 MockRead data_reads[] = {
8407 MockRead("HTTP/1.1 200 OK\r\n"),
8408 MockRead(alternate_protocol_http_header.c_str()),
8409 MockRead("hello world"),
8410 MockRead(SYNCHRONOUS, OK),
8413 HttpRequestInfo request;
8414 request.method = "GET";
8415 request.url = GURL("http://www.google.com/");
8416 request.load_flags = 0;
8418 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8420 session_deps_.socket_factory->AddSocketDataProvider(&data);
8422 TestCompletionCallback callback;
8424 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8425 scoped_ptr<HttpTransaction> trans(
8426 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8428 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8429 EXPECT_EQ(ERR_IO_PENDING, rv);
8431 HostPortPair http_host_port_pair("www.google.com", 80);
8432 HttpServerProperties& http_server_properties =
8433 *session->http_server_properties();
8434 EXPECT_FALSE(
8435 http_server_properties.HasAlternateProtocol(http_host_port_pair));
8437 EXPECT_EQ(OK, callback.WaitForResult());
8439 const HttpResponseInfo* response = trans->GetResponseInfo();
8440 ASSERT_TRUE(response != NULL);
8441 ASSERT_TRUE(response->headers.get() != NULL);
8442 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8443 EXPECT_FALSE(response->was_fetched_via_spdy);
8444 EXPECT_FALSE(response->was_npn_negotiated);
8446 std::string response_data;
8447 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8448 EXPECT_EQ("hello world", response_data);
8450 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
8451 const PortAlternateProtocolPair alternate =
8452 http_server_properties.GetAlternateProtocol(http_host_port_pair);
8453 PortAlternateProtocolPair expected_alternate;
8454 expected_alternate.port = 443;
8455 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
8456 EXPECT_TRUE(expected_alternate.Equals(alternate));
8459 TEST_P(HttpNetworkTransactionTest,
8460 MarkBrokenAlternateProtocolAndFallback) {
8461 session_deps_.use_alternate_protocols = true;
8463 HttpRequestInfo request;
8464 request.method = "GET";
8465 request.url = GURL("http://www.google.com/");
8466 request.load_flags = 0;
8468 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8469 StaticSocketDataProvider first_data;
8470 first_data.set_connect_data(mock_connect);
8471 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8473 MockRead data_reads[] = {
8474 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8475 MockRead("hello world"),
8476 MockRead(ASYNC, OK),
8478 StaticSocketDataProvider second_data(
8479 data_reads, arraysize(data_reads), NULL, 0);
8480 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8482 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8484 base::WeakPtr<HttpServerProperties> http_server_properties =
8485 session->http_server_properties();
8486 // Port must be < 1024, or the header will be ignored (since initial port was
8487 // port 80 (another restricted port).
8488 http_server_properties->SetAlternateProtocol(
8489 HostPortPair::FromURL(request.url),
8490 666 /* port is ignored by MockConnect anyway */,
8491 AlternateProtocolFromNextProto(GetParam()));
8493 scoped_ptr<HttpTransaction> trans(
8494 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8495 TestCompletionCallback callback;
8497 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8498 EXPECT_EQ(ERR_IO_PENDING, rv);
8499 EXPECT_EQ(OK, callback.WaitForResult());
8501 const HttpResponseInfo* response = trans->GetResponseInfo();
8502 ASSERT_TRUE(response != NULL);
8503 ASSERT_TRUE(response->headers.get() != NULL);
8504 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8506 std::string response_data;
8507 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8508 EXPECT_EQ("hello world", response_data);
8510 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8511 HostPortPair::FromURL(request.url)));
8512 const PortAlternateProtocolPair alternate =
8513 http_server_properties->GetAlternateProtocol(
8514 HostPortPair::FromURL(request.url));
8515 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8518 TEST_P(HttpNetworkTransactionTest,
8519 AlternateProtocolPortRestrictedBlocked) {
8520 // Ensure that we're not allowed to redirect traffic via an alternate
8521 // protocol to an unrestricted (port >= 1024) when the original traffic was
8522 // on a restricted port (port < 1024). Ensure that we can redirect in all
8523 // other cases.
8524 session_deps_.use_alternate_protocols = true;
8526 HttpRequestInfo restricted_port_request;
8527 restricted_port_request.method = "GET";
8528 restricted_port_request.url = GURL("http://www.google.com:1023/");
8529 restricted_port_request.load_flags = 0;
8531 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8532 StaticSocketDataProvider first_data;
8533 first_data.set_connect_data(mock_connect);
8534 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8536 MockRead data_reads[] = {
8537 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8538 MockRead("hello world"),
8539 MockRead(ASYNC, OK),
8541 StaticSocketDataProvider second_data(
8542 data_reads, arraysize(data_reads), NULL, 0);
8543 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8545 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8547 base::WeakPtr<HttpServerProperties> http_server_properties =
8548 session->http_server_properties();
8549 const int kUnrestrictedAlternatePort = 1024;
8550 http_server_properties->SetAlternateProtocol(
8551 HostPortPair::FromURL(restricted_port_request.url),
8552 kUnrestrictedAlternatePort,
8553 AlternateProtocolFromNextProto(GetParam()));
8555 scoped_ptr<HttpTransaction> trans(
8556 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8557 TestCompletionCallback callback;
8559 int rv = trans->Start(
8560 &restricted_port_request,
8561 callback.callback(), BoundNetLog());
8562 EXPECT_EQ(ERR_IO_PENDING, rv);
8563 // Invalid change to unrestricted port should fail.
8564 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8567 TEST_P(HttpNetworkTransactionTest,
8568 AlternateProtocolPortRestrictedPermitted) {
8569 // Ensure that we're allowed to redirect traffic via an alternate
8570 // protocol to an unrestricted (port >= 1024) when the original traffic was
8571 // on a restricted port (port < 1024) if we set
8572 // enable_user_alternate_protocol_ports.
8574 session_deps_.use_alternate_protocols = true;
8575 session_deps_.enable_user_alternate_protocol_ports = true;
8577 HttpRequestInfo restricted_port_request;
8578 restricted_port_request.method = "GET";
8579 restricted_port_request.url = GURL("http://www.google.com:1023/");
8580 restricted_port_request.load_flags = 0;
8582 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8583 StaticSocketDataProvider first_data;
8584 first_data.set_connect_data(mock_connect);
8585 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8587 MockRead data_reads[] = {
8588 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8589 MockRead("hello world"),
8590 MockRead(ASYNC, OK),
8592 StaticSocketDataProvider second_data(
8593 data_reads, arraysize(data_reads), NULL, 0);
8594 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8596 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8598 base::WeakPtr<HttpServerProperties> http_server_properties =
8599 session->http_server_properties();
8600 const int kUnrestrictedAlternatePort = 1024;
8601 http_server_properties->SetAlternateProtocol(
8602 HostPortPair::FromURL(restricted_port_request.url),
8603 kUnrestrictedAlternatePort,
8604 AlternateProtocolFromNextProto(GetParam()));
8606 scoped_ptr<HttpTransaction> trans(
8607 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8608 TestCompletionCallback callback;
8610 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8611 &restricted_port_request,
8612 callback.callback(), BoundNetLog()));
8613 // Change to unrestricted port should succeed.
8614 EXPECT_EQ(OK, callback.WaitForResult());
8617 TEST_P(HttpNetworkTransactionTest,
8618 AlternateProtocolPortRestrictedAllowed) {
8619 // Ensure that we're not allowed to redirect traffic via an alternate
8620 // protocol to an unrestricted (port >= 1024) when the original traffic was
8621 // on a restricted port (port < 1024). Ensure that we can redirect in all
8622 // other cases.
8623 session_deps_.use_alternate_protocols = true;
8625 HttpRequestInfo restricted_port_request;
8626 restricted_port_request.method = "GET";
8627 restricted_port_request.url = GURL("http://www.google.com:1023/");
8628 restricted_port_request.load_flags = 0;
8630 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8631 StaticSocketDataProvider first_data;
8632 first_data.set_connect_data(mock_connect);
8633 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8635 MockRead data_reads[] = {
8636 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8637 MockRead("hello world"),
8638 MockRead(ASYNC, OK),
8640 StaticSocketDataProvider second_data(
8641 data_reads, arraysize(data_reads), NULL, 0);
8642 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8644 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8646 base::WeakPtr<HttpServerProperties> http_server_properties =
8647 session->http_server_properties();
8648 const int kRestrictedAlternatePort = 80;
8649 http_server_properties->SetAlternateProtocol(
8650 HostPortPair::FromURL(restricted_port_request.url),
8651 kRestrictedAlternatePort,
8652 AlternateProtocolFromNextProto(GetParam()));
8654 scoped_ptr<HttpTransaction> trans(
8655 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8656 TestCompletionCallback callback;
8658 int rv = trans->Start(
8659 &restricted_port_request,
8660 callback.callback(), BoundNetLog());
8661 EXPECT_EQ(ERR_IO_PENDING, rv);
8662 // Valid change to restricted port should pass.
8663 EXPECT_EQ(OK, callback.WaitForResult());
8666 TEST_P(HttpNetworkTransactionTest,
8667 AlternateProtocolPortUnrestrictedAllowed1) {
8668 // Ensure that we're not allowed to redirect traffic via an alternate
8669 // protocol to an unrestricted (port >= 1024) when the original traffic was
8670 // on a restricted port (port < 1024). Ensure that we can redirect in all
8671 // other cases.
8672 session_deps_.use_alternate_protocols = true;
8674 HttpRequestInfo unrestricted_port_request;
8675 unrestricted_port_request.method = "GET";
8676 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8677 unrestricted_port_request.load_flags = 0;
8679 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8680 StaticSocketDataProvider first_data;
8681 first_data.set_connect_data(mock_connect);
8682 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8684 MockRead data_reads[] = {
8685 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8686 MockRead("hello world"),
8687 MockRead(ASYNC, OK),
8689 StaticSocketDataProvider second_data(
8690 data_reads, arraysize(data_reads), NULL, 0);
8691 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8693 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8695 base::WeakPtr<HttpServerProperties> http_server_properties =
8696 session->http_server_properties();
8697 const int kRestrictedAlternatePort = 80;
8698 http_server_properties->SetAlternateProtocol(
8699 HostPortPair::FromURL(unrestricted_port_request.url),
8700 kRestrictedAlternatePort,
8701 AlternateProtocolFromNextProto(GetParam()));
8703 scoped_ptr<HttpTransaction> trans(
8704 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8705 TestCompletionCallback callback;
8707 int rv = trans->Start(
8708 &unrestricted_port_request, callback.callback(), BoundNetLog());
8709 EXPECT_EQ(ERR_IO_PENDING, rv);
8710 // Valid change to restricted port should pass.
8711 EXPECT_EQ(OK, callback.WaitForResult());
8714 TEST_P(HttpNetworkTransactionTest,
8715 AlternateProtocolPortUnrestrictedAllowed2) {
8716 // Ensure that we're not allowed to redirect traffic via an alternate
8717 // protocol to an unrestricted (port >= 1024) when the original traffic was
8718 // on a restricted port (port < 1024). Ensure that we can redirect in all
8719 // other cases.
8720 session_deps_.use_alternate_protocols = true;
8722 HttpRequestInfo unrestricted_port_request;
8723 unrestricted_port_request.method = "GET";
8724 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8725 unrestricted_port_request.load_flags = 0;
8727 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8728 StaticSocketDataProvider first_data;
8729 first_data.set_connect_data(mock_connect);
8730 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8732 MockRead data_reads[] = {
8733 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8734 MockRead("hello world"),
8735 MockRead(ASYNC, OK),
8737 StaticSocketDataProvider second_data(
8738 data_reads, arraysize(data_reads), NULL, 0);
8739 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8741 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8743 base::WeakPtr<HttpServerProperties> http_server_properties =
8744 session->http_server_properties();
8745 const int kUnrestrictedAlternatePort = 1024;
8746 http_server_properties->SetAlternateProtocol(
8747 HostPortPair::FromURL(unrestricted_port_request.url),
8748 kUnrestrictedAlternatePort,
8749 AlternateProtocolFromNextProto(GetParam()));
8751 scoped_ptr<HttpTransaction> trans(
8752 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8753 TestCompletionCallback callback;
8755 int rv = trans->Start(
8756 &unrestricted_port_request, callback.callback(), BoundNetLog());
8757 EXPECT_EQ(ERR_IO_PENDING, rv);
8758 // Valid change to an unrestricted port should pass.
8759 EXPECT_EQ(OK, callback.WaitForResult());
8762 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
8763 // Ensure that we're not allowed to redirect traffic via an alternate
8764 // protocol to an unsafe port, and that we resume the second
8765 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8766 session_deps_.use_alternate_protocols = true;
8768 HttpRequestInfo request;
8769 request.method = "GET";
8770 request.url = GURL("http://www.google.com/");
8771 request.load_flags = 0;
8773 // The alternate protocol request will error out before we attempt to connect,
8774 // so only the standard HTTP request will try to connect.
8775 MockRead data_reads[] = {
8776 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8777 MockRead("hello world"),
8778 MockRead(ASYNC, OK),
8780 StaticSocketDataProvider data(
8781 data_reads, arraysize(data_reads), NULL, 0);
8782 session_deps_.socket_factory->AddSocketDataProvider(&data);
8784 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8786 base::WeakPtr<HttpServerProperties> http_server_properties =
8787 session->http_server_properties();
8788 const int kUnsafePort = 7;
8789 http_server_properties->SetAlternateProtocol(
8790 HostPortPair::FromURL(request.url),
8791 kUnsafePort,
8792 AlternateProtocolFromNextProto(GetParam()));
8794 scoped_ptr<HttpTransaction> trans(
8795 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8796 TestCompletionCallback callback;
8798 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8799 EXPECT_EQ(ERR_IO_PENDING, rv);
8800 // The HTTP request should succeed.
8801 EXPECT_EQ(OK, callback.WaitForResult());
8803 // Disable alternate protocol before the asserts.
8804 // HttpStreamFactory::set_use_alternate_protocols(false);
8806 const HttpResponseInfo* response = trans->GetResponseInfo();
8807 ASSERT_TRUE(response != NULL);
8808 ASSERT_TRUE(response->headers.get() != NULL);
8809 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8811 std::string response_data;
8812 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8813 EXPECT_EQ("hello world", response_data);
8816 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8817 session_deps_.use_alternate_protocols = true;
8818 session_deps_.next_protos = SpdyNextProtos();
8820 HttpRequestInfo request;
8821 request.method = "GET";
8822 request.url = GURL("http://www.google.com/");
8823 request.load_flags = 0;
8825 std::string alternate_protocol_http_header =
8826 GetAlternateProtocolHttpHeader();
8828 MockRead data_reads[] = {
8829 MockRead("HTTP/1.1 200 OK\r\n"),
8830 MockRead(alternate_protocol_http_header.c_str()),
8831 MockRead("hello world"),
8832 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8833 MockRead(ASYNC, OK)
8836 StaticSocketDataProvider first_transaction(
8837 data_reads, arraysize(data_reads), NULL, 0);
8838 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8840 SSLSocketDataProvider ssl(ASYNC, OK);
8841 ssl.SetNextProto(GetParam());
8842 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8844 scoped_ptr<SpdyFrame> req(
8845 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8846 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8848 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8849 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8850 MockRead spdy_reads[] = {
8851 CreateMockRead(*resp),
8852 CreateMockRead(*data),
8853 MockRead(ASYNC, 0, 0),
8856 DelayedSocketData spdy_data(
8857 1, // wait for one write to finish before reading.
8858 spdy_reads, arraysize(spdy_reads),
8859 spdy_writes, arraysize(spdy_writes));
8860 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8862 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8863 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8864 NULL, 0, NULL, 0);
8865 hanging_non_alternate_protocol_socket.set_connect_data(
8866 never_finishing_connect);
8867 session_deps_.socket_factory->AddSocketDataProvider(
8868 &hanging_non_alternate_protocol_socket);
8870 TestCompletionCallback callback;
8872 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8873 scoped_ptr<HttpTransaction> trans(
8874 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8876 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8877 EXPECT_EQ(ERR_IO_PENDING, rv);
8878 EXPECT_EQ(OK, callback.WaitForResult());
8880 const HttpResponseInfo* response = trans->GetResponseInfo();
8881 ASSERT_TRUE(response != NULL);
8882 ASSERT_TRUE(response->headers.get() != NULL);
8883 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8885 std::string response_data;
8886 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8887 EXPECT_EQ("hello world", response_data);
8889 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8891 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8892 EXPECT_EQ(ERR_IO_PENDING, rv);
8893 EXPECT_EQ(OK, callback.WaitForResult());
8895 response = trans->GetResponseInfo();
8896 ASSERT_TRUE(response != NULL);
8897 ASSERT_TRUE(response->headers.get() != NULL);
8898 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8899 EXPECT_TRUE(response->was_fetched_via_spdy);
8900 EXPECT_TRUE(response->was_npn_negotiated);
8902 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8903 EXPECT_EQ("hello!", response_data);
8906 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8907 session_deps_.use_alternate_protocols = true;
8908 session_deps_.next_protos = SpdyNextProtos();
8910 HttpRequestInfo request;
8911 request.method = "GET";
8912 request.url = GURL("http://www.google.com/");
8913 request.load_flags = 0;
8915 std::string alternate_protocol_http_header =
8916 GetAlternateProtocolHttpHeader();
8918 MockRead data_reads[] = {
8919 MockRead("HTTP/1.1 200 OK\r\n"),
8920 MockRead(alternate_protocol_http_header.c_str()),
8921 MockRead("hello world"),
8922 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8923 MockRead(ASYNC, OK),
8926 StaticSocketDataProvider first_transaction(
8927 data_reads, arraysize(data_reads), NULL, 0);
8928 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8929 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8931 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8932 StaticSocketDataProvider hanging_socket(
8933 NULL, 0, NULL, 0);
8934 hanging_socket.set_connect_data(never_finishing_connect);
8935 // Socket 2 and 3 are the hanging Alternate-Protocol and
8936 // non-Alternate-Protocol jobs from the 2nd transaction.
8937 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8938 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8940 SSLSocketDataProvider ssl(ASYNC, OK);
8941 ssl.SetNextProto(GetParam());
8942 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8944 scoped_ptr<SpdyFrame> req1(
8945 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8946 scoped_ptr<SpdyFrame> req2(
8947 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8948 MockWrite spdy_writes[] = {
8949 CreateMockWrite(*req1),
8950 CreateMockWrite(*req2),
8952 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8953 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8954 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8955 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8956 MockRead spdy_reads[] = {
8957 CreateMockRead(*resp1),
8958 CreateMockRead(*data1),
8959 CreateMockRead(*resp2),
8960 CreateMockRead(*data2),
8961 MockRead(ASYNC, 0, 0),
8964 DelayedSocketData spdy_data(
8965 2, // wait for writes to finish before reading.
8966 spdy_reads, arraysize(spdy_reads),
8967 spdy_writes, arraysize(spdy_writes));
8968 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8969 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8971 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8972 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8975 TestCompletionCallback callback1;
8976 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8978 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8979 EXPECT_EQ(ERR_IO_PENDING, rv);
8980 EXPECT_EQ(OK, callback1.WaitForResult());
8982 const HttpResponseInfo* response = trans1.GetResponseInfo();
8983 ASSERT_TRUE(response != NULL);
8984 ASSERT_TRUE(response->headers.get() != NULL);
8985 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8987 std::string response_data;
8988 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8989 EXPECT_EQ("hello world", response_data);
8991 TestCompletionCallback callback2;
8992 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8993 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8994 EXPECT_EQ(ERR_IO_PENDING, rv);
8996 TestCompletionCallback callback3;
8997 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8998 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8999 EXPECT_EQ(ERR_IO_PENDING, rv);
9001 EXPECT_EQ(OK, callback2.WaitForResult());
9002 EXPECT_EQ(OK, callback3.WaitForResult());
9004 response = trans2.GetResponseInfo();
9005 ASSERT_TRUE(response != NULL);
9006 ASSERT_TRUE(response->headers.get() != NULL);
9007 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9008 EXPECT_TRUE(response->was_fetched_via_spdy);
9009 EXPECT_TRUE(response->was_npn_negotiated);
9010 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9011 EXPECT_EQ("hello!", response_data);
9013 response = trans3.GetResponseInfo();
9014 ASSERT_TRUE(response != NULL);
9015 ASSERT_TRUE(response->headers.get() != NULL);
9016 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9017 EXPECT_TRUE(response->was_fetched_via_spdy);
9018 EXPECT_TRUE(response->was_npn_negotiated);
9019 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9020 EXPECT_EQ("hello!", response_data);
9023 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9024 session_deps_.use_alternate_protocols = true;
9025 session_deps_.next_protos = SpdyNextProtos();
9027 HttpRequestInfo request;
9028 request.method = "GET";
9029 request.url = GURL("http://www.google.com/");
9030 request.load_flags = 0;
9032 std::string alternate_protocol_http_header =
9033 GetAlternateProtocolHttpHeader();
9035 MockRead data_reads[] = {
9036 MockRead("HTTP/1.1 200 OK\r\n"),
9037 MockRead(alternate_protocol_http_header.c_str()),
9038 MockRead("hello world"),
9039 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9040 MockRead(ASYNC, OK),
9043 StaticSocketDataProvider first_transaction(
9044 data_reads, arraysize(data_reads), NULL, 0);
9045 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9047 SSLSocketDataProvider ssl(ASYNC, OK);
9048 ssl.SetNextProto(GetParam());
9049 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9051 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9052 StaticSocketDataProvider hanging_alternate_protocol_socket(
9053 NULL, 0, NULL, 0);
9054 hanging_alternate_protocol_socket.set_connect_data(
9055 never_finishing_connect);
9056 session_deps_.socket_factory->AddSocketDataProvider(
9057 &hanging_alternate_protocol_socket);
9059 // 2nd request is just a copy of the first one, over HTTP again.
9060 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9062 TestCompletionCallback callback;
9064 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9065 scoped_ptr<HttpTransaction> trans(
9066 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9068 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9069 EXPECT_EQ(ERR_IO_PENDING, rv);
9070 EXPECT_EQ(OK, callback.WaitForResult());
9072 const HttpResponseInfo* response = trans->GetResponseInfo();
9073 ASSERT_TRUE(response != NULL);
9074 ASSERT_TRUE(response->headers.get() != NULL);
9075 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9077 std::string response_data;
9078 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9079 EXPECT_EQ("hello world", response_data);
9081 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9083 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9084 EXPECT_EQ(ERR_IO_PENDING, rv);
9085 EXPECT_EQ(OK, callback.WaitForResult());
9087 response = trans->GetResponseInfo();
9088 ASSERT_TRUE(response != NULL);
9089 ASSERT_TRUE(response->headers.get() != NULL);
9090 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9091 EXPECT_FALSE(response->was_fetched_via_spdy);
9092 EXPECT_FALSE(response->was_npn_negotiated);
9094 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9095 EXPECT_EQ("hello world", response_data);
9098 class CapturingProxyResolver : public ProxyResolver {
9099 public:
9100 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9101 virtual ~CapturingProxyResolver() {}
9103 virtual int GetProxyForURL(const GURL& url,
9104 ProxyInfo* results,
9105 const CompletionCallback& callback,
9106 RequestHandle* request,
9107 const BoundNetLog& net_log) OVERRIDE {
9108 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9109 HostPortPair("myproxy", 80));
9110 results->UseProxyServer(proxy_server);
9111 resolved_.push_back(url);
9112 return OK;
9115 virtual void CancelRequest(RequestHandle request) OVERRIDE {
9116 NOTREACHED();
9119 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
9120 NOTREACHED();
9121 return LOAD_STATE_IDLE;
9124 virtual void CancelSetPacScript() OVERRIDE {
9125 NOTREACHED();
9128 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9129 const CompletionCallback& /*callback*/) OVERRIDE {
9130 return OK;
9133 const std::vector<GURL>& resolved() const { return resolved_; }
9135 private:
9136 std::vector<GURL> resolved_;
9138 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9141 TEST_P(HttpNetworkTransactionTest,
9142 UseAlternateProtocolForTunneledNpnSpdy) {
9143 session_deps_.use_alternate_protocols = true;
9144 session_deps_.next_protos = SpdyNextProtos();
9146 ProxyConfig proxy_config;
9147 proxy_config.set_auto_detect(true);
9148 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9150 CapturingProxyResolver* capturing_proxy_resolver =
9151 new CapturingProxyResolver();
9152 session_deps_.proxy_service.reset(new ProxyService(
9153 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
9154 NULL));
9155 CapturingNetLog net_log;
9156 session_deps_.net_log = &net_log;
9158 HttpRequestInfo request;
9159 request.method = "GET";
9160 request.url = GURL("http://www.google.com/");
9161 request.load_flags = 0;
9163 std::string alternate_protocol_http_header =
9164 GetAlternateProtocolHttpHeader();
9166 MockRead data_reads[] = {
9167 MockRead("HTTP/1.1 200 OK\r\n"),
9168 MockRead(alternate_protocol_http_header.c_str()),
9169 MockRead("hello world"),
9170 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9171 MockRead(ASYNC, OK),
9174 StaticSocketDataProvider first_transaction(
9175 data_reads, arraysize(data_reads), NULL, 0);
9176 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9178 SSLSocketDataProvider ssl(ASYNC, OK);
9179 ssl.SetNextProto(GetParam());
9180 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9182 scoped_ptr<SpdyFrame> req(
9183 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9184 MockWrite spdy_writes[] = {
9185 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9186 "Host: www.google.com\r\n"
9187 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9188 CreateMockWrite(*req), // 3
9191 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9193 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9194 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9195 MockRead spdy_reads[] = {
9196 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
9197 CreateMockRead(*resp.get(), 4), // 2, 4
9198 CreateMockRead(*data.get(), 4), // 5
9199 MockRead(ASYNC, 0, 0, 4), // 6
9202 OrderedSocketData spdy_data(
9203 spdy_reads, arraysize(spdy_reads),
9204 spdy_writes, arraysize(spdy_writes));
9205 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9207 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9208 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9209 NULL, 0, NULL, 0);
9210 hanging_non_alternate_protocol_socket.set_connect_data(
9211 never_finishing_connect);
9212 session_deps_.socket_factory->AddSocketDataProvider(
9213 &hanging_non_alternate_protocol_socket);
9215 TestCompletionCallback callback;
9217 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9218 scoped_ptr<HttpTransaction> trans(
9219 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9221 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9222 EXPECT_EQ(ERR_IO_PENDING, rv);
9223 EXPECT_EQ(OK, callback.WaitForResult());
9225 const HttpResponseInfo* response = trans->GetResponseInfo();
9226 ASSERT_TRUE(response != NULL);
9227 ASSERT_TRUE(response->headers.get() != NULL);
9228 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9229 EXPECT_FALSE(response->was_fetched_via_spdy);
9230 EXPECT_FALSE(response->was_npn_negotiated);
9232 std::string response_data;
9233 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9234 EXPECT_EQ("hello world", response_data);
9236 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9238 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9239 EXPECT_EQ(ERR_IO_PENDING, rv);
9240 EXPECT_EQ(OK, callback.WaitForResult());
9242 response = trans->GetResponseInfo();
9243 ASSERT_TRUE(response != NULL);
9244 ASSERT_TRUE(response->headers.get() != NULL);
9245 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9246 EXPECT_TRUE(response->was_fetched_via_spdy);
9247 EXPECT_TRUE(response->was_npn_negotiated);
9249 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9250 EXPECT_EQ("hello!", response_data);
9251 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
9252 EXPECT_EQ("http://www.google.com/",
9253 capturing_proxy_resolver->resolved()[0].spec());
9254 EXPECT_EQ("https://www.google.com/",
9255 capturing_proxy_resolver->resolved()[1].spec());
9257 LoadTimingInfo load_timing_info;
9258 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9259 TestLoadTimingNotReusedWithPac(load_timing_info,
9260 CONNECT_TIMING_HAS_SSL_TIMES);
9263 TEST_P(HttpNetworkTransactionTest,
9264 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9265 session_deps_.use_alternate_protocols = true;
9266 session_deps_.next_protos = SpdyNextProtos();
9268 HttpRequestInfo request;
9269 request.method = "GET";
9270 request.url = GURL("http://www.google.com/");
9271 request.load_flags = 0;
9273 std::string alternate_protocol_http_header =
9274 GetAlternateProtocolHttpHeader();
9276 MockRead data_reads[] = {
9277 MockRead("HTTP/1.1 200 OK\r\n"),
9278 MockRead(alternate_protocol_http_header.c_str()),
9279 MockRead("hello world"),
9280 MockRead(ASYNC, OK),
9283 StaticSocketDataProvider first_transaction(
9284 data_reads, arraysize(data_reads), NULL, 0);
9285 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9287 SSLSocketDataProvider ssl(ASYNC, OK);
9288 ssl.SetNextProto(GetParam());
9289 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9291 scoped_ptr<SpdyFrame> req(
9292 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9293 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9295 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9296 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9297 MockRead spdy_reads[] = {
9298 CreateMockRead(*resp),
9299 CreateMockRead(*data),
9300 MockRead(ASYNC, 0, 0),
9303 DelayedSocketData spdy_data(
9304 1, // wait for one write to finish before reading.
9305 spdy_reads, arraysize(spdy_reads),
9306 spdy_writes, arraysize(spdy_writes));
9307 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9309 TestCompletionCallback callback;
9311 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9313 scoped_ptr<HttpTransaction> trans(
9314 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9316 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9317 EXPECT_EQ(ERR_IO_PENDING, rv);
9318 EXPECT_EQ(OK, callback.WaitForResult());
9320 const HttpResponseInfo* response = trans->GetResponseInfo();
9321 ASSERT_TRUE(response != NULL);
9322 ASSERT_TRUE(response->headers.get() != NULL);
9323 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9325 std::string response_data;
9326 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9327 EXPECT_EQ("hello world", response_data);
9329 // Set up an initial SpdySession in the pool to reuse.
9330 HostPortPair host_port_pair("www.google.com", 443);
9331 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9332 PRIVACY_MODE_DISABLED);
9333 base::WeakPtr<SpdySession> spdy_session =
9334 CreateSecureSpdySession(session, key, BoundNetLog());
9336 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9338 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9339 EXPECT_EQ(ERR_IO_PENDING, rv);
9340 EXPECT_EQ(OK, callback.WaitForResult());
9342 response = trans->GetResponseInfo();
9343 ASSERT_TRUE(response != NULL);
9344 ASSERT_TRUE(response->headers.get() != NULL);
9345 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9346 EXPECT_TRUE(response->was_fetched_via_spdy);
9347 EXPECT_TRUE(response->was_npn_negotiated);
9349 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9350 EXPECT_EQ("hello!", response_data);
9353 // GenerateAuthToken is a mighty big test.
9354 // It tests all permutation of GenerateAuthToken behavior:
9355 // - Synchronous and Asynchronous completion.
9356 // - OK or error on completion.
9357 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9358 // - HTTP or HTTPS backend (to include proxy tunneling).
9359 // - Non-authenticating and authenticating backend.
9361 // In all, there are 44 reasonable permuations (for example, if there are
9362 // problems generating an auth token for an authenticating proxy, we don't
9363 // need to test all permutations of the backend server).
9365 // The test proceeds by going over each of the configuration cases, and
9366 // potentially running up to three rounds in each of the tests. The TestConfig
9367 // specifies both the configuration for the test as well as the expectations
9368 // for the results.
9369 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9370 static const char kServer[] = "http://www.example.com";
9371 static const char kSecureServer[] = "https://www.example.com";
9372 static const char kProxy[] = "myproxy:70";
9373 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9375 enum AuthTiming {
9376 AUTH_NONE,
9377 AUTH_SYNC,
9378 AUTH_ASYNC,
9381 const MockWrite kGet(
9382 "GET / HTTP/1.1\r\n"
9383 "Host: www.example.com\r\n"
9384 "Connection: keep-alive\r\n\r\n");
9385 const MockWrite kGetProxy(
9386 "GET http://www.example.com/ HTTP/1.1\r\n"
9387 "Host: www.example.com\r\n"
9388 "Proxy-Connection: keep-alive\r\n\r\n");
9389 const MockWrite kGetAuth(
9390 "GET / HTTP/1.1\r\n"
9391 "Host: www.example.com\r\n"
9392 "Connection: keep-alive\r\n"
9393 "Authorization: auth_token\r\n\r\n");
9394 const MockWrite kGetProxyAuth(
9395 "GET http://www.example.com/ HTTP/1.1\r\n"
9396 "Host: www.example.com\r\n"
9397 "Proxy-Connection: keep-alive\r\n"
9398 "Proxy-Authorization: auth_token\r\n\r\n");
9399 const MockWrite kGetAuthThroughProxy(
9400 "GET http://www.example.com/ HTTP/1.1\r\n"
9401 "Host: www.example.com\r\n"
9402 "Proxy-Connection: keep-alive\r\n"
9403 "Authorization: auth_token\r\n\r\n");
9404 const MockWrite kGetAuthWithProxyAuth(
9405 "GET http://www.example.com/ HTTP/1.1\r\n"
9406 "Host: www.example.com\r\n"
9407 "Proxy-Connection: keep-alive\r\n"
9408 "Proxy-Authorization: auth_token\r\n"
9409 "Authorization: auth_token\r\n\r\n");
9410 const MockWrite kConnect(
9411 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9412 "Host: www.example.com\r\n"
9413 "Proxy-Connection: keep-alive\r\n\r\n");
9414 const MockWrite kConnectProxyAuth(
9415 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9416 "Host: www.example.com\r\n"
9417 "Proxy-Connection: keep-alive\r\n"
9418 "Proxy-Authorization: auth_token\r\n\r\n");
9420 const MockRead kSuccess(
9421 "HTTP/1.1 200 OK\r\n"
9422 "Content-Type: text/html; charset=iso-8859-1\r\n"
9423 "Content-Length: 3\r\n\r\n"
9424 "Yes");
9425 const MockRead kFailure(
9426 "Should not be called.");
9427 const MockRead kServerChallenge(
9428 "HTTP/1.1 401 Unauthorized\r\n"
9429 "WWW-Authenticate: Mock realm=server\r\n"
9430 "Content-Type: text/html; charset=iso-8859-1\r\n"
9431 "Content-Length: 14\r\n\r\n"
9432 "Unauthorized\r\n");
9433 const MockRead kProxyChallenge(
9434 "HTTP/1.1 407 Unauthorized\r\n"
9435 "Proxy-Authenticate: Mock realm=proxy\r\n"
9436 "Proxy-Connection: close\r\n"
9437 "Content-Type: text/html; charset=iso-8859-1\r\n"
9438 "Content-Length: 14\r\n\r\n"
9439 "Unauthorized\r\n");
9440 const MockRead kProxyConnected(
9441 "HTTP/1.1 200 Connection Established\r\n\r\n");
9443 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9444 // no constructors, but the C++ compiler on Windows warns about
9445 // unspecified data in compound literals. So, moved to using constructors,
9446 // and TestRound's created with the default constructor should not be used.
9447 struct TestRound {
9448 TestRound()
9449 : expected_rv(ERR_UNEXPECTED),
9450 extra_write(NULL),
9451 extra_read(NULL) {
9453 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9454 int expected_rv_arg)
9455 : write(write_arg),
9456 read(read_arg),
9457 expected_rv(expected_rv_arg),
9458 extra_write(NULL),
9459 extra_read(NULL) {
9461 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9462 int expected_rv_arg, const MockWrite* extra_write_arg,
9463 const MockRead* extra_read_arg)
9464 : write(write_arg),
9465 read(read_arg),
9466 expected_rv(expected_rv_arg),
9467 extra_write(extra_write_arg),
9468 extra_read(extra_read_arg) {
9470 MockWrite write;
9471 MockRead read;
9472 int expected_rv;
9473 const MockWrite* extra_write;
9474 const MockRead* extra_read;
9477 static const int kNoSSL = 500;
9479 struct TestConfig {
9480 const char* proxy_url;
9481 AuthTiming proxy_auth_timing;
9482 int proxy_auth_rv;
9483 const char* server_url;
9484 AuthTiming server_auth_timing;
9485 int server_auth_rv;
9486 int num_auth_rounds;
9487 int first_ssl_round;
9488 TestRound rounds[3];
9489 } test_configs[] = {
9490 // Non-authenticating HTTP server with a direct connection.
9491 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9492 { TestRound(kGet, kSuccess, OK)}},
9493 // Authenticating HTTP server with a direct connection.
9494 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9495 { TestRound(kGet, kServerChallenge, OK),
9496 TestRound(kGetAuth, kSuccess, OK)}},
9497 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9498 { TestRound(kGet, kServerChallenge, OK),
9499 TestRound(kGetAuth, kFailure, kAuthErr)}},
9500 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9501 { TestRound(kGet, kServerChallenge, OK),
9502 TestRound(kGetAuth, kSuccess, OK)}},
9503 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9504 { TestRound(kGet, kServerChallenge, OK),
9505 TestRound(kGetAuth, kFailure, kAuthErr)}},
9506 // Non-authenticating HTTP server through a non-authenticating proxy.
9507 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9508 { TestRound(kGetProxy, kSuccess, OK)}},
9509 // Authenticating HTTP server through a non-authenticating proxy.
9510 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9511 { TestRound(kGetProxy, kServerChallenge, OK),
9512 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9513 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9514 { TestRound(kGetProxy, kServerChallenge, OK),
9515 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9516 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9517 { TestRound(kGetProxy, kServerChallenge, OK),
9518 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9519 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9520 { TestRound(kGetProxy, kServerChallenge, OK),
9521 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9522 // Non-authenticating HTTP server through an authenticating proxy.
9523 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9524 { TestRound(kGetProxy, kProxyChallenge, OK),
9525 TestRound(kGetProxyAuth, kSuccess, OK)}},
9526 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9527 { TestRound(kGetProxy, kProxyChallenge, OK),
9528 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9529 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9530 { TestRound(kGetProxy, kProxyChallenge, OK),
9531 TestRound(kGetProxyAuth, kSuccess, OK)}},
9532 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9533 { TestRound(kGetProxy, kProxyChallenge, OK),
9534 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9535 // Authenticating HTTP server through an authenticating proxy.
9536 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9537 { TestRound(kGetProxy, kProxyChallenge, OK),
9538 TestRound(kGetProxyAuth, kServerChallenge, OK),
9539 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9540 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9541 { TestRound(kGetProxy, kProxyChallenge, OK),
9542 TestRound(kGetProxyAuth, kServerChallenge, OK),
9543 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9544 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9545 { TestRound(kGetProxy, kProxyChallenge, OK),
9546 TestRound(kGetProxyAuth, kServerChallenge, OK),
9547 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9548 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9549 { TestRound(kGetProxy, kProxyChallenge, OK),
9550 TestRound(kGetProxyAuth, kServerChallenge, OK),
9551 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9552 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9553 { TestRound(kGetProxy, kProxyChallenge, OK),
9554 TestRound(kGetProxyAuth, kServerChallenge, OK),
9555 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9556 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9557 { TestRound(kGetProxy, kProxyChallenge, OK),
9558 TestRound(kGetProxyAuth, kServerChallenge, OK),
9559 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9560 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9561 { TestRound(kGetProxy, kProxyChallenge, OK),
9562 TestRound(kGetProxyAuth, kServerChallenge, OK),
9563 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9564 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9565 { TestRound(kGetProxy, kProxyChallenge, OK),
9566 TestRound(kGetProxyAuth, kServerChallenge, OK),
9567 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9568 // Non-authenticating HTTPS server with a direct connection.
9569 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9570 { TestRound(kGet, kSuccess, OK)}},
9571 // Authenticating HTTPS server with a direct connection.
9572 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9573 { TestRound(kGet, kServerChallenge, OK),
9574 TestRound(kGetAuth, kSuccess, OK)}},
9575 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9576 { TestRound(kGet, kServerChallenge, OK),
9577 TestRound(kGetAuth, kFailure, kAuthErr)}},
9578 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9579 { TestRound(kGet, kServerChallenge, OK),
9580 TestRound(kGetAuth, kSuccess, OK)}},
9581 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9582 { TestRound(kGet, kServerChallenge, OK),
9583 TestRound(kGetAuth, kFailure, kAuthErr)}},
9584 // Non-authenticating HTTPS server with a non-authenticating proxy.
9585 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9586 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9587 // Authenticating HTTPS server through a non-authenticating proxy.
9588 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9589 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9590 TestRound(kGetAuth, kSuccess, OK)}},
9591 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9592 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9593 TestRound(kGetAuth, kFailure, kAuthErr)}},
9594 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9595 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9596 TestRound(kGetAuth, kSuccess, OK)}},
9597 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9598 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9599 TestRound(kGetAuth, kFailure, kAuthErr)}},
9600 // Non-Authenticating HTTPS server through an authenticating proxy.
9601 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9602 { TestRound(kConnect, kProxyChallenge, OK),
9603 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9604 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9605 { TestRound(kConnect, kProxyChallenge, OK),
9606 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9607 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9608 { TestRound(kConnect, kProxyChallenge, OK),
9609 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9610 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9611 { TestRound(kConnect, kProxyChallenge, OK),
9612 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9613 // Authenticating HTTPS server through an authenticating proxy.
9614 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9615 { TestRound(kConnect, kProxyChallenge, OK),
9616 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9617 &kGet, &kServerChallenge),
9618 TestRound(kGetAuth, kSuccess, OK)}},
9619 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9620 { TestRound(kConnect, kProxyChallenge, OK),
9621 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9622 &kGet, &kServerChallenge),
9623 TestRound(kGetAuth, kFailure, kAuthErr)}},
9624 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9625 { TestRound(kConnect, kProxyChallenge, OK),
9626 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9627 &kGet, &kServerChallenge),
9628 TestRound(kGetAuth, kSuccess, OK)}},
9629 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9630 { TestRound(kConnect, kProxyChallenge, OK),
9631 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9632 &kGet, &kServerChallenge),
9633 TestRound(kGetAuth, kFailure, kAuthErr)}},
9634 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9635 { TestRound(kConnect, kProxyChallenge, OK),
9636 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9637 &kGet, &kServerChallenge),
9638 TestRound(kGetAuth, kSuccess, OK)}},
9639 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9640 { TestRound(kConnect, kProxyChallenge, OK),
9641 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9642 &kGet, &kServerChallenge),
9643 TestRound(kGetAuth, kFailure, kAuthErr)}},
9644 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9645 { TestRound(kConnect, kProxyChallenge, OK),
9646 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9647 &kGet, &kServerChallenge),
9648 TestRound(kGetAuth, kSuccess, OK)}},
9649 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9650 { TestRound(kConnect, kProxyChallenge, OK),
9651 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9652 &kGet, &kServerChallenge),
9653 TestRound(kGetAuth, kFailure, kAuthErr)}},
9656 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9657 HttpAuthHandlerMock::Factory* auth_factory(
9658 new HttpAuthHandlerMock::Factory());
9659 session_deps_.http_auth_handler_factory.reset(auth_factory);
9660 const TestConfig& test_config = test_configs[i];
9662 // Set up authentication handlers as necessary.
9663 if (test_config.proxy_auth_timing != AUTH_NONE) {
9664 for (int n = 0; n < 2; n++) {
9665 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9666 std::string auth_challenge = "Mock realm=proxy";
9667 GURL origin(test_config.proxy_url);
9668 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9669 auth_challenge.end());
9670 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9671 origin, BoundNetLog());
9672 auth_handler->SetGenerateExpectation(
9673 test_config.proxy_auth_timing == AUTH_ASYNC,
9674 test_config.proxy_auth_rv);
9675 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9678 if (test_config.server_auth_timing != AUTH_NONE) {
9679 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9680 std::string auth_challenge = "Mock realm=server";
9681 GURL origin(test_config.server_url);
9682 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9683 auth_challenge.end());
9684 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9685 origin, BoundNetLog());
9686 auth_handler->SetGenerateExpectation(
9687 test_config.server_auth_timing == AUTH_ASYNC,
9688 test_config.server_auth_rv);
9689 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9691 if (test_config.proxy_url) {
9692 session_deps_.proxy_service.reset(
9693 ProxyService::CreateFixed(test_config.proxy_url));
9694 } else {
9695 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9698 HttpRequestInfo request;
9699 request.method = "GET";
9700 request.url = GURL(test_config.server_url);
9701 request.load_flags = 0;
9703 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9704 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
9706 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9707 const TestRound& read_write_round = test_config.rounds[round];
9709 // Set up expected reads and writes.
9710 MockRead reads[2];
9711 reads[0] = read_write_round.read;
9712 size_t length_reads = 1;
9713 if (read_write_round.extra_read) {
9714 reads[1] = *read_write_round.extra_read;
9715 length_reads = 2;
9718 MockWrite writes[2];
9719 writes[0] = read_write_round.write;
9720 size_t length_writes = 1;
9721 if (read_write_round.extra_write) {
9722 writes[1] = *read_write_round.extra_write;
9723 length_writes = 2;
9725 StaticSocketDataProvider data_provider(
9726 reads, length_reads, writes, length_writes);
9727 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9729 // Add an SSL sequence if necessary.
9730 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9731 if (round >= test_config.first_ssl_round)
9732 session_deps_.socket_factory->AddSSLSocketDataProvider(
9733 &ssl_socket_data_provider);
9735 // Start or restart the transaction.
9736 TestCompletionCallback callback;
9737 int rv;
9738 if (round == 0) {
9739 rv = trans.Start(&request, callback.callback(), BoundNetLog());
9740 } else {
9741 rv = trans.RestartWithAuth(
9742 AuthCredentials(kFoo, kBar), callback.callback());
9744 if (rv == ERR_IO_PENDING)
9745 rv = callback.WaitForResult();
9747 // Compare results with expected data.
9748 EXPECT_EQ(read_write_round.expected_rv, rv);
9749 const HttpResponseInfo* response = trans.GetResponseInfo();
9750 if (read_write_round.expected_rv == OK) {
9751 ASSERT_TRUE(response != NULL);
9752 } else {
9753 EXPECT_TRUE(response == NULL);
9754 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9755 continue;
9757 if (round + 1 < test_config.num_auth_rounds) {
9758 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9759 } else {
9760 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9766 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9767 // Do multi-round authentication and make sure it works correctly.
9768 HttpAuthHandlerMock::Factory* auth_factory(
9769 new HttpAuthHandlerMock::Factory());
9770 session_deps_.http_auth_handler_factory.reset(auth_factory);
9771 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9772 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9773 session_deps_.host_resolver->set_synchronous_mode(true);
9775 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9776 auth_handler->set_connection_based(true);
9777 std::string auth_challenge = "Mock realm=server";
9778 GURL origin("http://www.example.com");
9779 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9780 auth_challenge.end());
9781 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9782 origin, BoundNetLog());
9783 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9785 int rv = OK;
9786 const HttpResponseInfo* response = NULL;
9787 HttpRequestInfo request;
9788 request.method = "GET";
9789 request.url = origin;
9790 request.load_flags = 0;
9792 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9794 // Use a TCP Socket Pool with only one connection per group. This is used
9795 // to validate that the TCP socket is not released to the pool between
9796 // each round of multi-round authentication.
9797 HttpNetworkSessionPeer session_peer(session);
9798 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9799 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9800 50, // Max sockets for pool
9801 1, // Max sockets per group
9802 &transport_pool_histograms,
9803 session_deps_.host_resolver.get(),
9804 session_deps_.socket_factory.get(),
9805 session_deps_.net_log);
9806 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
9807 new MockClientSocketPoolManager);
9808 mock_pool_manager->SetTransportSocketPool(transport_pool);
9809 session_peer.SetClientSocketPoolManager(
9810 mock_pool_manager.PassAs<ClientSocketPoolManager>());
9812 scoped_ptr<HttpTransaction> trans(
9813 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9814 TestCompletionCallback callback;
9816 const MockWrite kGet(
9817 "GET / HTTP/1.1\r\n"
9818 "Host: www.example.com\r\n"
9819 "Connection: keep-alive\r\n\r\n");
9820 const MockWrite kGetAuth(
9821 "GET / HTTP/1.1\r\n"
9822 "Host: www.example.com\r\n"
9823 "Connection: keep-alive\r\n"
9824 "Authorization: auth_token\r\n\r\n");
9826 const MockRead kServerChallenge(
9827 "HTTP/1.1 401 Unauthorized\r\n"
9828 "WWW-Authenticate: Mock realm=server\r\n"
9829 "Content-Type: text/html; charset=iso-8859-1\r\n"
9830 "Content-Length: 14\r\n\r\n"
9831 "Unauthorized\r\n");
9832 const MockRead kSuccess(
9833 "HTTP/1.1 200 OK\r\n"
9834 "Content-Type: text/html; charset=iso-8859-1\r\n"
9835 "Content-Length: 3\r\n\r\n"
9836 "Yes");
9838 MockWrite writes[] = {
9839 // First round
9840 kGet,
9841 // Second round
9842 kGetAuth,
9843 // Third round
9844 kGetAuth,
9845 // Fourth round
9846 kGetAuth,
9847 // Competing request
9848 kGet,
9850 MockRead reads[] = {
9851 // First round
9852 kServerChallenge,
9853 // Second round
9854 kServerChallenge,
9855 // Third round
9856 kServerChallenge,
9857 // Fourth round
9858 kSuccess,
9859 // Competing response
9860 kSuccess,
9862 StaticSocketDataProvider data_provider(reads, arraysize(reads),
9863 writes, arraysize(writes));
9864 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9866 const char* const kSocketGroup = "www.example.com:80";
9868 // First round of authentication.
9869 auth_handler->SetGenerateExpectation(false, OK);
9870 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9871 if (rv == ERR_IO_PENDING)
9872 rv = callback.WaitForResult();
9873 EXPECT_EQ(OK, rv);
9874 response = trans->GetResponseInfo();
9875 ASSERT_TRUE(response != NULL);
9876 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9877 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9879 // In between rounds, another request comes in for the same domain.
9880 // It should not be able to grab the TCP socket that trans has already
9881 // claimed.
9882 scoped_ptr<HttpTransaction> trans_compete(
9883 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9884 TestCompletionCallback callback_compete;
9885 rv = trans_compete->Start(
9886 &request, callback_compete.callback(), BoundNetLog());
9887 EXPECT_EQ(ERR_IO_PENDING, rv);
9888 // callback_compete.WaitForResult at this point would stall forever,
9889 // since the HttpNetworkTransaction does not release the request back to
9890 // the pool until after authentication completes.
9892 // Second round of authentication.
9893 auth_handler->SetGenerateExpectation(false, OK);
9894 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9895 if (rv == ERR_IO_PENDING)
9896 rv = callback.WaitForResult();
9897 EXPECT_EQ(OK, rv);
9898 response = trans->GetResponseInfo();
9899 ASSERT_TRUE(response != NULL);
9900 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9901 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9903 // Third round of authentication.
9904 auth_handler->SetGenerateExpectation(false, OK);
9905 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9906 if (rv == ERR_IO_PENDING)
9907 rv = callback.WaitForResult();
9908 EXPECT_EQ(OK, rv);
9909 response = trans->GetResponseInfo();
9910 ASSERT_TRUE(response != NULL);
9911 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9912 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9914 // Fourth round of authentication, which completes successfully.
9915 auth_handler->SetGenerateExpectation(false, OK);
9916 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9917 if (rv == ERR_IO_PENDING)
9918 rv = callback.WaitForResult();
9919 EXPECT_EQ(OK, rv);
9920 response = trans->GetResponseInfo();
9921 ASSERT_TRUE(response != NULL);
9922 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9923 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9925 // Read the body since the fourth round was successful. This will also
9926 // release the socket back to the pool.
9927 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9928 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9929 if (rv == ERR_IO_PENDING)
9930 rv = callback.WaitForResult();
9931 EXPECT_EQ(3, rv);
9932 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9933 EXPECT_EQ(0, rv);
9934 // There are still 0 idle sockets, since the trans_compete transaction
9935 // will be handed it immediately after trans releases it to the group.
9936 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9938 // The competing request can now finish. Wait for the headers and then
9939 // read the body.
9940 rv = callback_compete.WaitForResult();
9941 EXPECT_EQ(OK, rv);
9942 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9943 if (rv == ERR_IO_PENDING)
9944 rv = callback.WaitForResult();
9945 EXPECT_EQ(3, rv);
9946 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9947 EXPECT_EQ(0, rv);
9949 // Finally, the socket is released to the group.
9950 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9953 // This tests the case that a request is issued via http instead of spdy after
9954 // npn is negotiated.
9955 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9956 session_deps_.use_alternate_protocols = true;
9957 NextProtoVector next_protos;
9958 next_protos.push_back(kProtoHTTP11);
9959 session_deps_.next_protos = next_protos;
9961 HttpRequestInfo request;
9962 request.method = "GET";
9963 request.url = GURL("https://www.google.com/");
9964 request.load_flags = 0;
9966 MockWrite data_writes[] = {
9967 MockWrite("GET / HTTP/1.1\r\n"
9968 "Host: www.google.com\r\n"
9969 "Connection: keep-alive\r\n\r\n"),
9972 std::string alternate_protocol_http_header =
9973 GetAlternateProtocolHttpHeader();
9975 MockRead data_reads[] = {
9976 MockRead("HTTP/1.1 200 OK\r\n"),
9977 MockRead(alternate_protocol_http_header.c_str()),
9978 MockRead("hello world"),
9979 MockRead(SYNCHRONOUS, OK),
9982 SSLSocketDataProvider ssl(ASYNC, OK);
9983 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9984 ssl.next_proto = "http/1.1";
9985 ssl.protocol_negotiated = kProtoHTTP11;
9987 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9989 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9990 data_writes, arraysize(data_writes));
9991 session_deps_.socket_factory->AddSocketDataProvider(&data);
9993 TestCompletionCallback callback;
9995 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9996 scoped_ptr<HttpTransaction> trans(
9997 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9999 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10001 EXPECT_EQ(ERR_IO_PENDING, rv);
10002 EXPECT_EQ(OK, callback.WaitForResult());
10004 const HttpResponseInfo* response = trans->GetResponseInfo();
10005 ASSERT_TRUE(response != NULL);
10006 ASSERT_TRUE(response->headers.get() != NULL);
10007 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10009 std::string response_data;
10010 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10011 EXPECT_EQ("hello world", response_data);
10013 EXPECT_FALSE(response->was_fetched_via_spdy);
10014 EXPECT_TRUE(response->was_npn_negotiated);
10017 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
10018 // Simulate the SSL handshake completing with an NPN negotiation
10019 // followed by an immediate server closing of the socket.
10020 // Fix crash: http://crbug.com/46369
10021 session_deps_.use_alternate_protocols = true;
10022 session_deps_.next_protos = SpdyNextProtos();
10024 HttpRequestInfo request;
10025 request.method = "GET";
10026 request.url = GURL("https://www.google.com/");
10027 request.load_flags = 0;
10029 SSLSocketDataProvider ssl(ASYNC, OK);
10030 ssl.SetNextProto(GetParam());
10031 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10033 scoped_ptr<SpdyFrame> req(
10034 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10035 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10037 MockRead spdy_reads[] = {
10038 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10041 DelayedSocketData spdy_data(
10042 0, // don't wait in this case, immediate hangup.
10043 spdy_reads, arraysize(spdy_reads),
10044 spdy_writes, arraysize(spdy_writes));
10045 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10047 TestCompletionCallback callback;
10049 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10050 scoped_ptr<HttpTransaction> trans(
10051 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10053 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10054 EXPECT_EQ(ERR_IO_PENDING, rv);
10055 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10058 // A subclass of HttpAuthHandlerMock that records the request URL when
10059 // it gets it. This is needed since the auth handler may get destroyed
10060 // before we get a chance to query it.
10061 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10062 public:
10063 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10065 virtual ~UrlRecordingHttpAuthHandlerMock() {}
10067 protected:
10068 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10069 const HttpRequestInfo* request,
10070 const CompletionCallback& callback,
10071 std::string* auth_token) OVERRIDE {
10072 *url_ = request->url;
10073 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10074 credentials, request, callback, auth_token);
10077 private:
10078 GURL* url_;
10081 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10082 // This test ensures that the URL passed into the proxy is upgraded
10083 // to https when doing an Alternate Protocol upgrade.
10084 session_deps_.use_alternate_protocols = true;
10085 session_deps_.next_protos = SpdyNextProtos();
10087 session_deps_.proxy_service.reset(
10088 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10089 CapturingNetLog net_log;
10090 session_deps_.net_log = &net_log;
10091 GURL request_url;
10093 HttpAuthHandlerMock::Factory* auth_factory =
10094 new HttpAuthHandlerMock::Factory();
10095 UrlRecordingHttpAuthHandlerMock* auth_handler =
10096 new UrlRecordingHttpAuthHandlerMock(&request_url);
10097 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10098 auth_factory->set_do_init_from_challenge(true);
10099 session_deps_.http_auth_handler_factory.reset(auth_factory);
10102 HttpRequestInfo request;
10103 request.method = "GET";
10104 request.url = GURL("http://www.google.com");
10105 request.load_flags = 0;
10107 // First round goes unauthenticated through the proxy.
10108 MockWrite data_writes_1[] = {
10109 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10110 "Host: www.google.com\r\n"
10111 "Proxy-Connection: keep-alive\r\n"
10112 "\r\n"),
10114 MockRead data_reads_1[] = {
10115 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10116 MockRead("HTTP/1.1 200 OK\r\n"
10117 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10118 "Proxy-Connection: close\r\n"
10119 "\r\n"),
10121 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10122 data_writes_1, arraysize(data_writes_1));
10124 // Second round tries to tunnel to www.google.com due to the
10125 // Alternate-Protocol announcement in the first round. It fails due
10126 // to a proxy authentication challenge.
10127 // After the failure, a tunnel is established to www.google.com using
10128 // Proxy-Authorization headers. There is then a SPDY request round.
10130 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10131 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10132 // does a Disconnect and Connect on the same socket, rather than trying
10133 // to obtain a new one.
10135 // NOTE: Originally, the proxy response to the second CONNECT request
10136 // simply returned another 407 so the unit test could skip the SSL connection
10137 // establishment and SPDY framing issues. Alas, the
10138 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10139 // complicated to set up expectations for than the SPDY session.
10141 scoped_ptr<SpdyFrame> req(
10142 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10143 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10144 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10146 MockWrite data_writes_2[] = {
10147 // First connection attempt without Proxy-Authorization.
10148 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10149 "Host: www.google.com\r\n"
10150 "Proxy-Connection: keep-alive\r\n"
10151 "\r\n"),
10153 // Second connection attempt with Proxy-Authorization.
10154 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10155 "Host: www.google.com\r\n"
10156 "Proxy-Connection: keep-alive\r\n"
10157 "Proxy-Authorization: auth_token\r\n"
10158 "\r\n"),
10160 // SPDY request
10161 CreateMockWrite(*req),
10163 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10164 "Proxy-Authenticate: Mock\r\n"
10165 "Proxy-Connection: close\r\n"
10166 "\r\n");
10167 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10168 MockRead data_reads_2[] = {
10169 // First connection attempt fails
10170 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
10171 MockRead(ASYNC, kRejectConnectResponse,
10172 arraysize(kRejectConnectResponse) - 1, 1),
10174 // Second connection attempt passes
10175 MockRead(ASYNC, kAcceptConnectResponse,
10176 arraysize(kAcceptConnectResponse) -1, 4),
10178 // SPDY response
10179 CreateMockRead(*resp.get(), 6),
10180 CreateMockRead(*data.get(), 6),
10181 MockRead(ASYNC, 0, 0, 6),
10183 OrderedSocketData data_2(
10184 data_reads_2, arraysize(data_reads_2),
10185 data_writes_2, arraysize(data_writes_2));
10187 SSLSocketDataProvider ssl(ASYNC, OK);
10188 ssl.SetNextProto(GetParam());
10190 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10191 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10192 NULL, 0, NULL, 0);
10193 hanging_non_alternate_protocol_socket.set_connect_data(
10194 never_finishing_connect);
10196 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10197 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10198 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10199 session_deps_.socket_factory->AddSocketDataProvider(
10200 &hanging_non_alternate_protocol_socket);
10201 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10203 // First round should work and provide the Alternate-Protocol state.
10204 TestCompletionCallback callback_1;
10205 scoped_ptr<HttpTransaction> trans_1(
10206 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10207 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10208 EXPECT_EQ(ERR_IO_PENDING, rv);
10209 EXPECT_EQ(OK, callback_1.WaitForResult());
10211 // Second round should attempt a tunnel connect and get an auth challenge.
10212 TestCompletionCallback callback_2;
10213 scoped_ptr<HttpTransaction> trans_2(
10214 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10215 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10216 EXPECT_EQ(ERR_IO_PENDING, rv);
10217 EXPECT_EQ(OK, callback_2.WaitForResult());
10218 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10219 ASSERT_TRUE(response != NULL);
10220 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10222 // Restart with auth. Tunnel should work and response received.
10223 TestCompletionCallback callback_3;
10224 rv = trans_2->RestartWithAuth(
10225 AuthCredentials(kFoo, kBar), callback_3.callback());
10226 EXPECT_EQ(ERR_IO_PENDING, rv);
10227 EXPECT_EQ(OK, callback_3.WaitForResult());
10229 // After all that work, these two lines (or actually, just the scheme) are
10230 // what this test is all about. Make sure it happens correctly.
10231 EXPECT_EQ("https", request_url.scheme());
10232 EXPECT_EQ("www.google.com", request_url.host());
10234 LoadTimingInfo load_timing_info;
10235 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10236 TestLoadTimingNotReusedWithPac(load_timing_info,
10237 CONNECT_TIMING_HAS_SSL_TIMES);
10240 // Test that if we cancel the transaction as the connection is completing, that
10241 // everything tears down correctly.
10242 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10243 // Setup everything about the connection to complete synchronously, so that
10244 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10245 // for is the callback from the HttpStreamRequest.
10246 // Then cancel the transaction.
10247 // Verify that we don't crash.
10248 MockConnect mock_connect(SYNCHRONOUS, OK);
10249 MockRead data_reads[] = {
10250 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10251 MockRead(SYNCHRONOUS, "hello world"),
10252 MockRead(SYNCHRONOUS, OK),
10255 HttpRequestInfo request;
10256 request.method = "GET";
10257 request.url = GURL("http://www.google.com/");
10258 request.load_flags = 0;
10260 session_deps_.host_resolver->set_synchronous_mode(true);
10261 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10262 scoped_ptr<HttpTransaction> trans(
10263 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
10265 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10266 data.set_connect_data(mock_connect);
10267 session_deps_.socket_factory->AddSocketDataProvider(&data);
10269 TestCompletionCallback callback;
10271 CapturingBoundNetLog log;
10272 int rv = trans->Start(&request, callback.callback(), log.bound());
10273 EXPECT_EQ(ERR_IO_PENDING, rv);
10274 trans.reset(); // Cancel the transaction here.
10276 base::MessageLoop::current()->RunUntilIdle();
10279 // Test that if a transaction is cancelled after receiving the headers, the
10280 // stream is drained properly and added back to the socket pool. The main
10281 // purpose of this test is to make sure that an HttpStreamParser can be read
10282 // from after the HttpNetworkTransaction and the objects it owns have been
10283 // deleted.
10284 // See http://crbug.com/368418
10285 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10286 MockRead data_reads[] = {
10287 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10288 MockRead(ASYNC, "Content-Length: 2\r\n"),
10289 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10290 MockRead(ASYNC, "1"),
10291 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10292 // HttpNetworkTransaction has been deleted.
10293 MockRead(ASYNC, "2"),
10294 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10296 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10297 session_deps_.socket_factory->AddSocketDataProvider(&data);
10299 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10302 HttpRequestInfo request;
10303 request.method = "GET";
10304 request.url = GURL("http://www.google.com/");
10305 request.load_flags = 0;
10307 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
10308 TestCompletionCallback callback;
10310 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10311 EXPECT_EQ(ERR_IO_PENDING, rv);
10312 callback.WaitForResult();
10314 const HttpResponseInfo* response = trans.GetResponseInfo();
10315 ASSERT_TRUE(response != NULL);
10316 EXPECT_TRUE(response->headers.get() != NULL);
10317 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10319 // The transaction and HttpRequestInfo are deleted.
10322 // Let the HttpResponseBodyDrainer drain the socket.
10323 base::MessageLoop::current()->RunUntilIdle();
10325 // Socket should now be idle, waiting to be reused.
10326 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
10329 // Test a basic GET request through a proxy.
10330 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10331 session_deps_.proxy_service.reset(
10332 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10333 CapturingBoundNetLog log;
10334 session_deps_.net_log = log.bound().net_log();
10335 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10337 HttpRequestInfo request;
10338 request.method = "GET";
10339 request.url = GURL("http://www.google.com/");
10341 MockWrite data_writes1[] = {
10342 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10343 "Host: www.google.com\r\n"
10344 "Proxy-Connection: keep-alive\r\n\r\n"),
10347 MockRead data_reads1[] = {
10348 MockRead("HTTP/1.1 200 OK\r\n"),
10349 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10350 MockRead("Content-Length: 100\r\n\r\n"),
10351 MockRead(SYNCHRONOUS, OK),
10354 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10355 data_writes1, arraysize(data_writes1));
10356 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10358 TestCompletionCallback callback1;
10360 scoped_ptr<HttpTransaction> trans(
10361 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10362 BeforeProxyHeadersSentHandler proxy_headers_handler;
10363 trans->SetBeforeProxyHeadersSentCallback(
10364 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
10365 base::Unretained(&proxy_headers_handler)));
10367 int rv = trans->Start(&request, callback1.callback(), log.bound());
10368 EXPECT_EQ(ERR_IO_PENDING, rv);
10370 rv = callback1.WaitForResult();
10371 EXPECT_EQ(OK, rv);
10373 const HttpResponseInfo* response = trans->GetResponseInfo();
10374 ASSERT_TRUE(response != NULL);
10376 EXPECT_TRUE(response->headers->IsKeepAlive());
10377 EXPECT_EQ(200, response->headers->response_code());
10378 EXPECT_EQ(100, response->headers->GetContentLength());
10379 EXPECT_TRUE(response->was_fetched_via_proxy);
10380 EXPECT_TRUE(
10381 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10382 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
10383 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
10384 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10386 LoadTimingInfo load_timing_info;
10387 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10388 TestLoadTimingNotReusedWithPac(load_timing_info,
10389 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10392 // Test a basic HTTPS GET request through a proxy.
10393 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10394 session_deps_.proxy_service.reset(
10395 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10396 CapturingBoundNetLog log;
10397 session_deps_.net_log = log.bound().net_log();
10398 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10400 HttpRequestInfo request;
10401 request.method = "GET";
10402 request.url = GURL("https://www.google.com/");
10404 // Since we have proxy, should try to establish tunnel.
10405 MockWrite data_writes1[] = {
10406 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10407 "Host: www.google.com\r\n"
10408 "Proxy-Connection: keep-alive\r\n\r\n"),
10410 MockWrite("GET / HTTP/1.1\r\n"
10411 "Host: www.google.com\r\n"
10412 "Connection: keep-alive\r\n\r\n"),
10415 MockRead data_reads1[] = {
10416 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10418 MockRead("HTTP/1.1 200 OK\r\n"),
10419 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10420 MockRead("Content-Length: 100\r\n\r\n"),
10421 MockRead(SYNCHRONOUS, OK),
10424 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10425 data_writes1, arraysize(data_writes1));
10426 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10427 SSLSocketDataProvider ssl(ASYNC, OK);
10428 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10430 TestCompletionCallback callback1;
10432 scoped_ptr<HttpTransaction> trans(
10433 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10435 int rv = trans->Start(&request, callback1.callback(), log.bound());
10436 EXPECT_EQ(ERR_IO_PENDING, rv);
10438 rv = callback1.WaitForResult();
10439 EXPECT_EQ(OK, rv);
10440 net::CapturingNetLog::CapturedEntryList entries;
10441 log.GetEntries(&entries);
10442 size_t pos = ExpectLogContainsSomewhere(
10443 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10444 NetLog::PHASE_NONE);
10445 ExpectLogContainsSomewhere(
10446 entries, pos,
10447 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10448 NetLog::PHASE_NONE);
10450 const HttpResponseInfo* response = trans->GetResponseInfo();
10451 ASSERT_TRUE(response != NULL);
10453 EXPECT_TRUE(response->headers->IsKeepAlive());
10454 EXPECT_EQ(200, response->headers->response_code());
10455 EXPECT_EQ(100, response->headers->GetContentLength());
10456 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10457 EXPECT_TRUE(response->was_fetched_via_proxy);
10458 EXPECT_TRUE(
10459 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10461 LoadTimingInfo load_timing_info;
10462 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10463 TestLoadTimingNotReusedWithPac(load_timing_info,
10464 CONNECT_TIMING_HAS_SSL_TIMES);
10467 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10468 // while establishing the tunnel.
10469 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10470 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10471 CapturingBoundNetLog log;
10472 session_deps_.net_log = log.bound().net_log();
10473 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10475 HttpRequestInfo request;
10476 request.method = "GET";
10477 request.url = GURL("https://www.google.com/");
10479 // Since we have proxy, should try to establish tunnel.
10480 MockWrite data_writes1[] = {
10481 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10482 "Host: www.google.com\r\n"
10483 "Proxy-Connection: keep-alive\r\n\r\n"),
10485 MockWrite("GET / HTTP/1.1\r\n"
10486 "Host: www.google.com\r\n"
10487 "Connection: keep-alive\r\n\r\n"),
10490 MockRead data_reads1[] = {
10491 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10492 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10493 MockRead(ASYNC, 0, 0), // EOF
10496 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10497 data_writes1, arraysize(data_writes1));
10498 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10499 SSLSocketDataProvider ssl(ASYNC, OK);
10500 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10502 TestCompletionCallback callback1;
10504 scoped_ptr<HttpTransaction> trans(
10505 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10507 int rv = trans->Start(&request, callback1.callback(), log.bound());
10508 EXPECT_EQ(ERR_IO_PENDING, rv);
10510 rv = callback1.WaitForResult();
10511 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10512 net::CapturingNetLog::CapturedEntryList entries;
10513 log.GetEntries(&entries);
10514 size_t pos = ExpectLogContainsSomewhere(
10515 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10516 NetLog::PHASE_NONE);
10517 ExpectLogContainsSomewhere(
10518 entries, pos,
10519 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10520 NetLog::PHASE_NONE);
10523 // Test for crbug.com/55424.
10524 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10525 scoped_ptr<SpdyFrame> req(
10526 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10527 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10529 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10530 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10531 MockRead spdy_reads[] = {
10532 CreateMockRead(*resp),
10533 CreateMockRead(*data),
10534 MockRead(ASYNC, 0, 0),
10537 DelayedSocketData spdy_data(
10538 1, // wait for one write to finish before reading.
10539 spdy_reads, arraysize(spdy_reads),
10540 spdy_writes, arraysize(spdy_writes));
10541 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10543 SSLSocketDataProvider ssl(ASYNC, OK);
10544 ssl.SetNextProto(GetParam());
10545 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10547 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10549 // Set up an initial SpdySession in the pool to reuse.
10550 HostPortPair host_port_pair("www.google.com", 443);
10551 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10552 PRIVACY_MODE_DISABLED);
10553 base::WeakPtr<SpdySession> spdy_session =
10554 CreateInsecureSpdySession(session, key, BoundNetLog());
10556 HttpRequestInfo request;
10557 request.method = "GET";
10558 request.url = GURL("https://www.google.com/");
10559 request.load_flags = 0;
10561 // This is the important line that marks this as a preconnect.
10562 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10564 scoped_ptr<HttpTransaction> trans(
10565 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10567 TestCompletionCallback callback;
10568 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10569 EXPECT_EQ(ERR_IO_PENDING, rv);
10570 EXPECT_EQ(OK, callback.WaitForResult());
10573 // Given a net error, cause that error to be returned from the first Write()
10574 // call and verify that the HttpTransaction fails with that error.
10575 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10576 int error, IoMode mode) {
10577 net::HttpRequestInfo request_info;
10578 request_info.url = GURL("https://www.example.com/");
10579 request_info.method = "GET";
10580 request_info.load_flags = net::LOAD_NORMAL;
10582 SSLSocketDataProvider ssl_data(mode, OK);
10583 net::MockWrite data_writes[] = {
10584 net::MockWrite(mode, error),
10586 net::StaticSocketDataProvider data(NULL, 0,
10587 data_writes, arraysize(data_writes));
10588 session_deps_.socket_factory->AddSocketDataProvider(&data);
10589 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10591 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10592 scoped_ptr<HttpTransaction> trans(
10593 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10595 TestCompletionCallback callback;
10596 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10597 if (rv == net::ERR_IO_PENDING)
10598 rv = callback.WaitForResult();
10599 ASSERT_EQ(error, rv);
10602 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10603 // Just check a grab bag of cert errors.
10604 static const int kErrors[] = {
10605 ERR_CERT_COMMON_NAME_INVALID,
10606 ERR_CERT_AUTHORITY_INVALID,
10607 ERR_CERT_DATE_INVALID,
10609 for (size_t i = 0; i < arraysize(kErrors); i++) {
10610 CheckErrorIsPassedBack(kErrors[i], ASYNC);
10611 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10615 // Ensure that a client certificate is removed from the SSL client auth
10616 // cache when:
10617 // 1) No proxy is involved.
10618 // 2) TLS False Start is disabled.
10619 // 3) The initial TLS handshake requests a client certificate.
10620 // 4) The client supplies an invalid/unacceptable certificate.
10621 TEST_P(HttpNetworkTransactionTest,
10622 ClientAuthCertCache_Direct_NoFalseStart) {
10623 net::HttpRequestInfo request_info;
10624 request_info.url = GURL("https://www.example.com/");
10625 request_info.method = "GET";
10626 request_info.load_flags = net::LOAD_NORMAL;
10628 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10629 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10631 // [ssl_]data1 contains the data for the first SSL handshake. When a
10632 // CertificateRequest is received for the first time, the handshake will
10633 // be aborted to allow the caller to provide a certificate.
10634 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10635 ssl_data1.cert_request_info = cert_request.get();
10636 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10637 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10638 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10640 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10641 // False Start is not being used, the result of the SSL handshake will be
10642 // returned as part of the SSLClientSocket::Connect() call. This test
10643 // matches the result of a server sending a handshake_failure alert,
10644 // rather than a Finished message, because it requires a client
10645 // certificate and none was supplied.
10646 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10647 ssl_data2.cert_request_info = cert_request.get();
10648 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10649 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10650 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10652 // [ssl_]data3 contains the data for the third SSL handshake. When a
10653 // connection to a server fails during an SSL handshake,
10654 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10655 // connection was attempted with TLSv1.1. This is transparent to the caller
10656 // of the HttpNetworkTransaction. Because this test failure is due to
10657 // requiring a client certificate, this fallback handshake should also
10658 // fail.
10659 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10660 ssl_data3.cert_request_info = cert_request.get();
10661 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10662 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10663 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10665 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10666 // connection to a server fails during an SSL handshake,
10667 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10668 // connection was attempted with TLSv1. This is transparent to the caller
10669 // of the HttpNetworkTransaction. Because this test failure is due to
10670 // requiring a client certificate, this fallback handshake should also
10671 // fail.
10672 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10673 ssl_data4.cert_request_info = cert_request.get();
10674 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10675 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10676 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10678 // Need one more if TLSv1.2 is enabled.
10679 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10680 ssl_data5.cert_request_info = cert_request.get();
10681 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10682 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10683 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10685 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10686 scoped_ptr<HttpTransaction> trans(
10687 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10689 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10690 TestCompletionCallback callback;
10691 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10692 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10694 // Complete the SSL handshake, which should abort due to requiring a
10695 // client certificate.
10696 rv = callback.WaitForResult();
10697 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10699 // Indicate that no certificate should be supplied. From the perspective
10700 // of SSLClientCertCache, NULL is just as meaningful as a real
10701 // certificate, so this is the same as supply a
10702 // legitimate-but-unacceptable certificate.
10703 rv = trans->RestartWithCertificate(NULL, callback.callback());
10704 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10706 // Ensure the certificate was added to the client auth cache before
10707 // allowing the connection to continue restarting.
10708 scoped_refptr<X509Certificate> client_cert;
10709 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10710 HostPortPair("www.example.com", 443), &client_cert));
10711 ASSERT_EQ(NULL, client_cert.get());
10713 // Restart the handshake. This will consume ssl_data2, which fails, and
10714 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10715 // The result code is checked against what ssl_data4 should return.
10716 rv = callback.WaitForResult();
10717 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10719 // Ensure that the client certificate is removed from the cache on a
10720 // handshake failure.
10721 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10722 HostPortPair("www.example.com", 443), &client_cert));
10725 // Ensure that a client certificate is removed from the SSL client auth
10726 // cache when:
10727 // 1) No proxy is involved.
10728 // 2) TLS False Start is enabled.
10729 // 3) The initial TLS handshake requests a client certificate.
10730 // 4) The client supplies an invalid/unacceptable certificate.
10731 TEST_P(HttpNetworkTransactionTest,
10732 ClientAuthCertCache_Direct_FalseStart) {
10733 net::HttpRequestInfo request_info;
10734 request_info.url = GURL("https://www.example.com/");
10735 request_info.method = "GET";
10736 request_info.load_flags = net::LOAD_NORMAL;
10738 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10739 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10741 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10742 // return successfully after reading up to the peer's Certificate message.
10743 // This is to allow the caller to call SSLClientSocket::Write(), which can
10744 // enqueue application data to be sent in the same packet as the
10745 // ChangeCipherSpec and Finished messages.
10746 // The actual handshake will be finished when SSLClientSocket::Read() is
10747 // called, which expects to process the peer's ChangeCipherSpec and
10748 // Finished messages. If there was an error negotiating with the peer,
10749 // such as due to the peer requiring a client certificate when none was
10750 // supplied, the alert sent by the peer won't be processed until Read() is
10751 // called.
10753 // Like the non-False Start case, when a client certificate is requested by
10754 // the peer, the handshake is aborted during the Connect() call.
10755 // [ssl_]data1 represents the initial SSL handshake with the peer.
10756 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10757 ssl_data1.cert_request_info = cert_request.get();
10758 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10759 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10760 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10762 // When a client certificate is supplied, Connect() will not be aborted
10763 // when the peer requests the certificate. Instead, the handshake will
10764 // artificially succeed, allowing the caller to write the HTTP request to
10765 // the socket. The handshake messages are not processed until Read() is
10766 // called, which then detects that the handshake was aborted, due to the
10767 // peer sending a handshake_failure because it requires a client
10768 // certificate.
10769 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10770 ssl_data2.cert_request_info = cert_request.get();
10771 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10772 net::MockRead data2_reads[] = {
10773 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10775 net::StaticSocketDataProvider data2(
10776 data2_reads, arraysize(data2_reads), NULL, 0);
10777 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10779 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10780 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10781 // TLSv1. It has the same behaviour as [ssl_]data2.
10782 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10783 ssl_data3.cert_request_info = cert_request.get();
10784 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10785 net::StaticSocketDataProvider data3(
10786 data2_reads, arraysize(data2_reads), NULL, 0);
10787 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10789 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10790 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10791 SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10792 ssl_data4.cert_request_info = cert_request.get();
10793 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10794 net::StaticSocketDataProvider data4(
10795 data2_reads, arraysize(data2_reads), NULL, 0);
10796 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10798 // Need one more if TLSv1.2 is enabled.
10799 SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10800 ssl_data5.cert_request_info = cert_request.get();
10801 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10802 net::StaticSocketDataProvider data5(
10803 data2_reads, arraysize(data2_reads), NULL, 0);
10804 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10806 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10807 scoped_ptr<HttpTransaction> trans(
10808 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10810 // Begin the initial SSL handshake.
10811 TestCompletionCallback callback;
10812 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10813 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10815 // Complete the SSL handshake, which should abort due to requiring a
10816 // client certificate.
10817 rv = callback.WaitForResult();
10818 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10820 // Indicate that no certificate should be supplied. From the perspective
10821 // of SSLClientCertCache, NULL is just as meaningful as a real
10822 // certificate, so this is the same as supply a
10823 // legitimate-but-unacceptable certificate.
10824 rv = trans->RestartWithCertificate(NULL, callback.callback());
10825 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10827 // Ensure the certificate was added to the client auth cache before
10828 // allowing the connection to continue restarting.
10829 scoped_refptr<X509Certificate> client_cert;
10830 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10831 HostPortPair("www.example.com", 443), &client_cert));
10832 ASSERT_EQ(NULL, client_cert.get());
10834 // Restart the handshake. This will consume ssl_data2, which fails, and
10835 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10836 // The result code is checked against what ssl_data4 should return.
10837 rv = callback.WaitForResult();
10838 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10840 // Ensure that the client certificate is removed from the cache on a
10841 // handshake failure.
10842 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10843 HostPortPair("www.example.com", 443), &client_cert));
10846 // Ensure that a client certificate is removed from the SSL client auth
10847 // cache when:
10848 // 1) An HTTPS proxy is involved.
10849 // 3) The HTTPS proxy requests a client certificate.
10850 // 4) The client supplies an invalid/unacceptable certificate for the
10851 // proxy.
10852 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10853 // then for connecting to an HTTP endpoint.
10854 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10855 session_deps_.proxy_service.reset(
10856 ProxyService::CreateFixed("https://proxy:70"));
10857 CapturingBoundNetLog log;
10858 session_deps_.net_log = log.bound().net_log();
10860 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10861 cert_request->host_and_port = HostPortPair("proxy", 70);
10863 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10864 // [ssl_]data[1-3]. Rather than represending the endpoint
10865 // (www.example.com:443), they represent failures with the HTTPS proxy
10866 // (proxy:70).
10867 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10868 ssl_data1.cert_request_info = cert_request.get();
10869 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10870 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10871 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10873 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10874 ssl_data2.cert_request_info = cert_request.get();
10875 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10876 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10877 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10879 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10880 #if 0
10881 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10882 ssl_data3.cert_request_info = cert_request.get();
10883 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10884 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10885 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10886 #endif
10888 net::HttpRequestInfo requests[2];
10889 requests[0].url = GURL("https://www.example.com/");
10890 requests[0].method = "GET";
10891 requests[0].load_flags = net::LOAD_NORMAL;
10893 requests[1].url = GURL("http://www.example.com/");
10894 requests[1].method = "GET";
10895 requests[1].load_flags = net::LOAD_NORMAL;
10897 for (size_t i = 0; i < arraysize(requests); ++i) {
10898 session_deps_.socket_factory->ResetNextMockIndexes();
10899 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10900 scoped_ptr<HttpNetworkTransaction> trans(
10901 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10903 // Begin the SSL handshake with the proxy.
10904 TestCompletionCallback callback;
10905 int rv = trans->Start(
10906 &requests[i], callback.callback(), net::BoundNetLog());
10907 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10909 // Complete the SSL handshake, which should abort due to requiring a
10910 // client certificate.
10911 rv = callback.WaitForResult();
10912 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10914 // Indicate that no certificate should be supplied. From the perspective
10915 // of SSLClientCertCache, NULL is just as meaningful as a real
10916 // certificate, so this is the same as supply a
10917 // legitimate-but-unacceptable certificate.
10918 rv = trans->RestartWithCertificate(NULL, callback.callback());
10919 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10921 // Ensure the certificate was added to the client auth cache before
10922 // allowing the connection to continue restarting.
10923 scoped_refptr<X509Certificate> client_cert;
10924 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10925 HostPortPair("proxy", 70), &client_cert));
10926 ASSERT_EQ(NULL, client_cert.get());
10927 // Ensure the certificate was NOT cached for the endpoint. This only
10928 // applies to HTTPS requests, but is fine to check for HTTP requests.
10929 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10930 HostPortPair("www.example.com", 443), &client_cert));
10932 // Restart the handshake. This will consume ssl_data2, which fails, and
10933 // then consume ssl_data3, which should also fail. The result code is
10934 // checked against what ssl_data3 should return.
10935 rv = callback.WaitForResult();
10936 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10938 // Now that the new handshake has failed, ensure that the client
10939 // certificate was removed from the client auth cache.
10940 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10941 HostPortPair("proxy", 70), &client_cert));
10942 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10943 HostPortPair("www.example.com", 443), &client_cert));
10947 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10948 // TEST_P is a macro that expands directly to code that stringizes the
10949 // arguments. As a result, macros passed as parameters (such as prefix
10950 // or test_case_name) will not be expanded by the preprocessor. To
10951 // work around this, indirect the macro for TEST_P, so that the
10952 // pre-processor will expand macros such as MAYBE_test_name before
10953 // instantiating the test.
10954 #define WRAPPED_TEST_P(test_case_name, test_name) \
10955 TEST_P(test_case_name, test_name)
10957 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10958 #if defined(OS_WIN)
10959 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10960 #else
10961 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10962 #endif
10963 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10964 session_deps_.use_alternate_protocols = true;
10965 session_deps_.next_protos = SpdyNextProtos();
10967 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10968 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10969 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10970 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10971 pool_peer.DisableDomainAuthenticationVerification();
10973 SSLSocketDataProvider ssl(ASYNC, OK);
10974 ssl.SetNextProto(GetParam());
10975 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10977 scoped_ptr<SpdyFrame> host1_req(
10978 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10979 scoped_ptr<SpdyFrame> host2_req(
10980 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10981 MockWrite spdy_writes[] = {
10982 CreateMockWrite(*host1_req, 1),
10983 CreateMockWrite(*host2_req, 4),
10985 scoped_ptr<SpdyFrame> host1_resp(
10986 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10987 scoped_ptr<SpdyFrame> host1_resp_body(
10988 spdy_util_.ConstructSpdyBodyFrame(1, true));
10989 scoped_ptr<SpdyFrame> host2_resp(
10990 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10991 scoped_ptr<SpdyFrame> host2_resp_body(
10992 spdy_util_.ConstructSpdyBodyFrame(3, true));
10993 MockRead spdy_reads[] = {
10994 CreateMockRead(*host1_resp, 2),
10995 CreateMockRead(*host1_resp_body, 3),
10996 CreateMockRead(*host2_resp, 5),
10997 CreateMockRead(*host2_resp_body, 6),
10998 MockRead(ASYNC, 0, 7),
11001 IPAddressNumber ip;
11002 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11003 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11004 MockConnect connect(ASYNC, OK, peer_addr);
11005 OrderedSocketData spdy_data(
11006 connect,
11007 spdy_reads, arraysize(spdy_reads),
11008 spdy_writes, arraysize(spdy_writes));
11009 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11011 TestCompletionCallback callback;
11012 HttpRequestInfo request1;
11013 request1.method = "GET";
11014 request1.url = GURL("https://www.google.com/");
11015 request1.load_flags = 0;
11016 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11018 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11019 EXPECT_EQ(ERR_IO_PENDING, rv);
11020 EXPECT_EQ(OK, callback.WaitForResult());
11022 const HttpResponseInfo* response = trans1.GetResponseInfo();
11023 ASSERT_TRUE(response != NULL);
11024 ASSERT_TRUE(response->headers.get() != NULL);
11025 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11027 std::string response_data;
11028 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11029 EXPECT_EQ("hello!", response_data);
11031 // Preload www.gmail.com into HostCache.
11032 HostPortPair host_port("www.gmail.com", 443);
11033 HostResolver::RequestInfo resolve_info(host_port);
11034 AddressList ignored;
11035 rv = session_deps_.host_resolver->Resolve(resolve_info,
11036 DEFAULT_PRIORITY,
11037 &ignored,
11038 callback.callback(),
11039 NULL,
11040 BoundNetLog());
11041 EXPECT_EQ(ERR_IO_PENDING, rv);
11042 rv = callback.WaitForResult();
11043 EXPECT_EQ(OK, rv);
11045 HttpRequestInfo request2;
11046 request2.method = "GET";
11047 request2.url = GURL("https://www.gmail.com/");
11048 request2.load_flags = 0;
11049 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11051 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11052 EXPECT_EQ(ERR_IO_PENDING, rv);
11053 EXPECT_EQ(OK, callback.WaitForResult());
11055 response = trans2.GetResponseInfo();
11056 ASSERT_TRUE(response != NULL);
11057 ASSERT_TRUE(response->headers.get() != NULL);
11058 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11059 EXPECT_TRUE(response->was_fetched_via_spdy);
11060 EXPECT_TRUE(response->was_npn_negotiated);
11061 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11062 EXPECT_EQ("hello!", response_data);
11064 #undef MAYBE_UseIPConnectionPooling
11066 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11067 session_deps_.use_alternate_protocols = true;
11068 session_deps_.next_protos = SpdyNextProtos();
11070 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11071 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11072 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11073 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11074 pool_peer.DisableDomainAuthenticationVerification();
11076 SSLSocketDataProvider ssl(ASYNC, OK);
11077 ssl.SetNextProto(GetParam());
11078 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11080 scoped_ptr<SpdyFrame> host1_req(
11081 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
11082 scoped_ptr<SpdyFrame> host2_req(
11083 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11084 MockWrite spdy_writes[] = {
11085 CreateMockWrite(*host1_req, 1),
11086 CreateMockWrite(*host2_req, 4),
11088 scoped_ptr<SpdyFrame> host1_resp(
11089 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11090 scoped_ptr<SpdyFrame> host1_resp_body(
11091 spdy_util_.ConstructSpdyBodyFrame(1, true));
11092 scoped_ptr<SpdyFrame> host2_resp(
11093 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11094 scoped_ptr<SpdyFrame> host2_resp_body(
11095 spdy_util_.ConstructSpdyBodyFrame(3, true));
11096 MockRead spdy_reads[] = {
11097 CreateMockRead(*host1_resp, 2),
11098 CreateMockRead(*host1_resp_body, 3),
11099 CreateMockRead(*host2_resp, 5),
11100 CreateMockRead(*host2_resp_body, 6),
11101 MockRead(ASYNC, 0, 7),
11104 IPAddressNumber ip;
11105 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11106 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11107 MockConnect connect(ASYNC, OK, peer_addr);
11108 OrderedSocketData spdy_data(
11109 connect,
11110 spdy_reads, arraysize(spdy_reads),
11111 spdy_writes, arraysize(spdy_writes));
11112 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11114 TestCompletionCallback callback;
11115 HttpRequestInfo request1;
11116 request1.method = "GET";
11117 request1.url = GURL("https://www.google.com/");
11118 request1.load_flags = 0;
11119 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11121 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11122 EXPECT_EQ(ERR_IO_PENDING, rv);
11123 EXPECT_EQ(OK, callback.WaitForResult());
11125 const HttpResponseInfo* response = trans1.GetResponseInfo();
11126 ASSERT_TRUE(response != NULL);
11127 ASSERT_TRUE(response->headers.get() != NULL);
11128 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11130 std::string response_data;
11131 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11132 EXPECT_EQ("hello!", response_data);
11134 HttpRequestInfo request2;
11135 request2.method = "GET";
11136 request2.url = GURL("https://www.gmail.com/");
11137 request2.load_flags = 0;
11138 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11140 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11141 EXPECT_EQ(ERR_IO_PENDING, rv);
11142 EXPECT_EQ(OK, callback.WaitForResult());
11144 response = trans2.GetResponseInfo();
11145 ASSERT_TRUE(response != NULL);
11146 ASSERT_TRUE(response->headers.get() != NULL);
11147 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11148 EXPECT_TRUE(response->was_fetched_via_spdy);
11149 EXPECT_TRUE(response->was_npn_negotiated);
11150 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11151 EXPECT_EQ("hello!", response_data);
11154 class OneTimeCachingHostResolver : public net::HostResolver {
11155 public:
11156 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11157 : host_port_(host_port) {}
11158 virtual ~OneTimeCachingHostResolver() {}
11160 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11162 // HostResolver methods:
11163 virtual int Resolve(const RequestInfo& info,
11164 RequestPriority priority,
11165 AddressList* addresses,
11166 const CompletionCallback& callback,
11167 RequestHandle* out_req,
11168 const BoundNetLog& net_log) OVERRIDE {
11169 return host_resolver_.Resolve(
11170 info, priority, addresses, callback, out_req, net_log);
11173 virtual int ResolveFromCache(const RequestInfo& info,
11174 AddressList* addresses,
11175 const BoundNetLog& net_log) OVERRIDE {
11176 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11177 if (rv == OK && info.host_port_pair().Equals(host_port_))
11178 host_resolver_.GetHostCache()->clear();
11179 return rv;
11182 virtual void CancelRequest(RequestHandle req) OVERRIDE {
11183 host_resolver_.CancelRequest(req);
11186 MockCachingHostResolver* GetMockHostResolver() {
11187 return &host_resolver_;
11190 private:
11191 MockCachingHostResolver host_resolver_;
11192 const HostPortPair host_port_;
11195 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11196 #if defined(OS_WIN)
11197 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11198 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11199 #else
11200 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11201 UseIPConnectionPoolingWithHostCacheExpiration
11202 #endif
11203 WRAPPED_TEST_P(HttpNetworkTransactionTest,
11204 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
11205 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11206 // prefix doesn't work with parametrized tests).
11207 #if defined(OS_WIN)
11208 return;
11209 #else
11210 session_deps_.use_alternate_protocols = true;
11211 session_deps_.next_protos = SpdyNextProtos();
11213 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11214 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11215 HttpNetworkSession::Params params =
11216 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11217 params.host_resolver = &host_resolver;
11218 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11219 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11220 pool_peer.DisableDomainAuthenticationVerification();
11222 SSLSocketDataProvider ssl(ASYNC, OK);
11223 ssl.SetNextProto(GetParam());
11224 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11226 scoped_ptr<SpdyFrame> host1_req(
11227 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
11228 scoped_ptr<SpdyFrame> host2_req(
11229 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11230 MockWrite spdy_writes[] = {
11231 CreateMockWrite(*host1_req, 1),
11232 CreateMockWrite(*host2_req, 4),
11234 scoped_ptr<SpdyFrame> host1_resp(
11235 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11236 scoped_ptr<SpdyFrame> host1_resp_body(
11237 spdy_util_.ConstructSpdyBodyFrame(1, true));
11238 scoped_ptr<SpdyFrame> host2_resp(
11239 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11240 scoped_ptr<SpdyFrame> host2_resp_body(
11241 spdy_util_.ConstructSpdyBodyFrame(3, true));
11242 MockRead spdy_reads[] = {
11243 CreateMockRead(*host1_resp, 2),
11244 CreateMockRead(*host1_resp_body, 3),
11245 CreateMockRead(*host2_resp, 5),
11246 CreateMockRead(*host2_resp_body, 6),
11247 MockRead(ASYNC, 0, 7),
11250 IPAddressNumber ip;
11251 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11252 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11253 MockConnect connect(ASYNC, OK, peer_addr);
11254 OrderedSocketData spdy_data(
11255 connect,
11256 spdy_reads, arraysize(spdy_reads),
11257 spdy_writes, arraysize(spdy_writes));
11258 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11260 TestCompletionCallback callback;
11261 HttpRequestInfo request1;
11262 request1.method = "GET";
11263 request1.url = GURL("https://www.google.com/");
11264 request1.load_flags = 0;
11265 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11267 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11268 EXPECT_EQ(ERR_IO_PENDING, rv);
11269 EXPECT_EQ(OK, callback.WaitForResult());
11271 const HttpResponseInfo* response = trans1.GetResponseInfo();
11272 ASSERT_TRUE(response != NULL);
11273 ASSERT_TRUE(response->headers.get() != NULL);
11274 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11276 std::string response_data;
11277 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11278 EXPECT_EQ("hello!", response_data);
11280 // Preload cache entries into HostCache.
11281 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11282 AddressList ignored;
11283 rv = host_resolver.Resolve(resolve_info,
11284 DEFAULT_PRIORITY,
11285 &ignored,
11286 callback.callback(),
11287 NULL,
11288 BoundNetLog());
11289 EXPECT_EQ(ERR_IO_PENDING, rv);
11290 rv = callback.WaitForResult();
11291 EXPECT_EQ(OK, rv);
11293 HttpRequestInfo request2;
11294 request2.method = "GET";
11295 request2.url = GURL("https://www.gmail.com/");
11296 request2.load_flags = 0;
11297 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11299 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11300 EXPECT_EQ(ERR_IO_PENDING, rv);
11301 EXPECT_EQ(OK, callback.WaitForResult());
11303 response = trans2.GetResponseInfo();
11304 ASSERT_TRUE(response != NULL);
11305 ASSERT_TRUE(response->headers.get() != NULL);
11306 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11307 EXPECT_TRUE(response->was_fetched_via_spdy);
11308 EXPECT_TRUE(response->was_npn_negotiated);
11309 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11310 EXPECT_EQ("hello!", response_data);
11311 #endif
11313 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11315 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11316 const std::string https_url = "https://www.google.com/";
11317 const std::string http_url = "http://www.google.com:443/";
11319 // SPDY GET for HTTPS URL
11320 scoped_ptr<SpdyFrame> req1(
11321 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11323 MockWrite writes1[] = {
11324 CreateMockWrite(*req1, 0),
11327 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11328 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11329 MockRead reads1[] = {
11330 CreateMockRead(*resp1, 1),
11331 CreateMockRead(*body1, 2),
11332 MockRead(ASYNC, ERR_IO_PENDING, 3)
11335 DelayedSocketData data1(
11336 1, reads1, arraysize(reads1),
11337 writes1, arraysize(writes1));
11338 MockConnect connect_data1(ASYNC, OK);
11339 data1.set_connect_data(connect_data1);
11341 // HTTP GET for the HTTP URL
11342 MockWrite writes2[] = {
11343 MockWrite(ASYNC, 4,
11344 "GET / HTTP/1.1\r\n"
11345 "Host: www.google.com:443\r\n"
11346 "Connection: keep-alive\r\n\r\n"),
11349 MockRead reads2[] = {
11350 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11351 MockRead(ASYNC, 6, "hello"),
11352 MockRead(ASYNC, 7, OK),
11355 DelayedSocketData data2(
11356 1, reads2, arraysize(reads2),
11357 writes2, arraysize(writes2));
11359 SSLSocketDataProvider ssl(ASYNC, OK);
11360 ssl.SetNextProto(GetParam());
11361 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11362 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11363 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11365 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11367 // Start the first transaction to set up the SpdySession
11368 HttpRequestInfo request1;
11369 request1.method = "GET";
11370 request1.url = GURL(https_url);
11371 request1.load_flags = 0;
11372 HttpNetworkTransaction trans1(LOWEST, session.get());
11373 TestCompletionCallback callback1;
11374 EXPECT_EQ(ERR_IO_PENDING,
11375 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11376 base::MessageLoop::current()->RunUntilIdle();
11378 EXPECT_EQ(OK, callback1.WaitForResult());
11379 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11381 // Now, start the HTTP request
11382 HttpRequestInfo request2;
11383 request2.method = "GET";
11384 request2.url = GURL(http_url);
11385 request2.load_flags = 0;
11386 HttpNetworkTransaction trans2(MEDIUM, session.get());
11387 TestCompletionCallback callback2;
11388 EXPECT_EQ(ERR_IO_PENDING,
11389 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11390 base::MessageLoop::current()->RunUntilIdle();
11392 EXPECT_EQ(OK, callback2.WaitForResult());
11393 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11396 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
11397 const std::string https_url = "https://www.google.com/";
11398 const std::string http_url = "http://www.google.com:443/";
11400 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11401 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
11402 LOWEST));
11403 scoped_ptr<SpdyFrame> req1(
11404 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11405 scoped_ptr<SpdyFrame> wrapped_req1(
11406 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
11408 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11409 SpdyHeaderBlock req2_block;
11410 req2_block[spdy_util_.GetMethodKey()] = "GET";
11411 req2_block[spdy_util_.GetPathKey()] =
11412 spdy_util_.is_spdy2() ? http_url.c_str() : "/";
11413 req2_block[spdy_util_.GetHostKey()] = "www.google.com:443";
11414 req2_block[spdy_util_.GetSchemeKey()] = "http";
11415 spdy_util_.MaybeAddVersionHeader(&req2_block);
11416 scoped_ptr<SpdyFrame> req2(
11417 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
11419 MockWrite writes1[] = {
11420 CreateMockWrite(*connect, 0),
11421 CreateMockWrite(*wrapped_req1, 2),
11422 CreateMockWrite(*req2, 5),
11425 scoped_ptr<SpdyFrame> conn_resp(
11426 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11427 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11428 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11429 scoped_ptr<SpdyFrame> wrapped_resp1(
11430 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
11431 scoped_ptr<SpdyFrame> wrapped_body1(
11432 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
11433 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11434 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11435 MockRead reads1[] = {
11436 CreateMockRead(*conn_resp, 1),
11437 CreateMockRead(*wrapped_resp1, 3),
11438 CreateMockRead(*wrapped_body1, 4),
11439 CreateMockRead(*resp2, 6),
11440 CreateMockRead(*body2, 7),
11441 MockRead(ASYNC, ERR_IO_PENDING, 8)
11444 DeterministicSocketData data1(reads1, arraysize(reads1),
11445 writes1, arraysize(writes1));
11446 MockConnect connect_data1(ASYNC, OK);
11447 data1.set_connect_data(connect_data1);
11449 session_deps_.proxy_service.reset(
11450 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11451 CapturingNetLog log;
11452 session_deps_.net_log = &log;
11453 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11454 ssl1.SetNextProto(GetParam());
11455 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11456 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11457 ssl2.SetNextProto(GetParam());
11458 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11459 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
11461 scoped_refptr<HttpNetworkSession> session(
11462 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11464 // Start the first transaction to set up the SpdySession
11465 HttpRequestInfo request1;
11466 request1.method = "GET";
11467 request1.url = GURL(https_url);
11468 request1.load_flags = 0;
11469 HttpNetworkTransaction trans1(LOWEST, session.get());
11470 TestCompletionCallback callback1;
11471 EXPECT_EQ(ERR_IO_PENDING,
11472 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11473 base::MessageLoop::current()->RunUntilIdle();
11474 data1.RunFor(4);
11476 EXPECT_EQ(OK, callback1.WaitForResult());
11477 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11479 LoadTimingInfo load_timing_info1;
11480 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
11481 TestLoadTimingNotReusedWithPac(load_timing_info1,
11482 CONNECT_TIMING_HAS_SSL_TIMES);
11484 // Now, start the HTTP request
11485 HttpRequestInfo request2;
11486 request2.method = "GET";
11487 request2.url = GURL(http_url);
11488 request2.load_flags = 0;
11489 HttpNetworkTransaction trans2(MEDIUM, session.get());
11490 TestCompletionCallback callback2;
11491 EXPECT_EQ(ERR_IO_PENDING,
11492 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11493 base::MessageLoop::current()->RunUntilIdle();
11494 data1.RunFor(3);
11496 EXPECT_EQ(OK, callback2.WaitForResult());
11497 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11499 LoadTimingInfo load_timing_info2;
11500 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
11501 // The established SPDY sessions is considered reused by the HTTP request.
11502 TestLoadTimingReusedWithPac(load_timing_info2);
11503 // HTTP requests over a SPDY session should have a different connection
11504 // socket_log_id than requests over a tunnel.
11505 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
11508 TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
11509 session_deps_.force_spdy_always = true;
11510 const std::string https_url = "https://www.google.com/";
11511 const std::string http_url = "http://www.google.com:443/";
11513 // SPDY GET for HTTPS URL
11514 scoped_ptr<SpdyFrame> req1(
11515 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11516 // SPDY GET for the HTTP URL
11517 scoped_ptr<SpdyFrame> req2(
11518 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11520 MockWrite writes[] = {
11521 CreateMockWrite(*req1, 1),
11522 CreateMockWrite(*req2, 4),
11525 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11526 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11527 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11528 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11529 MockRead reads[] = {
11530 CreateMockRead(*resp1, 2),
11531 CreateMockRead(*body1, 3),
11532 CreateMockRead(*resp2, 5),
11533 CreateMockRead(*body2, 6),
11534 MockRead(ASYNC, ERR_IO_PENDING, 7)
11537 OrderedSocketData data(reads, arraysize(reads),
11538 writes, arraysize(writes));
11540 SSLSocketDataProvider ssl(ASYNC, OK);
11541 ssl.SetNextProto(GetParam());
11542 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11543 session_deps_.socket_factory->AddSocketDataProvider(&data);
11545 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11547 // Start the first transaction to set up the SpdySession
11548 HttpRequestInfo request1;
11549 request1.method = "GET";
11550 request1.url = GURL(https_url);
11551 request1.load_flags = 0;
11552 HttpNetworkTransaction trans1(LOWEST, session.get());
11553 TestCompletionCallback callback1;
11554 EXPECT_EQ(ERR_IO_PENDING,
11555 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11556 base::MessageLoop::current()->RunUntilIdle();
11558 EXPECT_EQ(OK, callback1.WaitForResult());
11559 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11561 // Now, start the HTTP request
11562 HttpRequestInfo request2;
11563 request2.method = "GET";
11564 request2.url = GURL(http_url);
11565 request2.load_flags = 0;
11566 HttpNetworkTransaction trans2(MEDIUM, session.get());
11567 TestCompletionCallback callback2;
11568 EXPECT_EQ(ERR_IO_PENDING,
11569 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11570 base::MessageLoop::current()->RunUntilIdle();
11572 EXPECT_EQ(OK, callback2.WaitForResult());
11573 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11576 // Test that in the case where we have a SPDY session to a SPDY proxy
11577 // that we do not pool other origins that resolve to the same IP when
11578 // the certificate does not match the new origin.
11579 // http://crbug.com/134690
11580 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11581 const std::string url1 = "http://www.google.com/";
11582 const std::string url2 = "https://mail.google.com/";
11583 const std::string ip_addr = "1.2.3.4";
11585 // SPDY GET for HTTP URL (through SPDY proxy)
11586 scoped_ptr<SpdyHeaderBlock> headers(
11587 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11588 scoped_ptr<SpdyFrame> req1(
11589 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
11591 MockWrite writes1[] = {
11592 CreateMockWrite(*req1, 0),
11595 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11596 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11597 MockRead reads1[] = {
11598 CreateMockRead(*resp1, 1),
11599 CreateMockRead(*body1, 2),
11600 MockRead(ASYNC, OK, 3) // EOF
11603 scoped_ptr<DeterministicSocketData> data1(
11604 new DeterministicSocketData(reads1, arraysize(reads1),
11605 writes1, arraysize(writes1)));
11606 IPAddressNumber ip;
11607 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11608 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11609 MockConnect connect_data1(ASYNC, OK, peer_addr);
11610 data1->set_connect_data(connect_data1);
11612 // SPDY GET for HTTPS URL (direct)
11613 scoped_ptr<SpdyFrame> req2(
11614 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11616 MockWrite writes2[] = {
11617 CreateMockWrite(*req2, 0),
11620 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11621 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11622 MockRead reads2[] = {
11623 CreateMockRead(*resp2, 1),
11624 CreateMockRead(*body2, 2),
11625 MockRead(ASYNC, OK, 3) // EOF
11628 scoped_ptr<DeterministicSocketData> data2(
11629 new DeterministicSocketData(reads2, arraysize(reads2),
11630 writes2, arraysize(writes2)));
11631 MockConnect connect_data2(ASYNC, OK);
11632 data2->set_connect_data(connect_data2);
11634 // Set up a proxy config that sends HTTP requests to a proxy, and
11635 // all others direct.
11636 ProxyConfig proxy_config;
11637 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11638 CapturingProxyResolver* capturing_proxy_resolver =
11639 new CapturingProxyResolver();
11640 session_deps_.proxy_service.reset(new ProxyService(
11641 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11642 NULL));
11644 // Load a valid cert. Note, that this does not need to
11645 // be valid for proxy because the MockSSLClientSocket does
11646 // not actually verify it. But SpdySession will use this
11647 // to see if it is valid for the new origin
11648 base::FilePath certs_dir = GetTestCertsDirectory();
11649 scoped_refptr<X509Certificate> server_cert(
11650 ImportCertFromFile(certs_dir, "ok_cert.pem"));
11651 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11653 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11654 ssl1.SetNextProto(GetParam());
11655 ssl1.cert = server_cert;
11656 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11657 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11658 data1.get());
11660 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11661 ssl2.SetNextProto(GetParam());
11662 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11663 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11664 data2.get());
11666 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11667 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11668 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11670 scoped_refptr<HttpNetworkSession> session(
11671 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11673 // Start the first transaction to set up the SpdySession
11674 HttpRequestInfo request1;
11675 request1.method = "GET";
11676 request1.url = GURL(url1);
11677 request1.load_flags = 0;
11678 HttpNetworkTransaction trans1(LOWEST, session.get());
11679 TestCompletionCallback callback1;
11680 ASSERT_EQ(ERR_IO_PENDING,
11681 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11682 data1->RunFor(3);
11684 ASSERT_TRUE(callback1.have_result());
11685 EXPECT_EQ(OK, callback1.WaitForResult());
11686 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11688 // Now, start the HTTP request
11689 HttpRequestInfo request2;
11690 request2.method = "GET";
11691 request2.url = GURL(url2);
11692 request2.load_flags = 0;
11693 HttpNetworkTransaction trans2(MEDIUM, session.get());
11694 TestCompletionCallback callback2;
11695 EXPECT_EQ(ERR_IO_PENDING,
11696 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11697 base::MessageLoop::current()->RunUntilIdle();
11698 data2->RunFor(3);
11700 ASSERT_TRUE(callback2.have_result());
11701 EXPECT_EQ(OK, callback2.WaitForResult());
11702 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11705 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11706 // error) in SPDY session, removes the socket from pool and closes the SPDY
11707 // session. Verify that new url's from the same HttpNetworkSession (and a new
11708 // SpdySession) do work. http://crbug.com/224701
11709 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11710 const std::string https_url = "https://www.google.com/";
11712 MockRead reads1[] = {
11713 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11716 scoped_ptr<DeterministicSocketData> data1(
11717 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11718 data1->SetStop(1);
11720 scoped_ptr<SpdyFrame> req2(
11721 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11722 MockWrite writes2[] = {
11723 CreateMockWrite(*req2, 0),
11726 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11727 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11728 MockRead reads2[] = {
11729 CreateMockRead(*resp2, 1),
11730 CreateMockRead(*body2, 2),
11731 MockRead(ASYNC, OK, 3) // EOF
11734 scoped_ptr<DeterministicSocketData> data2(
11735 new DeterministicSocketData(reads2, arraysize(reads2),
11736 writes2, arraysize(writes2)));
11738 SSLSocketDataProvider ssl1(ASYNC, OK);
11739 ssl1.SetNextProto(GetParam());
11740 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11741 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11742 data1.get());
11744 SSLSocketDataProvider ssl2(ASYNC, OK);
11745 ssl2.SetNextProto(GetParam());
11746 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11747 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11748 data2.get());
11750 scoped_refptr<HttpNetworkSession> session(
11751 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11753 // Start the first transaction to set up the SpdySession and verify that
11754 // connection was closed.
11755 HttpRequestInfo request1;
11756 request1.method = "GET";
11757 request1.url = GURL(https_url);
11758 request1.load_flags = 0;
11759 HttpNetworkTransaction trans1(MEDIUM, session.get());
11760 TestCompletionCallback callback1;
11761 EXPECT_EQ(ERR_IO_PENDING,
11762 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11763 base::MessageLoop::current()->RunUntilIdle();
11764 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11766 // Now, start the second request and make sure it succeeds.
11767 HttpRequestInfo request2;
11768 request2.method = "GET";
11769 request2.url = GURL(https_url);
11770 request2.load_flags = 0;
11771 HttpNetworkTransaction trans2(MEDIUM, session.get());
11772 TestCompletionCallback callback2;
11773 EXPECT_EQ(ERR_IO_PENDING,
11774 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11775 base::MessageLoop::current()->RunUntilIdle();
11776 data2->RunFor(3);
11778 ASSERT_TRUE(callback2.have_result());
11779 EXPECT_EQ(OK, callback2.WaitForResult());
11780 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11783 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11784 session_deps_.next_protos = SpdyNextProtos();
11785 ClientSocketPoolManager::set_max_sockets_per_group(
11786 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11787 ClientSocketPoolManager::set_max_sockets_per_pool(
11788 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11790 // Use two different hosts with different IPs so they don't get pooled.
11791 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11792 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11793 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11795 SSLSocketDataProvider ssl1(ASYNC, OK);
11796 ssl1.SetNextProto(GetParam());
11797 SSLSocketDataProvider ssl2(ASYNC, OK);
11798 ssl2.SetNextProto(GetParam());
11799 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11802 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11803 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11804 MockWrite spdy1_writes[] = {
11805 CreateMockWrite(*host1_req, 1),
11807 scoped_ptr<SpdyFrame> host1_resp(
11808 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11809 scoped_ptr<SpdyFrame> host1_resp_body(
11810 spdy_util_.ConstructSpdyBodyFrame(1, true));
11811 MockRead spdy1_reads[] = {
11812 CreateMockRead(*host1_resp, 2),
11813 CreateMockRead(*host1_resp_body, 3),
11814 MockRead(ASYNC, ERR_IO_PENDING, 4),
11817 scoped_ptr<OrderedSocketData> spdy1_data(
11818 new OrderedSocketData(
11819 spdy1_reads, arraysize(spdy1_reads),
11820 spdy1_writes, arraysize(spdy1_writes)));
11821 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11823 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11824 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11825 MockWrite spdy2_writes[] = {
11826 CreateMockWrite(*host2_req, 1),
11828 scoped_ptr<SpdyFrame> host2_resp(
11829 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11830 scoped_ptr<SpdyFrame> host2_resp_body(
11831 spdy_util_.ConstructSpdyBodyFrame(1, true));
11832 MockRead spdy2_reads[] = {
11833 CreateMockRead(*host2_resp, 2),
11834 CreateMockRead(*host2_resp_body, 3),
11835 MockRead(ASYNC, ERR_IO_PENDING, 4),
11838 scoped_ptr<OrderedSocketData> spdy2_data(
11839 new OrderedSocketData(
11840 spdy2_reads, arraysize(spdy2_reads),
11841 spdy2_writes, arraysize(spdy2_writes)));
11842 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11844 MockWrite http_write[] = {
11845 MockWrite("GET / HTTP/1.1\r\n"
11846 "Host: www.a.com\r\n"
11847 "Connection: keep-alive\r\n\r\n"),
11850 MockRead http_read[] = {
11851 MockRead("HTTP/1.1 200 OK\r\n"),
11852 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11853 MockRead("Content-Length: 6\r\n\r\n"),
11854 MockRead("hello!"),
11856 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11857 http_write, arraysize(http_write));
11858 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11860 HostPortPair host_port_pair_a("www.a.com", 443);
11861 SpdySessionKey spdy_session_key_a(
11862 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11863 EXPECT_FALSE(
11864 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11866 TestCompletionCallback callback;
11867 HttpRequestInfo request1;
11868 request1.method = "GET";
11869 request1.url = GURL("https://www.a.com/");
11870 request1.load_flags = 0;
11871 scoped_ptr<HttpNetworkTransaction> trans(
11872 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11874 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11875 EXPECT_EQ(ERR_IO_PENDING, rv);
11876 EXPECT_EQ(OK, callback.WaitForResult());
11878 const HttpResponseInfo* response = trans->GetResponseInfo();
11879 ASSERT_TRUE(response != NULL);
11880 ASSERT_TRUE(response->headers.get() != NULL);
11881 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11882 EXPECT_TRUE(response->was_fetched_via_spdy);
11883 EXPECT_TRUE(response->was_npn_negotiated);
11885 std::string response_data;
11886 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11887 EXPECT_EQ("hello!", response_data);
11888 trans.reset();
11889 EXPECT_TRUE(
11890 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11892 HostPortPair host_port_pair_b("www.b.com", 443);
11893 SpdySessionKey spdy_session_key_b(
11894 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11895 EXPECT_FALSE(
11896 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11897 HttpRequestInfo request2;
11898 request2.method = "GET";
11899 request2.url = GURL("https://www.b.com/");
11900 request2.load_flags = 0;
11901 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11903 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11904 EXPECT_EQ(ERR_IO_PENDING, rv);
11905 EXPECT_EQ(OK, callback.WaitForResult());
11907 response = trans->GetResponseInfo();
11908 ASSERT_TRUE(response != NULL);
11909 ASSERT_TRUE(response->headers.get() != NULL);
11910 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11911 EXPECT_TRUE(response->was_fetched_via_spdy);
11912 EXPECT_TRUE(response->was_npn_negotiated);
11913 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11914 EXPECT_EQ("hello!", response_data);
11915 EXPECT_FALSE(
11916 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11917 EXPECT_TRUE(
11918 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11920 HostPortPair host_port_pair_a1("www.a.com", 80);
11921 SpdySessionKey spdy_session_key_a1(
11922 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11923 EXPECT_FALSE(
11924 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11925 HttpRequestInfo request3;
11926 request3.method = "GET";
11927 request3.url = GURL("http://www.a.com/");
11928 request3.load_flags = 0;
11929 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11931 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11932 EXPECT_EQ(ERR_IO_PENDING, rv);
11933 EXPECT_EQ(OK, callback.WaitForResult());
11935 response = trans->GetResponseInfo();
11936 ASSERT_TRUE(response != NULL);
11937 ASSERT_TRUE(response->headers.get() != NULL);
11938 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11939 EXPECT_FALSE(response->was_fetched_via_spdy);
11940 EXPECT_FALSE(response->was_npn_negotiated);
11941 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11942 EXPECT_EQ("hello!", response_data);
11943 EXPECT_FALSE(
11944 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11945 EXPECT_FALSE(
11946 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11949 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11950 HttpRequestInfo request;
11951 request.method = "GET";
11952 request.url = GURL("http://www.google.com/");
11953 request.load_flags = 0;
11955 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11956 scoped_ptr<HttpTransaction> trans(
11957 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11959 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11960 StaticSocketDataProvider data;
11961 data.set_connect_data(mock_connect);
11962 session_deps_.socket_factory->AddSocketDataProvider(&data);
11964 TestCompletionCallback callback;
11966 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11967 EXPECT_EQ(ERR_IO_PENDING, rv);
11969 rv = callback.WaitForResult();
11970 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11972 EXPECT_EQ(NULL, trans->GetResponseInfo());
11974 // We don't care whether this succeeds or fails, but it shouldn't crash.
11975 HttpRequestHeaders request_headers;
11976 trans->GetFullRequestHeaders(&request_headers);
11979 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11980 HttpRequestInfo request;
11981 request.method = "GET";
11982 request.url = GURL("http://www.google.com/");
11983 request.load_flags = 0;
11985 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11986 scoped_ptr<HttpTransaction> trans(
11987 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11989 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11990 StaticSocketDataProvider data;
11991 data.set_connect_data(mock_connect);
11992 session_deps_.socket_factory->AddSocketDataProvider(&data);
11994 TestCompletionCallback callback;
11996 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11997 EXPECT_EQ(ERR_IO_PENDING, rv);
11999 rv = callback.WaitForResult();
12000 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12002 EXPECT_EQ(NULL, trans->GetResponseInfo());
12004 // We don't care whether this succeeds or fails, but it shouldn't crash.
12005 HttpRequestHeaders request_headers;
12006 trans->GetFullRequestHeaders(&request_headers);
12009 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
12010 HttpRequestInfo request;
12011 request.method = "GET";
12012 request.url = GURL("http://www.google.com/");
12013 request.load_flags = 0;
12015 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12016 scoped_ptr<HttpTransaction> trans(
12017 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12019 MockWrite data_writes[] = {
12020 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12022 MockRead data_reads[] = {
12023 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12026 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12027 data_writes, arraysize(data_writes));
12028 session_deps_.socket_factory->AddSocketDataProvider(&data);
12030 TestCompletionCallback callback;
12032 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12033 EXPECT_EQ(ERR_IO_PENDING, rv);
12035 rv = callback.WaitForResult();
12036 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12038 EXPECT_EQ(NULL, trans->GetResponseInfo());
12040 HttpRequestHeaders request_headers;
12041 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12042 EXPECT_TRUE(request_headers.HasHeader("Host"));
12045 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
12046 HttpRequestInfo request;
12047 request.method = "GET";
12048 request.url = GURL("http://www.google.com/");
12049 request.load_flags = 0;
12051 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12052 scoped_ptr<HttpTransaction> trans(
12053 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12055 MockWrite data_writes[] = {
12056 MockWrite(ASYNC, ERR_CONNECTION_RESET),
12058 MockRead data_reads[] = {
12059 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12062 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12063 data_writes, arraysize(data_writes));
12064 session_deps_.socket_factory->AddSocketDataProvider(&data);
12066 TestCompletionCallback callback;
12068 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12069 EXPECT_EQ(ERR_IO_PENDING, rv);
12071 rv = callback.WaitForResult();
12072 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12074 EXPECT_EQ(NULL, trans->GetResponseInfo());
12076 HttpRequestHeaders request_headers;
12077 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12078 EXPECT_TRUE(request_headers.HasHeader("Host"));
12081 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
12082 HttpRequestInfo request;
12083 request.method = "GET";
12084 request.url = GURL("http://www.google.com/");
12085 request.load_flags = 0;
12087 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12088 scoped_ptr<HttpTransaction> trans(
12089 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12091 MockWrite data_writes[] = {
12092 MockWrite("GET / HTTP/1.1\r\n"
12093 "Host: www.google.com\r\n"
12094 "Connection: keep-alive\r\n\r\n"),
12096 MockRead data_reads[] = {
12097 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
12100 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12101 data_writes, arraysize(data_writes));
12102 session_deps_.socket_factory->AddSocketDataProvider(&data);
12104 TestCompletionCallback callback;
12106 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12107 EXPECT_EQ(ERR_IO_PENDING, rv);
12109 rv = callback.WaitForResult();
12110 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12112 EXPECT_EQ(NULL, trans->GetResponseInfo());
12114 HttpRequestHeaders request_headers;
12115 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12116 EXPECT_TRUE(request_headers.HasHeader("Host"));
12119 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
12120 HttpRequestInfo request;
12121 request.method = "GET";
12122 request.url = GURL("http://www.google.com/");
12123 request.load_flags = 0;
12125 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12126 scoped_ptr<HttpTransaction> trans(
12127 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12129 MockWrite data_writes[] = {
12130 MockWrite("GET / HTTP/1.1\r\n"
12131 "Host: www.google.com\r\n"
12132 "Connection: keep-alive\r\n\r\n"),
12134 MockRead data_reads[] = {
12135 MockRead(ASYNC, ERR_CONNECTION_RESET),
12138 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12139 data_writes, arraysize(data_writes));
12140 session_deps_.socket_factory->AddSocketDataProvider(&data);
12142 TestCompletionCallback callback;
12144 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12145 EXPECT_EQ(ERR_IO_PENDING, rv);
12147 rv = callback.WaitForResult();
12148 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12150 EXPECT_EQ(NULL, trans->GetResponseInfo());
12152 HttpRequestHeaders request_headers;
12153 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12154 EXPECT_TRUE(request_headers.HasHeader("Host"));
12157 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12158 HttpRequestInfo request;
12159 request.method = "GET";
12160 request.url = GURL("http://www.google.com/");
12161 request.load_flags = 0;
12162 request.extra_headers.SetHeader("X-Foo", "bar");
12164 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12165 scoped_ptr<HttpTransaction> trans(
12166 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12168 MockWrite data_writes[] = {
12169 MockWrite("GET / HTTP/1.1\r\n"
12170 "Host: www.google.com\r\n"
12171 "Connection: keep-alive\r\n"
12172 "X-Foo: bar\r\n\r\n"),
12174 MockRead data_reads[] = {
12175 MockRead("HTTP/1.1 200 OK\r\n"
12176 "Content-Length: 5\r\n\r\n"
12177 "hello"),
12178 MockRead(ASYNC, ERR_UNEXPECTED),
12181 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12182 data_writes, arraysize(data_writes));
12183 session_deps_.socket_factory->AddSocketDataProvider(&data);
12185 TestCompletionCallback callback;
12187 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12188 EXPECT_EQ(ERR_IO_PENDING, rv);
12190 rv = callback.WaitForResult();
12191 EXPECT_EQ(OK, rv);
12193 HttpRequestHeaders request_headers;
12194 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12195 std::string foo;
12196 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12197 EXPECT_EQ("bar", foo);
12200 namespace {
12202 // Fake HttpStreamBase that simply records calls to SetPriority().
12203 class FakeStream : public HttpStreamBase,
12204 public base::SupportsWeakPtr<FakeStream> {
12205 public:
12206 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12207 virtual ~FakeStream() {}
12209 RequestPriority priority() const { return priority_; }
12211 virtual int InitializeStream(const HttpRequestInfo* request_info,
12212 RequestPriority priority,
12213 const BoundNetLog& net_log,
12214 const CompletionCallback& callback) OVERRIDE {
12215 return ERR_IO_PENDING;
12218 virtual int SendRequest(const HttpRequestHeaders& request_headers,
12219 HttpResponseInfo* response,
12220 const CompletionCallback& callback) OVERRIDE {
12221 ADD_FAILURE();
12222 return ERR_UNEXPECTED;
12225 virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
12226 ADD_FAILURE();
12227 return ERR_UNEXPECTED;
12230 virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
12231 const CompletionCallback& callback) OVERRIDE {
12232 ADD_FAILURE();
12233 return ERR_UNEXPECTED;
12236 virtual void Close(bool not_reusable) OVERRIDE {}
12238 virtual bool IsResponseBodyComplete() const OVERRIDE {
12239 ADD_FAILURE();
12240 return false;
12243 virtual bool CanFindEndOfResponse() const OVERRIDE {
12244 return false;
12247 virtual bool IsConnectionReused() const OVERRIDE {
12248 ADD_FAILURE();
12249 return false;
12252 virtual void SetConnectionReused() OVERRIDE {
12253 ADD_FAILURE();
12256 virtual bool IsConnectionReusable() const OVERRIDE {
12257 ADD_FAILURE();
12258 return false;
12261 virtual int64 GetTotalReceivedBytes() const OVERRIDE {
12262 ADD_FAILURE();
12263 return 0;
12266 virtual bool GetLoadTimingInfo(
12267 LoadTimingInfo* load_timing_info) const OVERRIDE {
12268 ADD_FAILURE();
12269 return false;
12272 virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
12273 ADD_FAILURE();
12276 virtual void GetSSLCertRequestInfo(
12277 SSLCertRequestInfo* cert_request_info) OVERRIDE {
12278 ADD_FAILURE();
12281 virtual bool IsSpdyHttpStream() const OVERRIDE {
12282 ADD_FAILURE();
12283 return false;
12286 virtual void Drain(HttpNetworkSession* session) OVERRIDE {
12287 ADD_FAILURE();
12290 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12291 priority_ = priority;
12294 private:
12295 RequestPriority priority_;
12297 DISALLOW_COPY_AND_ASSIGN(FakeStream);
12300 // Fake HttpStreamRequest that simply records calls to SetPriority()
12301 // and vends FakeStreams with its current priority.
12302 class FakeStreamRequest : public HttpStreamRequest,
12303 public base::SupportsWeakPtr<FakeStreamRequest> {
12304 public:
12305 FakeStreamRequest(RequestPriority priority,
12306 HttpStreamRequest::Delegate* delegate)
12307 : priority_(priority),
12308 delegate_(delegate),
12309 websocket_stream_create_helper_(NULL) {}
12311 FakeStreamRequest(RequestPriority priority,
12312 HttpStreamRequest::Delegate* delegate,
12313 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
12314 : priority_(priority),
12315 delegate_(delegate),
12316 websocket_stream_create_helper_(create_helper) {}
12318 virtual ~FakeStreamRequest() {}
12320 RequestPriority priority() const { return priority_; }
12322 const WebSocketHandshakeStreamBase::CreateHelper*
12323 websocket_stream_create_helper() const {
12324 return websocket_stream_create_helper_;
12327 // Create a new FakeStream and pass it to the request's
12328 // delegate. Returns a weak pointer to the FakeStream.
12329 base::WeakPtr<FakeStream> FinishStreamRequest() {
12330 FakeStream* fake_stream = new FakeStream(priority_);
12331 // Do this before calling OnStreamReady() as OnStreamReady() may
12332 // immediately delete |fake_stream|.
12333 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
12334 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
12335 return weak_stream;
12338 virtual int RestartTunnelWithProxyAuth(
12339 const AuthCredentials& credentials) OVERRIDE {
12340 ADD_FAILURE();
12341 return ERR_UNEXPECTED;
12344 virtual LoadState GetLoadState() const OVERRIDE {
12345 ADD_FAILURE();
12346 return LoadState();
12349 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12350 priority_ = priority;
12353 virtual bool was_npn_negotiated() const OVERRIDE {
12354 return false;
12357 virtual NextProto protocol_negotiated() const OVERRIDE {
12358 return kProtoUnknown;
12361 virtual bool using_spdy() const OVERRIDE {
12362 return false;
12365 private:
12366 RequestPriority priority_;
12367 HttpStreamRequest::Delegate* const delegate_;
12368 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
12370 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12373 // Fake HttpStreamFactory that vends FakeStreamRequests.
12374 class FakeStreamFactory : public HttpStreamFactory {
12375 public:
12376 FakeStreamFactory() {}
12377 virtual ~FakeStreamFactory() {}
12379 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12380 // RequestStream() (which may be NULL if it was destroyed already).
12381 base::WeakPtr<FakeStreamRequest> last_stream_request() {
12382 return last_stream_request_;
12385 virtual HttpStreamRequest* RequestStream(
12386 const HttpRequestInfo& info,
12387 RequestPriority priority,
12388 const SSLConfig& server_ssl_config,
12389 const SSLConfig& proxy_ssl_config,
12390 HttpStreamRequest::Delegate* delegate,
12391 const BoundNetLog& net_log) OVERRIDE {
12392 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12393 last_stream_request_ = fake_request->AsWeakPtr();
12394 return fake_request;
12397 virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
12398 const HttpRequestInfo& info,
12399 RequestPriority priority,
12400 const SSLConfig& server_ssl_config,
12401 const SSLConfig& proxy_ssl_config,
12402 HttpStreamRequest::Delegate* delegate,
12403 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
12404 const BoundNetLog& net_log) OVERRIDE {
12405 FakeStreamRequest* fake_request =
12406 new FakeStreamRequest(priority, delegate, create_helper);
12407 last_stream_request_ = fake_request->AsWeakPtr();
12408 return fake_request;
12411 virtual void PreconnectStreams(int num_streams,
12412 const HttpRequestInfo& info,
12413 RequestPriority priority,
12414 const SSLConfig& server_ssl_config,
12415 const SSLConfig& proxy_ssl_config) OVERRIDE {
12416 ADD_FAILURE();
12419 virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
12420 ADD_FAILURE();
12421 return NULL;
12424 private:
12425 base::WeakPtr<FakeStreamRequest> last_stream_request_;
12427 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12430 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12431 // worth doing.
12432 class FakeWebSocketStreamCreateHelper :
12433 public WebSocketHandshakeStreamBase::CreateHelper {
12434 public:
12435 virtual WebSocketHandshakeStreamBase* CreateBasicStream(
12436 scoped_ptr<ClientSocketHandle> connection,
12437 bool using_proxy) OVERRIDE {
12438 NOTREACHED();
12439 return NULL;
12442 virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
12443 const base::WeakPtr<SpdySession>& session,
12444 bool use_relative_url) OVERRIDE {
12445 NOTREACHED();
12446 return NULL;
12449 virtual ~FakeWebSocketStreamCreateHelper() {}
12451 virtual scoped_ptr<WebSocketStream> Upgrade() {
12452 NOTREACHED();
12453 return scoped_ptr<WebSocketStream>();
12457 } // namespace
12459 // Make sure that HttpNetworkTransaction passes on its priority to its
12460 // stream request on start.
12461 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
12462 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12463 HttpNetworkSessionPeer peer(session);
12464 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12465 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12467 HttpNetworkTransaction trans(LOW, session);
12469 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
12471 HttpRequestInfo request;
12472 TestCompletionCallback callback;
12473 EXPECT_EQ(ERR_IO_PENDING,
12474 trans.Start(&request, callback.callback(), BoundNetLog()));
12476 base::WeakPtr<FakeStreamRequest> fake_request =
12477 fake_factory->last_stream_request();
12478 ASSERT_TRUE(fake_request != NULL);
12479 EXPECT_EQ(LOW, fake_request->priority());
12482 // Make sure that HttpNetworkTransaction passes on its priority
12483 // updates to its stream request.
12484 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
12485 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12486 HttpNetworkSessionPeer peer(session);
12487 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12488 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12490 HttpNetworkTransaction trans(LOW, session);
12492 HttpRequestInfo request;
12493 TestCompletionCallback callback;
12494 EXPECT_EQ(ERR_IO_PENDING,
12495 trans.Start(&request, callback.callback(), BoundNetLog()));
12497 base::WeakPtr<FakeStreamRequest> fake_request =
12498 fake_factory->last_stream_request();
12499 ASSERT_TRUE(fake_request != NULL);
12500 EXPECT_EQ(LOW, fake_request->priority());
12502 trans.SetPriority(LOWEST);
12503 ASSERT_TRUE(fake_request != NULL);
12504 EXPECT_EQ(LOWEST, fake_request->priority());
12507 // Make sure that HttpNetworkTransaction passes on its priority
12508 // updates to its stream.
12509 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
12510 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12511 HttpNetworkSessionPeer peer(session);
12512 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12513 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12515 HttpNetworkTransaction trans(LOW, session);
12517 HttpRequestInfo request;
12518 TestCompletionCallback callback;
12519 EXPECT_EQ(ERR_IO_PENDING,
12520 trans.Start(&request, callback.callback(), BoundNetLog()));
12522 base::WeakPtr<FakeStreamRequest> fake_request =
12523 fake_factory->last_stream_request();
12524 ASSERT_TRUE(fake_request != NULL);
12525 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
12526 ASSERT_TRUE(fake_stream != NULL);
12527 EXPECT_EQ(LOW, fake_stream->priority());
12529 trans.SetPriority(LOWEST);
12530 EXPECT_EQ(LOWEST, fake_stream->priority());
12533 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
12534 // The same logic needs to be tested for both ws: and wss: schemes, but this
12535 // test is already parameterised on NextProto, so it uses a loop to verify
12536 // that the different schemes work.
12537 std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"};
12538 for (size_t i = 0; i < arraysize(test_cases); ++i) {
12539 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12540 HttpNetworkSessionPeer peer(session);
12541 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12542 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
12543 peer.SetHttpStreamFactoryForWebSocket(
12544 scoped_ptr<HttpStreamFactory>(fake_factory));
12546 HttpNetworkTransaction trans(LOW, session);
12547 trans.SetWebSocketHandshakeStreamCreateHelper(
12548 &websocket_stream_create_helper);
12550 HttpRequestInfo request;
12551 TestCompletionCallback callback;
12552 request.method = "GET";
12553 request.url = GURL(test_cases[i]);
12555 EXPECT_EQ(ERR_IO_PENDING,
12556 trans.Start(&request, callback.callback(), BoundNetLog()));
12558 base::WeakPtr<FakeStreamRequest> fake_request =
12559 fake_factory->last_stream_request();
12560 ASSERT_TRUE(fake_request != NULL);
12561 EXPECT_EQ(&websocket_stream_create_helper,
12562 fake_request->websocket_stream_create_helper());
12566 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12567 // if the transport socket pool is stalled on the global socket limit.
12568 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
12569 ClientSocketPoolManager::set_max_sockets_per_group(
12570 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12571 ClientSocketPoolManager::set_max_sockets_per_pool(
12572 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12574 // Set up SSL request.
12576 HttpRequestInfo ssl_request;
12577 ssl_request.method = "GET";
12578 ssl_request.url = GURL("https://www.google.com/");
12580 MockWrite ssl_writes[] = {
12581 MockWrite("GET / HTTP/1.1\r\n"
12582 "Host: www.google.com\r\n"
12583 "Connection: keep-alive\r\n\r\n"),
12585 MockRead ssl_reads[] = {
12586 MockRead("HTTP/1.1 200 OK\r\n"),
12587 MockRead("Content-Length: 11\r\n\r\n"),
12588 MockRead("hello world"),
12589 MockRead(SYNCHRONOUS, OK),
12591 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
12592 ssl_writes, arraysize(ssl_writes));
12593 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12595 SSLSocketDataProvider ssl(ASYNC, OK);
12596 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12598 // Set up HTTP request.
12600 HttpRequestInfo http_request;
12601 http_request.method = "GET";
12602 http_request.url = GURL("http://www.google.com/");
12604 MockWrite http_writes[] = {
12605 MockWrite("GET / HTTP/1.1\r\n"
12606 "Host: www.google.com\r\n"
12607 "Connection: keep-alive\r\n\r\n"),
12609 MockRead http_reads[] = {
12610 MockRead("HTTP/1.1 200 OK\r\n"),
12611 MockRead("Content-Length: 7\r\n\r\n"),
12612 MockRead("falafel"),
12613 MockRead(SYNCHRONOUS, OK),
12615 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12616 http_writes, arraysize(http_writes));
12617 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12619 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12621 // Start the SSL request.
12622 TestCompletionCallback ssl_callback;
12623 scoped_ptr<HttpTransaction> ssl_trans(
12624 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12625 ASSERT_EQ(ERR_IO_PENDING,
12626 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
12627 BoundNetLog()));
12629 // Start the HTTP request. Pool should stall.
12630 TestCompletionCallback http_callback;
12631 scoped_ptr<HttpTransaction> http_trans(
12632 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12633 ASSERT_EQ(ERR_IO_PENDING,
12634 http_trans->Start(&http_request, http_callback.callback(),
12635 BoundNetLog()));
12636 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12638 // Wait for response from SSL request.
12639 ASSERT_EQ(OK, ssl_callback.WaitForResult());
12640 std::string response_data;
12641 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
12642 EXPECT_EQ("hello world", response_data);
12644 // The SSL socket should automatically be closed, so the HTTP request can
12645 // start.
12646 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12647 ASSERT_FALSE(IsTransportSocketPoolStalled(session));
12649 // The HTTP request can now complete.
12650 ASSERT_EQ(OK, http_callback.WaitForResult());
12651 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12652 EXPECT_EQ("falafel", response_data);
12654 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12657 // Tests that when a SSL connection is established but there's no corresponding
12658 // request that needs it, the new socket is closed if the transport socket pool
12659 // is stalled on the global socket limit.
12660 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
12661 ClientSocketPoolManager::set_max_sockets_per_group(
12662 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12663 ClientSocketPoolManager::set_max_sockets_per_pool(
12664 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12666 // Set up an ssl request.
12668 HttpRequestInfo ssl_request;
12669 ssl_request.method = "GET";
12670 ssl_request.url = GURL("https://www.foopy.com/");
12672 // No data will be sent on the SSL socket.
12673 StaticSocketDataProvider ssl_data;
12674 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12676 SSLSocketDataProvider ssl(ASYNC, OK);
12677 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12679 // Set up HTTP request.
12681 HttpRequestInfo http_request;
12682 http_request.method = "GET";
12683 http_request.url = GURL("http://www.google.com/");
12685 MockWrite http_writes[] = {
12686 MockWrite("GET / HTTP/1.1\r\n"
12687 "Host: www.google.com\r\n"
12688 "Connection: keep-alive\r\n\r\n"),
12690 MockRead http_reads[] = {
12691 MockRead("HTTP/1.1 200 OK\r\n"),
12692 MockRead("Content-Length: 7\r\n\r\n"),
12693 MockRead("falafel"),
12694 MockRead(SYNCHRONOUS, OK),
12696 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12697 http_writes, arraysize(http_writes));
12698 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12700 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12702 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12703 // cancelled when a normal transaction is cancelled.
12704 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
12705 net::SSLConfig ssl_config;
12706 session->ssl_config_service()->GetSSLConfig(&ssl_config);
12707 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
12708 ssl_config, ssl_config);
12709 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12711 // Start the HTTP request. Pool should stall.
12712 TestCompletionCallback http_callback;
12713 scoped_ptr<HttpTransaction> http_trans(
12714 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12715 ASSERT_EQ(ERR_IO_PENDING,
12716 http_trans->Start(&http_request, http_callback.callback(),
12717 BoundNetLog()));
12718 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12720 // The SSL connection will automatically be closed once the connection is
12721 // established, to let the HTTP request start.
12722 ASSERT_EQ(OK, http_callback.WaitForResult());
12723 std::string response_data;
12724 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12725 EXPECT_EQ("falafel", response_data);
12727 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12730 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
12731 ScopedVector<UploadElementReader> element_readers;
12732 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12733 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12735 HttpRequestInfo request;
12736 request.method = "POST";
12737 request.url = GURL("http://www.foo.com/");
12738 request.upload_data_stream = &upload_data_stream;
12739 request.load_flags = 0;
12741 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12742 scoped_ptr<HttpTransaction> trans(
12743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12744 // Send headers successfully, but get an error while sending the body.
12745 MockWrite data_writes[] = {
12746 MockWrite("POST / HTTP/1.1\r\n"
12747 "Host: www.foo.com\r\n"
12748 "Connection: keep-alive\r\n"
12749 "Content-Length: 3\r\n\r\n"),
12750 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12753 MockRead data_reads[] = {
12754 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12755 MockRead("hello world"),
12756 MockRead(SYNCHRONOUS, OK),
12758 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12759 arraysize(data_writes));
12760 session_deps_.socket_factory->AddSocketDataProvider(&data);
12762 TestCompletionCallback callback;
12764 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12765 EXPECT_EQ(ERR_IO_PENDING, rv);
12767 rv = callback.WaitForResult();
12768 EXPECT_EQ(OK, rv);
12770 const HttpResponseInfo* response = trans->GetResponseInfo();
12771 ASSERT_TRUE(response != NULL);
12773 EXPECT_TRUE(response->headers.get() != NULL);
12774 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12776 std::string response_data;
12777 rv = ReadTransaction(trans.get(), &response_data);
12778 EXPECT_EQ(OK, rv);
12779 EXPECT_EQ("hello world", response_data);
12782 // This test makes sure the retry logic doesn't trigger when reading an error
12783 // response from a server that rejected a POST with a CONNECTION_RESET.
12784 TEST_P(HttpNetworkTransactionTest,
12785 PostReadsErrorResponseAfterResetOnReusedSocket) {
12786 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12787 MockWrite data_writes[] = {
12788 MockWrite("GET / HTTP/1.1\r\n"
12789 "Host: www.foo.com\r\n"
12790 "Connection: keep-alive\r\n\r\n"),
12791 MockWrite("POST / HTTP/1.1\r\n"
12792 "Host: www.foo.com\r\n"
12793 "Connection: keep-alive\r\n"
12794 "Content-Length: 3\r\n\r\n"),
12795 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12798 MockRead data_reads[] = {
12799 MockRead("HTTP/1.1 200 Peachy\r\n"
12800 "Content-Length: 14\r\n\r\n"),
12801 MockRead("first response"),
12802 MockRead("HTTP/1.1 400 Not OK\r\n"
12803 "Content-Length: 15\r\n\r\n"),
12804 MockRead("second response"),
12805 MockRead(SYNCHRONOUS, OK),
12807 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12808 arraysize(data_writes));
12809 session_deps_.socket_factory->AddSocketDataProvider(&data);
12811 TestCompletionCallback callback;
12812 HttpRequestInfo request1;
12813 request1.method = "GET";
12814 request1.url = GURL("http://www.foo.com/");
12815 request1.load_flags = 0;
12817 scoped_ptr<HttpTransaction> trans1(
12818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12819 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
12820 EXPECT_EQ(ERR_IO_PENDING, rv);
12822 rv = callback.WaitForResult();
12823 EXPECT_EQ(OK, rv);
12825 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12826 ASSERT_TRUE(response1 != NULL);
12828 EXPECT_TRUE(response1->headers.get() != NULL);
12829 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
12831 std::string response_data1;
12832 rv = ReadTransaction(trans1.get(), &response_data1);
12833 EXPECT_EQ(OK, rv);
12834 EXPECT_EQ("first response", response_data1);
12835 // Delete the transaction to release the socket back into the socket pool.
12836 trans1.reset();
12838 ScopedVector<UploadElementReader> element_readers;
12839 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12840 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12842 HttpRequestInfo request2;
12843 request2.method = "POST";
12844 request2.url = GURL("http://www.foo.com/");
12845 request2.upload_data_stream = &upload_data_stream;
12846 request2.load_flags = 0;
12848 scoped_ptr<HttpTransaction> trans2(
12849 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12850 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
12851 EXPECT_EQ(ERR_IO_PENDING, rv);
12853 rv = callback.WaitForResult();
12854 EXPECT_EQ(OK, rv);
12856 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
12857 ASSERT_TRUE(response2 != NULL);
12859 EXPECT_TRUE(response2->headers.get() != NULL);
12860 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
12862 std::string response_data2;
12863 rv = ReadTransaction(trans2.get(), &response_data2);
12864 EXPECT_EQ(OK, rv);
12865 EXPECT_EQ("second response", response_data2);
12868 TEST_P(HttpNetworkTransactionTest,
12869 PostReadsErrorResponseAfterResetPartialBodySent) {
12870 ScopedVector<UploadElementReader> element_readers;
12871 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12872 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12874 HttpRequestInfo request;
12875 request.method = "POST";
12876 request.url = GURL("http://www.foo.com/");
12877 request.upload_data_stream = &upload_data_stream;
12878 request.load_flags = 0;
12880 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12881 scoped_ptr<HttpTransaction> trans(
12882 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12883 // Send headers successfully, but get an error while sending the body.
12884 MockWrite data_writes[] = {
12885 MockWrite("POST / HTTP/1.1\r\n"
12886 "Host: www.foo.com\r\n"
12887 "Connection: keep-alive\r\n"
12888 "Content-Length: 3\r\n\r\n"
12889 "fo"),
12890 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12893 MockRead data_reads[] = {
12894 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12895 MockRead("hello world"),
12896 MockRead(SYNCHRONOUS, OK),
12898 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12899 arraysize(data_writes));
12900 session_deps_.socket_factory->AddSocketDataProvider(&data);
12902 TestCompletionCallback callback;
12904 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12905 EXPECT_EQ(ERR_IO_PENDING, rv);
12907 rv = callback.WaitForResult();
12908 EXPECT_EQ(OK, rv);
12910 const HttpResponseInfo* response = trans->GetResponseInfo();
12911 ASSERT_TRUE(response != NULL);
12913 EXPECT_TRUE(response->headers.get() != NULL);
12914 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12916 std::string response_data;
12917 rv = ReadTransaction(trans.get(), &response_data);
12918 EXPECT_EQ(OK, rv);
12919 EXPECT_EQ("hello world", response_data);
12922 // This tests the more common case than the previous test, where headers and
12923 // body are not merged into a single request.
12924 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
12925 ScopedVector<UploadElementReader> element_readers;
12926 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12927 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
12929 HttpRequestInfo request;
12930 request.method = "POST";
12931 request.url = GURL("http://www.foo.com/");
12932 request.upload_data_stream = &upload_data_stream;
12933 request.load_flags = 0;
12935 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12936 scoped_ptr<HttpTransaction> trans(
12937 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12938 // Send headers successfully, but get an error while sending the body.
12939 MockWrite data_writes[] = {
12940 MockWrite("POST / HTTP/1.1\r\n"
12941 "Host: www.foo.com\r\n"
12942 "Connection: keep-alive\r\n"
12943 "Transfer-Encoding: chunked\r\n\r\n"),
12944 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12947 MockRead data_reads[] = {
12948 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12949 MockRead("hello world"),
12950 MockRead(SYNCHRONOUS, OK),
12952 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12953 arraysize(data_writes));
12954 session_deps_.socket_factory->AddSocketDataProvider(&data);
12956 TestCompletionCallback callback;
12958 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12959 EXPECT_EQ(ERR_IO_PENDING, rv);
12960 // Make sure the headers are sent before adding a chunk. This ensures that
12961 // they can't be merged with the body in a single send. Not currently
12962 // necessary since a chunked body is never merged with headers, but this makes
12963 // the test more future proof.
12964 base::RunLoop().RunUntilIdle();
12966 upload_data_stream.AppendChunk("last chunk", 10, true);
12968 rv = callback.WaitForResult();
12969 EXPECT_EQ(OK, rv);
12971 const HttpResponseInfo* response = trans->GetResponseInfo();
12972 ASSERT_TRUE(response != NULL);
12974 EXPECT_TRUE(response->headers.get() != NULL);
12975 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12977 std::string response_data;
12978 rv = ReadTransaction(trans.get(), &response_data);
12979 EXPECT_EQ(OK, rv);
12980 EXPECT_EQ("hello world", response_data);
12983 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
12984 ScopedVector<UploadElementReader> element_readers;
12985 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12986 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12988 HttpRequestInfo request;
12989 request.method = "POST";
12990 request.url = GURL("http://www.foo.com/");
12991 request.upload_data_stream = &upload_data_stream;
12992 request.load_flags = 0;
12994 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12995 scoped_ptr<HttpTransaction> trans(
12996 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12998 MockWrite data_writes[] = {
12999 MockWrite("POST / HTTP/1.1\r\n"
13000 "Host: www.foo.com\r\n"
13001 "Connection: keep-alive\r\n"
13002 "Content-Length: 3\r\n\r\n"),
13003 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13006 MockRead data_reads[] = {
13007 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13008 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13009 MockRead("hello world"),
13010 MockRead(SYNCHRONOUS, OK),
13012 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13013 arraysize(data_writes));
13014 session_deps_.socket_factory->AddSocketDataProvider(&data);
13016 TestCompletionCallback callback;
13018 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13019 EXPECT_EQ(ERR_IO_PENDING, rv);
13021 rv = callback.WaitForResult();
13022 EXPECT_EQ(OK, rv);
13024 const HttpResponseInfo* response = trans->GetResponseInfo();
13025 ASSERT_TRUE(response != NULL);
13027 EXPECT_TRUE(response->headers.get() != NULL);
13028 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13030 std::string response_data;
13031 rv = ReadTransaction(trans.get(), &response_data);
13032 EXPECT_EQ(OK, rv);
13033 EXPECT_EQ("hello world", response_data);
13036 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
13037 ScopedVector<UploadElementReader> element_readers;
13038 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13039 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13041 HttpRequestInfo request;
13042 request.method = "POST";
13043 request.url = GURL("http://www.foo.com/");
13044 request.upload_data_stream = &upload_data_stream;
13045 request.load_flags = 0;
13047 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13048 scoped_ptr<HttpTransaction> trans(
13049 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13050 // Send headers successfully, but get an error while sending the body.
13051 MockWrite data_writes[] = {
13052 MockWrite("POST / HTTP/1.1\r\n"
13053 "Host: www.foo.com\r\n"
13054 "Connection: keep-alive\r\n"
13055 "Content-Length: 3\r\n\r\n"),
13056 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13059 MockRead data_reads[] = {
13060 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13061 MockRead("hello world"),
13062 MockRead(SYNCHRONOUS, OK),
13064 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13065 arraysize(data_writes));
13066 session_deps_.socket_factory->AddSocketDataProvider(&data);
13068 TestCompletionCallback callback;
13070 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13071 EXPECT_EQ(ERR_IO_PENDING, rv);
13073 rv = callback.WaitForResult();
13074 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13076 const HttpResponseInfo* response = trans->GetResponseInfo();
13077 EXPECT_TRUE(response == NULL);
13080 TEST_P(HttpNetworkTransactionTest,
13081 PostIgnoresNonErrorResponseAfterResetAnd100) {
13082 ScopedVector<UploadElementReader> element_readers;
13083 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13084 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13086 HttpRequestInfo request;
13087 request.method = "POST";
13088 request.url = GURL("http://www.foo.com/");
13089 request.upload_data_stream = &upload_data_stream;
13090 request.load_flags = 0;
13092 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13093 scoped_ptr<HttpTransaction> trans(
13094 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13095 // Send headers successfully, but get an error while sending the body.
13096 MockWrite data_writes[] = {
13097 MockWrite("POST / HTTP/1.1\r\n"
13098 "Host: www.foo.com\r\n"
13099 "Connection: keep-alive\r\n"
13100 "Content-Length: 3\r\n\r\n"),
13101 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13104 MockRead data_reads[] = {
13105 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13106 MockRead("HTTP/1.0 302 Redirect\r\n"),
13107 MockRead("Location: http://somewhere-else.com/\r\n"),
13108 MockRead("Content-Length: 0\r\n\r\n"),
13109 MockRead(SYNCHRONOUS, OK),
13111 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13112 arraysize(data_writes));
13113 session_deps_.socket_factory->AddSocketDataProvider(&data);
13115 TestCompletionCallback callback;
13117 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13118 EXPECT_EQ(ERR_IO_PENDING, rv);
13120 rv = callback.WaitForResult();
13121 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13123 const HttpResponseInfo* response = trans->GetResponseInfo();
13124 EXPECT_TRUE(response == NULL);
13127 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
13128 ScopedVector<UploadElementReader> element_readers;
13129 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13130 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13132 HttpRequestInfo request;
13133 request.method = "POST";
13134 request.url = GURL("http://www.foo.com/");
13135 request.upload_data_stream = &upload_data_stream;
13136 request.load_flags = 0;
13138 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13139 scoped_ptr<HttpTransaction> trans(
13140 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13141 // Send headers successfully, but get an error while sending the body.
13142 MockWrite data_writes[] = {
13143 MockWrite("POST / HTTP/1.1\r\n"
13144 "Host: www.foo.com\r\n"
13145 "Connection: keep-alive\r\n"
13146 "Content-Length: 3\r\n\r\n"),
13147 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13150 MockRead data_reads[] = {
13151 MockRead("HTTP 0.9 rocks!"),
13152 MockRead(SYNCHRONOUS, OK),
13154 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13155 arraysize(data_writes));
13156 session_deps_.socket_factory->AddSocketDataProvider(&data);
13158 TestCompletionCallback callback;
13160 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13161 EXPECT_EQ(ERR_IO_PENDING, rv);
13163 rv = callback.WaitForResult();
13164 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13166 const HttpResponseInfo* response = trans->GetResponseInfo();
13167 EXPECT_TRUE(response == NULL);
13170 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
13171 ScopedVector<UploadElementReader> element_readers;
13172 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13173 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13175 HttpRequestInfo request;
13176 request.method = "POST";
13177 request.url = GURL("http://www.foo.com/");
13178 request.upload_data_stream = &upload_data_stream;
13179 request.load_flags = 0;
13181 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13182 scoped_ptr<HttpTransaction> trans(
13183 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13184 // Send headers successfully, but get an error while sending the body.
13185 MockWrite data_writes[] = {
13186 MockWrite("POST / HTTP/1.1\r\n"
13187 "Host: www.foo.com\r\n"
13188 "Connection: keep-alive\r\n"
13189 "Content-Length: 3\r\n\r\n"),
13190 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13193 MockRead data_reads[] = {
13194 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13195 MockRead(SYNCHRONOUS, OK),
13197 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13198 arraysize(data_writes));
13199 session_deps_.socket_factory->AddSocketDataProvider(&data);
13201 TestCompletionCallback callback;
13203 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13204 EXPECT_EQ(ERR_IO_PENDING, rv);
13206 rv = callback.WaitForResult();
13207 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13209 const HttpResponseInfo* response = trans->GetResponseInfo();
13210 EXPECT_TRUE(response == NULL);
13213 } // namespace net