Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blob6a3efdd2c71fae66aa33e9ef6210f96890347611
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.get()));
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 false,
589 NULL) {
592 //-----------------------------------------------------------------------------
594 // Helper functions for validating that AuthChallengeInfo's are correctly
595 // configured for common cases.
596 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
597 if (!auth_challenge)
598 return false;
599 EXPECT_FALSE(auth_challenge->is_proxy);
600 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
601 EXPECT_EQ("MyRealm1", auth_challenge->realm);
602 EXPECT_EQ("basic", auth_challenge->scheme);
603 return true;
606 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
607 if (!auth_challenge)
608 return false;
609 EXPECT_TRUE(auth_challenge->is_proxy);
610 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
611 EXPECT_EQ("MyRealm1", auth_challenge->realm);
612 EXPECT_EQ("basic", auth_challenge->scheme);
613 return true;
616 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
617 if (!auth_challenge)
618 return false;
619 EXPECT_FALSE(auth_challenge->is_proxy);
620 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
621 EXPECT_EQ("digestive", auth_challenge->realm);
622 EXPECT_EQ("digest", auth_challenge->scheme);
623 return true;
626 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
627 if (!auth_challenge)
628 return false;
629 EXPECT_FALSE(auth_challenge->is_proxy);
630 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
631 EXPECT_EQ(std::string(), auth_challenge->realm);
632 EXPECT_EQ("ntlm", auth_challenge->scheme);
633 return true;
636 } // namespace
638 TEST_P(HttpNetworkTransactionTest, Basic) {
639 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
640 scoped_ptr<HttpTransaction> trans(
641 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
644 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
645 MockRead data_reads[] = {
646 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
647 MockRead("hello world"),
648 MockRead(SYNCHRONOUS, OK),
650 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
651 arraysize(data_reads));
652 EXPECT_EQ(OK, out.rv);
653 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
654 EXPECT_EQ("hello world", out.response_data);
655 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
656 EXPECT_EQ(reads_size, out.totalReceivedBytes);
659 // Response with no status line.
660 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
661 MockRead data_reads[] = {
662 MockRead("hello world"),
663 MockRead(SYNCHRONOUS, OK),
665 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
666 arraysize(data_reads));
667 EXPECT_EQ(OK, out.rv);
668 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
669 EXPECT_EQ("hello world", out.response_data);
670 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
671 EXPECT_EQ(reads_size, out.totalReceivedBytes);
674 // Allow up to 4 bytes of junk to precede status line.
675 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
676 MockRead data_reads[] = {
677 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
678 MockRead(SYNCHRONOUS, OK),
680 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
681 arraysize(data_reads));
682 EXPECT_EQ(OK, out.rv);
683 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
684 EXPECT_EQ("DATA", out.response_data);
685 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
686 EXPECT_EQ(reads_size, out.totalReceivedBytes);
689 // Allow up to 4 bytes of junk to precede status line.
690 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
691 MockRead data_reads[] = {
692 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
693 MockRead(SYNCHRONOUS, OK),
695 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
696 arraysize(data_reads));
697 EXPECT_EQ(OK, out.rv);
698 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
699 EXPECT_EQ("DATA", out.response_data);
700 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
701 EXPECT_EQ(reads_size, out.totalReceivedBytes);
704 // Beyond 4 bytes of slop and it should fail to find a status line.
705 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
706 MockRead data_reads[] = {
707 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
708 MockRead(SYNCHRONOUS, OK),
710 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
711 arraysize(data_reads));
712 EXPECT_EQ(OK, out.rv);
713 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
714 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
715 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
716 EXPECT_EQ(reads_size, out.totalReceivedBytes);
719 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
720 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
721 MockRead data_reads[] = {
722 MockRead("\n"),
723 MockRead("\n"),
724 MockRead("Q"),
725 MockRead("J"),
726 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
727 MockRead(SYNCHRONOUS, OK),
729 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
730 arraysize(data_reads));
731 EXPECT_EQ(OK, out.rv);
732 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
733 EXPECT_EQ("DATA", out.response_data);
734 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
735 EXPECT_EQ(reads_size, out.totalReceivedBytes);
738 // Close the connection before enough bytes to have a status line.
739 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
740 MockRead data_reads[] = {
741 MockRead("HTT"),
742 MockRead(SYNCHRONOUS, OK),
744 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
745 arraysize(data_reads));
746 EXPECT_EQ(OK, out.rv);
747 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
748 EXPECT_EQ("HTT", out.response_data);
749 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
750 EXPECT_EQ(reads_size, out.totalReceivedBytes);
753 // Simulate a 204 response, lacking a Content-Length header, sent over a
754 // persistent connection. The response should still terminate since a 204
755 // cannot have a response body.
756 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
757 char junk[] = "junk";
758 MockRead data_reads[] = {
759 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
760 MockRead(junk), // Should not be read!!
761 MockRead(SYNCHRONOUS, OK),
763 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
764 arraysize(data_reads));
765 EXPECT_EQ(OK, out.rv);
766 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
767 EXPECT_EQ("", out.response_data);
768 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
769 int64 response_size = reads_size - strlen(junk);
770 EXPECT_EQ(response_size, out.totalReceivedBytes);
773 // A simple request using chunked encoding with some extra data after.
774 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
775 std::string final_chunk = "0\r\n\r\n";
776 std::string extra_data = "HTTP/1.1 200 OK\r\n";
777 std::string last_read = final_chunk + extra_data;
778 MockRead data_reads[] = {
779 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
780 MockRead("5\r\nHello\r\n"),
781 MockRead("1\r\n"),
782 MockRead(" \r\n"),
783 MockRead("5\r\nworld\r\n"),
784 MockRead(last_read.data()),
785 MockRead(SYNCHRONOUS, OK),
787 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
788 arraysize(data_reads));
789 EXPECT_EQ(OK, out.rv);
790 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
791 EXPECT_EQ("Hello world", out.response_data);
792 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
793 int64 response_size = reads_size - extra_data.size();
794 EXPECT_EQ(response_size, out.totalReceivedBytes);
797 // Next tests deal with http://crbug.com/56344.
799 TEST_P(HttpNetworkTransactionTest,
800 MultipleContentLengthHeadersNoTransferEncoding) {
801 MockRead data_reads[] = {
802 MockRead("HTTP/1.1 200 OK\r\n"),
803 MockRead("Content-Length: 10\r\n"),
804 MockRead("Content-Length: 5\r\n\r\n"),
806 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
807 arraysize(data_reads));
808 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
811 TEST_P(HttpNetworkTransactionTest,
812 DuplicateContentLengthHeadersNoTransferEncoding) {
813 MockRead data_reads[] = {
814 MockRead("HTTP/1.1 200 OK\r\n"),
815 MockRead("Content-Length: 5\r\n"),
816 MockRead("Content-Length: 5\r\n\r\n"),
817 MockRead("Hello"),
819 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
820 arraysize(data_reads));
821 EXPECT_EQ(OK, out.rv);
822 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
823 EXPECT_EQ("Hello", out.response_data);
826 TEST_P(HttpNetworkTransactionTest,
827 ComplexContentLengthHeadersNoTransferEncoding) {
828 // More than 2 dupes.
830 MockRead data_reads[] = {
831 MockRead("HTTP/1.1 200 OK\r\n"),
832 MockRead("Content-Length: 5\r\n"),
833 MockRead("Content-Length: 5\r\n"),
834 MockRead("Content-Length: 5\r\n\r\n"),
835 MockRead("Hello"),
837 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
838 arraysize(data_reads));
839 EXPECT_EQ(OK, out.rv);
840 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
841 EXPECT_EQ("Hello", out.response_data);
843 // HTTP/1.0
845 MockRead data_reads[] = {
846 MockRead("HTTP/1.0 200 OK\r\n"),
847 MockRead("Content-Length: 5\r\n"),
848 MockRead("Content-Length: 5\r\n"),
849 MockRead("Content-Length: 5\r\n\r\n"),
850 MockRead("Hello"),
852 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
853 arraysize(data_reads));
854 EXPECT_EQ(OK, out.rv);
855 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
856 EXPECT_EQ("Hello", out.response_data);
858 // 2 dupes and one mismatched.
860 MockRead data_reads[] = {
861 MockRead("HTTP/1.1 200 OK\r\n"),
862 MockRead("Content-Length: 10\r\n"),
863 MockRead("Content-Length: 10\r\n"),
864 MockRead("Content-Length: 5\r\n\r\n"),
866 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
867 arraysize(data_reads));
868 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
872 TEST_P(HttpNetworkTransactionTest,
873 MultipleContentLengthHeadersTransferEncoding) {
874 MockRead data_reads[] = {
875 MockRead("HTTP/1.1 200 OK\r\n"),
876 MockRead("Content-Length: 666\r\n"),
877 MockRead("Content-Length: 1337\r\n"),
878 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
879 MockRead("5\r\nHello\r\n"),
880 MockRead("1\r\n"),
881 MockRead(" \r\n"),
882 MockRead("5\r\nworld\r\n"),
883 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
884 MockRead(SYNCHRONOUS, OK),
886 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
887 arraysize(data_reads));
888 EXPECT_EQ(OK, out.rv);
889 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
890 EXPECT_EQ("Hello world", out.response_data);
893 // Next tests deal with http://crbug.com/98895.
895 // Checks that a single Content-Disposition header results in no error.
896 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
897 MockRead data_reads[] = {
898 MockRead("HTTP/1.1 200 OK\r\n"),
899 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
900 MockRead("Content-Length: 5\r\n\r\n"),
901 MockRead("Hello"),
903 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
904 arraysize(data_reads));
905 EXPECT_EQ(OK, out.rv);
906 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
907 EXPECT_EQ("Hello", out.response_data);
910 // Checks that two identical Content-Disposition headers result in no error.
911 TEST_P(HttpNetworkTransactionTest,
912 TwoIdenticalContentDispositionHeaders) {
913 MockRead data_reads[] = {
914 MockRead("HTTP/1.1 200 OK\r\n"),
915 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
916 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
917 MockRead("Content-Length: 5\r\n\r\n"),
918 MockRead("Hello"),
920 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
921 arraysize(data_reads));
922 EXPECT_EQ(OK, out.rv);
923 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
924 EXPECT_EQ("Hello", out.response_data);
927 // Checks that two distinct Content-Disposition headers result in an error.
928 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
929 MockRead data_reads[] = {
930 MockRead("HTTP/1.1 200 OK\r\n"),
931 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
932 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
933 MockRead("Content-Length: 5\r\n\r\n"),
934 MockRead("Hello"),
936 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
937 arraysize(data_reads));
938 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
941 // Checks that two identical Location headers result in no error.
942 // Also tests Location header behavior.
943 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
944 MockRead data_reads[] = {
945 MockRead("HTTP/1.1 302 Redirect\r\n"),
946 MockRead("Location: http://good.com/\r\n"),
947 MockRead("Location: http://good.com/\r\n"),
948 MockRead("Content-Length: 0\r\n\r\n"),
949 MockRead(SYNCHRONOUS, OK),
952 HttpRequestInfo request;
953 request.method = "GET";
954 request.url = GURL("http://redirect.com/");
955 request.load_flags = 0;
957 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
958 scoped_ptr<HttpTransaction> trans(
959 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
961 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
962 session_deps_.socket_factory->AddSocketDataProvider(&data);
964 TestCompletionCallback callback;
966 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
967 EXPECT_EQ(ERR_IO_PENDING, rv);
969 EXPECT_EQ(OK, callback.WaitForResult());
971 const HttpResponseInfo* response = trans->GetResponseInfo();
972 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
973 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
974 std::string url;
975 EXPECT_TRUE(response->headers->IsRedirect(&url));
976 EXPECT_EQ("http://good.com/", url);
977 EXPECT_TRUE(response->proxy_server.IsEmpty());
980 // Checks that two distinct Location headers result in an error.
981 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
982 MockRead data_reads[] = {
983 MockRead("HTTP/1.1 302 Redirect\r\n"),
984 MockRead("Location: http://good.com/\r\n"),
985 MockRead("Location: http://evil.com/\r\n"),
986 MockRead("Content-Length: 0\r\n\r\n"),
987 MockRead(SYNCHRONOUS, OK),
989 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
990 arraysize(data_reads));
991 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
994 // Do a request using the HEAD method. Verify that we don't try to read the
995 // message body (since HEAD has none).
996 TEST_P(HttpNetworkTransactionTest, Head) {
997 HttpRequestInfo request;
998 request.method = "HEAD";
999 request.url = GURL("http://www.google.com/");
1000 request.load_flags = 0;
1002 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1003 scoped_ptr<HttpTransaction> trans(
1004 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1005 BeforeProxyHeadersSentHandler proxy_headers_handler;
1006 trans->SetBeforeProxyHeadersSentCallback(
1007 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1008 base::Unretained(&proxy_headers_handler)));
1010 MockWrite data_writes1[] = {
1011 MockWrite("HEAD / HTTP/1.1\r\n"
1012 "Host: www.google.com\r\n"
1013 "Connection: keep-alive\r\n"
1014 "Content-Length: 0\r\n\r\n"),
1016 MockRead data_reads1[] = {
1017 MockRead("HTTP/1.1 404 Not Found\r\n"),
1018 MockRead("Server: Blah\r\n"),
1019 MockRead("Content-Length: 1234\r\n\r\n"),
1021 // No response body because the test stops reading here.
1022 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1025 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1026 data_writes1, arraysize(data_writes1));
1027 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1029 TestCompletionCallback callback1;
1031 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1032 EXPECT_EQ(ERR_IO_PENDING, rv);
1034 rv = callback1.WaitForResult();
1035 EXPECT_EQ(OK, rv);
1037 const HttpResponseInfo* response = trans->GetResponseInfo();
1038 ASSERT_TRUE(response != NULL);
1040 // Check that the headers got parsed.
1041 EXPECT_TRUE(response->headers.get() != NULL);
1042 EXPECT_EQ(1234, response->headers->GetContentLength());
1043 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1044 EXPECT_TRUE(response->proxy_server.IsEmpty());
1045 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1047 std::string server_header;
1048 void* iter = NULL;
1049 bool has_server_header = response->headers->EnumerateHeader(
1050 &iter, "Server", &server_header);
1051 EXPECT_TRUE(has_server_header);
1052 EXPECT_EQ("Blah", server_header);
1054 // Reading should give EOF right away, since there is no message body
1055 // (despite non-zero content-length).
1056 std::string response_data;
1057 rv = ReadTransaction(trans.get(), &response_data);
1058 EXPECT_EQ(OK, rv);
1059 EXPECT_EQ("", response_data);
1062 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1063 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1065 MockRead data_reads[] = {
1066 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1067 MockRead("hello"),
1068 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1069 MockRead("world"),
1070 MockRead(SYNCHRONOUS, OK),
1072 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1073 session_deps_.socket_factory->AddSocketDataProvider(&data);
1075 const char* const kExpectedResponseData[] = {
1076 "hello", "world"
1079 for (int i = 0; i < 2; ++i) {
1080 HttpRequestInfo request;
1081 request.method = "GET";
1082 request.url = GURL("http://www.google.com/");
1083 request.load_flags = 0;
1085 scoped_ptr<HttpTransaction> trans(
1086 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1088 TestCompletionCallback callback;
1090 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1091 EXPECT_EQ(ERR_IO_PENDING, rv);
1093 rv = callback.WaitForResult();
1094 EXPECT_EQ(OK, rv);
1096 const HttpResponseInfo* response = trans->GetResponseInfo();
1097 ASSERT_TRUE(response != NULL);
1099 EXPECT_TRUE(response->headers.get() != NULL);
1100 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1101 EXPECT_TRUE(response->proxy_server.IsEmpty());
1103 std::string response_data;
1104 rv = ReadTransaction(trans.get(), &response_data);
1105 EXPECT_EQ(OK, rv);
1106 EXPECT_EQ(kExpectedResponseData[i], response_data);
1110 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1111 ScopedVector<UploadElementReader> element_readers;
1112 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1113 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1115 HttpRequestInfo request;
1116 request.method = "POST";
1117 request.url = GURL("http://www.foo.com/");
1118 request.upload_data_stream = &upload_data_stream;
1119 request.load_flags = 0;
1121 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1122 scoped_ptr<HttpTransaction> trans(
1123 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1125 MockRead data_reads[] = {
1126 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1127 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1128 MockRead("hello world"),
1129 MockRead(SYNCHRONOUS, OK),
1131 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1132 session_deps_.socket_factory->AddSocketDataProvider(&data);
1134 TestCompletionCallback callback;
1136 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1137 EXPECT_EQ(ERR_IO_PENDING, rv);
1139 rv = callback.WaitForResult();
1140 EXPECT_EQ(OK, rv);
1142 const HttpResponseInfo* response = trans->GetResponseInfo();
1143 ASSERT_TRUE(response != NULL);
1145 EXPECT_TRUE(response->headers.get() != NULL);
1146 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1148 std::string response_data;
1149 rv = ReadTransaction(trans.get(), &response_data);
1150 EXPECT_EQ(OK, rv);
1151 EXPECT_EQ("hello world", response_data);
1154 // This test is almost the same as Ignores100 above, but the response contains
1155 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1156 // HTTP/1.1 and the two status headers are read in one read.
1157 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1158 HttpRequestInfo request;
1159 request.method = "GET";
1160 request.url = GURL("http://www.foo.com/");
1161 request.load_flags = 0;
1163 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1164 scoped_ptr<HttpTransaction> trans(
1165 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1167 MockRead data_reads[] = {
1168 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1169 "HTTP/1.1 200 OK\r\n\r\n"),
1170 MockRead("hello world"),
1171 MockRead(SYNCHRONOUS, OK),
1173 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1174 session_deps_.socket_factory->AddSocketDataProvider(&data);
1176 TestCompletionCallback callback;
1178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1179 EXPECT_EQ(ERR_IO_PENDING, rv);
1181 rv = callback.WaitForResult();
1182 EXPECT_EQ(OK, rv);
1184 const HttpResponseInfo* response = trans->GetResponseInfo();
1185 ASSERT_TRUE(response != NULL);
1187 EXPECT_TRUE(response->headers.get() != NULL);
1188 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1190 std::string response_data;
1191 rv = ReadTransaction(trans.get(), &response_data);
1192 EXPECT_EQ(OK, rv);
1193 EXPECT_EQ("hello world", response_data);
1196 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1197 HttpRequestInfo request;
1198 request.method = "POST";
1199 request.url = GURL("http://www.foo.com/");
1200 request.load_flags = 0;
1202 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1203 scoped_ptr<HttpTransaction> trans(
1204 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1206 MockRead data_reads[] = {
1207 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1208 MockRead(ASYNC, 0),
1210 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1211 session_deps_.socket_factory->AddSocketDataProvider(&data);
1213 TestCompletionCallback callback;
1215 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1216 EXPECT_EQ(ERR_IO_PENDING, rv);
1218 rv = callback.WaitForResult();
1219 EXPECT_EQ(OK, rv);
1221 std::string response_data;
1222 rv = ReadTransaction(trans.get(), &response_data);
1223 EXPECT_EQ(OK, rv);
1224 EXPECT_EQ("", response_data);
1227 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1228 HttpRequestInfo request;
1229 request.method = "POST";
1230 request.url = GURL("http://www.foo.com/");
1231 request.load_flags = 0;
1233 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1234 scoped_ptr<HttpTransaction> trans(
1235 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1237 MockRead data_reads[] = {
1238 MockRead(ASYNC, 0),
1240 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1241 session_deps_.socket_factory->AddSocketDataProvider(&data);
1243 TestCompletionCallback callback;
1245 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1246 EXPECT_EQ(ERR_IO_PENDING, rv);
1248 rv = callback.WaitForResult();
1249 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1252 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1253 const MockWrite* write_failure,
1254 const MockRead* read_failure) {
1255 HttpRequestInfo request;
1256 request.method = "GET";
1257 request.url = GURL("http://www.foo.com/");
1258 request.load_flags = 0;
1260 CapturingNetLog net_log;
1261 session_deps_.net_log = &net_log;
1262 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1264 // Written data for successfully sending both requests.
1265 MockWrite data1_writes[] = {
1266 MockWrite("GET / HTTP/1.1\r\n"
1267 "Host: www.foo.com\r\n"
1268 "Connection: keep-alive\r\n\r\n"),
1269 MockWrite("GET / HTTP/1.1\r\n"
1270 "Host: www.foo.com\r\n"
1271 "Connection: keep-alive\r\n\r\n")
1274 // Read results for the first request.
1275 MockRead data1_reads[] = {
1276 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1277 MockRead("hello"),
1278 MockRead(ASYNC, OK),
1281 if (write_failure) {
1282 ASSERT_FALSE(read_failure);
1283 data1_writes[1] = *write_failure;
1284 } else {
1285 ASSERT_TRUE(read_failure);
1286 data1_reads[2] = *read_failure;
1289 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1290 data1_writes, arraysize(data1_writes));
1291 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1293 MockRead data2_reads[] = {
1294 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1295 MockRead("world"),
1296 MockRead(ASYNC, OK),
1298 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1299 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1301 const char* kExpectedResponseData[] = {
1302 "hello", "world"
1305 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1306 for (int i = 0; i < 2; ++i) {
1307 TestCompletionCallback callback;
1309 scoped_ptr<HttpTransaction> trans(
1310 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1312 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1313 EXPECT_EQ(ERR_IO_PENDING, rv);
1315 rv = callback.WaitForResult();
1316 EXPECT_EQ(OK, rv);
1318 LoadTimingInfo load_timing_info;
1319 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1320 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1321 if (i == 0) {
1322 first_socket_log_id = load_timing_info.socket_log_id;
1323 } else {
1324 // The second request should be using a new socket.
1325 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1328 const HttpResponseInfo* response = trans->GetResponseInfo();
1329 ASSERT_TRUE(response != NULL);
1331 EXPECT_TRUE(response->headers.get() != NULL);
1332 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1334 std::string response_data;
1335 rv = ReadTransaction(trans.get(), &response_data);
1336 EXPECT_EQ(OK, rv);
1337 EXPECT_EQ(kExpectedResponseData[i], response_data);
1341 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1342 const MockWrite* write_failure,
1343 const MockRead* read_failure,
1344 bool use_spdy) {
1345 HttpRequestInfo request;
1346 request.method = "GET";
1347 request.url = GURL("https://www.foo.com/");
1348 request.load_flags = 0;
1350 CapturingNetLog net_log;
1351 session_deps_.net_log = &net_log;
1352 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1354 SSLSocketDataProvider ssl1(ASYNC, OK);
1355 SSLSocketDataProvider ssl2(ASYNC, OK);
1356 if (use_spdy) {
1357 ssl1.SetNextProto(GetParam());
1358 ssl2.SetNextProto(GetParam());
1360 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1361 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1363 // SPDY versions of the request and response.
1364 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1365 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1366 scoped_ptr<SpdyFrame> spdy_response(
1367 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1368 scoped_ptr<SpdyFrame> spdy_data(
1369 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1371 // HTTP/1.1 versions of the request and response.
1372 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1373 "Host: www.foo.com\r\n"
1374 "Connection: keep-alive\r\n\r\n";
1375 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1376 const char kHttpData[] = "hello";
1378 std::vector<MockRead> data1_reads;
1379 std::vector<MockWrite> data1_writes;
1380 if (write_failure) {
1381 ASSERT_FALSE(read_failure);
1382 data1_writes.push_back(*write_failure);
1383 data1_reads.push_back(MockRead(ASYNC, OK));
1384 } else {
1385 ASSERT_TRUE(read_failure);
1386 if (use_spdy) {
1387 data1_writes.push_back(CreateMockWrite(*spdy_request));
1388 } else {
1389 data1_writes.push_back(MockWrite(kHttpRequest));
1391 data1_reads.push_back(*read_failure);
1394 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1395 &data1_writes[0], data1_writes.size());
1396 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1398 std::vector<MockRead> data2_reads;
1399 std::vector<MockWrite> data2_writes;
1401 if (use_spdy) {
1402 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1404 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1405 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1406 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1407 } else {
1408 data2_writes.push_back(
1409 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1411 data2_reads.push_back(
1412 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1413 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1414 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1416 OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
1417 &data2_writes[0], data2_writes.size());
1418 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1420 // Preconnect a socket.
1421 net::SSLConfig ssl_config;
1422 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1423 session->GetNextProtos(&ssl_config.next_protos);
1424 session->http_stream_factory()->PreconnectStreams(
1425 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1426 // Wait for the preconnect to complete.
1427 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1428 base::RunLoop().RunUntilIdle();
1429 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1431 // Make the request.
1432 TestCompletionCallback callback;
1434 scoped_ptr<HttpTransaction> trans(
1435 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1437 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1438 EXPECT_EQ(ERR_IO_PENDING, rv);
1440 rv = callback.WaitForResult();
1441 EXPECT_EQ(OK, rv);
1443 LoadTimingInfo load_timing_info;
1444 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1445 TestLoadTimingNotReused(
1446 load_timing_info,
1447 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1449 const HttpResponseInfo* response = trans->GetResponseInfo();
1450 ASSERT_TRUE(response != NULL);
1452 EXPECT_TRUE(response->headers.get() != NULL);
1453 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1455 std::string response_data;
1456 rv = ReadTransaction(trans.get(), &response_data);
1457 EXPECT_EQ(OK, rv);
1458 EXPECT_EQ(kHttpData, response_data);
1461 TEST_P(HttpNetworkTransactionTest,
1462 KeepAliveConnectionNotConnectedOnWrite) {
1463 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1464 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1467 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1468 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1469 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1472 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1473 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1474 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1477 // Make sure that on a 408 response (Request Timeout), the request is retried,
1478 // if the socket was a reused keep alive socket.
1479 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1480 MockRead read_failure(SYNCHRONOUS,
1481 "HTTP/1.1 408 Request Timeout\r\n"
1482 "Connection: Keep-Alive\r\n"
1483 "Content-Length: 6\r\n\r\n"
1484 "Pickle");
1485 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1488 TEST_P(HttpNetworkTransactionTest,
1489 PreconnectErrorNotConnectedOnWrite) {
1490 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1491 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1494 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1495 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1496 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1499 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1500 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1501 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1504 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1505 MockRead read_failure(ASYNC, OK); // EOF
1506 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1509 // Make sure that on a 408 response (Request Timeout), the request is retried,
1510 // if the socket was a preconnected (UNUSED_IDLE) socket.
1511 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1512 MockRead read_failure(SYNCHRONOUS,
1513 "HTTP/1.1 408 Request Timeout\r\n"
1514 "Connection: Keep-Alive\r\n"
1515 "Content-Length: 6\r\n\r\n"
1516 "Pickle");
1517 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1518 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1521 TEST_P(HttpNetworkTransactionTest,
1522 SpdyPreconnectErrorNotConnectedOnWrite) {
1523 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1524 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1527 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1528 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1529 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1532 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1533 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1534 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1537 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1538 MockRead read_failure(ASYNC, OK); // EOF
1539 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1542 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1543 HttpRequestInfo request;
1544 request.method = "GET";
1545 request.url = GURL("http://www.google.com/");
1546 request.load_flags = 0;
1548 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1549 scoped_ptr<HttpTransaction> trans(
1550 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1552 MockRead data_reads[] = {
1553 MockRead(ASYNC, ERR_CONNECTION_RESET),
1554 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1555 MockRead("hello world"),
1556 MockRead(SYNCHRONOUS, OK),
1558 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1559 session_deps_.socket_factory->AddSocketDataProvider(&data);
1561 TestCompletionCallback callback;
1563 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1564 EXPECT_EQ(ERR_IO_PENDING, rv);
1566 rv = callback.WaitForResult();
1567 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1569 const HttpResponseInfo* response = trans->GetResponseInfo();
1570 EXPECT_TRUE(response == NULL);
1573 // What do various browsers do when the server closes a non-keepalive
1574 // connection without sending any response header or body?
1576 // IE7: error page
1577 // Safari 3.1.2 (Windows): error page
1578 // Firefox 3.0.1: blank page
1579 // Opera 9.52: after five attempts, blank page
1580 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1581 // Us: error page (EMPTY_RESPONSE)
1582 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1583 MockRead data_reads[] = {
1584 MockRead(SYNCHRONOUS, OK), // EOF
1585 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1586 MockRead("hello world"),
1587 MockRead(SYNCHRONOUS, OK),
1589 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1590 arraysize(data_reads));
1591 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1594 // Test that network access can be deferred and resumed.
1595 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1596 HttpRequestInfo request;
1597 request.method = "GET";
1598 request.url = GURL("http://www.google.com/");
1599 request.load_flags = 0;
1601 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1602 scoped_ptr<HttpTransaction> trans(
1603 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1605 // Defer on OnBeforeNetworkStart.
1606 BeforeNetworkStartHandler net_start_handler(true); // defer
1607 trans->SetBeforeNetworkStartCallback(
1608 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1609 base::Unretained(&net_start_handler)));
1611 MockRead data_reads[] = {
1612 MockRead("HTTP/1.0 200 OK\r\n"),
1613 MockRead("Content-Length: 5\r\n\r\n"),
1614 MockRead("hello"),
1615 MockRead(SYNCHRONOUS, 0),
1617 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1618 session_deps_.socket_factory->AddSocketDataProvider(&data);
1620 TestCompletionCallback callback;
1622 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1623 EXPECT_EQ(ERR_IO_PENDING, rv);
1624 base::MessageLoop::current()->RunUntilIdle();
1626 // Should have deferred for network start.
1627 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1628 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1629 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1631 trans->ResumeNetworkStart();
1632 rv = callback.WaitForResult();
1633 EXPECT_EQ(OK, rv);
1634 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1636 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1637 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1638 if (rv == ERR_IO_PENDING)
1639 rv = callback.WaitForResult();
1640 EXPECT_EQ(5, rv);
1641 trans.reset();
1644 // Test that network use can be deferred and canceled.
1645 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1646 HttpRequestInfo request;
1647 request.method = "GET";
1648 request.url = GURL("http://www.google.com/");
1649 request.load_flags = 0;
1651 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1652 scoped_ptr<HttpTransaction> trans(
1653 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1655 // Defer on OnBeforeNetworkStart.
1656 BeforeNetworkStartHandler net_start_handler(true); // defer
1657 trans->SetBeforeNetworkStartCallback(
1658 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1659 base::Unretained(&net_start_handler)));
1661 TestCompletionCallback callback;
1663 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1664 EXPECT_EQ(ERR_IO_PENDING, rv);
1665 base::MessageLoop::current()->RunUntilIdle();
1667 // Should have deferred for network start.
1668 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1669 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1670 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1673 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1674 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1675 // destructor in such situations.
1676 // See http://crbug.com/154712 and http://crbug.com/156609.
1677 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1678 HttpRequestInfo request;
1679 request.method = "GET";
1680 request.url = GURL("http://www.google.com/");
1681 request.load_flags = 0;
1683 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1684 scoped_ptr<HttpTransaction> trans(
1685 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1687 MockRead data_reads[] = {
1688 MockRead("HTTP/1.0 200 OK\r\n"),
1689 MockRead("Connection: keep-alive\r\n"),
1690 MockRead("Content-Length: 100\r\n\r\n"),
1691 MockRead("hello"),
1692 MockRead(SYNCHRONOUS, 0),
1694 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1695 session_deps_.socket_factory->AddSocketDataProvider(&data);
1697 TestCompletionCallback callback;
1699 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1700 EXPECT_EQ(ERR_IO_PENDING, rv);
1702 rv = callback.WaitForResult();
1703 EXPECT_EQ(OK, rv);
1705 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1706 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1707 if (rv == ERR_IO_PENDING)
1708 rv = callback.WaitForResult();
1709 EXPECT_EQ(5, rv);
1710 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1711 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1713 trans.reset();
1714 base::MessageLoop::current()->RunUntilIdle();
1715 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1718 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1719 HttpRequestInfo request;
1720 request.method = "GET";
1721 request.url = GURL("http://www.google.com/");
1722 request.load_flags = 0;
1724 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1725 scoped_ptr<HttpTransaction> trans(
1726 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1728 MockRead data_reads[] = {
1729 MockRead("HTTP/1.0 200 OK\r\n"),
1730 MockRead("Connection: keep-alive\r\n"),
1731 MockRead("Content-Length: 100\r\n\r\n"),
1732 MockRead(SYNCHRONOUS, 0),
1734 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1735 session_deps_.socket_factory->AddSocketDataProvider(&data);
1737 TestCompletionCallback callback;
1739 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1740 EXPECT_EQ(ERR_IO_PENDING, rv);
1742 rv = callback.WaitForResult();
1743 EXPECT_EQ(OK, rv);
1745 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1746 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1747 if (rv == ERR_IO_PENDING)
1748 rv = callback.WaitForResult();
1749 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1751 trans.reset();
1752 base::MessageLoop::current()->RunUntilIdle();
1753 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1756 // Test that we correctly reuse a keep-alive connection after not explicitly
1757 // reading the body.
1758 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1759 HttpRequestInfo request;
1760 request.method = "GET";
1761 request.url = GURL("http://www.foo.com/");
1762 request.load_flags = 0;
1764 CapturingNetLog net_log;
1765 session_deps_.net_log = &net_log;
1766 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1768 // Note that because all these reads happen in the same
1769 // StaticSocketDataProvider, it shows that the same socket is being reused for
1770 // all transactions.
1771 MockRead data1_reads[] = {
1772 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1773 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1774 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1775 MockRead("HTTP/1.1 302 Found\r\n"
1776 "Content-Length: 0\r\n\r\n"),
1777 MockRead("HTTP/1.1 302 Found\r\n"
1778 "Content-Length: 5\r\n\r\n"
1779 "hello"),
1780 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1781 "Content-Length: 0\r\n\r\n"),
1782 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1783 "Content-Length: 5\r\n\r\n"
1784 "hello"),
1785 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1786 MockRead("hello"),
1788 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1789 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1791 MockRead data2_reads[] = {
1792 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1794 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1795 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1797 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1798 std::string response_lines[kNumUnreadBodies];
1800 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1801 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1802 TestCompletionCallback callback;
1804 scoped_ptr<HttpTransaction> trans(
1805 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1807 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1808 EXPECT_EQ(ERR_IO_PENDING, rv);
1810 rv = callback.WaitForResult();
1811 EXPECT_EQ(OK, rv);
1813 LoadTimingInfo load_timing_info;
1814 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1815 if (i == 0) {
1816 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1817 first_socket_log_id = load_timing_info.socket_log_id;
1818 } else {
1819 TestLoadTimingReused(load_timing_info);
1820 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1823 const HttpResponseInfo* response = trans->GetResponseInfo();
1824 ASSERT_TRUE(response != NULL);
1826 ASSERT_TRUE(response->headers.get() != NULL);
1827 response_lines[i] = response->headers->GetStatusLine();
1829 // We intentionally don't read the response bodies.
1832 const char* const kStatusLines[] = {
1833 "HTTP/1.1 204 No Content",
1834 "HTTP/1.1 205 Reset Content",
1835 "HTTP/1.1 304 Not Modified",
1836 "HTTP/1.1 302 Found",
1837 "HTTP/1.1 302 Found",
1838 "HTTP/1.1 301 Moved Permanently",
1839 "HTTP/1.1 301 Moved Permanently",
1842 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1843 forgot_to_update_kStatusLines);
1845 for (int i = 0; i < kNumUnreadBodies; ++i)
1846 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1848 TestCompletionCallback callback;
1849 scoped_ptr<HttpTransaction> trans(
1850 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1851 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1852 EXPECT_EQ(ERR_IO_PENDING, rv);
1853 rv = callback.WaitForResult();
1854 EXPECT_EQ(OK, rv);
1855 const HttpResponseInfo* response = trans->GetResponseInfo();
1856 ASSERT_TRUE(response != NULL);
1857 ASSERT_TRUE(response->headers.get() != NULL);
1858 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1859 std::string response_data;
1860 rv = ReadTransaction(trans.get(), &response_data);
1861 EXPECT_EQ(OK, rv);
1862 EXPECT_EQ("hello", response_data);
1865 // Test the request-challenge-retry sequence for basic auth.
1866 // (basic auth is the easiest to mock, because it has no randomness).
1867 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1868 HttpRequestInfo request;
1869 request.method = "GET";
1870 request.url = GURL("http://www.google.com/");
1871 request.load_flags = 0;
1873 CapturingNetLog log;
1874 session_deps_.net_log = &log;
1875 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1876 scoped_ptr<HttpTransaction> trans(
1877 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1879 MockWrite data_writes1[] = {
1880 MockWrite("GET / HTTP/1.1\r\n"
1881 "Host: www.google.com\r\n"
1882 "Connection: keep-alive\r\n\r\n"),
1885 MockRead data_reads1[] = {
1886 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1887 // Give a couple authenticate options (only the middle one is actually
1888 // supported).
1889 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1890 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1891 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1892 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1893 // Large content-length -- won't matter, as connection will be reset.
1894 MockRead("Content-Length: 10000\r\n\r\n"),
1895 MockRead(SYNCHRONOUS, ERR_FAILED),
1898 // After calling trans->RestartWithAuth(), this is the request we should
1899 // be issuing -- the final header line contains the credentials.
1900 MockWrite data_writes2[] = {
1901 MockWrite("GET / HTTP/1.1\r\n"
1902 "Host: www.google.com\r\n"
1903 "Connection: keep-alive\r\n"
1904 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1907 // Lastly, the server responds with the actual content.
1908 MockRead data_reads2[] = {
1909 MockRead("HTTP/1.0 200 OK\r\n"),
1910 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1911 MockRead("Content-Length: 100\r\n\r\n"),
1912 MockRead(SYNCHRONOUS, OK),
1915 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1916 data_writes1, arraysize(data_writes1));
1917 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1918 data_writes2, arraysize(data_writes2));
1919 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1920 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1922 TestCompletionCallback callback1;
1924 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1925 EXPECT_EQ(ERR_IO_PENDING, rv);
1927 rv = callback1.WaitForResult();
1928 EXPECT_EQ(OK, rv);
1930 LoadTimingInfo load_timing_info1;
1931 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1932 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1934 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1935 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1937 const HttpResponseInfo* response = trans->GetResponseInfo();
1938 ASSERT_TRUE(response != NULL);
1939 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1941 TestCompletionCallback callback2;
1943 rv = trans->RestartWithAuth(
1944 AuthCredentials(kFoo, kBar), callback2.callback());
1945 EXPECT_EQ(ERR_IO_PENDING, rv);
1947 rv = callback2.WaitForResult();
1948 EXPECT_EQ(OK, rv);
1950 LoadTimingInfo load_timing_info2;
1951 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1952 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1953 // The load timing after restart should have a new socket ID, and times after
1954 // those of the first load timing.
1955 EXPECT_LE(load_timing_info1.receive_headers_end,
1956 load_timing_info2.connect_timing.connect_start);
1957 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1959 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1960 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1962 response = trans->GetResponseInfo();
1963 ASSERT_TRUE(response != NULL);
1964 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1965 EXPECT_EQ(100, response->headers->GetContentLength());
1968 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1969 HttpRequestInfo request;
1970 request.method = "GET";
1971 request.url = GURL("http://www.google.com/");
1972 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1975 scoped_ptr<HttpTransaction> trans(
1976 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1978 MockWrite data_writes[] = {
1979 MockWrite("GET / HTTP/1.1\r\n"
1980 "Host: www.google.com\r\n"
1981 "Connection: keep-alive\r\n\r\n"),
1984 MockRead data_reads[] = {
1985 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1986 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1987 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1988 // Large content-length -- won't matter, as connection will be reset.
1989 MockRead("Content-Length: 10000\r\n\r\n"),
1990 MockRead(SYNCHRONOUS, ERR_FAILED),
1993 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1994 data_writes, arraysize(data_writes));
1995 session_deps_.socket_factory->AddSocketDataProvider(&data);
1996 TestCompletionCallback callback;
1998 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1999 EXPECT_EQ(ERR_IO_PENDING, rv);
2001 rv = callback.WaitForResult();
2002 EXPECT_EQ(0, rv);
2004 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2005 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2007 const HttpResponseInfo* response = trans->GetResponseInfo();
2008 ASSERT_TRUE(response != NULL);
2009 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2012 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2013 // connection.
2014 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2015 HttpRequestInfo request;
2016 request.method = "GET";
2017 request.url = GURL("http://www.google.com/");
2018 request.load_flags = 0;
2020 CapturingNetLog log;
2021 session_deps_.net_log = &log;
2022 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2024 MockWrite data_writes1[] = {
2025 MockWrite("GET / HTTP/1.1\r\n"
2026 "Host: www.google.com\r\n"
2027 "Connection: keep-alive\r\n\r\n"),
2029 // After calling trans->RestartWithAuth(), this is the request we should
2030 // be issuing -- the final header line contains the credentials.
2031 MockWrite("GET / HTTP/1.1\r\n"
2032 "Host: www.google.com\r\n"
2033 "Connection: keep-alive\r\n"
2034 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2037 MockRead data_reads1[] = {
2038 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2039 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2040 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2041 MockRead("Content-Length: 14\r\n\r\n"),
2042 MockRead("Unauthorized\r\n"),
2044 // Lastly, the server responds with the actual content.
2045 MockRead("HTTP/1.1 200 OK\r\n"),
2046 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2047 MockRead("Content-Length: 5\r\n\r\n"),
2048 MockRead("Hello"),
2051 // If there is a regression where we disconnect a Keep-Alive
2052 // connection during an auth roundtrip, we'll end up reading this.
2053 MockRead data_reads2[] = {
2054 MockRead(SYNCHRONOUS, ERR_FAILED),
2057 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2058 data_writes1, arraysize(data_writes1));
2059 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2060 NULL, 0);
2061 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2062 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2064 TestCompletionCallback callback1;
2066 scoped_ptr<HttpTransaction> trans(
2067 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2068 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2069 EXPECT_EQ(ERR_IO_PENDING, rv);
2071 rv = callback1.WaitForResult();
2072 EXPECT_EQ(OK, rv);
2074 LoadTimingInfo load_timing_info1;
2075 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2076 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2078 const HttpResponseInfo* response = trans->GetResponseInfo();
2079 ASSERT_TRUE(response != NULL);
2080 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2082 TestCompletionCallback callback2;
2084 rv = trans->RestartWithAuth(
2085 AuthCredentials(kFoo, kBar), callback2.callback());
2086 EXPECT_EQ(ERR_IO_PENDING, rv);
2088 rv = callback2.WaitForResult();
2089 EXPECT_EQ(OK, rv);
2091 LoadTimingInfo load_timing_info2;
2092 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2093 TestLoadTimingReused(load_timing_info2);
2094 // The load timing after restart should have the same socket ID, and times
2095 // those of the first load timing.
2096 EXPECT_LE(load_timing_info1.receive_headers_end,
2097 load_timing_info2.send_start);
2098 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2100 response = trans->GetResponseInfo();
2101 ASSERT_TRUE(response != NULL);
2102 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2103 EXPECT_EQ(5, response->headers->GetContentLength());
2105 std::string response_data;
2106 rv = ReadTransaction(trans.get(), &response_data);
2107 EXPECT_EQ(OK, rv);
2108 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2109 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2112 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2113 // connection and with no response body to drain.
2114 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2115 HttpRequestInfo request;
2116 request.method = "GET";
2117 request.url = GURL("http://www.google.com/");
2118 request.load_flags = 0;
2120 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2122 MockWrite data_writes1[] = {
2123 MockWrite("GET / HTTP/1.1\r\n"
2124 "Host: www.google.com\r\n"
2125 "Connection: keep-alive\r\n\r\n"),
2127 // After calling trans->RestartWithAuth(), this is the request we should
2128 // be issuing -- the final header line contains the credentials.
2129 MockWrite("GET / HTTP/1.1\r\n"
2130 "Host: www.google.com\r\n"
2131 "Connection: keep-alive\r\n"
2132 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2135 MockRead data_reads1[] = {
2136 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2137 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2138 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2140 // Lastly, the server responds with the actual content.
2141 MockRead("HTTP/1.1 200 OK\r\n"),
2142 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2143 MockRead("Content-Length: 5\r\n\r\n"),
2144 MockRead("hello"),
2147 // An incorrect reconnect would cause this to be read.
2148 MockRead data_reads2[] = {
2149 MockRead(SYNCHRONOUS, ERR_FAILED),
2152 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2153 data_writes1, arraysize(data_writes1));
2154 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2155 NULL, 0);
2156 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2157 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2159 TestCompletionCallback callback1;
2161 scoped_ptr<HttpTransaction> trans(
2162 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2163 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2164 EXPECT_EQ(ERR_IO_PENDING, rv);
2166 rv = callback1.WaitForResult();
2167 EXPECT_EQ(OK, rv);
2169 const HttpResponseInfo* response = trans->GetResponseInfo();
2170 ASSERT_TRUE(response != NULL);
2171 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2173 TestCompletionCallback callback2;
2175 rv = trans->RestartWithAuth(
2176 AuthCredentials(kFoo, kBar), callback2.callback());
2177 EXPECT_EQ(ERR_IO_PENDING, rv);
2179 rv = callback2.WaitForResult();
2180 EXPECT_EQ(OK, rv);
2182 response = trans->GetResponseInfo();
2183 ASSERT_TRUE(response != NULL);
2184 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2185 EXPECT_EQ(5, response->headers->GetContentLength());
2188 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2189 // connection and with a large response body to drain.
2190 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2191 HttpRequestInfo request;
2192 request.method = "GET";
2193 request.url = GURL("http://www.google.com/");
2194 request.load_flags = 0;
2196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2198 MockWrite data_writes1[] = {
2199 MockWrite("GET / HTTP/1.1\r\n"
2200 "Host: www.google.com\r\n"
2201 "Connection: keep-alive\r\n\r\n"),
2203 // After calling trans->RestartWithAuth(), this is the request we should
2204 // be issuing -- the final header line contains the credentials.
2205 MockWrite("GET / HTTP/1.1\r\n"
2206 "Host: www.google.com\r\n"
2207 "Connection: keep-alive\r\n"
2208 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2211 // Respond with 5 kb of response body.
2212 std::string large_body_string("Unauthorized");
2213 large_body_string.append(5 * 1024, ' ');
2214 large_body_string.append("\r\n");
2216 MockRead data_reads1[] = {
2217 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2218 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2219 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2220 // 5134 = 12 + 5 * 1024 + 2
2221 MockRead("Content-Length: 5134\r\n\r\n"),
2222 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2224 // Lastly, the server responds with the actual content.
2225 MockRead("HTTP/1.1 200 OK\r\n"),
2226 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2227 MockRead("Content-Length: 5\r\n\r\n"),
2228 MockRead("hello"),
2231 // An incorrect reconnect would cause this to be read.
2232 MockRead data_reads2[] = {
2233 MockRead(SYNCHRONOUS, ERR_FAILED),
2236 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2237 data_writes1, arraysize(data_writes1));
2238 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2239 NULL, 0);
2240 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2241 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2243 TestCompletionCallback callback1;
2245 scoped_ptr<HttpTransaction> trans(
2246 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2247 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2248 EXPECT_EQ(ERR_IO_PENDING, rv);
2250 rv = callback1.WaitForResult();
2251 EXPECT_EQ(OK, rv);
2253 const HttpResponseInfo* response = trans->GetResponseInfo();
2254 ASSERT_TRUE(response != NULL);
2255 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2257 TestCompletionCallback callback2;
2259 rv = trans->RestartWithAuth(
2260 AuthCredentials(kFoo, kBar), callback2.callback());
2261 EXPECT_EQ(ERR_IO_PENDING, rv);
2263 rv = callback2.WaitForResult();
2264 EXPECT_EQ(OK, rv);
2266 response = trans->GetResponseInfo();
2267 ASSERT_TRUE(response != NULL);
2268 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2269 EXPECT_EQ(5, response->headers->GetContentLength());
2272 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2273 // connection, but the server gets impatient and closes the connection.
2274 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2275 HttpRequestInfo request;
2276 request.method = "GET";
2277 request.url = GURL("http://www.google.com/");
2278 request.load_flags = 0;
2280 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2282 MockWrite data_writes1[] = {
2283 MockWrite("GET / HTTP/1.1\r\n"
2284 "Host: www.google.com\r\n"
2285 "Connection: keep-alive\r\n\r\n"),
2286 // This simulates the seemingly successful write to a closed connection
2287 // if the bug is not fixed.
2288 MockWrite("GET / HTTP/1.1\r\n"
2289 "Host: www.google.com\r\n"
2290 "Connection: keep-alive\r\n"
2291 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2294 MockRead data_reads1[] = {
2295 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2296 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2297 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2298 MockRead("Content-Length: 14\r\n\r\n"),
2299 // Tell MockTCPClientSocket to simulate the server closing the connection.
2300 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2301 MockRead("Unauthorized\r\n"),
2302 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2305 // After calling trans->RestartWithAuth(), this is the request we should
2306 // be issuing -- the final header line contains the credentials.
2307 MockWrite data_writes2[] = {
2308 MockWrite("GET / HTTP/1.1\r\n"
2309 "Host: www.google.com\r\n"
2310 "Connection: keep-alive\r\n"
2311 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2314 // Lastly, the server responds with the actual content.
2315 MockRead data_reads2[] = {
2316 MockRead("HTTP/1.1 200 OK\r\n"),
2317 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2318 MockRead("Content-Length: 5\r\n\r\n"),
2319 MockRead("hello"),
2322 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2323 data_writes1, arraysize(data_writes1));
2324 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2325 data_writes2, arraysize(data_writes2));
2326 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2327 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2329 TestCompletionCallback callback1;
2331 scoped_ptr<HttpTransaction> trans(
2332 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2333 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2334 EXPECT_EQ(ERR_IO_PENDING, rv);
2336 rv = callback1.WaitForResult();
2337 EXPECT_EQ(OK, rv);
2339 const HttpResponseInfo* response = trans->GetResponseInfo();
2340 ASSERT_TRUE(response != NULL);
2341 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2343 TestCompletionCallback callback2;
2345 rv = trans->RestartWithAuth(
2346 AuthCredentials(kFoo, kBar), callback2.callback());
2347 EXPECT_EQ(ERR_IO_PENDING, rv);
2349 rv = callback2.WaitForResult();
2350 EXPECT_EQ(OK, rv);
2352 response = trans->GetResponseInfo();
2353 ASSERT_TRUE(response != NULL);
2354 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2355 EXPECT_EQ(5, response->headers->GetContentLength());
2358 // Test the request-challenge-retry sequence for basic auth, over a connection
2359 // that requires a restart when setting up an SSL tunnel.
2360 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
2361 HttpRequestInfo request;
2362 request.method = "GET";
2363 request.url = GURL("https://www.google.com/");
2364 // when the no authentication data flag is set.
2365 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2367 // Configure against proxy server "myproxy:70".
2368 session_deps_.proxy_service.reset(
2369 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2370 CapturingBoundNetLog log;
2371 session_deps_.net_log = log.bound().net_log();
2372 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2374 // Since we have proxy, should try to establish tunnel.
2375 MockWrite data_writes1[] = {
2376 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2377 "Host: www.google.com\r\n"
2378 "Proxy-Connection: keep-alive\r\n\r\n"),
2380 // After calling trans->RestartWithAuth(), this is the request we should
2381 // be issuing -- the final header line contains the credentials.
2382 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2383 "Host: www.google.com\r\n"
2384 "Proxy-Connection: keep-alive\r\n"
2385 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2387 MockWrite("GET / HTTP/1.1\r\n"
2388 "Host: www.google.com\r\n"
2389 "Connection: keep-alive\r\n\r\n"),
2392 // The proxy responds to the connect with a 407, using a persistent
2393 // connection.
2394 MockRead data_reads1[] = {
2395 // No credentials.
2396 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2397 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2398 MockRead("Proxy-Connection: close\r\n\r\n"),
2400 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2402 MockRead("HTTP/1.1 200 OK\r\n"),
2403 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2404 MockRead("Content-Length: 5\r\n\r\n"),
2405 MockRead(SYNCHRONOUS, "hello"),
2408 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2409 data_writes1, arraysize(data_writes1));
2410 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2411 SSLSocketDataProvider ssl(ASYNC, OK);
2412 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2414 TestCompletionCallback callback1;
2416 scoped_ptr<HttpTransaction> trans(
2417 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2419 int rv = trans->Start(&request, callback1.callback(), log.bound());
2420 EXPECT_EQ(ERR_IO_PENDING, rv);
2422 rv = callback1.WaitForResult();
2423 EXPECT_EQ(OK, rv);
2424 net::CapturingNetLog::CapturedEntryList entries;
2425 log.GetEntries(&entries);
2426 size_t pos = ExpectLogContainsSomewhere(
2427 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2428 NetLog::PHASE_NONE);
2429 ExpectLogContainsSomewhere(
2430 entries, pos,
2431 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2432 NetLog::PHASE_NONE);
2434 const HttpResponseInfo* response = trans->GetResponseInfo();
2435 ASSERT_TRUE(response != NULL);
2436 ASSERT_FALSE(response->headers.get() == NULL);
2437 EXPECT_EQ(407, response->headers->response_code());
2438 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2439 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2441 LoadTimingInfo load_timing_info;
2442 // CONNECT requests and responses are handled at the connect job level, so
2443 // the transaction does not yet have a connection.
2444 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2446 TestCompletionCallback callback2;
2448 rv = trans->RestartWithAuth(
2449 AuthCredentials(kFoo, kBar), callback2.callback());
2450 EXPECT_EQ(ERR_IO_PENDING, rv);
2452 rv = callback2.WaitForResult();
2453 EXPECT_EQ(OK, rv);
2455 response = trans->GetResponseInfo();
2456 ASSERT_TRUE(response != NULL);
2458 EXPECT_TRUE(response->headers->IsKeepAlive());
2459 EXPECT_EQ(200, response->headers->response_code());
2460 EXPECT_EQ(5, response->headers->GetContentLength());
2461 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2463 // The password prompt info should not be set.
2464 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2466 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2467 TestLoadTimingNotReusedWithPac(load_timing_info,
2468 CONNECT_TIMING_HAS_SSL_TIMES);
2470 trans.reset();
2471 session->CloseAllConnections();
2474 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2475 // proxy connection, when setting up an SSL tunnel.
2476 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2477 HttpRequestInfo request;
2478 request.method = "GET";
2479 request.url = GURL("https://www.google.com/");
2480 // Ensure that proxy authentication is attempted even
2481 // when the no authentication data flag is set.
2482 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2484 // Configure against proxy server "myproxy:70".
2485 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2486 CapturingBoundNetLog log;
2487 session_deps_.net_log = log.bound().net_log();
2488 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2490 scoped_ptr<HttpTransaction> trans(
2491 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2493 // Since we have proxy, should try to establish tunnel.
2494 MockWrite data_writes1[] = {
2495 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2496 "Host: www.google.com\r\n"
2497 "Proxy-Connection: keep-alive\r\n\r\n"),
2499 // After calling trans->RestartWithAuth(), this is the request we should
2500 // be issuing -- the final header line contains the credentials.
2501 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2502 "Host: www.google.com\r\n"
2503 "Proxy-Connection: keep-alive\r\n"
2504 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2507 // The proxy responds to the connect with a 407, using a persistent
2508 // connection.
2509 MockRead data_reads1[] = {
2510 // No credentials.
2511 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2512 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2513 MockRead("Content-Length: 10\r\n\r\n"),
2514 MockRead("0123456789"),
2516 // Wrong credentials (wrong password).
2517 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2518 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2519 MockRead("Content-Length: 10\r\n\r\n"),
2520 // No response body because the test stops reading here.
2521 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2524 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2525 data_writes1, arraysize(data_writes1));
2526 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2528 TestCompletionCallback callback1;
2530 int rv = trans->Start(&request, callback1.callback(), log.bound());
2531 EXPECT_EQ(ERR_IO_PENDING, rv);
2533 rv = callback1.WaitForResult();
2534 EXPECT_EQ(OK, rv);
2535 net::CapturingNetLog::CapturedEntryList entries;
2536 log.GetEntries(&entries);
2537 size_t pos = ExpectLogContainsSomewhere(
2538 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2539 NetLog::PHASE_NONE);
2540 ExpectLogContainsSomewhere(
2541 entries, pos,
2542 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2543 NetLog::PHASE_NONE);
2545 const HttpResponseInfo* response = trans->GetResponseInfo();
2546 ASSERT_TRUE(response != NULL);
2547 ASSERT_FALSE(response->headers.get() == NULL);
2548 EXPECT_TRUE(response->headers->IsKeepAlive());
2549 EXPECT_EQ(407, response->headers->response_code());
2550 EXPECT_EQ(10, response->headers->GetContentLength());
2551 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2552 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2554 TestCompletionCallback callback2;
2556 // Wrong password (should be "bar").
2557 rv = trans->RestartWithAuth(
2558 AuthCredentials(kFoo, kBaz), callback2.callback());
2559 EXPECT_EQ(ERR_IO_PENDING, rv);
2561 rv = callback2.WaitForResult();
2562 EXPECT_EQ(OK, rv);
2564 response = trans->GetResponseInfo();
2565 ASSERT_TRUE(response != NULL);
2566 ASSERT_FALSE(response->headers.get() == NULL);
2567 EXPECT_TRUE(response->headers->IsKeepAlive());
2568 EXPECT_EQ(407, response->headers->response_code());
2569 EXPECT_EQ(10, response->headers->GetContentLength());
2570 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2571 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2573 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2574 // out of scope.
2575 session->CloseAllConnections();
2578 // Test that we don't read the response body when we fail to establish a tunnel,
2579 // even if the user cancels the proxy's auth attempt.
2580 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2581 HttpRequestInfo request;
2582 request.method = "GET";
2583 request.url = GURL("https://www.google.com/");
2584 request.load_flags = 0;
2586 // Configure against proxy server "myproxy:70".
2587 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2589 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2591 scoped_ptr<HttpTransaction> trans(
2592 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2594 // Since we have proxy, should try to establish tunnel.
2595 MockWrite data_writes[] = {
2596 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2597 "Host: www.google.com\r\n"
2598 "Proxy-Connection: keep-alive\r\n\r\n"),
2601 // The proxy responds to the connect with a 407.
2602 MockRead data_reads[] = {
2603 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2604 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2605 MockRead("Content-Length: 10\r\n\r\n"),
2606 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2609 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2610 data_writes, arraysize(data_writes));
2611 session_deps_.socket_factory->AddSocketDataProvider(&data);
2613 TestCompletionCallback callback;
2615 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2616 EXPECT_EQ(ERR_IO_PENDING, rv);
2618 rv = callback.WaitForResult();
2619 EXPECT_EQ(OK, rv);
2621 const HttpResponseInfo* response = trans->GetResponseInfo();
2622 ASSERT_TRUE(response != NULL);
2624 EXPECT_TRUE(response->headers->IsKeepAlive());
2625 EXPECT_EQ(407, response->headers->response_code());
2626 EXPECT_EQ(10, response->headers->GetContentLength());
2627 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2629 std::string response_data;
2630 rv = ReadTransaction(trans.get(), &response_data);
2631 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2633 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2634 session->CloseAllConnections();
2637 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2638 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2639 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2640 HttpRequestInfo request;
2641 request.method = "GET";
2642 request.url = GURL("http://www.google.com/");
2643 request.load_flags = 0;
2645 // We are using a DIRECT connection (i.e. no proxy) for this session.
2646 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2647 scoped_ptr<HttpTransaction> trans(
2648 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2650 MockWrite data_writes1[] = {
2651 MockWrite("GET / HTTP/1.1\r\n"
2652 "Host: www.google.com\r\n"
2653 "Connection: keep-alive\r\n\r\n"),
2656 MockRead data_reads1[] = {
2657 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2658 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2659 // Large content-length -- won't matter, as connection will be reset.
2660 MockRead("Content-Length: 10000\r\n\r\n"),
2661 MockRead(SYNCHRONOUS, ERR_FAILED),
2664 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2665 data_writes1, arraysize(data_writes1));
2666 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2668 TestCompletionCallback callback;
2670 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2671 EXPECT_EQ(ERR_IO_PENDING, rv);
2673 rv = callback.WaitForResult();
2674 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2677 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2678 // through a non-authenticating proxy. The request should fail with
2679 // ERR_UNEXPECTED_PROXY_AUTH.
2680 // Note that it is impossible to detect if an HTTP server returns a 407 through
2681 // a non-authenticating proxy - there is nothing to indicate whether the
2682 // response came from the proxy or the server, so it is treated as if the proxy
2683 // issued the challenge.
2684 TEST_P(HttpNetworkTransactionTest,
2685 HttpsServerRequestsProxyAuthThroughProxy) {
2686 HttpRequestInfo request;
2687 request.method = "GET";
2688 request.url = GURL("https://www.google.com/");
2690 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2691 CapturingBoundNetLog log;
2692 session_deps_.net_log = log.bound().net_log();
2693 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2695 // Since we have proxy, should try to establish tunnel.
2696 MockWrite data_writes1[] = {
2697 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2698 "Host: www.google.com\r\n"
2699 "Proxy-Connection: keep-alive\r\n\r\n"),
2701 MockWrite("GET / HTTP/1.1\r\n"
2702 "Host: www.google.com\r\n"
2703 "Connection: keep-alive\r\n\r\n"),
2706 MockRead data_reads1[] = {
2707 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2709 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2710 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2711 MockRead("\r\n"),
2712 MockRead(SYNCHRONOUS, OK),
2715 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2716 data_writes1, arraysize(data_writes1));
2717 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2718 SSLSocketDataProvider ssl(ASYNC, OK);
2719 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2721 TestCompletionCallback callback1;
2723 scoped_ptr<HttpTransaction> trans(
2724 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2726 int rv = trans->Start(&request, callback1.callback(), log.bound());
2727 EXPECT_EQ(ERR_IO_PENDING, rv);
2729 rv = callback1.WaitForResult();
2730 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2731 net::CapturingNetLog::CapturedEntryList entries;
2732 log.GetEntries(&entries);
2733 size_t pos = ExpectLogContainsSomewhere(
2734 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2735 NetLog::PHASE_NONE);
2736 ExpectLogContainsSomewhere(
2737 entries, pos,
2738 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2739 NetLog::PHASE_NONE);
2742 // Test the load timing for HTTPS requests with an HTTP proxy.
2743 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2744 HttpRequestInfo request1;
2745 request1.method = "GET";
2746 request1.url = GURL("https://www.google.com/1");
2748 HttpRequestInfo request2;
2749 request2.method = "GET";
2750 request2.url = GURL("https://www.google.com/2");
2752 // Configure against proxy server "myproxy:70".
2753 session_deps_.proxy_service.reset(
2754 ProxyService::CreateFixed("PROXY myproxy:70"));
2755 CapturingBoundNetLog log;
2756 session_deps_.net_log = log.bound().net_log();
2757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2759 // Since we have proxy, should try to establish tunnel.
2760 MockWrite data_writes1[] = {
2761 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2762 "Host: www.google.com\r\n"
2763 "Proxy-Connection: keep-alive\r\n\r\n"),
2765 MockWrite("GET /1 HTTP/1.1\r\n"
2766 "Host: www.google.com\r\n"
2767 "Connection: keep-alive\r\n\r\n"),
2769 MockWrite("GET /2 HTTP/1.1\r\n"
2770 "Host: www.google.com\r\n"
2771 "Connection: keep-alive\r\n\r\n"),
2774 // The proxy responds to the connect with a 407, using a persistent
2775 // connection.
2776 MockRead data_reads1[] = {
2777 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2779 MockRead("HTTP/1.1 200 OK\r\n"),
2780 MockRead("Content-Length: 1\r\n\r\n"),
2781 MockRead(SYNCHRONOUS, "1"),
2783 MockRead("HTTP/1.1 200 OK\r\n"),
2784 MockRead("Content-Length: 2\r\n\r\n"),
2785 MockRead(SYNCHRONOUS, "22"),
2788 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2789 data_writes1, arraysize(data_writes1));
2790 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2791 SSLSocketDataProvider ssl(ASYNC, OK);
2792 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2794 TestCompletionCallback callback1;
2795 scoped_ptr<HttpTransaction> trans1(
2796 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2798 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2799 EXPECT_EQ(ERR_IO_PENDING, rv);
2801 rv = callback1.WaitForResult();
2802 EXPECT_EQ(OK, rv);
2804 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2805 ASSERT_TRUE(response1 != NULL);
2806 ASSERT_TRUE(response1->headers.get() != NULL);
2807 EXPECT_EQ(1, response1->headers->GetContentLength());
2809 LoadTimingInfo load_timing_info1;
2810 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2811 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2813 trans1.reset();
2815 TestCompletionCallback callback2;
2816 scoped_ptr<HttpTransaction> trans2(
2817 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2819 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2820 EXPECT_EQ(ERR_IO_PENDING, rv);
2822 rv = callback2.WaitForResult();
2823 EXPECT_EQ(OK, rv);
2825 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2826 ASSERT_TRUE(response2 != NULL);
2827 ASSERT_TRUE(response2->headers.get() != NULL);
2828 EXPECT_EQ(2, response2->headers->GetContentLength());
2830 LoadTimingInfo load_timing_info2;
2831 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2832 TestLoadTimingReused(load_timing_info2);
2834 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2836 trans2.reset();
2837 session->CloseAllConnections();
2840 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2841 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2842 HttpRequestInfo request1;
2843 request1.method = "GET";
2844 request1.url = GURL("https://www.google.com/1");
2846 HttpRequestInfo request2;
2847 request2.method = "GET";
2848 request2.url = GURL("https://www.google.com/2");
2850 // Configure against proxy server "myproxy:70".
2851 session_deps_.proxy_service.reset(
2852 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2853 CapturingBoundNetLog log;
2854 session_deps_.net_log = log.bound().net_log();
2855 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2857 // Since we have proxy, should try to establish tunnel.
2858 MockWrite data_writes1[] = {
2859 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2860 "Host: www.google.com\r\n"
2861 "Proxy-Connection: keep-alive\r\n\r\n"),
2863 MockWrite("GET /1 HTTP/1.1\r\n"
2864 "Host: www.google.com\r\n"
2865 "Connection: keep-alive\r\n\r\n"),
2867 MockWrite("GET /2 HTTP/1.1\r\n"
2868 "Host: www.google.com\r\n"
2869 "Connection: keep-alive\r\n\r\n"),
2872 // The proxy responds to the connect with a 407, using a persistent
2873 // connection.
2874 MockRead data_reads1[] = {
2875 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2877 MockRead("HTTP/1.1 200 OK\r\n"),
2878 MockRead("Content-Length: 1\r\n\r\n"),
2879 MockRead(SYNCHRONOUS, "1"),
2881 MockRead("HTTP/1.1 200 OK\r\n"),
2882 MockRead("Content-Length: 2\r\n\r\n"),
2883 MockRead(SYNCHRONOUS, "22"),
2886 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2887 data_writes1, arraysize(data_writes1));
2888 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2889 SSLSocketDataProvider ssl(ASYNC, OK);
2890 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2892 TestCompletionCallback callback1;
2893 scoped_ptr<HttpTransaction> trans1(
2894 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2896 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2897 EXPECT_EQ(ERR_IO_PENDING, rv);
2899 rv = callback1.WaitForResult();
2900 EXPECT_EQ(OK, rv);
2902 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2903 ASSERT_TRUE(response1 != NULL);
2904 ASSERT_TRUE(response1->headers.get() != NULL);
2905 EXPECT_EQ(1, response1->headers->GetContentLength());
2907 LoadTimingInfo load_timing_info1;
2908 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2909 TestLoadTimingNotReusedWithPac(load_timing_info1,
2910 CONNECT_TIMING_HAS_SSL_TIMES);
2912 trans1.reset();
2914 TestCompletionCallback callback2;
2915 scoped_ptr<HttpTransaction> trans2(
2916 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2918 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2919 EXPECT_EQ(ERR_IO_PENDING, rv);
2921 rv = callback2.WaitForResult();
2922 EXPECT_EQ(OK, rv);
2924 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2925 ASSERT_TRUE(response2 != NULL);
2926 ASSERT_TRUE(response2->headers.get() != NULL);
2927 EXPECT_EQ(2, response2->headers->GetContentLength());
2929 LoadTimingInfo load_timing_info2;
2930 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2931 TestLoadTimingReusedWithPac(load_timing_info2);
2933 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2935 trans2.reset();
2936 session->CloseAllConnections();
2939 // Test a simple get through an HTTPS Proxy.
2940 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2941 HttpRequestInfo request;
2942 request.method = "GET";
2943 request.url = GURL("http://www.google.com/");
2945 // Configure against https proxy server "proxy:70".
2946 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2947 "https://proxy:70"));
2948 CapturingBoundNetLog log;
2949 session_deps_.net_log = log.bound().net_log();
2950 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2952 // Since we have proxy, should use full url
2953 MockWrite data_writes1[] = {
2954 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2955 "Host: www.google.com\r\n"
2956 "Proxy-Connection: keep-alive\r\n\r\n"),
2959 MockRead data_reads1[] = {
2960 MockRead("HTTP/1.1 200 OK\r\n"),
2961 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2962 MockRead("Content-Length: 100\r\n\r\n"),
2963 MockRead(SYNCHRONOUS, OK),
2966 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2967 data_writes1, arraysize(data_writes1));
2968 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2969 SSLSocketDataProvider ssl(ASYNC, OK);
2970 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2972 TestCompletionCallback callback1;
2974 scoped_ptr<HttpTransaction> trans(
2975 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2977 int rv = trans->Start(&request, callback1.callback(), log.bound());
2978 EXPECT_EQ(ERR_IO_PENDING, rv);
2980 rv = callback1.WaitForResult();
2981 EXPECT_EQ(OK, rv);
2983 LoadTimingInfo load_timing_info;
2984 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2985 TestLoadTimingNotReused(load_timing_info,
2986 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2988 const HttpResponseInfo* response = trans->GetResponseInfo();
2989 ASSERT_TRUE(response != NULL);
2991 EXPECT_TRUE(response->headers->IsKeepAlive());
2992 EXPECT_EQ(200, response->headers->response_code());
2993 EXPECT_EQ(100, response->headers->GetContentLength());
2994 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2996 // The password prompt info should not be set.
2997 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3000 // Test a SPDY get through an HTTPS Proxy.
3001 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3002 HttpRequestInfo request;
3003 request.method = "GET";
3004 request.url = GURL("http://www.google.com/");
3005 request.load_flags = 0;
3007 // Configure against https proxy server "proxy:70".
3008 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3009 "https://proxy:70"));
3010 CapturingBoundNetLog log;
3011 session_deps_.net_log = log.bound().net_log();
3012 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3014 // fetch http://www.google.com/ via SPDY
3015 scoped_ptr<SpdyFrame> req(
3016 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3017 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
3019 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3020 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3021 MockRead spdy_reads[] = {
3022 CreateMockRead(*resp),
3023 CreateMockRead(*data),
3024 MockRead(ASYNC, 0, 0),
3027 DelayedSocketData spdy_data(
3028 1, // wait for one write to finish before reading.
3029 spdy_reads, arraysize(spdy_reads),
3030 spdy_writes, arraysize(spdy_writes));
3031 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3033 SSLSocketDataProvider ssl(ASYNC, OK);
3034 ssl.SetNextProto(GetParam());
3035 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3037 TestCompletionCallback callback1;
3039 scoped_ptr<HttpTransaction> trans(
3040 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3042 int rv = trans->Start(&request, callback1.callback(), log.bound());
3043 EXPECT_EQ(ERR_IO_PENDING, rv);
3045 rv = callback1.WaitForResult();
3046 EXPECT_EQ(OK, rv);
3048 LoadTimingInfo load_timing_info;
3049 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3050 TestLoadTimingNotReused(load_timing_info,
3051 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3053 const HttpResponseInfo* response = trans->GetResponseInfo();
3054 ASSERT_TRUE(response != NULL);
3055 ASSERT_TRUE(response->headers.get() != NULL);
3056 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3058 std::string response_data;
3059 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3060 EXPECT_EQ(kUploadData, response_data);
3063 // Verifies that a session which races and wins against the owning transaction
3064 // (completing prior to host resolution), doesn't fail the transaction.
3065 // Regression test for crbug.com/334413.
3066 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3067 HttpRequestInfo request;
3068 request.method = "GET";
3069 request.url = GURL("http://www.google.com/");
3070 request.load_flags = 0;
3072 // Configure SPDY proxy server "proxy:70".
3073 session_deps_.proxy_service.reset(
3074 ProxyService::CreateFixed("https://proxy:70"));
3075 CapturingBoundNetLog log;
3076 session_deps_.net_log = log.bound().net_log();
3077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3079 // Fetch http://www.google.com/ through the SPDY proxy.
3080 scoped_ptr<SpdyFrame> req(
3081 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3082 MockWrite spdy_writes[] = {CreateMockWrite(*req)};
3084 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3085 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3086 MockRead spdy_reads[] = {
3087 CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0),
3090 DelayedSocketData spdy_data(
3091 1, // wait for one write to finish before reading.
3092 spdy_reads,
3093 arraysize(spdy_reads),
3094 spdy_writes,
3095 arraysize(spdy_writes));
3096 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3098 SSLSocketDataProvider ssl(ASYNC, OK);
3099 ssl.SetNextProto(GetParam());
3100 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3102 TestCompletionCallback callback1;
3104 scoped_ptr<HttpTransaction> trans(
3105 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3107 // Stall the hostname resolution begun by the transaction.
3108 session_deps_.host_resolver->set_synchronous_mode(false);
3109 session_deps_.host_resolver->set_ondemand_mode(true);
3111 int rv = trans->Start(&request, callback1.callback(), log.bound());
3112 EXPECT_EQ(ERR_IO_PENDING, rv);
3114 // Race a session to the proxy, which completes first.
3115 session_deps_.host_resolver->set_ondemand_mode(false);
3116 SpdySessionKey key(
3117 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3118 base::WeakPtr<SpdySession> spdy_session =
3119 CreateSecureSpdySession(session, key, log.bound());
3121 // Unstall the resolution begun by the transaction.
3122 session_deps_.host_resolver->set_ondemand_mode(true);
3123 session_deps_.host_resolver->ResolveAllPending();
3125 EXPECT_FALSE(callback1.have_result());
3126 rv = callback1.WaitForResult();
3127 EXPECT_EQ(OK, rv);
3129 const HttpResponseInfo* response = trans->GetResponseInfo();
3130 ASSERT_TRUE(response != NULL);
3131 ASSERT_TRUE(response->headers.get() != NULL);
3132 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3134 std::string response_data;
3135 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3136 EXPECT_EQ(kUploadData, response_data);
3139 // Test a SPDY get through an HTTPS Proxy.
3140 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3141 HttpRequestInfo request;
3142 request.method = "GET";
3143 request.url = GURL("http://www.google.com/");
3144 request.load_flags = 0;
3146 // Configure against https proxy server "myproxy:70".
3147 session_deps_.proxy_service.reset(
3148 ProxyService::CreateFixed("https://myproxy:70"));
3149 CapturingBoundNetLog log;
3150 session_deps_.net_log = log.bound().net_log();
3151 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3153 // The first request will be a bare GET, the second request will be a
3154 // GET with a Proxy-Authorization header.
3155 scoped_ptr<SpdyFrame> req_get(
3156 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3157 const char* const kExtraAuthorizationHeaders[] = {
3158 "proxy-authorization", "Basic Zm9vOmJhcg=="
3160 scoped_ptr<SpdyFrame> req_get_authorization(
3161 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3162 arraysize(kExtraAuthorizationHeaders) / 2,
3163 false,
3165 LOWEST,
3166 false));
3167 MockWrite spdy_writes[] = {
3168 CreateMockWrite(*req_get, 1),
3169 CreateMockWrite(*req_get_authorization, 4),
3172 // The first response is a 407 proxy authentication challenge, and the second
3173 // response will be a 200 response since the second request includes a valid
3174 // Authorization header.
3175 const char* const kExtraAuthenticationHeaders[] = {
3176 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3178 scoped_ptr<SpdyFrame> resp_authentication(
3179 spdy_util_.ConstructSpdySynReplyError(
3180 "407 Proxy Authentication Required",
3181 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3182 1));
3183 scoped_ptr<SpdyFrame> body_authentication(
3184 spdy_util_.ConstructSpdyBodyFrame(1, true));
3185 scoped_ptr<SpdyFrame> resp_data(
3186 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3187 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3188 MockRead spdy_reads[] = {
3189 CreateMockRead(*resp_authentication, 2),
3190 CreateMockRead(*body_authentication, 3),
3191 CreateMockRead(*resp_data, 5),
3192 CreateMockRead(*body_data, 6),
3193 MockRead(ASYNC, 0, 7),
3196 OrderedSocketData data(
3197 spdy_reads, arraysize(spdy_reads),
3198 spdy_writes, arraysize(spdy_writes));
3199 session_deps_.socket_factory->AddSocketDataProvider(&data);
3201 SSLSocketDataProvider ssl(ASYNC, OK);
3202 ssl.SetNextProto(GetParam());
3203 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3205 TestCompletionCallback callback1;
3207 scoped_ptr<HttpTransaction> trans(
3208 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3210 int rv = trans->Start(&request, callback1.callback(), log.bound());
3211 EXPECT_EQ(ERR_IO_PENDING, rv);
3213 rv = callback1.WaitForResult();
3214 EXPECT_EQ(OK, rv);
3216 const HttpResponseInfo* const response = trans->GetResponseInfo();
3218 ASSERT_TRUE(response != NULL);
3219 ASSERT_TRUE(response->headers.get() != NULL);
3220 EXPECT_EQ(407, response->headers->response_code());
3221 EXPECT_TRUE(response->was_fetched_via_spdy);
3222 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3224 TestCompletionCallback callback2;
3226 rv = trans->RestartWithAuth(
3227 AuthCredentials(kFoo, kBar), callback2.callback());
3228 EXPECT_EQ(ERR_IO_PENDING, rv);
3230 rv = callback2.WaitForResult();
3231 EXPECT_EQ(OK, rv);
3233 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3235 ASSERT_TRUE(response_restart != NULL);
3236 ASSERT_TRUE(response_restart->headers.get() != NULL);
3237 EXPECT_EQ(200, response_restart->headers->response_code());
3238 // The password prompt info should not be set.
3239 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3242 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3243 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3244 HttpRequestInfo request;
3245 request.method = "GET";
3246 request.url = GURL("https://www.google.com/");
3247 request.load_flags = 0;
3249 // Configure against https proxy server "proxy:70".
3250 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3251 "https://proxy:70"));
3252 CapturingBoundNetLog log;
3253 session_deps_.net_log = log.bound().net_log();
3254 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3256 scoped_ptr<HttpTransaction> trans(
3257 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3259 // CONNECT to www.google.com:443 via SPDY
3260 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3261 LOWEST));
3262 // fetch https://www.google.com/ via HTTP
3264 const char get[] = "GET / HTTP/1.1\r\n"
3265 "Host: www.google.com\r\n"
3266 "Connection: keep-alive\r\n\r\n";
3267 scoped_ptr<SpdyFrame> wrapped_get(
3268 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3269 scoped_ptr<SpdyFrame> conn_resp(
3270 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3271 const char resp[] = "HTTP/1.1 200 OK\r\n"
3272 "Content-Length: 10\r\n\r\n";
3273 scoped_ptr<SpdyFrame> wrapped_get_resp(
3274 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3275 scoped_ptr<SpdyFrame> wrapped_body(
3276 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3277 scoped_ptr<SpdyFrame> window_update(
3278 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3280 MockWrite spdy_writes[] = {
3281 CreateMockWrite(*connect, 1),
3282 CreateMockWrite(*wrapped_get, 3),
3283 CreateMockWrite(*window_update, 5),
3286 MockRead spdy_reads[] = {
3287 CreateMockRead(*conn_resp, 2, ASYNC),
3288 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3289 CreateMockRead(*wrapped_body, 6, ASYNC),
3290 CreateMockRead(*wrapped_body, 7, ASYNC),
3291 MockRead(ASYNC, 0, 8),
3294 OrderedSocketData spdy_data(
3295 spdy_reads, arraysize(spdy_reads),
3296 spdy_writes, arraysize(spdy_writes));
3297 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3299 SSLSocketDataProvider ssl(ASYNC, OK);
3300 ssl.SetNextProto(GetParam());
3301 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3302 SSLSocketDataProvider ssl2(ASYNC, OK);
3303 ssl2.was_npn_negotiated = false;
3304 ssl2.protocol_negotiated = kProtoUnknown;
3305 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3307 TestCompletionCallback callback1;
3309 int rv = trans->Start(&request, callback1.callback(), log.bound());
3310 EXPECT_EQ(ERR_IO_PENDING, rv);
3312 rv = callback1.WaitForResult();
3313 EXPECT_EQ(OK, rv);
3315 LoadTimingInfo load_timing_info;
3316 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3317 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3319 const HttpResponseInfo* response = trans->GetResponseInfo();
3320 ASSERT_TRUE(response != NULL);
3321 ASSERT_TRUE(response->headers.get() != NULL);
3322 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3324 std::string response_data;
3325 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3326 EXPECT_EQ("1234567890", response_data);
3329 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3330 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3331 HttpRequestInfo request;
3332 request.method = "GET";
3333 request.url = GURL("https://www.google.com/");
3334 request.load_flags = 0;
3336 // Configure against https proxy server "proxy:70".
3337 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3338 "https://proxy:70"));
3339 CapturingBoundNetLog log;
3340 session_deps_.net_log = log.bound().net_log();
3341 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3343 scoped_ptr<HttpTransaction> trans(
3344 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3346 // CONNECT to www.google.com:443 via SPDY
3347 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3348 LOWEST));
3349 // fetch https://www.google.com/ via SPDY
3350 const char* const kMyUrl = "https://www.google.com/";
3351 scoped_ptr<SpdyFrame> get(
3352 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3353 scoped_ptr<SpdyFrame> wrapped_get(
3354 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3355 scoped_ptr<SpdyFrame> conn_resp(
3356 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3357 scoped_ptr<SpdyFrame> get_resp(
3358 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3359 scoped_ptr<SpdyFrame> wrapped_get_resp(
3360 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3361 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3362 scoped_ptr<SpdyFrame> wrapped_body(
3363 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3364 scoped_ptr<SpdyFrame> window_update_get_resp(
3365 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3366 scoped_ptr<SpdyFrame> window_update_body(
3367 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3369 MockWrite spdy_writes[] = {
3370 CreateMockWrite(*connect, 1),
3371 CreateMockWrite(*wrapped_get, 3),
3372 CreateMockWrite(*window_update_get_resp, 5),
3373 CreateMockWrite(*window_update_body, 7),
3376 MockRead spdy_reads[] = {
3377 CreateMockRead(*conn_resp, 2, ASYNC),
3378 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3379 CreateMockRead(*wrapped_body, 6, ASYNC),
3380 MockRead(ASYNC, 0, 8),
3383 OrderedSocketData spdy_data(
3384 spdy_reads, arraysize(spdy_reads),
3385 spdy_writes, arraysize(spdy_writes));
3386 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3388 SSLSocketDataProvider ssl(ASYNC, OK);
3389 ssl.SetNextProto(GetParam());
3390 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3391 SSLSocketDataProvider ssl2(ASYNC, OK);
3392 ssl2.SetNextProto(GetParam());
3393 ssl2.protocol_negotiated = GetParam();
3394 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3396 TestCompletionCallback callback1;
3398 int rv = trans->Start(&request, callback1.callback(), log.bound());
3399 EXPECT_EQ(ERR_IO_PENDING, rv);
3401 rv = callback1.WaitForResult();
3402 EXPECT_EQ(OK, rv);
3404 LoadTimingInfo load_timing_info;
3405 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3406 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3408 const HttpResponseInfo* response = trans->GetResponseInfo();
3409 ASSERT_TRUE(response != NULL);
3410 ASSERT_TRUE(response->headers.get() != NULL);
3411 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3413 std::string response_data;
3414 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3415 EXPECT_EQ(kUploadData, response_data);
3418 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3419 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3420 HttpRequestInfo request;
3421 request.method = "GET";
3422 request.url = GURL("https://www.google.com/");
3423 request.load_flags = 0;
3425 // Configure against https proxy server "proxy:70".
3426 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3427 "https://proxy:70"));
3428 CapturingBoundNetLog log;
3429 session_deps_.net_log = log.bound().net_log();
3430 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3432 scoped_ptr<HttpTransaction> trans(
3433 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3435 // CONNECT to www.google.com:443 via SPDY
3436 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3437 LOWEST));
3438 scoped_ptr<SpdyFrame> get(
3439 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3441 MockWrite spdy_writes[] = {
3442 CreateMockWrite(*connect, 1),
3443 CreateMockWrite(*get, 3),
3446 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3447 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3448 MockRead spdy_reads[] = {
3449 CreateMockRead(*resp, 2, ASYNC),
3450 MockRead(ASYNC, 0, 4),
3453 OrderedSocketData spdy_data(
3454 spdy_reads, arraysize(spdy_reads),
3455 spdy_writes, arraysize(spdy_writes));
3456 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3458 SSLSocketDataProvider ssl(ASYNC, OK);
3459 ssl.SetNextProto(GetParam());
3460 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3461 SSLSocketDataProvider ssl2(ASYNC, OK);
3462 ssl2.SetNextProto(GetParam());
3463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3465 TestCompletionCallback callback1;
3467 int rv = trans->Start(&request, callback1.callback(), log.bound());
3468 EXPECT_EQ(ERR_IO_PENDING, rv);
3470 rv = callback1.WaitForResult();
3471 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3473 // TODO(ttuttle): Anything else to check here?
3476 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3477 // HTTPS Proxy to different servers.
3478 TEST_P(HttpNetworkTransactionTest,
3479 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3480 // Configure against https proxy server "proxy:70".
3481 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3482 "https://proxy:70"));
3483 CapturingBoundNetLog log;
3484 session_deps_.net_log = log.bound().net_log();
3485 scoped_refptr<HttpNetworkSession> session(
3486 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3488 HttpRequestInfo request1;
3489 request1.method = "GET";
3490 request1.url = GURL("https://www.google.com/");
3491 request1.load_flags = 0;
3493 HttpRequestInfo request2;
3494 request2.method = "GET";
3495 request2.url = GURL("https://news.google.com/");
3496 request2.load_flags = 0;
3498 // CONNECT to www.google.com:443 via SPDY.
3499 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3500 LOWEST));
3501 scoped_ptr<SpdyFrame> conn_resp1(
3502 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3504 // Fetch https://www.google.com/ via HTTP.
3505 const char get1[] = "GET / HTTP/1.1\r\n"
3506 "Host: www.google.com\r\n"
3507 "Connection: keep-alive\r\n\r\n";
3508 scoped_ptr<SpdyFrame> wrapped_get1(
3509 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3510 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3511 "Content-Length: 1\r\n\r\n";
3512 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3513 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3514 scoped_ptr<SpdyFrame> wrapped_body1(
3515 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3516 scoped_ptr<SpdyFrame> window_update(
3517 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3519 // CONNECT to news.google.com:443 via SPDY.
3520 SpdyHeaderBlock connect2_block;
3521 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3522 connect2_block[spdy_util_.GetPathKey()] = "news.google.com:443";
3523 connect2_block[spdy_util_.GetHostKey()] = "news.google.com";
3524 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3525 scoped_ptr<SpdyFrame> connect2(
3526 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3528 scoped_ptr<SpdyFrame> conn_resp2(
3529 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3531 // Fetch https://news.google.com/ via HTTP.
3532 const char get2[] = "GET / HTTP/1.1\r\n"
3533 "Host: news.google.com\r\n"
3534 "Connection: keep-alive\r\n\r\n";
3535 scoped_ptr<SpdyFrame> wrapped_get2(
3536 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3537 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3538 "Content-Length: 2\r\n\r\n";
3539 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3540 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3541 scoped_ptr<SpdyFrame> wrapped_body2(
3542 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3544 MockWrite spdy_writes[] = {
3545 CreateMockWrite(*connect1, 0),
3546 CreateMockWrite(*wrapped_get1, 2),
3547 CreateMockWrite(*connect2, 5),
3548 CreateMockWrite(*wrapped_get2, 7),
3551 MockRead spdy_reads[] = {
3552 CreateMockRead(*conn_resp1, 1, ASYNC),
3553 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3554 CreateMockRead(*wrapped_body1, 4, ASYNC),
3555 CreateMockRead(*conn_resp2, 6, ASYNC),
3556 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3557 CreateMockRead(*wrapped_body2, 9, ASYNC),
3558 MockRead(ASYNC, 0, 10),
3561 DeterministicSocketData spdy_data(
3562 spdy_reads, arraysize(spdy_reads),
3563 spdy_writes, arraysize(spdy_writes));
3564 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3566 SSLSocketDataProvider ssl(ASYNC, OK);
3567 ssl.SetNextProto(GetParam());
3568 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3569 SSLSocketDataProvider ssl2(ASYNC, OK);
3570 ssl2.was_npn_negotiated = false;
3571 ssl2.protocol_negotiated = kProtoUnknown;
3572 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3573 SSLSocketDataProvider ssl3(ASYNC, OK);
3574 ssl3.was_npn_negotiated = false;
3575 ssl3.protocol_negotiated = kProtoUnknown;
3576 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3578 TestCompletionCallback callback;
3580 scoped_ptr<HttpTransaction> trans(
3581 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3582 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3583 EXPECT_EQ(ERR_IO_PENDING, rv);
3584 // The first connect and request, each of their responses, and the body.
3585 spdy_data.RunFor(5);
3587 rv = callback.WaitForResult();
3588 EXPECT_EQ(OK, rv);
3590 LoadTimingInfo load_timing_info;
3591 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3592 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3594 const HttpResponseInfo* response = trans->GetResponseInfo();
3595 ASSERT_TRUE(response != NULL);
3596 ASSERT_TRUE(response->headers.get() != NULL);
3597 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3599 std::string response_data;
3600 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3601 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3603 scoped_ptr<HttpTransaction> trans2(
3604 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3605 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3606 EXPECT_EQ(ERR_IO_PENDING, rv);
3608 // The second connect and request, each of their responses, and the body.
3609 spdy_data.RunFor(5);
3610 rv = callback.WaitForResult();
3611 EXPECT_EQ(OK, rv);
3613 LoadTimingInfo load_timing_info2;
3614 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3615 // Even though the SPDY connection is reused, a new tunnelled connection has
3616 // to be created, so the socket's load timing looks like a fresh connection.
3617 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3619 // The requests should have different IDs, since they each are using their own
3620 // separate stream.
3621 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3623 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3626 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3627 // HTTPS Proxy to the same server.
3628 TEST_P(HttpNetworkTransactionTest,
3629 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3630 // Configure against https proxy server "proxy:70".
3631 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3632 "https://proxy:70"));
3633 CapturingBoundNetLog log;
3634 session_deps_.net_log = log.bound().net_log();
3635 scoped_refptr<HttpNetworkSession> session(
3636 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3638 HttpRequestInfo request1;
3639 request1.method = "GET";
3640 request1.url = GURL("https://www.google.com/");
3641 request1.load_flags = 0;
3643 HttpRequestInfo request2;
3644 request2.method = "GET";
3645 request2.url = GURL("https://www.google.com/2");
3646 request2.load_flags = 0;
3648 // CONNECT to www.google.com:443 via SPDY.
3649 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3650 LOWEST));
3651 scoped_ptr<SpdyFrame> conn_resp1(
3652 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3654 // Fetch https://www.google.com/ via HTTP.
3655 const char get1[] = "GET / HTTP/1.1\r\n"
3656 "Host: www.google.com\r\n"
3657 "Connection: keep-alive\r\n\r\n";
3658 scoped_ptr<SpdyFrame> wrapped_get1(
3659 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3660 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3661 "Content-Length: 1\r\n\r\n";
3662 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3663 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3664 scoped_ptr<SpdyFrame> wrapped_body1(
3665 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3666 scoped_ptr<SpdyFrame> window_update(
3667 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3669 // Fetch https://www.google.com/2 via HTTP.
3670 const char get2[] = "GET /2 HTTP/1.1\r\n"
3671 "Host: www.google.com\r\n"
3672 "Connection: keep-alive\r\n\r\n";
3673 scoped_ptr<SpdyFrame> wrapped_get2(
3674 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3675 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3676 "Content-Length: 2\r\n\r\n";
3677 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3678 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3679 scoped_ptr<SpdyFrame> wrapped_body2(
3680 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3682 MockWrite spdy_writes[] = {
3683 CreateMockWrite(*connect1, 0),
3684 CreateMockWrite(*wrapped_get1, 2),
3685 CreateMockWrite(*wrapped_get2, 5),
3688 MockRead spdy_reads[] = {
3689 CreateMockRead(*conn_resp1, 1, ASYNC),
3690 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3691 CreateMockRead(*wrapped_body1, 4, ASYNC),
3692 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3693 CreateMockRead(*wrapped_body2, 7, ASYNC),
3694 MockRead(ASYNC, 0, 8),
3697 DeterministicSocketData spdy_data(
3698 spdy_reads, arraysize(spdy_reads),
3699 spdy_writes, arraysize(spdy_writes));
3700 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3702 SSLSocketDataProvider ssl(ASYNC, OK);
3703 ssl.SetNextProto(GetParam());
3704 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3705 SSLSocketDataProvider ssl2(ASYNC, OK);
3706 ssl2.was_npn_negotiated = false;
3707 ssl2.protocol_negotiated = kProtoUnknown;
3708 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3710 TestCompletionCallback callback;
3712 scoped_ptr<HttpTransaction> trans(
3713 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3714 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3715 EXPECT_EQ(ERR_IO_PENDING, rv);
3716 // The first connect and request, each of their responses, and the body.
3717 spdy_data.RunFor(5);
3719 rv = callback.WaitForResult();
3720 EXPECT_EQ(OK, rv);
3722 LoadTimingInfo load_timing_info;
3723 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3724 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3726 const HttpResponseInfo* response = trans->GetResponseInfo();
3727 ASSERT_TRUE(response != NULL);
3728 ASSERT_TRUE(response->headers.get() != NULL);
3729 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3731 std::string response_data;
3732 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3733 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3734 trans.reset();
3736 scoped_ptr<HttpTransaction> trans2(
3737 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3738 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3739 EXPECT_EQ(ERR_IO_PENDING, rv);
3741 // The second request, response, and body. There should not be a second
3742 // connect.
3743 spdy_data.RunFor(3);
3744 rv = callback.WaitForResult();
3745 EXPECT_EQ(OK, rv);
3747 LoadTimingInfo load_timing_info2;
3748 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3749 TestLoadTimingReused(load_timing_info2);
3751 // The requests should have the same ID.
3752 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3754 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3757 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3758 // Proxy to different servers.
3759 TEST_P(HttpNetworkTransactionTest,
3760 HttpsProxySpdyLoadTimingTwoHttpRequests) {
3761 // Configure against https proxy server "proxy:70".
3762 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3763 "https://proxy:70"));
3764 CapturingBoundNetLog log;
3765 session_deps_.net_log = log.bound().net_log();
3766 scoped_refptr<HttpNetworkSession> session(
3767 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3769 HttpRequestInfo request1;
3770 request1.method = "GET";
3771 request1.url = GURL("http://www.google.com/");
3772 request1.load_flags = 0;
3774 HttpRequestInfo request2;
3775 request2.method = "GET";
3776 request2.url = GURL("http://news.google.com/");
3777 request2.load_flags = 0;
3779 // http://www.google.com/
3780 scoped_ptr<SpdyHeaderBlock> headers(
3781 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3782 scoped_ptr<SpdyFrame> get1(
3783 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
3784 scoped_ptr<SpdyFrame> get_resp1(
3785 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3786 scoped_ptr<SpdyFrame> body1(
3787 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3789 // http://news.google.com/
3790 scoped_ptr<SpdyHeaderBlock> headers2(
3791 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3792 scoped_ptr<SpdyFrame> get2(
3793 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
3794 scoped_ptr<SpdyFrame> get_resp2(
3795 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3796 scoped_ptr<SpdyFrame> body2(
3797 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3799 MockWrite spdy_writes[] = {
3800 CreateMockWrite(*get1, 0),
3801 CreateMockWrite(*get2, 3),
3804 MockRead spdy_reads[] = {
3805 CreateMockRead(*get_resp1, 1, ASYNC),
3806 CreateMockRead(*body1, 2, ASYNC),
3807 CreateMockRead(*get_resp2, 4, ASYNC),
3808 CreateMockRead(*body2, 5, ASYNC),
3809 MockRead(ASYNC, 0, 6),
3812 DeterministicSocketData spdy_data(
3813 spdy_reads, arraysize(spdy_reads),
3814 spdy_writes, arraysize(spdy_writes));
3815 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3817 SSLSocketDataProvider ssl(ASYNC, OK);
3818 ssl.SetNextProto(GetParam());
3819 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3821 TestCompletionCallback callback;
3823 scoped_ptr<HttpTransaction> trans(
3824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3825 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3826 EXPECT_EQ(ERR_IO_PENDING, rv);
3827 spdy_data.RunFor(2);
3829 rv = callback.WaitForResult();
3830 EXPECT_EQ(OK, rv);
3832 LoadTimingInfo load_timing_info;
3833 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3834 TestLoadTimingNotReused(load_timing_info,
3835 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3837 const HttpResponseInfo* response = trans->GetResponseInfo();
3838 ASSERT_TRUE(response != NULL);
3839 ASSERT_TRUE(response->headers.get() != NULL);
3840 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3842 std::string response_data;
3843 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3844 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3845 spdy_data.RunFor(1);
3846 EXPECT_EQ(1, callback.WaitForResult());
3847 // Delete the first request, so the second one can reuse the socket.
3848 trans.reset();
3850 scoped_ptr<HttpTransaction> trans2(
3851 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3852 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3853 EXPECT_EQ(ERR_IO_PENDING, rv);
3855 spdy_data.RunFor(2);
3856 rv = callback.WaitForResult();
3857 EXPECT_EQ(OK, rv);
3859 LoadTimingInfo load_timing_info2;
3860 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3861 TestLoadTimingReused(load_timing_info2);
3863 // The requests should have the same ID.
3864 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3866 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3867 spdy_data.RunFor(1);
3868 EXPECT_EQ(2, callback.WaitForResult());
3871 // Test the challenge-response-retry sequence through an HTTPS Proxy
3872 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3873 HttpRequestInfo request;
3874 request.method = "GET";
3875 request.url = GURL("http://www.google.com/");
3876 // when the no authentication data flag is set.
3877 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3879 // Configure against https proxy server "myproxy:70".
3880 session_deps_.proxy_service.reset(
3881 ProxyService::CreateFixed("https://myproxy:70"));
3882 CapturingBoundNetLog log;
3883 session_deps_.net_log = log.bound().net_log();
3884 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3886 // Since we have proxy, should use full url
3887 MockWrite data_writes1[] = {
3888 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3889 "Host: www.google.com\r\n"
3890 "Proxy-Connection: keep-alive\r\n\r\n"),
3892 // After calling trans->RestartWithAuth(), this is the request we should
3893 // be issuing -- the final header line contains the credentials.
3894 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3895 "Host: www.google.com\r\n"
3896 "Proxy-Connection: keep-alive\r\n"
3897 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3900 // The proxy responds to the GET with a 407, using a persistent
3901 // connection.
3902 MockRead data_reads1[] = {
3903 // No credentials.
3904 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3905 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3906 MockRead("Proxy-Connection: keep-alive\r\n"),
3907 MockRead("Content-Length: 0\r\n\r\n"),
3909 MockRead("HTTP/1.1 200 OK\r\n"),
3910 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3911 MockRead("Content-Length: 100\r\n\r\n"),
3912 MockRead(SYNCHRONOUS, OK),
3915 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3916 data_writes1, arraysize(data_writes1));
3917 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3918 SSLSocketDataProvider ssl(ASYNC, OK);
3919 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3921 TestCompletionCallback callback1;
3923 scoped_ptr<HttpTransaction> trans(
3924 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3926 int rv = trans->Start(&request, callback1.callback(), log.bound());
3927 EXPECT_EQ(ERR_IO_PENDING, rv);
3929 rv = callback1.WaitForResult();
3930 EXPECT_EQ(OK, rv);
3932 LoadTimingInfo load_timing_info;
3933 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3934 TestLoadTimingNotReused(load_timing_info,
3935 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3937 const HttpResponseInfo* response = trans->GetResponseInfo();
3938 ASSERT_TRUE(response != NULL);
3939 ASSERT_FALSE(response->headers.get() == NULL);
3940 EXPECT_EQ(407, response->headers->response_code());
3941 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3942 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3944 TestCompletionCallback callback2;
3946 rv = trans->RestartWithAuth(
3947 AuthCredentials(kFoo, kBar), callback2.callback());
3948 EXPECT_EQ(ERR_IO_PENDING, rv);
3950 rv = callback2.WaitForResult();
3951 EXPECT_EQ(OK, rv);
3953 load_timing_info = LoadTimingInfo();
3954 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3955 // Retrying with HTTP AUTH is considered to be reusing a socket.
3956 TestLoadTimingReused(load_timing_info);
3958 response = trans->GetResponseInfo();
3959 ASSERT_TRUE(response != NULL);
3961 EXPECT_TRUE(response->headers->IsKeepAlive());
3962 EXPECT_EQ(200, response->headers->response_code());
3963 EXPECT_EQ(100, response->headers->GetContentLength());
3964 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3966 // The password prompt info should not be set.
3967 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3970 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3971 const MockRead& status, int expected_status) {
3972 HttpRequestInfo request;
3973 request.method = "GET";
3974 request.url = GURL("https://www.google.com/");
3975 request.load_flags = 0;
3977 // Configure against proxy server "myproxy:70".
3978 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3979 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3981 // Since we have proxy, should try to establish tunnel.
3982 MockWrite data_writes[] = {
3983 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3984 "Host: www.google.com\r\n"
3985 "Proxy-Connection: keep-alive\r\n\r\n"),
3988 MockRead data_reads[] = {
3989 status,
3990 MockRead("Content-Length: 10\r\n\r\n"),
3991 // No response body because the test stops reading here.
3992 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3995 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3996 data_writes, arraysize(data_writes));
3997 session_deps_.socket_factory->AddSocketDataProvider(&data);
3999 TestCompletionCallback callback;
4001 scoped_ptr<HttpTransaction> trans(
4002 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4004 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4005 EXPECT_EQ(ERR_IO_PENDING, rv);
4007 rv = callback.WaitForResult();
4008 EXPECT_EQ(expected_status, rv);
4011 void HttpNetworkTransactionTest::ConnectStatusHelper(
4012 const MockRead& status) {
4013 ConnectStatusHelperWithExpectedStatus(
4014 status, ERR_TUNNEL_CONNECTION_FAILED);
4017 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4018 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4021 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4022 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4025 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4026 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4029 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4030 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4033 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4034 ConnectStatusHelper(
4035 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4038 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4039 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4042 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4043 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4046 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4047 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4050 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4051 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4054 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4055 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4058 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4059 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4062 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4063 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4066 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4067 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4070 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4071 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4074 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4075 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4078 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4079 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4082 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4083 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4086 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4087 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4090 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4091 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4094 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4095 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4098 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4099 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4102 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4103 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4106 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4107 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4110 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4111 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4114 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4115 ConnectStatusHelperWithExpectedStatus(
4116 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4117 ERR_PROXY_AUTH_UNSUPPORTED);
4120 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4121 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4124 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4125 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4128 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4129 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4132 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4133 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4136 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4137 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4140 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4141 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4144 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4145 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4148 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4149 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4152 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4153 ConnectStatusHelper(
4154 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4157 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4158 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4161 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4162 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4165 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4166 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4169 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4170 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4173 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4174 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4177 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4178 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4181 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4182 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4185 // Test the flow when both the proxy server AND origin server require
4186 // authentication. Again, this uses basic auth for both since that is
4187 // the simplest to mock.
4188 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4189 HttpRequestInfo request;
4190 request.method = "GET";
4191 request.url = GURL("http://www.google.com/");
4192 request.load_flags = 0;
4194 // Configure against proxy server "myproxy:70".
4195 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4198 scoped_ptr<HttpTransaction> trans(
4199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4201 MockWrite data_writes1[] = {
4202 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4203 "Host: www.google.com\r\n"
4204 "Proxy-Connection: keep-alive\r\n\r\n"),
4207 MockRead data_reads1[] = {
4208 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4209 // Give a couple authenticate options (only the middle one is actually
4210 // supported).
4211 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4212 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4213 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4214 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4215 // Large content-length -- won't matter, as connection will be reset.
4216 MockRead("Content-Length: 10000\r\n\r\n"),
4217 MockRead(SYNCHRONOUS, ERR_FAILED),
4220 // After calling trans->RestartWithAuth() the first time, this is the
4221 // request we should be issuing -- the final header line contains the
4222 // proxy's credentials.
4223 MockWrite data_writes2[] = {
4224 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4225 "Host: www.google.com\r\n"
4226 "Proxy-Connection: keep-alive\r\n"
4227 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4230 // Now the proxy server lets the request pass through to origin server.
4231 // The origin server responds with a 401.
4232 MockRead data_reads2[] = {
4233 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4234 // Note: We are using the same realm-name as the proxy server. This is
4235 // completely valid, as realms are unique across hosts.
4236 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4237 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4238 MockRead("Content-Length: 2000\r\n\r\n"),
4239 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4242 // After calling trans->RestartWithAuth() the second time, we should send
4243 // the credentials for both the proxy and origin server.
4244 MockWrite data_writes3[] = {
4245 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4246 "Host: www.google.com\r\n"
4247 "Proxy-Connection: keep-alive\r\n"
4248 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4249 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4252 // Lastly we get the desired content.
4253 MockRead data_reads3[] = {
4254 MockRead("HTTP/1.0 200 OK\r\n"),
4255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4256 MockRead("Content-Length: 100\r\n\r\n"),
4257 MockRead(SYNCHRONOUS, OK),
4260 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4261 data_writes1, arraysize(data_writes1));
4262 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4263 data_writes2, arraysize(data_writes2));
4264 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4265 data_writes3, arraysize(data_writes3));
4266 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4267 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4268 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4270 TestCompletionCallback callback1;
4272 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4273 EXPECT_EQ(ERR_IO_PENDING, rv);
4275 rv = callback1.WaitForResult();
4276 EXPECT_EQ(OK, rv);
4278 const HttpResponseInfo* response = trans->GetResponseInfo();
4279 ASSERT_TRUE(response != NULL);
4280 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4282 TestCompletionCallback callback2;
4284 rv = trans->RestartWithAuth(
4285 AuthCredentials(kFoo, kBar), callback2.callback());
4286 EXPECT_EQ(ERR_IO_PENDING, rv);
4288 rv = callback2.WaitForResult();
4289 EXPECT_EQ(OK, rv);
4291 response = trans->GetResponseInfo();
4292 ASSERT_TRUE(response != NULL);
4293 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4295 TestCompletionCallback callback3;
4297 rv = trans->RestartWithAuth(
4298 AuthCredentials(kFoo2, kBar2), callback3.callback());
4299 EXPECT_EQ(ERR_IO_PENDING, rv);
4301 rv = callback3.WaitForResult();
4302 EXPECT_EQ(OK, rv);
4304 response = trans->GetResponseInfo();
4305 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4306 EXPECT_EQ(100, response->headers->GetContentLength());
4309 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4310 // can't hook into its internals to cause it to generate predictable NTLM
4311 // authorization headers.
4312 #if defined(NTLM_PORTABLE)
4313 // The NTLM authentication unit tests were generated by capturing the HTTP
4314 // requests and responses using Fiddler 2 and inspecting the generated random
4315 // bytes in the debugger.
4317 // Enter the correct password and authenticate successfully.
4318 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4319 HttpRequestInfo request;
4320 request.method = "GET";
4321 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4323 // Ensure load is not disrupted by flags which suppress behaviour specific
4324 // to other auth schemes.
4325 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4327 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4328 MockGetHostName);
4329 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4331 MockWrite data_writes1[] = {
4332 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4333 "Host: 172.22.68.17\r\n"
4334 "Connection: keep-alive\r\n\r\n"),
4337 MockRead data_reads1[] = {
4338 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4339 // Negotiate and NTLM are often requested together. However, we only want
4340 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4341 // the header that requests Negotiate for this test.
4342 MockRead("WWW-Authenticate: NTLM\r\n"),
4343 MockRead("Connection: close\r\n"),
4344 MockRead("Content-Length: 42\r\n"),
4345 MockRead("Content-Type: text/html\r\n\r\n"),
4346 // Missing content -- won't matter, as connection will be reset.
4347 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4350 MockWrite data_writes2[] = {
4351 // After restarting with a null identity, this is the
4352 // request we should be issuing -- the final header line contains a Type
4353 // 1 message.
4354 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4355 "Host: 172.22.68.17\r\n"
4356 "Connection: keep-alive\r\n"
4357 "Authorization: NTLM "
4358 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4360 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4361 // (the credentials for the origin server). The second request continues
4362 // on the same connection.
4363 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4364 "Host: 172.22.68.17\r\n"
4365 "Connection: keep-alive\r\n"
4366 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4367 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4368 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4369 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4370 "ahlhx5I=\r\n\r\n"),
4373 MockRead data_reads2[] = {
4374 // The origin server responds with a Type 2 message.
4375 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4376 MockRead("WWW-Authenticate: NTLM "
4377 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4378 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4379 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4380 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4381 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4382 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4383 "BtAAAAAAA=\r\n"),
4384 MockRead("Content-Length: 42\r\n"),
4385 MockRead("Content-Type: text/html\r\n\r\n"),
4386 MockRead("You are not authorized to view this page\r\n"),
4388 // Lastly we get the desired content.
4389 MockRead("HTTP/1.1 200 OK\r\n"),
4390 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4391 MockRead("Content-Length: 13\r\n\r\n"),
4392 MockRead("Please Login\r\n"),
4393 MockRead(SYNCHRONOUS, OK),
4396 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4397 data_writes1, arraysize(data_writes1));
4398 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4399 data_writes2, arraysize(data_writes2));
4400 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4401 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4403 TestCompletionCallback callback1;
4405 scoped_ptr<HttpTransaction> trans(
4406 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4408 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4409 EXPECT_EQ(ERR_IO_PENDING, rv);
4411 rv = callback1.WaitForResult();
4412 EXPECT_EQ(OK, rv);
4414 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4416 const HttpResponseInfo* response = trans->GetResponseInfo();
4417 ASSERT_FALSE(response == NULL);
4418 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4420 TestCompletionCallback callback2;
4422 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4423 callback2.callback());
4424 EXPECT_EQ(ERR_IO_PENDING, rv);
4426 rv = callback2.WaitForResult();
4427 EXPECT_EQ(OK, rv);
4429 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4431 response = trans->GetResponseInfo();
4432 ASSERT_TRUE(response != NULL);
4433 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4435 TestCompletionCallback callback3;
4437 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4438 EXPECT_EQ(ERR_IO_PENDING, rv);
4440 rv = callback3.WaitForResult();
4441 EXPECT_EQ(OK, rv);
4443 response = trans->GetResponseInfo();
4444 ASSERT_TRUE(response != NULL);
4445 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4446 EXPECT_EQ(13, response->headers->GetContentLength());
4449 // Enter a wrong password, and then the correct one.
4450 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4451 HttpRequestInfo request;
4452 request.method = "GET";
4453 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4454 request.load_flags = 0;
4456 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4457 MockGetHostName);
4458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4460 MockWrite data_writes1[] = {
4461 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4462 "Host: 172.22.68.17\r\n"
4463 "Connection: keep-alive\r\n\r\n"),
4466 MockRead data_reads1[] = {
4467 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4468 // Negotiate and NTLM are often requested together. However, we only want
4469 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4470 // the header that requests Negotiate for this test.
4471 MockRead("WWW-Authenticate: NTLM\r\n"),
4472 MockRead("Connection: close\r\n"),
4473 MockRead("Content-Length: 42\r\n"),
4474 MockRead("Content-Type: text/html\r\n\r\n"),
4475 // Missing content -- won't matter, as connection will be reset.
4476 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4479 MockWrite data_writes2[] = {
4480 // After restarting with a null identity, this is the
4481 // request we should be issuing -- the final header line contains a Type
4482 // 1 message.
4483 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4484 "Host: 172.22.68.17\r\n"
4485 "Connection: keep-alive\r\n"
4486 "Authorization: NTLM "
4487 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4489 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4490 // (the credentials for the origin server). The second request continues
4491 // on the same connection.
4492 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4493 "Host: 172.22.68.17\r\n"
4494 "Connection: keep-alive\r\n"
4495 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4496 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4497 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4498 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4499 "4Ww7b7E=\r\n\r\n"),
4502 MockRead data_reads2[] = {
4503 // The origin server responds with a Type 2 message.
4504 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4505 MockRead("WWW-Authenticate: NTLM "
4506 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4507 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4508 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4509 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4510 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4511 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4512 "BtAAAAAAA=\r\n"),
4513 MockRead("Content-Length: 42\r\n"),
4514 MockRead("Content-Type: text/html\r\n\r\n"),
4515 MockRead("You are not authorized to view this page\r\n"),
4517 // Wrong password.
4518 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4519 MockRead("WWW-Authenticate: NTLM\r\n"),
4520 MockRead("Connection: close\r\n"),
4521 MockRead("Content-Length: 42\r\n"),
4522 MockRead("Content-Type: text/html\r\n\r\n"),
4523 // Missing content -- won't matter, as connection will be reset.
4524 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4527 MockWrite data_writes3[] = {
4528 // After restarting with a null identity, this is the
4529 // request we should be issuing -- the final header line contains a Type
4530 // 1 message.
4531 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4532 "Host: 172.22.68.17\r\n"
4533 "Connection: keep-alive\r\n"
4534 "Authorization: NTLM "
4535 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4537 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4538 // (the credentials for the origin server). The second request continues
4539 // on the same connection.
4540 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4541 "Host: 172.22.68.17\r\n"
4542 "Connection: keep-alive\r\n"
4543 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4544 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4545 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4546 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4547 "+4MUm7c=\r\n\r\n"),
4550 MockRead data_reads3[] = {
4551 // The origin server responds with a Type 2 message.
4552 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4553 MockRead("WWW-Authenticate: NTLM "
4554 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4555 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4556 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4557 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4558 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4559 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4560 "BtAAAAAAA=\r\n"),
4561 MockRead("Content-Length: 42\r\n"),
4562 MockRead("Content-Type: text/html\r\n\r\n"),
4563 MockRead("You are not authorized to view this page\r\n"),
4565 // Lastly we get the desired content.
4566 MockRead("HTTP/1.1 200 OK\r\n"),
4567 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4568 MockRead("Content-Length: 13\r\n\r\n"),
4569 MockRead("Please Login\r\n"),
4570 MockRead(SYNCHRONOUS, OK),
4573 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4574 data_writes1, arraysize(data_writes1));
4575 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4576 data_writes2, arraysize(data_writes2));
4577 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4578 data_writes3, arraysize(data_writes3));
4579 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4580 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4581 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4583 TestCompletionCallback callback1;
4585 scoped_ptr<HttpTransaction> trans(
4586 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4588 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4589 EXPECT_EQ(ERR_IO_PENDING, rv);
4591 rv = callback1.WaitForResult();
4592 EXPECT_EQ(OK, rv);
4594 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4596 const HttpResponseInfo* response = trans->GetResponseInfo();
4597 ASSERT_TRUE(response != NULL);
4598 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4600 TestCompletionCallback callback2;
4602 // Enter the wrong password.
4603 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4604 callback2.callback());
4605 EXPECT_EQ(ERR_IO_PENDING, rv);
4607 rv = callback2.WaitForResult();
4608 EXPECT_EQ(OK, rv);
4610 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4611 TestCompletionCallback callback3;
4612 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4613 EXPECT_EQ(ERR_IO_PENDING, rv);
4614 rv = callback3.WaitForResult();
4615 EXPECT_EQ(OK, rv);
4616 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4618 response = trans->GetResponseInfo();
4619 ASSERT_FALSE(response == NULL);
4620 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4622 TestCompletionCallback callback4;
4624 // Now enter the right password.
4625 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4626 callback4.callback());
4627 EXPECT_EQ(ERR_IO_PENDING, rv);
4629 rv = callback4.WaitForResult();
4630 EXPECT_EQ(OK, rv);
4632 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4634 TestCompletionCallback callback5;
4636 // One more roundtrip
4637 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4638 EXPECT_EQ(ERR_IO_PENDING, rv);
4640 rv = callback5.WaitForResult();
4641 EXPECT_EQ(OK, rv);
4643 response = trans->GetResponseInfo();
4644 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4645 EXPECT_EQ(13, response->headers->GetContentLength());
4647 #endif // NTLM_PORTABLE
4649 // Test reading a server response which has only headers, and no body.
4650 // After some maximum number of bytes is consumed, the transaction should
4651 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4652 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4653 HttpRequestInfo request;
4654 request.method = "GET";
4655 request.url = GURL("http://www.google.com/");
4656 request.load_flags = 0;
4658 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4659 scoped_ptr<HttpTransaction> trans(
4660 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4662 // Respond with 300 kb of headers (we should fail after 256 kb).
4663 std::string large_headers_string;
4664 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4666 MockRead data_reads[] = {
4667 MockRead("HTTP/1.0 200 OK\r\n"),
4668 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4669 MockRead("\r\nBODY"),
4670 MockRead(SYNCHRONOUS, OK),
4672 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4673 session_deps_.socket_factory->AddSocketDataProvider(&data);
4675 TestCompletionCallback callback;
4677 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4678 EXPECT_EQ(ERR_IO_PENDING, rv);
4680 rv = callback.WaitForResult();
4681 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4683 const HttpResponseInfo* response = trans->GetResponseInfo();
4684 EXPECT_TRUE(response == NULL);
4687 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4688 // establish tunnel.
4689 // http://code.google.com/p/chromium/issues/detail?id=3772
4690 TEST_P(HttpNetworkTransactionTest,
4691 DontRecycleTransportSocketForSSLTunnel) {
4692 HttpRequestInfo request;
4693 request.method = "GET";
4694 request.url = GURL("https://www.google.com/");
4695 request.load_flags = 0;
4697 // Configure against proxy server "myproxy:70".
4698 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4700 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4702 scoped_ptr<HttpTransaction> trans(
4703 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4705 // Since we have proxy, should try to establish tunnel.
4706 MockWrite data_writes1[] = {
4707 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4708 "Host: www.google.com\r\n"
4709 "Proxy-Connection: keep-alive\r\n\r\n"),
4712 // The proxy responds to the connect with a 404, using a persistent
4713 // connection. Usually a proxy would return 501 (not implemented),
4714 // or 200 (tunnel established).
4715 MockRead data_reads1[] = {
4716 MockRead("HTTP/1.1 404 Not Found\r\n"),
4717 MockRead("Content-Length: 10\r\n\r\n"),
4718 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4721 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4722 data_writes1, arraysize(data_writes1));
4723 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4725 TestCompletionCallback callback1;
4727 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4728 EXPECT_EQ(ERR_IO_PENDING, rv);
4730 rv = callback1.WaitForResult();
4731 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4733 const HttpResponseInfo* response = trans->GetResponseInfo();
4734 EXPECT_TRUE(response == NULL);
4736 // Empty the current queue. This is necessary because idle sockets are
4737 // added to the connection pool asynchronously with a PostTask.
4738 base::MessageLoop::current()->RunUntilIdle();
4740 // We now check to make sure the TCPClientSocket was not added back to
4741 // the pool.
4742 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4743 trans.reset();
4744 base::MessageLoop::current()->RunUntilIdle();
4745 // Make sure that the socket didn't get recycled after calling the destructor.
4746 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4749 // Make sure that we recycle a socket after reading all of the response body.
4750 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4751 HttpRequestInfo request;
4752 request.method = "GET";
4753 request.url = GURL("http://www.google.com/");
4754 request.load_flags = 0;
4756 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4758 scoped_ptr<HttpTransaction> trans(
4759 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4761 MockRead data_reads[] = {
4762 // A part of the response body is received with the response headers.
4763 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4764 // The rest of the response body is received in two parts.
4765 MockRead("lo"),
4766 MockRead(" world"),
4767 MockRead("junk"), // Should not be read!!
4768 MockRead(SYNCHRONOUS, OK),
4771 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4772 session_deps_.socket_factory->AddSocketDataProvider(&data);
4774 TestCompletionCallback callback;
4776 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4777 EXPECT_EQ(ERR_IO_PENDING, rv);
4779 rv = callback.WaitForResult();
4780 EXPECT_EQ(OK, rv);
4782 const HttpResponseInfo* response = trans->GetResponseInfo();
4783 ASSERT_TRUE(response != NULL);
4785 EXPECT_TRUE(response->headers.get() != NULL);
4786 std::string status_line = response->headers->GetStatusLine();
4787 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4789 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4791 std::string response_data;
4792 rv = ReadTransaction(trans.get(), &response_data);
4793 EXPECT_EQ(OK, rv);
4794 EXPECT_EQ("hello world", response_data);
4796 // Empty the current queue. This is necessary because idle sockets are
4797 // added to the connection pool asynchronously with a PostTask.
4798 base::MessageLoop::current()->RunUntilIdle();
4800 // We now check to make sure the socket was added back to the pool.
4801 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4804 // Make sure that we recycle a SSL socket after reading all of the response
4805 // body.
4806 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4807 HttpRequestInfo request;
4808 request.method = "GET";
4809 request.url = GURL("https://www.google.com/");
4810 request.load_flags = 0;
4812 MockWrite data_writes[] = {
4813 MockWrite("GET / HTTP/1.1\r\n"
4814 "Host: www.google.com\r\n"
4815 "Connection: keep-alive\r\n\r\n"),
4818 MockRead data_reads[] = {
4819 MockRead("HTTP/1.1 200 OK\r\n"),
4820 MockRead("Content-Length: 11\r\n\r\n"),
4821 MockRead("hello world"),
4822 MockRead(SYNCHRONOUS, OK),
4825 SSLSocketDataProvider ssl(ASYNC, OK);
4826 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4828 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4829 data_writes, arraysize(data_writes));
4830 session_deps_.socket_factory->AddSocketDataProvider(&data);
4832 TestCompletionCallback callback;
4834 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4835 scoped_ptr<HttpTransaction> trans(
4836 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4838 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4840 EXPECT_EQ(ERR_IO_PENDING, rv);
4841 EXPECT_EQ(OK, callback.WaitForResult());
4843 const HttpResponseInfo* response = trans->GetResponseInfo();
4844 ASSERT_TRUE(response != NULL);
4845 ASSERT_TRUE(response->headers.get() != NULL);
4846 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4848 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4850 std::string response_data;
4851 rv = ReadTransaction(trans.get(), &response_data);
4852 EXPECT_EQ(OK, rv);
4853 EXPECT_EQ("hello world", response_data);
4855 // Empty the current queue. This is necessary because idle sockets are
4856 // added to the connection pool asynchronously with a PostTask.
4857 base::MessageLoop::current()->RunUntilIdle();
4859 // We now check to make sure the socket was added back to the pool.
4860 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4863 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4864 // from the pool and make sure that we recover okay.
4865 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4866 HttpRequestInfo request;
4867 request.method = "GET";
4868 request.url = GURL("https://www.google.com/");
4869 request.load_flags = 0;
4871 MockWrite data_writes[] = {
4872 MockWrite("GET / HTTP/1.1\r\n"
4873 "Host: www.google.com\r\n"
4874 "Connection: keep-alive\r\n\r\n"),
4875 MockWrite("GET / HTTP/1.1\r\n"
4876 "Host: www.google.com\r\n"
4877 "Connection: keep-alive\r\n\r\n"),
4880 MockRead data_reads[] = {
4881 MockRead("HTTP/1.1 200 OK\r\n"),
4882 MockRead("Content-Length: 11\r\n\r\n"),
4883 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4884 MockRead("hello world"),
4885 MockRead(ASYNC, 0, 0) // EOF
4888 SSLSocketDataProvider ssl(ASYNC, OK);
4889 SSLSocketDataProvider ssl2(ASYNC, OK);
4890 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4893 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4894 data_writes, arraysize(data_writes));
4895 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4896 data_writes, arraysize(data_writes));
4897 session_deps_.socket_factory->AddSocketDataProvider(&data);
4898 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4900 TestCompletionCallback callback;
4902 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4903 scoped_ptr<HttpTransaction> trans(
4904 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4906 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4908 EXPECT_EQ(ERR_IO_PENDING, rv);
4909 EXPECT_EQ(OK, callback.WaitForResult());
4911 const HttpResponseInfo* response = trans->GetResponseInfo();
4912 ASSERT_TRUE(response != NULL);
4913 ASSERT_TRUE(response->headers.get() != NULL);
4914 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4916 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4918 std::string response_data;
4919 rv = ReadTransaction(trans.get(), &response_data);
4920 EXPECT_EQ(OK, rv);
4921 EXPECT_EQ("hello world", response_data);
4923 // Empty the current queue. This is necessary because idle sockets are
4924 // added to the connection pool asynchronously with a PostTask.
4925 base::MessageLoop::current()->RunUntilIdle();
4927 // We now check to make sure the socket was added back to the pool.
4928 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4930 // Now start the second transaction, which should reuse the previous socket.
4932 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4934 rv = trans->Start(&request, callback.callback(), BoundNetLog());
4936 EXPECT_EQ(ERR_IO_PENDING, rv);
4937 EXPECT_EQ(OK, callback.WaitForResult());
4939 response = trans->GetResponseInfo();
4940 ASSERT_TRUE(response != NULL);
4941 ASSERT_TRUE(response->headers.get() != NULL);
4942 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4944 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4946 rv = ReadTransaction(trans.get(), &response_data);
4947 EXPECT_EQ(OK, rv);
4948 EXPECT_EQ("hello world", response_data);
4950 // Empty the current queue. This is necessary because idle sockets are
4951 // added to the connection pool asynchronously with a PostTask.
4952 base::MessageLoop::current()->RunUntilIdle();
4954 // We now check to make sure the socket was added back to the pool.
4955 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4958 // Make sure that we recycle a socket after a zero-length response.
4959 // http://crbug.com/9880
4960 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4961 HttpRequestInfo request;
4962 request.method = "GET";
4963 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4964 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4965 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4966 "rt=prt.2642,ol.2649,xjs.2951");
4967 request.load_flags = 0;
4969 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4971 scoped_ptr<HttpTransaction> trans(
4972 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4974 MockRead data_reads[] = {
4975 MockRead("HTTP/1.1 204 No Content\r\n"
4976 "Content-Length: 0\r\n"
4977 "Content-Type: text/html\r\n\r\n"),
4978 MockRead("junk"), // Should not be read!!
4979 MockRead(SYNCHRONOUS, OK),
4982 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4983 session_deps_.socket_factory->AddSocketDataProvider(&data);
4985 TestCompletionCallback callback;
4987 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4988 EXPECT_EQ(ERR_IO_PENDING, rv);
4990 rv = callback.WaitForResult();
4991 EXPECT_EQ(OK, rv);
4993 const HttpResponseInfo* response = trans->GetResponseInfo();
4994 ASSERT_TRUE(response != NULL);
4996 EXPECT_TRUE(response->headers.get() != NULL);
4997 std::string status_line = response->headers->GetStatusLine();
4998 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5000 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5002 std::string response_data;
5003 rv = ReadTransaction(trans.get(), &response_data);
5004 EXPECT_EQ(OK, rv);
5005 EXPECT_EQ("", response_data);
5007 // Empty the current queue. This is necessary because idle sockets are
5008 // added to the connection pool asynchronously with a PostTask.
5009 base::MessageLoop::current()->RunUntilIdle();
5011 // We now check to make sure the socket was added back to the pool.
5012 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5015 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5016 ScopedVector<UploadElementReader> element_readers;
5017 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5018 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
5020 HttpRequestInfo request[2];
5021 // Transaction 1: a GET request that succeeds. The socket is recycled
5022 // after use.
5023 request[0].method = "GET";
5024 request[0].url = GURL("http://www.google.com/");
5025 request[0].load_flags = 0;
5026 // Transaction 2: a POST request. Reuses the socket kept alive from
5027 // transaction 1. The first attempts fails when writing the POST data.
5028 // This causes the transaction to retry with a new socket. The second
5029 // attempt succeeds.
5030 request[1].method = "POST";
5031 request[1].url = GURL("http://www.google.com/login.cgi");
5032 request[1].upload_data_stream = &upload_data_stream;
5033 request[1].load_flags = 0;
5035 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5037 // The first socket is used for transaction 1 and the first attempt of
5038 // transaction 2.
5040 // The response of transaction 1.
5041 MockRead data_reads1[] = {
5042 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5043 MockRead("hello world"),
5044 MockRead(SYNCHRONOUS, OK),
5046 // The mock write results of transaction 1 and the first attempt of
5047 // transaction 2.
5048 MockWrite data_writes1[] = {
5049 MockWrite(SYNCHRONOUS, 64), // GET
5050 MockWrite(SYNCHRONOUS, 93), // POST
5051 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5053 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5054 data_writes1, arraysize(data_writes1));
5056 // The second socket is used for the second attempt of transaction 2.
5058 // The response of transaction 2.
5059 MockRead data_reads2[] = {
5060 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5061 MockRead("welcome"),
5062 MockRead(SYNCHRONOUS, OK),
5064 // The mock write results of the second attempt of transaction 2.
5065 MockWrite data_writes2[] = {
5066 MockWrite(SYNCHRONOUS, 93), // POST
5067 MockWrite(SYNCHRONOUS, 3), // POST data
5069 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5070 data_writes2, arraysize(data_writes2));
5072 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5073 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5075 const char* kExpectedResponseData[] = {
5076 "hello world", "welcome"
5079 for (int i = 0; i < 2; ++i) {
5080 scoped_ptr<HttpTransaction> trans(
5081 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5083 TestCompletionCallback callback;
5085 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5086 EXPECT_EQ(ERR_IO_PENDING, rv);
5088 rv = callback.WaitForResult();
5089 EXPECT_EQ(OK, rv);
5091 const HttpResponseInfo* response = trans->GetResponseInfo();
5092 ASSERT_TRUE(response != NULL);
5094 EXPECT_TRUE(response->headers.get() != NULL);
5095 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5097 std::string response_data;
5098 rv = ReadTransaction(trans.get(), &response_data);
5099 EXPECT_EQ(OK, rv);
5100 EXPECT_EQ(kExpectedResponseData[i], response_data);
5104 // Test the request-challenge-retry sequence for basic auth when there is
5105 // an identity in the URL. The request should be sent as normal, but when
5106 // it fails the identity from the URL is used to answer the challenge.
5107 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5108 HttpRequestInfo request;
5109 request.method = "GET";
5110 request.url = GURL("http://foo:b@r@www.google.com/");
5111 request.load_flags = LOAD_NORMAL;
5113 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5114 scoped_ptr<HttpTransaction> trans(
5115 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5117 // The password contains an escaped character -- for this test to pass it
5118 // will need to be unescaped by HttpNetworkTransaction.
5119 EXPECT_EQ("b%40r", request.url.password());
5121 MockWrite data_writes1[] = {
5122 MockWrite("GET / HTTP/1.1\r\n"
5123 "Host: www.google.com\r\n"
5124 "Connection: keep-alive\r\n\r\n"),
5127 MockRead data_reads1[] = {
5128 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5129 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5130 MockRead("Content-Length: 10\r\n\r\n"),
5131 MockRead(SYNCHRONOUS, ERR_FAILED),
5134 // After the challenge above, the transaction will be restarted using the
5135 // identity from the url (foo, b@r) to answer the challenge.
5136 MockWrite data_writes2[] = {
5137 MockWrite("GET / HTTP/1.1\r\n"
5138 "Host: www.google.com\r\n"
5139 "Connection: keep-alive\r\n"
5140 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5143 MockRead data_reads2[] = {
5144 MockRead("HTTP/1.0 200 OK\r\n"),
5145 MockRead("Content-Length: 100\r\n\r\n"),
5146 MockRead(SYNCHRONOUS, OK),
5149 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5150 data_writes1, arraysize(data_writes1));
5151 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5152 data_writes2, arraysize(data_writes2));
5153 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5154 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5156 TestCompletionCallback callback1;
5157 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5158 EXPECT_EQ(ERR_IO_PENDING, rv);
5159 rv = callback1.WaitForResult();
5160 EXPECT_EQ(OK, rv);
5161 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5163 TestCompletionCallback callback2;
5164 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5165 EXPECT_EQ(ERR_IO_PENDING, rv);
5166 rv = callback2.WaitForResult();
5167 EXPECT_EQ(OK, rv);
5168 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5170 const HttpResponseInfo* response = trans->GetResponseInfo();
5171 ASSERT_TRUE(response != NULL);
5173 // There is no challenge info, since the identity in URL worked.
5174 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5176 EXPECT_EQ(100, response->headers->GetContentLength());
5178 // Empty the current queue.
5179 base::MessageLoop::current()->RunUntilIdle();
5182 // Test the request-challenge-retry sequence for basic auth when there is an
5183 // incorrect identity in the URL. The identity from the URL should be used only
5184 // once.
5185 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5186 HttpRequestInfo request;
5187 request.method = "GET";
5188 // Note: the URL has a username:password in it. The password "baz" is
5189 // wrong (should be "bar").
5190 request.url = GURL("http://foo:baz@www.google.com/");
5192 request.load_flags = LOAD_NORMAL;
5194 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5195 scoped_ptr<HttpTransaction> trans(
5196 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5198 MockWrite data_writes1[] = {
5199 MockWrite("GET / HTTP/1.1\r\n"
5200 "Host: www.google.com\r\n"
5201 "Connection: keep-alive\r\n\r\n"),
5204 MockRead data_reads1[] = {
5205 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5206 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5207 MockRead("Content-Length: 10\r\n\r\n"),
5208 MockRead(SYNCHRONOUS, ERR_FAILED),
5211 // After the challenge above, the transaction will be restarted using the
5212 // identity from the url (foo, baz) to answer the challenge.
5213 MockWrite data_writes2[] = {
5214 MockWrite("GET / HTTP/1.1\r\n"
5215 "Host: www.google.com\r\n"
5216 "Connection: keep-alive\r\n"
5217 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5220 MockRead data_reads2[] = {
5221 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5222 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5223 MockRead("Content-Length: 10\r\n\r\n"),
5224 MockRead(SYNCHRONOUS, ERR_FAILED),
5227 // After the challenge above, the transaction will be restarted using the
5228 // identity supplied by the user (foo, bar) to answer the challenge.
5229 MockWrite data_writes3[] = {
5230 MockWrite("GET / HTTP/1.1\r\n"
5231 "Host: www.google.com\r\n"
5232 "Connection: keep-alive\r\n"
5233 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5236 MockRead data_reads3[] = {
5237 MockRead("HTTP/1.0 200 OK\r\n"),
5238 MockRead("Content-Length: 100\r\n\r\n"),
5239 MockRead(SYNCHRONOUS, OK),
5242 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5243 data_writes1, arraysize(data_writes1));
5244 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5245 data_writes2, arraysize(data_writes2));
5246 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5247 data_writes3, arraysize(data_writes3));
5248 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5249 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5250 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5252 TestCompletionCallback callback1;
5254 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5255 EXPECT_EQ(ERR_IO_PENDING, rv);
5257 rv = callback1.WaitForResult();
5258 EXPECT_EQ(OK, rv);
5260 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5261 TestCompletionCallback callback2;
5262 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5263 EXPECT_EQ(ERR_IO_PENDING, rv);
5264 rv = callback2.WaitForResult();
5265 EXPECT_EQ(OK, rv);
5266 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5268 const HttpResponseInfo* response = trans->GetResponseInfo();
5269 ASSERT_TRUE(response != NULL);
5270 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5272 TestCompletionCallback callback3;
5273 rv = trans->RestartWithAuth(
5274 AuthCredentials(kFoo, kBar), callback3.callback());
5275 EXPECT_EQ(ERR_IO_PENDING, rv);
5276 rv = callback3.WaitForResult();
5277 EXPECT_EQ(OK, rv);
5278 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5280 response = trans->GetResponseInfo();
5281 ASSERT_TRUE(response != NULL);
5283 // There is no challenge info, since the identity worked.
5284 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5286 EXPECT_EQ(100, response->headers->GetContentLength());
5288 // Empty the current queue.
5289 base::MessageLoop::current()->RunUntilIdle();
5293 // Test the request-challenge-retry sequence for basic auth when there is a
5294 // correct identity in the URL, but its use is being suppressed. The identity
5295 // from the URL should never be used.
5296 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5297 HttpRequestInfo request;
5298 request.method = "GET";
5299 request.url = GURL("http://foo:bar@www.google.com/");
5300 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5302 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5303 scoped_ptr<HttpTransaction> trans(
5304 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5306 MockWrite data_writes1[] = {
5307 MockWrite("GET / HTTP/1.1\r\n"
5308 "Host: www.google.com\r\n"
5309 "Connection: keep-alive\r\n\r\n"),
5312 MockRead data_reads1[] = {
5313 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5314 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5315 MockRead("Content-Length: 10\r\n\r\n"),
5316 MockRead(SYNCHRONOUS, ERR_FAILED),
5319 // After the challenge above, the transaction will be restarted using the
5320 // identity supplied by the user, not the one in the URL, to answer the
5321 // challenge.
5322 MockWrite data_writes3[] = {
5323 MockWrite("GET / HTTP/1.1\r\n"
5324 "Host: www.google.com\r\n"
5325 "Connection: keep-alive\r\n"
5326 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5329 MockRead data_reads3[] = {
5330 MockRead("HTTP/1.0 200 OK\r\n"),
5331 MockRead("Content-Length: 100\r\n\r\n"),
5332 MockRead(SYNCHRONOUS, OK),
5335 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5336 data_writes1, arraysize(data_writes1));
5337 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5338 data_writes3, arraysize(data_writes3));
5339 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5340 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5342 TestCompletionCallback callback1;
5343 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5344 EXPECT_EQ(ERR_IO_PENDING, rv);
5345 rv = callback1.WaitForResult();
5346 EXPECT_EQ(OK, rv);
5347 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5349 const HttpResponseInfo* response = trans->GetResponseInfo();
5350 ASSERT_TRUE(response != NULL);
5351 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5353 TestCompletionCallback callback3;
5354 rv = trans->RestartWithAuth(
5355 AuthCredentials(kFoo, kBar), callback3.callback());
5356 EXPECT_EQ(ERR_IO_PENDING, rv);
5357 rv = callback3.WaitForResult();
5358 EXPECT_EQ(OK, rv);
5359 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5361 response = trans->GetResponseInfo();
5362 ASSERT_TRUE(response != NULL);
5364 // There is no challenge info, since the identity worked.
5365 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5366 EXPECT_EQ(100, response->headers->GetContentLength());
5368 // Empty the current queue.
5369 base::MessageLoop::current()->RunUntilIdle();
5372 // Test that previously tried username/passwords for a realm get re-used.
5373 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5374 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5376 // Transaction 1: authenticate (foo, bar) on MyRealm1
5378 HttpRequestInfo request;
5379 request.method = "GET";
5380 request.url = GURL("http://www.google.com/x/y/z");
5381 request.load_flags = 0;
5383 scoped_ptr<HttpTransaction> trans(
5384 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5386 MockWrite data_writes1[] = {
5387 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5388 "Host: www.google.com\r\n"
5389 "Connection: keep-alive\r\n\r\n"),
5392 MockRead data_reads1[] = {
5393 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5394 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5395 MockRead("Content-Length: 10000\r\n\r\n"),
5396 MockRead(SYNCHRONOUS, ERR_FAILED),
5399 // Resend with authorization (username=foo, password=bar)
5400 MockWrite data_writes2[] = {
5401 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5402 "Host: www.google.com\r\n"
5403 "Connection: keep-alive\r\n"
5404 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5407 // Sever accepts the authorization.
5408 MockRead data_reads2[] = {
5409 MockRead("HTTP/1.0 200 OK\r\n"),
5410 MockRead("Content-Length: 100\r\n\r\n"),
5411 MockRead(SYNCHRONOUS, OK),
5414 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5415 data_writes1, arraysize(data_writes1));
5416 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5417 data_writes2, arraysize(data_writes2));
5418 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5419 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5421 TestCompletionCallback callback1;
5423 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5424 EXPECT_EQ(ERR_IO_PENDING, rv);
5426 rv = callback1.WaitForResult();
5427 EXPECT_EQ(OK, rv);
5429 const HttpResponseInfo* response = trans->GetResponseInfo();
5430 ASSERT_TRUE(response != NULL);
5431 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5433 TestCompletionCallback callback2;
5435 rv = trans->RestartWithAuth(
5436 AuthCredentials(kFoo, kBar), callback2.callback());
5437 EXPECT_EQ(ERR_IO_PENDING, rv);
5439 rv = callback2.WaitForResult();
5440 EXPECT_EQ(OK, rv);
5442 response = trans->GetResponseInfo();
5443 ASSERT_TRUE(response != NULL);
5444 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5445 EXPECT_EQ(100, response->headers->GetContentLength());
5448 // ------------------------------------------------------------------------
5450 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5452 HttpRequestInfo request;
5453 request.method = "GET";
5454 // Note that Transaction 1 was at /x/y/z, so this is in the same
5455 // protection space as MyRealm1.
5456 request.url = GURL("http://www.google.com/x/y/a/b");
5457 request.load_flags = 0;
5459 scoped_ptr<HttpTransaction> trans(
5460 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5462 MockWrite data_writes1[] = {
5463 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5464 "Host: www.google.com\r\n"
5465 "Connection: keep-alive\r\n"
5466 // Send preemptive authorization for MyRealm1
5467 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5470 // The server didn't like the preemptive authorization, and
5471 // challenges us for a different realm (MyRealm2).
5472 MockRead data_reads1[] = {
5473 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5474 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5475 MockRead("Content-Length: 10000\r\n\r\n"),
5476 MockRead(SYNCHRONOUS, ERR_FAILED),
5479 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5480 MockWrite data_writes2[] = {
5481 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5482 "Host: www.google.com\r\n"
5483 "Connection: keep-alive\r\n"
5484 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5487 // Sever accepts the authorization.
5488 MockRead data_reads2[] = {
5489 MockRead("HTTP/1.0 200 OK\r\n"),
5490 MockRead("Content-Length: 100\r\n\r\n"),
5491 MockRead(SYNCHRONOUS, OK),
5494 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5495 data_writes1, arraysize(data_writes1));
5496 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5497 data_writes2, arraysize(data_writes2));
5498 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5499 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5501 TestCompletionCallback callback1;
5503 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5504 EXPECT_EQ(ERR_IO_PENDING, rv);
5506 rv = callback1.WaitForResult();
5507 EXPECT_EQ(OK, rv);
5509 const HttpResponseInfo* response = trans->GetResponseInfo();
5510 ASSERT_TRUE(response != NULL);
5511 ASSERT_TRUE(response->auth_challenge.get());
5512 EXPECT_FALSE(response->auth_challenge->is_proxy);
5513 EXPECT_EQ("www.google.com:80",
5514 response->auth_challenge->challenger.ToString());
5515 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5516 EXPECT_EQ("basic", response->auth_challenge->scheme);
5518 TestCompletionCallback callback2;
5520 rv = trans->RestartWithAuth(
5521 AuthCredentials(kFoo2, kBar2), callback2.callback());
5522 EXPECT_EQ(ERR_IO_PENDING, rv);
5524 rv = callback2.WaitForResult();
5525 EXPECT_EQ(OK, rv);
5527 response = trans->GetResponseInfo();
5528 ASSERT_TRUE(response != NULL);
5529 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5530 EXPECT_EQ(100, response->headers->GetContentLength());
5533 // ------------------------------------------------------------------------
5535 // Transaction 3: Resend a request in MyRealm's protection space --
5536 // succeed with preemptive authorization.
5538 HttpRequestInfo request;
5539 request.method = "GET";
5540 request.url = GURL("http://www.google.com/x/y/z2");
5541 request.load_flags = 0;
5543 scoped_ptr<HttpTransaction> trans(
5544 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5546 MockWrite data_writes1[] = {
5547 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5548 "Host: www.google.com\r\n"
5549 "Connection: keep-alive\r\n"
5550 // The authorization for MyRealm1 gets sent preemptively
5551 // (since the url is in the same protection space)
5552 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5555 // Sever accepts the preemptive authorization
5556 MockRead data_reads1[] = {
5557 MockRead("HTTP/1.0 200 OK\r\n"),
5558 MockRead("Content-Length: 100\r\n\r\n"),
5559 MockRead(SYNCHRONOUS, OK),
5562 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5563 data_writes1, arraysize(data_writes1));
5564 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5566 TestCompletionCallback callback1;
5568 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5569 EXPECT_EQ(ERR_IO_PENDING, rv);
5571 rv = callback1.WaitForResult();
5572 EXPECT_EQ(OK, rv);
5574 const HttpResponseInfo* response = trans->GetResponseInfo();
5575 ASSERT_TRUE(response != NULL);
5577 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5578 EXPECT_EQ(100, response->headers->GetContentLength());
5581 // ------------------------------------------------------------------------
5583 // Transaction 4: request another URL in MyRealm (however the
5584 // url is not known to belong to the protection space, so no pre-auth).
5586 HttpRequestInfo request;
5587 request.method = "GET";
5588 request.url = GURL("http://www.google.com/x/1");
5589 request.load_flags = 0;
5591 scoped_ptr<HttpTransaction> trans(
5592 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5594 MockWrite data_writes1[] = {
5595 MockWrite("GET /x/1 HTTP/1.1\r\n"
5596 "Host: www.google.com\r\n"
5597 "Connection: keep-alive\r\n\r\n"),
5600 MockRead data_reads1[] = {
5601 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5602 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5603 MockRead("Content-Length: 10000\r\n\r\n"),
5604 MockRead(SYNCHRONOUS, ERR_FAILED),
5607 // Resend with authorization from MyRealm's cache.
5608 MockWrite data_writes2[] = {
5609 MockWrite("GET /x/1 HTTP/1.1\r\n"
5610 "Host: www.google.com\r\n"
5611 "Connection: keep-alive\r\n"
5612 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5615 // Sever accepts the authorization.
5616 MockRead data_reads2[] = {
5617 MockRead("HTTP/1.0 200 OK\r\n"),
5618 MockRead("Content-Length: 100\r\n\r\n"),
5619 MockRead(SYNCHRONOUS, OK),
5622 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5623 data_writes1, arraysize(data_writes1));
5624 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5625 data_writes2, arraysize(data_writes2));
5626 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5627 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5629 TestCompletionCallback callback1;
5631 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5632 EXPECT_EQ(ERR_IO_PENDING, rv);
5634 rv = callback1.WaitForResult();
5635 EXPECT_EQ(OK, rv);
5637 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5638 TestCompletionCallback callback2;
5639 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5640 EXPECT_EQ(ERR_IO_PENDING, rv);
5641 rv = callback2.WaitForResult();
5642 EXPECT_EQ(OK, rv);
5643 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5645 const HttpResponseInfo* response = trans->GetResponseInfo();
5646 ASSERT_TRUE(response != NULL);
5647 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5648 EXPECT_EQ(100, response->headers->GetContentLength());
5651 // ------------------------------------------------------------------------
5653 // Transaction 5: request a URL in MyRealm, but the server rejects the
5654 // cached identity. Should invalidate and re-prompt.
5656 HttpRequestInfo request;
5657 request.method = "GET";
5658 request.url = GURL("http://www.google.com/p/q/t");
5659 request.load_flags = 0;
5661 scoped_ptr<HttpTransaction> trans(
5662 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5664 MockWrite data_writes1[] = {
5665 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5666 "Host: www.google.com\r\n"
5667 "Connection: keep-alive\r\n\r\n"),
5670 MockRead data_reads1[] = {
5671 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5672 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5673 MockRead("Content-Length: 10000\r\n\r\n"),
5674 MockRead(SYNCHRONOUS, ERR_FAILED),
5677 // Resend with authorization from cache for MyRealm.
5678 MockWrite data_writes2[] = {
5679 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5680 "Host: www.google.com\r\n"
5681 "Connection: keep-alive\r\n"
5682 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5685 // Sever rejects the authorization.
5686 MockRead data_reads2[] = {
5687 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5688 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5689 MockRead("Content-Length: 10000\r\n\r\n"),
5690 MockRead(SYNCHRONOUS, ERR_FAILED),
5693 // At this point we should prompt for new credentials for MyRealm.
5694 // Restart with username=foo3, password=foo4.
5695 MockWrite data_writes3[] = {
5696 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5697 "Host: www.google.com\r\n"
5698 "Connection: keep-alive\r\n"
5699 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5702 // Sever accepts the authorization.
5703 MockRead data_reads3[] = {
5704 MockRead("HTTP/1.0 200 OK\r\n"),
5705 MockRead("Content-Length: 100\r\n\r\n"),
5706 MockRead(SYNCHRONOUS, OK),
5709 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5710 data_writes1, arraysize(data_writes1));
5711 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5712 data_writes2, arraysize(data_writes2));
5713 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5714 data_writes3, arraysize(data_writes3));
5715 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5716 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5717 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5719 TestCompletionCallback callback1;
5721 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5722 EXPECT_EQ(ERR_IO_PENDING, rv);
5724 rv = callback1.WaitForResult();
5725 EXPECT_EQ(OK, rv);
5727 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5728 TestCompletionCallback callback2;
5729 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5730 EXPECT_EQ(ERR_IO_PENDING, rv);
5731 rv = callback2.WaitForResult();
5732 EXPECT_EQ(OK, rv);
5733 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5735 const HttpResponseInfo* response = trans->GetResponseInfo();
5736 ASSERT_TRUE(response != NULL);
5737 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5739 TestCompletionCallback callback3;
5741 rv = trans->RestartWithAuth(
5742 AuthCredentials(kFoo3, kBar3), callback3.callback());
5743 EXPECT_EQ(ERR_IO_PENDING, rv);
5745 rv = callback3.WaitForResult();
5746 EXPECT_EQ(OK, rv);
5748 response = trans->GetResponseInfo();
5749 ASSERT_TRUE(response != NULL);
5750 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5751 EXPECT_EQ(100, response->headers->GetContentLength());
5755 // Tests that nonce count increments when multiple auth attempts
5756 // are started with the same nonce.
5757 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5758 HttpAuthHandlerDigest::Factory* digest_factory =
5759 new HttpAuthHandlerDigest::Factory();
5760 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5761 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5762 digest_factory->set_nonce_generator(nonce_generator);
5763 session_deps_.http_auth_handler_factory.reset(digest_factory);
5764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5766 // Transaction 1: authenticate (foo, bar) on MyRealm1
5768 HttpRequestInfo request;
5769 request.method = "GET";
5770 request.url = GURL("http://www.google.com/x/y/z");
5771 request.load_flags = 0;
5773 scoped_ptr<HttpTransaction> trans(
5774 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5776 MockWrite data_writes1[] = {
5777 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5778 "Host: www.google.com\r\n"
5779 "Connection: keep-alive\r\n\r\n"),
5782 MockRead data_reads1[] = {
5783 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5784 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5785 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5786 MockRead(SYNCHRONOUS, OK),
5789 // Resend with authorization (username=foo, password=bar)
5790 MockWrite data_writes2[] = {
5791 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5792 "Host: www.google.com\r\n"
5793 "Connection: keep-alive\r\n"
5794 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5795 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5796 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5797 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5800 // Sever accepts the authorization.
5801 MockRead data_reads2[] = {
5802 MockRead("HTTP/1.0 200 OK\r\n"),
5803 MockRead(SYNCHRONOUS, OK),
5806 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5807 data_writes1, arraysize(data_writes1));
5808 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5809 data_writes2, arraysize(data_writes2));
5810 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5811 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5813 TestCompletionCallback callback1;
5815 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5816 EXPECT_EQ(ERR_IO_PENDING, rv);
5818 rv = callback1.WaitForResult();
5819 EXPECT_EQ(OK, rv);
5821 const HttpResponseInfo* response = trans->GetResponseInfo();
5822 ASSERT_TRUE(response != NULL);
5823 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5825 TestCompletionCallback callback2;
5827 rv = trans->RestartWithAuth(
5828 AuthCredentials(kFoo, kBar), callback2.callback());
5829 EXPECT_EQ(ERR_IO_PENDING, rv);
5831 rv = callback2.WaitForResult();
5832 EXPECT_EQ(OK, rv);
5834 response = trans->GetResponseInfo();
5835 ASSERT_TRUE(response != NULL);
5836 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5839 // ------------------------------------------------------------------------
5841 // Transaction 2: Request another resource in digestive's protection space.
5842 // This will preemptively add an Authorization header which should have an
5843 // "nc" value of 2 (as compared to 1 in the first use.
5845 HttpRequestInfo request;
5846 request.method = "GET";
5847 // Note that Transaction 1 was at /x/y/z, so this is in the same
5848 // protection space as digest.
5849 request.url = GURL("http://www.google.com/x/y/a/b");
5850 request.load_flags = 0;
5852 scoped_ptr<HttpTransaction> trans(
5853 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5855 MockWrite data_writes1[] = {
5856 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5857 "Host: www.google.com\r\n"
5858 "Connection: keep-alive\r\n"
5859 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5860 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5861 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5862 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5865 // Sever accepts the authorization.
5866 MockRead data_reads1[] = {
5867 MockRead("HTTP/1.0 200 OK\r\n"),
5868 MockRead("Content-Length: 100\r\n\r\n"),
5869 MockRead(SYNCHRONOUS, OK),
5872 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5873 data_writes1, arraysize(data_writes1));
5874 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5876 TestCompletionCallback callback1;
5878 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5879 EXPECT_EQ(ERR_IO_PENDING, rv);
5881 rv = callback1.WaitForResult();
5882 EXPECT_EQ(OK, rv);
5884 const HttpResponseInfo* response = trans->GetResponseInfo();
5885 ASSERT_TRUE(response != NULL);
5886 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5890 // Test the ResetStateForRestart() private method.
5891 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5892 // Create a transaction (the dependencies aren't important).
5893 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5894 scoped_ptr<HttpNetworkTransaction> trans(
5895 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5897 // Setup some state (which we expect ResetStateForRestart() will clear).
5898 trans->read_buf_ = new IOBuffer(15);
5899 trans->read_buf_len_ = 15;
5900 trans->request_headers_.SetHeader("Authorization", "NTLM");
5902 // Setup state in response_
5903 HttpResponseInfo* response = &trans->response_;
5904 response->auth_challenge = new AuthChallengeInfo();
5905 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
5906 response->response_time = base::Time::Now();
5907 response->was_cached = true; // (Wouldn't ever actually be true...)
5909 { // Setup state for response_.vary_data
5910 HttpRequestInfo request;
5911 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5912 std::replace(temp.begin(), temp.end(), '\n', '\0');
5913 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5914 request.extra_headers.SetHeader("Foo", "1");
5915 request.extra_headers.SetHeader("bar", "23");
5916 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5919 // Cause the above state to be reset.
5920 trans->ResetStateForRestart();
5922 // Verify that the state that needed to be reset, has been reset.
5923 EXPECT_TRUE(trans->read_buf_.get() == NULL);
5924 EXPECT_EQ(0, trans->read_buf_len_);
5925 EXPECT_TRUE(trans->request_headers_.IsEmpty());
5926 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5927 EXPECT_TRUE(response->headers.get() == NULL);
5928 EXPECT_FALSE(response->was_cached);
5929 EXPECT_EQ(0U, response->ssl_info.cert_status);
5930 EXPECT_FALSE(response->vary_data.is_valid());
5933 // Test HTTPS connections to a site with a bad certificate
5934 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5935 HttpRequestInfo request;
5936 request.method = "GET";
5937 request.url = GURL("https://www.google.com/");
5938 request.load_flags = 0;
5940 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5941 scoped_ptr<HttpTransaction> trans(
5942 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5944 MockWrite data_writes[] = {
5945 MockWrite("GET / HTTP/1.1\r\n"
5946 "Host: www.google.com\r\n"
5947 "Connection: keep-alive\r\n\r\n"),
5950 MockRead data_reads[] = {
5951 MockRead("HTTP/1.0 200 OK\r\n"),
5952 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5953 MockRead("Content-Length: 100\r\n\r\n"),
5954 MockRead(SYNCHRONOUS, OK),
5957 StaticSocketDataProvider ssl_bad_certificate;
5958 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5959 data_writes, arraysize(data_writes));
5960 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5961 SSLSocketDataProvider ssl(ASYNC, OK);
5963 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5964 session_deps_.socket_factory->AddSocketDataProvider(&data);
5965 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5966 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5968 TestCompletionCallback callback;
5970 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5971 EXPECT_EQ(ERR_IO_PENDING, rv);
5973 rv = callback.WaitForResult();
5974 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5976 rv = trans->RestartIgnoringLastError(callback.callback());
5977 EXPECT_EQ(ERR_IO_PENDING, rv);
5979 rv = callback.WaitForResult();
5980 EXPECT_EQ(OK, rv);
5982 const HttpResponseInfo* response = trans->GetResponseInfo();
5984 ASSERT_TRUE(response != NULL);
5985 EXPECT_EQ(100, response->headers->GetContentLength());
5988 // Test HTTPS connections to a site with a bad certificate, going through a
5989 // proxy
5990 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5991 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5993 HttpRequestInfo request;
5994 request.method = "GET";
5995 request.url = GURL("https://www.google.com/");
5996 request.load_flags = 0;
5998 MockWrite proxy_writes[] = {
5999 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6000 "Host: www.google.com\r\n"
6001 "Proxy-Connection: keep-alive\r\n\r\n"),
6004 MockRead proxy_reads[] = {
6005 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6006 MockRead(SYNCHRONOUS, OK)
6009 MockWrite data_writes[] = {
6010 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6011 "Host: www.google.com\r\n"
6012 "Proxy-Connection: keep-alive\r\n\r\n"),
6013 MockWrite("GET / HTTP/1.1\r\n"
6014 "Host: www.google.com\r\n"
6015 "Connection: keep-alive\r\n\r\n"),
6018 MockRead data_reads[] = {
6019 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6020 MockRead("HTTP/1.0 200 OK\r\n"),
6021 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6022 MockRead("Content-Length: 100\r\n\r\n"),
6023 MockRead(SYNCHRONOUS, OK),
6026 StaticSocketDataProvider ssl_bad_certificate(
6027 proxy_reads, arraysize(proxy_reads),
6028 proxy_writes, arraysize(proxy_writes));
6029 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6030 data_writes, arraysize(data_writes));
6031 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6032 SSLSocketDataProvider ssl(ASYNC, OK);
6034 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6035 session_deps_.socket_factory->AddSocketDataProvider(&data);
6036 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6037 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6039 TestCompletionCallback callback;
6041 for (int i = 0; i < 2; i++) {
6042 session_deps_.socket_factory->ResetNextMockIndexes();
6044 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6045 scoped_ptr<HttpTransaction> trans(
6046 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6048 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6049 EXPECT_EQ(ERR_IO_PENDING, rv);
6051 rv = callback.WaitForResult();
6052 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6054 rv = trans->RestartIgnoringLastError(callback.callback());
6055 EXPECT_EQ(ERR_IO_PENDING, rv);
6057 rv = callback.WaitForResult();
6058 EXPECT_EQ(OK, rv);
6060 const HttpResponseInfo* response = trans->GetResponseInfo();
6062 ASSERT_TRUE(response != NULL);
6063 EXPECT_EQ(100, response->headers->GetContentLength());
6068 // Test HTTPS connections to a site, going through an HTTPS proxy
6069 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6070 session_deps_.proxy_service.reset(
6071 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6072 CapturingNetLog net_log;
6073 session_deps_.net_log = &net_log;
6075 HttpRequestInfo request;
6076 request.method = "GET";
6077 request.url = GURL("https://www.google.com/");
6078 request.load_flags = 0;
6080 MockWrite data_writes[] = {
6081 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6082 "Host: www.google.com\r\n"
6083 "Proxy-Connection: keep-alive\r\n\r\n"),
6084 MockWrite("GET / HTTP/1.1\r\n"
6085 "Host: www.google.com\r\n"
6086 "Connection: keep-alive\r\n\r\n"),
6089 MockRead data_reads[] = {
6090 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6091 MockRead("HTTP/1.1 200 OK\r\n"),
6092 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6093 MockRead("Content-Length: 100\r\n\r\n"),
6094 MockRead(SYNCHRONOUS, OK),
6097 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6098 data_writes, arraysize(data_writes));
6099 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6100 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6102 session_deps_.socket_factory->AddSocketDataProvider(&data);
6103 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6104 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6106 TestCompletionCallback callback;
6108 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6109 scoped_ptr<HttpTransaction> trans(
6110 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6112 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6113 EXPECT_EQ(ERR_IO_PENDING, rv);
6115 rv = callback.WaitForResult();
6116 EXPECT_EQ(OK, rv);
6117 const HttpResponseInfo* response = trans->GetResponseInfo();
6119 ASSERT_TRUE(response != NULL);
6121 EXPECT_TRUE(response->headers->IsKeepAlive());
6122 EXPECT_EQ(200, response->headers->response_code());
6123 EXPECT_EQ(100, response->headers->GetContentLength());
6124 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6126 LoadTimingInfo load_timing_info;
6127 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6128 TestLoadTimingNotReusedWithPac(load_timing_info,
6129 CONNECT_TIMING_HAS_SSL_TIMES);
6132 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6133 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6134 session_deps_.proxy_service.reset(
6135 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6136 CapturingNetLog net_log;
6137 session_deps_.net_log = &net_log;
6139 HttpRequestInfo request;
6140 request.method = "GET";
6141 request.url = GURL("https://www.google.com/");
6142 request.load_flags = 0;
6144 MockWrite data_writes[] = {
6145 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6146 "Host: www.google.com\r\n"
6147 "Proxy-Connection: keep-alive\r\n\r\n"),
6150 MockRead data_reads[] = {
6151 MockRead("HTTP/1.1 302 Redirect\r\n"),
6152 MockRead("Location: http://login.example.com/\r\n"),
6153 MockRead("Content-Length: 0\r\n\r\n"),
6154 MockRead(SYNCHRONOUS, OK),
6157 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6158 data_writes, arraysize(data_writes));
6159 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6161 session_deps_.socket_factory->AddSocketDataProvider(&data);
6162 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6164 TestCompletionCallback callback;
6166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6167 scoped_ptr<HttpTransaction> trans(
6168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6170 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6171 EXPECT_EQ(ERR_IO_PENDING, rv);
6173 rv = callback.WaitForResult();
6174 EXPECT_EQ(OK, rv);
6175 const HttpResponseInfo* response = trans->GetResponseInfo();
6177 ASSERT_TRUE(response != NULL);
6179 EXPECT_EQ(302, response->headers->response_code());
6180 std::string url;
6181 EXPECT_TRUE(response->headers->IsRedirect(&url));
6182 EXPECT_EQ("http://login.example.com/", url);
6184 // In the case of redirects from proxies, HttpNetworkTransaction returns
6185 // timing for the proxy connection instead of the connection to the host,
6186 // and no send / receive times.
6187 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6188 LoadTimingInfo load_timing_info;
6189 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6191 EXPECT_FALSE(load_timing_info.socket_reused);
6192 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6194 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6195 EXPECT_LE(load_timing_info.proxy_resolve_start,
6196 load_timing_info.proxy_resolve_end);
6197 EXPECT_LE(load_timing_info.proxy_resolve_end,
6198 load_timing_info.connect_timing.connect_start);
6199 ExpectConnectTimingHasTimes(
6200 load_timing_info.connect_timing,
6201 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6203 EXPECT_TRUE(load_timing_info.send_start.is_null());
6204 EXPECT_TRUE(load_timing_info.send_end.is_null());
6205 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6208 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6209 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6210 session_deps_.proxy_service.reset(
6211 ProxyService::CreateFixed("https://proxy:70"));
6213 HttpRequestInfo request;
6214 request.method = "GET";
6215 request.url = GURL("https://www.google.com/");
6216 request.load_flags = 0;
6218 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6219 LOWEST));
6220 scoped_ptr<SpdyFrame> goaway(
6221 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6222 MockWrite data_writes[] = {
6223 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6224 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
6227 static const char* const kExtraHeaders[] = {
6228 "location",
6229 "http://login.example.com/",
6231 scoped_ptr<SpdyFrame> resp(
6232 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6233 arraysize(kExtraHeaders)/2, 1));
6234 MockRead data_reads[] = {
6235 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6236 MockRead(ASYNC, 0, 2), // EOF
6239 DelayedSocketData data(
6240 1, // wait for one write to finish before reading.
6241 data_reads, arraysize(data_reads),
6242 data_writes, arraysize(data_writes));
6243 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6244 proxy_ssl.SetNextProto(GetParam());
6246 session_deps_.socket_factory->AddSocketDataProvider(&data);
6247 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6249 TestCompletionCallback callback;
6251 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6252 scoped_ptr<HttpTransaction> trans(
6253 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6255 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6256 EXPECT_EQ(ERR_IO_PENDING, rv);
6258 rv = callback.WaitForResult();
6259 EXPECT_EQ(OK, rv);
6260 const HttpResponseInfo* response = trans->GetResponseInfo();
6262 ASSERT_TRUE(response != NULL);
6264 EXPECT_EQ(302, response->headers->response_code());
6265 std::string url;
6266 EXPECT_TRUE(response->headers->IsRedirect(&url));
6267 EXPECT_EQ("http://login.example.com/", url);
6270 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6271 TEST_P(HttpNetworkTransactionTest,
6272 ErrorResponseToHttpsConnectViaHttpsProxy) {
6273 session_deps_.proxy_service.reset(
6274 ProxyService::CreateFixed("https://proxy:70"));
6276 HttpRequestInfo request;
6277 request.method = "GET";
6278 request.url = GURL("https://www.google.com/");
6279 request.load_flags = 0;
6281 MockWrite data_writes[] = {
6282 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6283 "Host: www.google.com\r\n"
6284 "Proxy-Connection: keep-alive\r\n\r\n"),
6287 MockRead data_reads[] = {
6288 MockRead("HTTP/1.1 404 Not Found\r\n"),
6289 MockRead("Content-Length: 23\r\n\r\n"),
6290 MockRead("The host does not exist"),
6291 MockRead(SYNCHRONOUS, OK),
6294 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6295 data_writes, arraysize(data_writes));
6296 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6298 session_deps_.socket_factory->AddSocketDataProvider(&data);
6299 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6301 TestCompletionCallback callback;
6303 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6304 scoped_ptr<HttpTransaction> trans(
6305 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6307 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6308 EXPECT_EQ(ERR_IO_PENDING, rv);
6310 rv = callback.WaitForResult();
6311 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6313 // TODO(ttuttle): Anything else to check here?
6316 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6317 TEST_P(HttpNetworkTransactionTest,
6318 ErrorResponseToHttpsConnectViaSpdyProxy) {
6319 session_deps_.proxy_service.reset(
6320 ProxyService::CreateFixed("https://proxy:70"));
6322 HttpRequestInfo request;
6323 request.method = "GET";
6324 request.url = GURL("https://www.google.com/");
6325 request.load_flags = 0;
6327 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6328 LOWEST));
6329 scoped_ptr<SpdyFrame> rst(
6330 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6331 MockWrite data_writes[] = {
6332 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6333 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6336 static const char* const kExtraHeaders[] = {
6337 "location",
6338 "http://login.example.com/",
6340 scoped_ptr<SpdyFrame> resp(
6341 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6342 arraysize(kExtraHeaders)/2, 1));
6343 scoped_ptr<SpdyFrame> body(
6344 spdy_util_.ConstructSpdyBodyFrame(
6345 1, "The host does not exist", 23, true));
6346 MockRead data_reads[] = {
6347 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6348 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6349 MockRead(ASYNC, 0, 4), // EOF
6352 DelayedSocketData data(
6353 1, // wait for one write to finish before reading.
6354 data_reads, arraysize(data_reads),
6355 data_writes, arraysize(data_writes));
6356 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6357 proxy_ssl.SetNextProto(GetParam());
6359 session_deps_.socket_factory->AddSocketDataProvider(&data);
6360 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6362 TestCompletionCallback callback;
6364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6365 scoped_ptr<HttpTransaction> trans(
6366 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6368 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6369 EXPECT_EQ(ERR_IO_PENDING, rv);
6371 rv = callback.WaitForResult();
6372 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6374 // TODO(ttuttle): Anything else to check here?
6377 // Test the request-challenge-retry sequence for basic auth, through
6378 // a SPDY proxy over a single SPDY session.
6379 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6380 HttpRequestInfo request;
6381 request.method = "GET";
6382 request.url = GURL("https://www.google.com/");
6383 // when the no authentication data flag is set.
6384 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
6386 // Configure against https proxy server "myproxy:70".
6387 session_deps_.proxy_service.reset(
6388 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6389 CapturingBoundNetLog log;
6390 session_deps_.net_log = log.bound().net_log();
6391 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6393 // Since we have proxy, should try to establish tunnel.
6394 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6395 LOWEST));
6396 scoped_ptr<SpdyFrame> rst(
6397 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6399 // After calling trans->RestartWithAuth(), this is the request we should
6400 // be issuing -- the final header line contains the credentials.
6401 const char* const kAuthCredentials[] = {
6402 "proxy-authorization", "Basic Zm9vOmJhcg==",
6404 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6405 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
6406 // fetch https://www.google.com/ via HTTP
6407 const char get[] = "GET / HTTP/1.1\r\n"
6408 "Host: www.google.com\r\n"
6409 "Connection: keep-alive\r\n\r\n";
6410 scoped_ptr<SpdyFrame> wrapped_get(
6411 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6413 MockWrite spdy_writes[] = {
6414 CreateMockWrite(*req, 1, ASYNC),
6415 CreateMockWrite(*rst, 4, ASYNC),
6416 CreateMockWrite(*connect2, 5),
6417 CreateMockWrite(*wrapped_get, 8),
6420 // The proxy responds to the connect with a 407, using a persistent
6421 // connection.
6422 const char* const kAuthStatus = "407";
6423 const char* const kAuthChallenge[] = {
6424 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6426 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6427 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6429 scoped_ptr<SpdyFrame> conn_resp(
6430 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6431 const char resp[] = "HTTP/1.1 200 OK\r\n"
6432 "Content-Length: 5\r\n\r\n";
6434 scoped_ptr<SpdyFrame> wrapped_get_resp(
6435 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6436 scoped_ptr<SpdyFrame> wrapped_body(
6437 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6438 MockRead spdy_reads[] = {
6439 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6440 CreateMockRead(*conn_resp, 6, ASYNC),
6441 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6442 CreateMockRead(*wrapped_body, 10, ASYNC),
6443 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6446 OrderedSocketData spdy_data(
6447 spdy_reads, arraysize(spdy_reads),
6448 spdy_writes, arraysize(spdy_writes));
6449 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6450 // Negotiate SPDY to the proxy
6451 SSLSocketDataProvider proxy(ASYNC, OK);
6452 proxy.SetNextProto(GetParam());
6453 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6454 // Vanilla SSL to the server
6455 SSLSocketDataProvider server(ASYNC, OK);
6456 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6458 TestCompletionCallback callback1;
6460 scoped_ptr<HttpTransaction> trans(
6461 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6463 int rv = trans->Start(&request, callback1.callback(), log.bound());
6464 EXPECT_EQ(ERR_IO_PENDING, rv);
6466 rv = callback1.WaitForResult();
6467 EXPECT_EQ(OK, rv);
6468 net::CapturingNetLog::CapturedEntryList entries;
6469 log.GetEntries(&entries);
6470 size_t pos = ExpectLogContainsSomewhere(
6471 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6472 NetLog::PHASE_NONE);
6473 ExpectLogContainsSomewhere(
6474 entries, pos,
6475 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6476 NetLog::PHASE_NONE);
6478 const HttpResponseInfo* response = trans->GetResponseInfo();
6479 ASSERT_TRUE(response != NULL);
6480 ASSERT_FALSE(response->headers.get() == NULL);
6481 EXPECT_EQ(407, response->headers->response_code());
6482 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6483 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6484 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6486 TestCompletionCallback callback2;
6488 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6489 callback2.callback());
6490 EXPECT_EQ(ERR_IO_PENDING, rv);
6492 rv = callback2.WaitForResult();
6493 EXPECT_EQ(OK, rv);
6495 response = trans->GetResponseInfo();
6496 ASSERT_TRUE(response != NULL);
6498 EXPECT_TRUE(response->headers->IsKeepAlive());
6499 EXPECT_EQ(200, response->headers->response_code());
6500 EXPECT_EQ(5, response->headers->GetContentLength());
6501 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6503 // The password prompt info should not be set.
6504 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6506 LoadTimingInfo load_timing_info;
6507 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6508 TestLoadTimingNotReusedWithPac(load_timing_info,
6509 CONNECT_TIMING_HAS_SSL_TIMES);
6511 trans.reset();
6512 session->CloseAllConnections();
6515 // Test that an explicitly trusted SPDY proxy can push a resource from an
6516 // origin that is different from that of its associated resource.
6517 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6518 HttpRequestInfo request;
6519 HttpRequestInfo push_request;
6521 request.method = "GET";
6522 request.url = GURL("http://www.google.com/");
6523 push_request.method = "GET";
6524 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6526 // Configure against https proxy server "myproxy:70".
6527 session_deps_.proxy_service.reset(
6528 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6529 CapturingBoundNetLog log;
6530 session_deps_.net_log = log.bound().net_log();
6532 // Enable cross-origin push.
6533 session_deps_.trusted_spdy_proxy = "myproxy:70";
6535 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6537 scoped_ptr<SpdyFrame> stream1_syn(
6538 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6540 MockWrite spdy_writes[] = {
6541 CreateMockWrite(*stream1_syn, 1, ASYNC),
6544 scoped_ptr<SpdyFrame>
6545 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6547 scoped_ptr<SpdyFrame>
6548 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6550 scoped_ptr<SpdyFrame>
6551 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6555 "http://www.another-origin.com/foo.dat"));
6556 const char kPushedData[] = "pushed";
6557 scoped_ptr<SpdyFrame> stream2_body(
6558 spdy_util_.ConstructSpdyBodyFrame(
6559 2, kPushedData, strlen(kPushedData), true));
6561 MockRead spdy_reads[] = {
6562 CreateMockRead(*stream1_reply, 2, ASYNC),
6563 CreateMockRead(*stream2_syn, 3, ASYNC),
6564 CreateMockRead(*stream1_body, 4, ASYNC),
6565 CreateMockRead(*stream2_body, 5, ASYNC),
6566 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6569 OrderedSocketData spdy_data(
6570 spdy_reads, arraysize(spdy_reads),
6571 spdy_writes, arraysize(spdy_writes));
6572 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6573 // Negotiate SPDY to the proxy
6574 SSLSocketDataProvider proxy(ASYNC, OK);
6575 proxy.SetNextProto(GetParam());
6576 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6578 scoped_ptr<HttpTransaction> trans(
6579 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6580 TestCompletionCallback callback;
6581 int rv = trans->Start(&request, callback.callback(), log.bound());
6582 EXPECT_EQ(ERR_IO_PENDING, rv);
6584 rv = callback.WaitForResult();
6585 EXPECT_EQ(OK, rv);
6586 const HttpResponseInfo* response = trans->GetResponseInfo();
6588 scoped_ptr<HttpTransaction> push_trans(
6589 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6590 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6591 EXPECT_EQ(ERR_IO_PENDING, rv);
6593 rv = callback.WaitForResult();
6594 EXPECT_EQ(OK, rv);
6595 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6597 ASSERT_TRUE(response != NULL);
6598 EXPECT_TRUE(response->headers->IsKeepAlive());
6600 EXPECT_EQ(200, response->headers->response_code());
6601 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6603 std::string response_data;
6604 rv = ReadTransaction(trans.get(), &response_data);
6605 EXPECT_EQ(OK, rv);
6606 EXPECT_EQ("hello!", response_data);
6608 LoadTimingInfo load_timing_info;
6609 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6610 TestLoadTimingNotReusedWithPac(load_timing_info,
6611 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6613 // Verify the pushed stream.
6614 EXPECT_TRUE(push_response->headers.get() != NULL);
6615 EXPECT_EQ(200, push_response->headers->response_code());
6617 rv = ReadTransaction(push_trans.get(), &response_data);
6618 EXPECT_EQ(OK, rv);
6619 EXPECT_EQ("pushed", response_data);
6621 LoadTimingInfo push_load_timing_info;
6622 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6623 TestLoadTimingReusedWithPac(push_load_timing_info);
6624 // The transactions should share a socket ID, despite being for different
6625 // origins.
6626 EXPECT_EQ(load_timing_info.socket_log_id,
6627 push_load_timing_info.socket_log_id);
6629 trans.reset();
6630 push_trans.reset();
6631 session->CloseAllConnections();
6634 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6635 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6636 HttpRequestInfo request;
6638 request.method = "GET";
6639 request.url = GURL("http://www.google.com/");
6641 // Configure against https proxy server "myproxy:70".
6642 session_deps_.proxy_service.reset(
6643 ProxyService::CreateFixed("https://myproxy:70"));
6644 CapturingBoundNetLog log;
6645 session_deps_.net_log = log.bound().net_log();
6647 // Enable cross-origin push.
6648 session_deps_.trusted_spdy_proxy = "myproxy:70";
6650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6652 scoped_ptr<SpdyFrame> stream1_syn(
6653 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6655 scoped_ptr<SpdyFrame> push_rst(
6656 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6658 MockWrite spdy_writes[] = {
6659 CreateMockWrite(*stream1_syn, 1, ASYNC),
6660 CreateMockWrite(*push_rst, 4),
6663 scoped_ptr<SpdyFrame>
6664 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6666 scoped_ptr<SpdyFrame>
6667 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6669 scoped_ptr<SpdyFrame>
6670 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6674 "https://www.another-origin.com/foo.dat"));
6676 MockRead spdy_reads[] = {
6677 CreateMockRead(*stream1_reply, 2, ASYNC),
6678 CreateMockRead(*stream2_syn, 3, ASYNC),
6679 CreateMockRead(*stream1_body, 5, ASYNC),
6680 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6683 OrderedSocketData spdy_data(
6684 spdy_reads, arraysize(spdy_reads),
6685 spdy_writes, arraysize(spdy_writes));
6686 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6687 // Negotiate SPDY to the proxy
6688 SSLSocketDataProvider proxy(ASYNC, OK);
6689 proxy.SetNextProto(GetParam());
6690 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6692 scoped_ptr<HttpTransaction> trans(
6693 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6694 TestCompletionCallback callback;
6695 int rv = trans->Start(&request, callback.callback(), log.bound());
6696 EXPECT_EQ(ERR_IO_PENDING, rv);
6698 rv = callback.WaitForResult();
6699 EXPECT_EQ(OK, rv);
6700 const HttpResponseInfo* response = trans->GetResponseInfo();
6702 ASSERT_TRUE(response != NULL);
6703 EXPECT_TRUE(response->headers->IsKeepAlive());
6705 EXPECT_EQ(200, response->headers->response_code());
6706 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6708 std::string response_data;
6709 rv = ReadTransaction(trans.get(), &response_data);
6710 EXPECT_EQ(OK, rv);
6711 EXPECT_EQ("hello!", response_data);
6713 trans.reset();
6714 session->CloseAllConnections();
6717 // Test HTTPS connections to a site with a bad certificate, going through an
6718 // HTTPS proxy
6719 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6720 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6721 "https://proxy:70"));
6723 HttpRequestInfo request;
6724 request.method = "GET";
6725 request.url = GURL("https://www.google.com/");
6726 request.load_flags = 0;
6728 // Attempt to fetch the URL from a server with a bad cert
6729 MockWrite bad_cert_writes[] = {
6730 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6731 "Host: www.google.com\r\n"
6732 "Proxy-Connection: keep-alive\r\n\r\n"),
6735 MockRead bad_cert_reads[] = {
6736 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6737 MockRead(SYNCHRONOUS, OK)
6740 // Attempt to fetch the URL with a good cert
6741 MockWrite good_data_writes[] = {
6742 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6743 "Host: www.google.com\r\n"
6744 "Proxy-Connection: keep-alive\r\n\r\n"),
6745 MockWrite("GET / HTTP/1.1\r\n"
6746 "Host: www.google.com\r\n"
6747 "Connection: keep-alive\r\n\r\n"),
6750 MockRead good_cert_reads[] = {
6751 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6752 MockRead("HTTP/1.0 200 OK\r\n"),
6753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6754 MockRead("Content-Length: 100\r\n\r\n"),
6755 MockRead(SYNCHRONOUS, OK),
6758 StaticSocketDataProvider ssl_bad_certificate(
6759 bad_cert_reads, arraysize(bad_cert_reads),
6760 bad_cert_writes, arraysize(bad_cert_writes));
6761 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6762 good_data_writes, arraysize(good_data_writes));
6763 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6764 SSLSocketDataProvider ssl(ASYNC, OK);
6766 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6767 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6768 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6769 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6771 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6772 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6773 session_deps_.socket_factory->AddSocketDataProvider(&data);
6774 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6776 TestCompletionCallback callback;
6778 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6779 scoped_ptr<HttpTransaction> trans(
6780 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6782 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6783 EXPECT_EQ(ERR_IO_PENDING, rv);
6785 rv = callback.WaitForResult();
6786 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6788 rv = trans->RestartIgnoringLastError(callback.callback());
6789 EXPECT_EQ(ERR_IO_PENDING, rv);
6791 rv = callback.WaitForResult();
6792 EXPECT_EQ(OK, rv);
6794 const HttpResponseInfo* response = trans->GetResponseInfo();
6796 ASSERT_TRUE(response != NULL);
6797 EXPECT_EQ(100, response->headers->GetContentLength());
6800 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6801 HttpRequestInfo request;
6802 request.method = "GET";
6803 request.url = GURL("http://www.google.com/");
6804 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6805 "Chromium Ultra Awesome X Edition");
6807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6808 scoped_ptr<HttpTransaction> trans(
6809 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6811 MockWrite data_writes[] = {
6812 MockWrite("GET / HTTP/1.1\r\n"
6813 "Host: www.google.com\r\n"
6814 "Connection: keep-alive\r\n"
6815 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6818 // Lastly, the server responds with the actual content.
6819 MockRead data_reads[] = {
6820 MockRead("HTTP/1.0 200 OK\r\n"),
6821 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6822 MockRead("Content-Length: 100\r\n\r\n"),
6823 MockRead(SYNCHRONOUS, OK),
6826 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6827 data_writes, arraysize(data_writes));
6828 session_deps_.socket_factory->AddSocketDataProvider(&data);
6830 TestCompletionCallback callback;
6832 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6833 EXPECT_EQ(ERR_IO_PENDING, rv);
6835 rv = callback.WaitForResult();
6836 EXPECT_EQ(OK, rv);
6839 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6840 HttpRequestInfo request;
6841 request.method = "GET";
6842 request.url = GURL("https://www.google.com/");
6843 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6844 "Chromium Ultra Awesome X Edition");
6846 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6847 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6848 scoped_ptr<HttpTransaction> trans(
6849 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6851 MockWrite data_writes[] = {
6852 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6853 "Host: www.google.com\r\n"
6854 "Proxy-Connection: keep-alive\r\n"
6855 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6857 MockRead data_reads[] = {
6858 // Return an error, so the transaction stops here (this test isn't
6859 // interested in the rest).
6860 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6861 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6862 MockRead("Proxy-Connection: close\r\n\r\n"),
6865 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6866 data_writes, arraysize(data_writes));
6867 session_deps_.socket_factory->AddSocketDataProvider(&data);
6869 TestCompletionCallback callback;
6871 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6872 EXPECT_EQ(ERR_IO_PENDING, rv);
6874 rv = callback.WaitForResult();
6875 EXPECT_EQ(OK, rv);
6878 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6879 HttpRequestInfo request;
6880 request.method = "GET";
6881 request.url = GURL("http://www.google.com/");
6882 request.load_flags = 0;
6883 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6884 "http://the.previous.site.com/");
6886 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6887 scoped_ptr<HttpTransaction> trans(
6888 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6890 MockWrite data_writes[] = {
6891 MockWrite("GET / HTTP/1.1\r\n"
6892 "Host: www.google.com\r\n"
6893 "Connection: keep-alive\r\n"
6894 "Referer: http://the.previous.site.com/\r\n\r\n"),
6897 // Lastly, the server responds with the actual content.
6898 MockRead data_reads[] = {
6899 MockRead("HTTP/1.0 200 OK\r\n"),
6900 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6901 MockRead("Content-Length: 100\r\n\r\n"),
6902 MockRead(SYNCHRONOUS, OK),
6905 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6906 data_writes, arraysize(data_writes));
6907 session_deps_.socket_factory->AddSocketDataProvider(&data);
6909 TestCompletionCallback callback;
6911 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6912 EXPECT_EQ(ERR_IO_PENDING, rv);
6914 rv = callback.WaitForResult();
6915 EXPECT_EQ(OK, rv);
6918 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6919 HttpRequestInfo request;
6920 request.method = "POST";
6921 request.url = GURL("http://www.google.com/");
6923 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6924 scoped_ptr<HttpTransaction> trans(
6925 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6927 MockWrite data_writes[] = {
6928 MockWrite("POST / HTTP/1.1\r\n"
6929 "Host: www.google.com\r\n"
6930 "Connection: keep-alive\r\n"
6931 "Content-Length: 0\r\n\r\n"),
6934 // Lastly, the server responds with the actual content.
6935 MockRead data_reads[] = {
6936 MockRead("HTTP/1.0 200 OK\r\n"),
6937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6938 MockRead("Content-Length: 100\r\n\r\n"),
6939 MockRead(SYNCHRONOUS, OK),
6942 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6943 data_writes, arraysize(data_writes));
6944 session_deps_.socket_factory->AddSocketDataProvider(&data);
6946 TestCompletionCallback callback;
6948 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6949 EXPECT_EQ(ERR_IO_PENDING, rv);
6951 rv = callback.WaitForResult();
6952 EXPECT_EQ(OK, rv);
6955 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6956 HttpRequestInfo request;
6957 request.method = "PUT";
6958 request.url = GURL("http://www.google.com/");
6960 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6961 scoped_ptr<HttpTransaction> trans(
6962 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6964 MockWrite data_writes[] = {
6965 MockWrite("PUT / HTTP/1.1\r\n"
6966 "Host: www.google.com\r\n"
6967 "Connection: keep-alive\r\n"
6968 "Content-Length: 0\r\n\r\n"),
6971 // Lastly, the server responds with the actual content.
6972 MockRead data_reads[] = {
6973 MockRead("HTTP/1.0 200 OK\r\n"),
6974 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6975 MockRead("Content-Length: 100\r\n\r\n"),
6976 MockRead(SYNCHRONOUS, OK),
6979 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6980 data_writes, arraysize(data_writes));
6981 session_deps_.socket_factory->AddSocketDataProvider(&data);
6983 TestCompletionCallback callback;
6985 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6986 EXPECT_EQ(ERR_IO_PENDING, rv);
6988 rv = callback.WaitForResult();
6989 EXPECT_EQ(OK, rv);
6992 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6993 HttpRequestInfo request;
6994 request.method = "HEAD";
6995 request.url = GURL("http://www.google.com/");
6997 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6998 scoped_ptr<HttpTransaction> trans(
6999 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7001 MockWrite data_writes[] = {
7002 MockWrite("HEAD / HTTP/1.1\r\n"
7003 "Host: www.google.com\r\n"
7004 "Connection: keep-alive\r\n"
7005 "Content-Length: 0\r\n\r\n"),
7008 // Lastly, the server responds with the actual content.
7009 MockRead data_reads[] = {
7010 MockRead("HTTP/1.0 200 OK\r\n"),
7011 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7012 MockRead("Content-Length: 100\r\n\r\n"),
7013 MockRead(SYNCHRONOUS, OK),
7016 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7017 data_writes, arraysize(data_writes));
7018 session_deps_.socket_factory->AddSocketDataProvider(&data);
7020 TestCompletionCallback callback;
7022 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7023 EXPECT_EQ(ERR_IO_PENDING, rv);
7025 rv = callback.WaitForResult();
7026 EXPECT_EQ(OK, rv);
7029 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7030 HttpRequestInfo request;
7031 request.method = "GET";
7032 request.url = GURL("http://www.google.com/");
7033 request.load_flags = LOAD_BYPASS_CACHE;
7035 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7036 scoped_ptr<HttpTransaction> trans(
7037 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7039 MockWrite data_writes[] = {
7040 MockWrite("GET / HTTP/1.1\r\n"
7041 "Host: www.google.com\r\n"
7042 "Connection: keep-alive\r\n"
7043 "Pragma: no-cache\r\n"
7044 "Cache-Control: no-cache\r\n\r\n"),
7047 // Lastly, the server responds with the actual content.
7048 MockRead data_reads[] = {
7049 MockRead("HTTP/1.0 200 OK\r\n"),
7050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7051 MockRead("Content-Length: 100\r\n\r\n"),
7052 MockRead(SYNCHRONOUS, OK),
7055 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7056 data_writes, arraysize(data_writes));
7057 session_deps_.socket_factory->AddSocketDataProvider(&data);
7059 TestCompletionCallback callback;
7061 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7062 EXPECT_EQ(ERR_IO_PENDING, rv);
7064 rv = callback.WaitForResult();
7065 EXPECT_EQ(OK, rv);
7068 TEST_P(HttpNetworkTransactionTest,
7069 BuildRequest_CacheControlValidateCache) {
7070 HttpRequestInfo request;
7071 request.method = "GET";
7072 request.url = GURL("http://www.google.com/");
7073 request.load_flags = LOAD_VALIDATE_CACHE;
7075 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7076 scoped_ptr<HttpTransaction> trans(
7077 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7079 MockWrite data_writes[] = {
7080 MockWrite("GET / HTTP/1.1\r\n"
7081 "Host: www.google.com\r\n"
7082 "Connection: keep-alive\r\n"
7083 "Cache-Control: max-age=0\r\n\r\n"),
7086 // Lastly, the server responds with the actual content.
7087 MockRead data_reads[] = {
7088 MockRead("HTTP/1.0 200 OK\r\n"),
7089 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7090 MockRead("Content-Length: 100\r\n\r\n"),
7091 MockRead(SYNCHRONOUS, OK),
7094 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7095 data_writes, arraysize(data_writes));
7096 session_deps_.socket_factory->AddSocketDataProvider(&data);
7098 TestCompletionCallback callback;
7100 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7101 EXPECT_EQ(ERR_IO_PENDING, rv);
7103 rv = callback.WaitForResult();
7104 EXPECT_EQ(OK, rv);
7107 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7108 HttpRequestInfo request;
7109 request.method = "GET";
7110 request.url = GURL("http://www.google.com/");
7111 request.extra_headers.SetHeader("FooHeader", "Bar");
7113 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7114 scoped_ptr<HttpTransaction> trans(
7115 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7117 MockWrite data_writes[] = {
7118 MockWrite("GET / HTTP/1.1\r\n"
7119 "Host: www.google.com\r\n"
7120 "Connection: keep-alive\r\n"
7121 "FooHeader: Bar\r\n\r\n"),
7124 // Lastly, the server responds with the actual content.
7125 MockRead data_reads[] = {
7126 MockRead("HTTP/1.0 200 OK\r\n"),
7127 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7128 MockRead("Content-Length: 100\r\n\r\n"),
7129 MockRead(SYNCHRONOUS, OK),
7132 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7133 data_writes, arraysize(data_writes));
7134 session_deps_.socket_factory->AddSocketDataProvider(&data);
7136 TestCompletionCallback callback;
7138 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7139 EXPECT_EQ(ERR_IO_PENDING, rv);
7141 rv = callback.WaitForResult();
7142 EXPECT_EQ(OK, rv);
7145 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7146 HttpRequestInfo request;
7147 request.method = "GET";
7148 request.url = GURL("http://www.google.com/");
7149 request.extra_headers.SetHeader("referer", "www.foo.com");
7150 request.extra_headers.SetHeader("hEllo", "Kitty");
7151 request.extra_headers.SetHeader("FoO", "bar");
7153 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7154 scoped_ptr<HttpTransaction> trans(
7155 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7157 MockWrite data_writes[] = {
7158 MockWrite("GET / HTTP/1.1\r\n"
7159 "Host: www.google.com\r\n"
7160 "Connection: keep-alive\r\n"
7161 "referer: www.foo.com\r\n"
7162 "hEllo: Kitty\r\n"
7163 "FoO: bar\r\n\r\n"),
7166 // Lastly, the server responds with the actual content.
7167 MockRead data_reads[] = {
7168 MockRead("HTTP/1.0 200 OK\r\n"),
7169 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7170 MockRead("Content-Length: 100\r\n\r\n"),
7171 MockRead(SYNCHRONOUS, OK),
7174 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7175 data_writes, arraysize(data_writes));
7176 session_deps_.socket_factory->AddSocketDataProvider(&data);
7178 TestCompletionCallback callback;
7180 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7181 EXPECT_EQ(ERR_IO_PENDING, rv);
7183 rv = callback.WaitForResult();
7184 EXPECT_EQ(OK, rv);
7187 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7188 HttpRequestInfo request;
7189 request.method = "GET";
7190 request.url = GURL("http://www.google.com/");
7191 request.load_flags = 0;
7193 session_deps_.proxy_service.reset(
7194 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7195 CapturingNetLog net_log;
7196 session_deps_.net_log = &net_log;
7198 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7199 scoped_ptr<HttpTransaction> trans(
7200 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7202 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7203 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7205 MockWrite data_writes[] = {
7206 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7207 MockWrite("GET / HTTP/1.1\r\n"
7208 "Host: www.google.com\r\n"
7209 "Connection: keep-alive\r\n\r\n")
7212 MockRead data_reads[] = {
7213 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7214 MockRead("HTTP/1.0 200 OK\r\n"),
7215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7216 MockRead("Payload"),
7217 MockRead(SYNCHRONOUS, OK)
7220 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7221 data_writes, arraysize(data_writes));
7222 session_deps_.socket_factory->AddSocketDataProvider(&data);
7224 TestCompletionCallback callback;
7226 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7227 EXPECT_EQ(ERR_IO_PENDING, rv);
7229 rv = callback.WaitForResult();
7230 EXPECT_EQ(OK, rv);
7232 const HttpResponseInfo* response = trans->GetResponseInfo();
7233 ASSERT_TRUE(response != NULL);
7235 LoadTimingInfo load_timing_info;
7236 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7237 TestLoadTimingNotReusedWithPac(load_timing_info,
7238 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7240 std::string response_text;
7241 rv = ReadTransaction(trans.get(), &response_text);
7242 EXPECT_EQ(OK, rv);
7243 EXPECT_EQ("Payload", response_text);
7246 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7247 HttpRequestInfo request;
7248 request.method = "GET";
7249 request.url = GURL("https://www.google.com/");
7250 request.load_flags = 0;
7252 session_deps_.proxy_service.reset(
7253 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7254 CapturingNetLog net_log;
7255 session_deps_.net_log = &net_log;
7257 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7258 scoped_ptr<HttpTransaction> trans(
7259 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7261 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7262 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7264 MockWrite data_writes[] = {
7265 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7266 arraysize(write_buffer)),
7267 MockWrite("GET / HTTP/1.1\r\n"
7268 "Host: www.google.com\r\n"
7269 "Connection: keep-alive\r\n\r\n")
7272 MockRead data_reads[] = {
7273 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7274 arraysize(read_buffer)),
7275 MockRead("HTTP/1.0 200 OK\r\n"),
7276 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7277 MockRead("Payload"),
7278 MockRead(SYNCHRONOUS, OK)
7281 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7282 data_writes, arraysize(data_writes));
7283 session_deps_.socket_factory->AddSocketDataProvider(&data);
7285 SSLSocketDataProvider ssl(ASYNC, OK);
7286 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7288 TestCompletionCallback callback;
7290 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7291 EXPECT_EQ(ERR_IO_PENDING, rv);
7293 rv = callback.WaitForResult();
7294 EXPECT_EQ(OK, rv);
7296 LoadTimingInfo load_timing_info;
7297 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7298 TestLoadTimingNotReusedWithPac(load_timing_info,
7299 CONNECT_TIMING_HAS_SSL_TIMES);
7301 const HttpResponseInfo* response = trans->GetResponseInfo();
7302 ASSERT_TRUE(response != NULL);
7304 std::string response_text;
7305 rv = ReadTransaction(trans.get(), &response_text);
7306 EXPECT_EQ(OK, rv);
7307 EXPECT_EQ("Payload", response_text);
7310 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7311 HttpRequestInfo request;
7312 request.method = "GET";
7313 request.url = GURL("http://www.google.com/");
7314 request.load_flags = 0;
7316 session_deps_.proxy_service.reset(
7317 ProxyService::CreateFixed("socks4://myproxy:1080"));
7318 CapturingNetLog net_log;
7319 session_deps_.net_log = &net_log;
7321 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7322 scoped_ptr<HttpTransaction> trans(
7323 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7325 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7326 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7328 MockWrite data_writes[] = {
7329 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7330 MockWrite("GET / HTTP/1.1\r\n"
7331 "Host: www.google.com\r\n"
7332 "Connection: keep-alive\r\n\r\n")
7335 MockRead data_reads[] = {
7336 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7337 MockRead("HTTP/1.0 200 OK\r\n"),
7338 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7339 MockRead("Payload"),
7340 MockRead(SYNCHRONOUS, OK)
7343 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7344 data_writes, arraysize(data_writes));
7345 session_deps_.socket_factory->AddSocketDataProvider(&data);
7347 TestCompletionCallback callback;
7349 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7350 EXPECT_EQ(ERR_IO_PENDING, rv);
7352 rv = callback.WaitForResult();
7353 EXPECT_EQ(OK, rv);
7355 const HttpResponseInfo* response = trans->GetResponseInfo();
7356 ASSERT_TRUE(response != NULL);
7358 LoadTimingInfo load_timing_info;
7359 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7360 TestLoadTimingNotReused(load_timing_info,
7361 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7363 std::string response_text;
7364 rv = ReadTransaction(trans.get(), &response_text);
7365 EXPECT_EQ(OK, rv);
7366 EXPECT_EQ("Payload", response_text);
7369 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7370 HttpRequestInfo request;
7371 request.method = "GET";
7372 request.url = GURL("http://www.google.com/");
7373 request.load_flags = 0;
7375 session_deps_.proxy_service.reset(
7376 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7377 CapturingNetLog net_log;
7378 session_deps_.net_log = &net_log;
7380 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7381 scoped_ptr<HttpTransaction> trans(
7382 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7384 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7385 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7386 const char kSOCKS5OkRequest[] = {
7387 0x05, // Version
7388 0x01, // Command (CONNECT)
7389 0x00, // Reserved.
7390 0x03, // Address type (DOMAINNAME).
7391 0x0E, // Length of domain (14)
7392 // Domain string:
7393 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7394 0x00, 0x50, // 16-bit port (80)
7396 const char kSOCKS5OkResponse[] =
7397 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7399 MockWrite data_writes[] = {
7400 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7401 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7402 MockWrite("GET / HTTP/1.1\r\n"
7403 "Host: www.google.com\r\n"
7404 "Connection: keep-alive\r\n\r\n")
7407 MockRead data_reads[] = {
7408 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7409 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7410 MockRead("HTTP/1.0 200 OK\r\n"),
7411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7412 MockRead("Payload"),
7413 MockRead(SYNCHRONOUS, OK)
7416 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7417 data_writes, arraysize(data_writes));
7418 session_deps_.socket_factory->AddSocketDataProvider(&data);
7420 TestCompletionCallback callback;
7422 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7423 EXPECT_EQ(ERR_IO_PENDING, rv);
7425 rv = callback.WaitForResult();
7426 EXPECT_EQ(OK, rv);
7428 const HttpResponseInfo* response = trans->GetResponseInfo();
7429 ASSERT_TRUE(response != NULL);
7431 LoadTimingInfo load_timing_info;
7432 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7433 TestLoadTimingNotReusedWithPac(load_timing_info,
7434 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7436 std::string response_text;
7437 rv = ReadTransaction(trans.get(), &response_text);
7438 EXPECT_EQ(OK, rv);
7439 EXPECT_EQ("Payload", response_text);
7442 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7443 HttpRequestInfo request;
7444 request.method = "GET";
7445 request.url = GURL("https://www.google.com/");
7446 request.load_flags = 0;
7448 session_deps_.proxy_service.reset(
7449 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7450 CapturingNetLog net_log;
7451 session_deps_.net_log = &net_log;
7453 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7454 scoped_ptr<HttpTransaction> trans(
7455 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7457 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7458 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7459 const unsigned char kSOCKS5OkRequest[] = {
7460 0x05, // Version
7461 0x01, // Command (CONNECT)
7462 0x00, // Reserved.
7463 0x03, // Address type (DOMAINNAME).
7464 0x0E, // Length of domain (14)
7465 // Domain string:
7466 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7467 0x01, 0xBB, // 16-bit port (443)
7470 const char kSOCKS5OkResponse[] =
7471 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7473 MockWrite data_writes[] = {
7474 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7475 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7476 arraysize(kSOCKS5OkRequest)),
7477 MockWrite("GET / HTTP/1.1\r\n"
7478 "Host: www.google.com\r\n"
7479 "Connection: keep-alive\r\n\r\n")
7482 MockRead data_reads[] = {
7483 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7484 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7485 MockRead("HTTP/1.0 200 OK\r\n"),
7486 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7487 MockRead("Payload"),
7488 MockRead(SYNCHRONOUS, OK)
7491 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7492 data_writes, arraysize(data_writes));
7493 session_deps_.socket_factory->AddSocketDataProvider(&data);
7495 SSLSocketDataProvider ssl(ASYNC, OK);
7496 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7498 TestCompletionCallback callback;
7500 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7501 EXPECT_EQ(ERR_IO_PENDING, rv);
7503 rv = callback.WaitForResult();
7504 EXPECT_EQ(OK, rv);
7506 const HttpResponseInfo* response = trans->GetResponseInfo();
7507 ASSERT_TRUE(response != NULL);
7509 LoadTimingInfo load_timing_info;
7510 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7511 TestLoadTimingNotReusedWithPac(load_timing_info,
7512 CONNECT_TIMING_HAS_SSL_TIMES);
7514 std::string response_text;
7515 rv = ReadTransaction(trans.get(), &response_text);
7516 EXPECT_EQ(OK, rv);
7517 EXPECT_EQ("Payload", response_text);
7520 namespace {
7522 // Tests that for connection endpoints the group names are correctly set.
7524 struct GroupNameTest {
7525 std::string proxy_server;
7526 std::string url;
7527 std::string expected_group_name;
7528 bool ssl;
7531 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7532 NextProto next_proto,
7533 SpdySessionDependencies* session_deps_) {
7534 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7536 base::WeakPtr<HttpServerProperties> http_server_properties =
7537 session->http_server_properties();
7538 http_server_properties->SetAlternateProtocol(
7539 HostPortPair("host.with.alternate", 80), 443,
7540 AlternateProtocolFromNextProto(next_proto), 1);
7542 return session;
7545 int GroupNameTransactionHelper(
7546 const std::string& url,
7547 const scoped_refptr<HttpNetworkSession>& session) {
7548 HttpRequestInfo request;
7549 request.method = "GET";
7550 request.url = GURL(url);
7551 request.load_flags = 0;
7553 scoped_ptr<HttpTransaction> trans(
7554 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7556 TestCompletionCallback callback;
7558 // We do not complete this request, the dtor will clean the transaction up.
7559 return trans->Start(&request, callback.callback(), BoundNetLog());
7562 } // namespace
7564 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7565 const GroupNameTest tests[] = {
7567 "", // unused
7568 "http://www.google.com/direct",
7569 "www.google.com:80",
7570 false,
7573 "", // unused
7574 "http://[2001:1418:13:1::25]/direct",
7575 "[2001:1418:13:1::25]:80",
7576 false,
7579 // SSL Tests
7581 "", // unused
7582 "https://www.google.com/direct_ssl",
7583 "ssl/www.google.com:443",
7584 true,
7587 "", // unused
7588 "https://[2001:1418:13:1::25]/direct",
7589 "ssl/[2001:1418:13:1::25]:443",
7590 true,
7593 "", // unused
7594 "http://host.with.alternate/direct",
7595 "ssl/host.with.alternate:443",
7596 true,
7600 session_deps_.use_alternate_protocols = true;
7602 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7603 session_deps_.proxy_service.reset(
7604 ProxyService::CreateFixed(tests[i].proxy_server));
7605 scoped_refptr<HttpNetworkSession> session(
7606 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7608 HttpNetworkSessionPeer peer(session);
7609 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7610 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7611 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7612 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7613 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7614 new MockClientSocketPoolManager);
7615 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7616 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7617 peer.SetClientSocketPoolManager(
7618 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7620 EXPECT_EQ(ERR_IO_PENDING,
7621 GroupNameTransactionHelper(tests[i].url, session));
7622 if (tests[i].ssl)
7623 EXPECT_EQ(tests[i].expected_group_name,
7624 ssl_conn_pool->last_group_name_received());
7625 else
7626 EXPECT_EQ(tests[i].expected_group_name,
7627 transport_conn_pool->last_group_name_received());
7632 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7633 const GroupNameTest tests[] = {
7635 "http_proxy",
7636 "http://www.google.com/http_proxy_normal",
7637 "www.google.com:80",
7638 false,
7641 // SSL Tests
7643 "http_proxy",
7644 "https://www.google.com/http_connect_ssl",
7645 "ssl/www.google.com:443",
7646 true,
7650 "http_proxy",
7651 "http://host.with.alternate/direct",
7652 "ssl/host.with.alternate:443",
7653 true,
7657 "http_proxy",
7658 "ftp://ftp.google.com/http_proxy_normal",
7659 "ftp/ftp.google.com:21",
7660 false,
7664 session_deps_.use_alternate_protocols = true;
7666 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7667 session_deps_.proxy_service.reset(
7668 ProxyService::CreateFixed(tests[i].proxy_server));
7669 scoped_refptr<HttpNetworkSession> session(
7670 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7672 HttpNetworkSessionPeer peer(session);
7674 HostPortPair proxy_host("http_proxy", 80);
7675 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7676 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7677 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7678 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7680 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7681 new MockClientSocketPoolManager);
7682 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7683 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7684 peer.SetClientSocketPoolManager(
7685 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7687 EXPECT_EQ(ERR_IO_PENDING,
7688 GroupNameTransactionHelper(tests[i].url, session));
7689 if (tests[i].ssl)
7690 EXPECT_EQ(tests[i].expected_group_name,
7691 ssl_conn_pool->last_group_name_received());
7692 else
7693 EXPECT_EQ(tests[i].expected_group_name,
7694 http_proxy_pool->last_group_name_received());
7698 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7699 const GroupNameTest tests[] = {
7701 "socks4://socks_proxy:1080",
7702 "http://www.google.com/socks4_direct",
7703 "socks4/www.google.com:80",
7704 false,
7707 "socks5://socks_proxy:1080",
7708 "http://www.google.com/socks5_direct",
7709 "socks5/www.google.com:80",
7710 false,
7713 // SSL Tests
7715 "socks4://socks_proxy:1080",
7716 "https://www.google.com/socks4_ssl",
7717 "socks4/ssl/www.google.com:443",
7718 true,
7721 "socks5://socks_proxy:1080",
7722 "https://www.google.com/socks5_ssl",
7723 "socks5/ssl/www.google.com:443",
7724 true,
7728 "socks4://socks_proxy:1080",
7729 "http://host.with.alternate/direct",
7730 "socks4/ssl/host.with.alternate:443",
7731 true,
7735 session_deps_.use_alternate_protocols = true;
7737 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7738 session_deps_.proxy_service.reset(
7739 ProxyService::CreateFixed(tests[i].proxy_server));
7740 scoped_refptr<HttpNetworkSession> session(
7741 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7743 HttpNetworkSessionPeer peer(session);
7745 HostPortPair proxy_host("socks_proxy", 1080);
7746 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7747 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7748 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7749 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7751 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7752 new MockClientSocketPoolManager);
7753 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7754 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7755 peer.SetClientSocketPoolManager(
7756 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7758 scoped_ptr<HttpTransaction> trans(
7759 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7761 EXPECT_EQ(ERR_IO_PENDING,
7762 GroupNameTransactionHelper(tests[i].url, session));
7763 if (tests[i].ssl)
7764 EXPECT_EQ(tests[i].expected_group_name,
7765 ssl_conn_pool->last_group_name_received());
7766 else
7767 EXPECT_EQ(tests[i].expected_group_name,
7768 socks_conn_pool->last_group_name_received());
7772 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7773 HttpRequestInfo request;
7774 request.method = "GET";
7775 request.url = GURL("http://www.google.com/");
7777 session_deps_.proxy_service.reset(
7778 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7780 // This simulates failure resolving all hostnames; that means we will fail
7781 // connecting to both proxies (myproxy:70 and foobar:80).
7782 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7784 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7785 scoped_ptr<HttpTransaction> trans(
7786 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7788 TestCompletionCallback callback;
7790 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7791 EXPECT_EQ(ERR_IO_PENDING, rv);
7793 rv = callback.WaitForResult();
7794 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7797 // Base test to make sure that when the load flags for a request specify to
7798 // bypass the cache, the DNS cache is not used.
7799 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7800 int load_flags) {
7801 // Issue a request, asking to bypass the cache(s).
7802 HttpRequestInfo request;
7803 request.method = "GET";
7804 request.load_flags = load_flags;
7805 request.url = GURL("http://www.google.com/");
7807 // Select a host resolver that does caching.
7808 session_deps_.host_resolver.reset(new MockCachingHostResolver);
7810 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7811 scoped_ptr<HttpTransaction> trans(
7812 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7814 // Warm up the host cache so it has an entry for "www.google.com".
7815 AddressList addrlist;
7816 TestCompletionCallback callback;
7817 int rv = session_deps_.host_resolver->Resolve(
7818 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7819 DEFAULT_PRIORITY,
7820 &addrlist,
7821 callback.callback(),
7822 NULL,
7823 BoundNetLog());
7824 EXPECT_EQ(ERR_IO_PENDING, rv);
7825 rv = callback.WaitForResult();
7826 EXPECT_EQ(OK, rv);
7828 // Verify that it was added to host cache, by doing a subsequent async lookup
7829 // and confirming it completes synchronously.
7830 rv = session_deps_.host_resolver->Resolve(
7831 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7832 DEFAULT_PRIORITY,
7833 &addrlist,
7834 callback.callback(),
7835 NULL,
7836 BoundNetLog());
7837 ASSERT_EQ(OK, rv);
7839 // Inject a failure the next time that "www.google.com" is resolved. This way
7840 // we can tell if the next lookup hit the cache, or the "network".
7841 // (cache --> success, "network" --> failure).
7842 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7844 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7845 // first read -- this won't be reached as the host resolution will fail first.
7846 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7847 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7848 session_deps_.socket_factory->AddSocketDataProvider(&data);
7850 // Run the request.
7851 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7852 ASSERT_EQ(ERR_IO_PENDING, rv);
7853 rv = callback.WaitForResult();
7855 // If we bypassed the cache, we would have gotten a failure while resolving
7856 // "www.google.com".
7857 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7860 // There are multiple load flags that should trigger the host cache bypass.
7861 // Test each in isolation:
7862 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7863 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7866 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7867 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7870 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7871 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7874 // Make sure we can handle an error when writing the request.
7875 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7876 HttpRequestInfo request;
7877 request.method = "GET";
7878 request.url = GURL("http://www.foo.com/");
7879 request.load_flags = 0;
7881 MockWrite write_failure[] = {
7882 MockWrite(ASYNC, ERR_CONNECTION_RESET),
7884 StaticSocketDataProvider data(NULL, 0,
7885 write_failure, arraysize(write_failure));
7886 session_deps_.socket_factory->AddSocketDataProvider(&data);
7887 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7889 TestCompletionCallback callback;
7891 scoped_ptr<HttpTransaction> trans(
7892 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7894 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7895 EXPECT_EQ(ERR_IO_PENDING, rv);
7897 rv = callback.WaitForResult();
7898 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7901 // Check that a connection closed after the start of the headers finishes ok.
7902 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7903 HttpRequestInfo request;
7904 request.method = "GET";
7905 request.url = GURL("http://www.foo.com/");
7906 request.load_flags = 0;
7908 MockRead data_reads[] = {
7909 MockRead("HTTP/1."),
7910 MockRead(SYNCHRONOUS, OK),
7913 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7914 session_deps_.socket_factory->AddSocketDataProvider(&data);
7915 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7917 TestCompletionCallback callback;
7919 scoped_ptr<HttpTransaction> trans(
7920 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7922 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7923 EXPECT_EQ(ERR_IO_PENDING, rv);
7925 rv = callback.WaitForResult();
7926 EXPECT_EQ(OK, rv);
7928 const HttpResponseInfo* response = trans->GetResponseInfo();
7929 ASSERT_TRUE(response != NULL);
7931 EXPECT_TRUE(response->headers.get() != NULL);
7932 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7934 std::string response_data;
7935 rv = ReadTransaction(trans.get(), &response_data);
7936 EXPECT_EQ(OK, rv);
7937 EXPECT_EQ("", response_data);
7940 // Make sure that a dropped connection while draining the body for auth
7941 // restart does the right thing.
7942 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7943 HttpRequestInfo request;
7944 request.method = "GET";
7945 request.url = GURL("http://www.google.com/");
7946 request.load_flags = 0;
7948 MockWrite data_writes1[] = {
7949 MockWrite("GET / HTTP/1.1\r\n"
7950 "Host: www.google.com\r\n"
7951 "Connection: keep-alive\r\n\r\n"),
7954 MockRead data_reads1[] = {
7955 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7956 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7957 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7958 MockRead("Content-Length: 14\r\n\r\n"),
7959 MockRead("Unauth"),
7960 MockRead(ASYNC, ERR_CONNECTION_RESET),
7963 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7964 data_writes1, arraysize(data_writes1));
7965 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7967 // After calling trans->RestartWithAuth(), this is the request we should
7968 // be issuing -- the final header line contains the credentials.
7969 MockWrite data_writes2[] = {
7970 MockWrite("GET / HTTP/1.1\r\n"
7971 "Host: www.google.com\r\n"
7972 "Connection: keep-alive\r\n"
7973 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7976 // Lastly, the server responds with the actual content.
7977 MockRead data_reads2[] = {
7978 MockRead("HTTP/1.1 200 OK\r\n"),
7979 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7980 MockRead("Content-Length: 100\r\n\r\n"),
7981 MockRead(SYNCHRONOUS, OK),
7984 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7985 data_writes2, arraysize(data_writes2));
7986 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7987 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7989 TestCompletionCallback callback1;
7991 scoped_ptr<HttpTransaction> trans(
7992 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7994 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7995 EXPECT_EQ(ERR_IO_PENDING, rv);
7997 rv = callback1.WaitForResult();
7998 EXPECT_EQ(OK, rv);
8000 const HttpResponseInfo* response = trans->GetResponseInfo();
8001 ASSERT_TRUE(response != NULL);
8002 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8004 TestCompletionCallback callback2;
8006 rv = trans->RestartWithAuth(
8007 AuthCredentials(kFoo, kBar), callback2.callback());
8008 EXPECT_EQ(ERR_IO_PENDING, rv);
8010 rv = callback2.WaitForResult();
8011 EXPECT_EQ(OK, rv);
8013 response = trans->GetResponseInfo();
8014 ASSERT_TRUE(response != NULL);
8015 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8016 EXPECT_EQ(100, response->headers->GetContentLength());
8019 // Test HTTPS connections going through a proxy that sends extra data.
8020 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8021 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8023 HttpRequestInfo request;
8024 request.method = "GET";
8025 request.url = GURL("https://www.google.com/");
8026 request.load_flags = 0;
8028 MockRead proxy_reads[] = {
8029 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8030 MockRead(SYNCHRONOUS, OK)
8033 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8034 SSLSocketDataProvider ssl(ASYNC, OK);
8036 session_deps_.socket_factory->AddSocketDataProvider(&data);
8037 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8039 TestCompletionCallback callback;
8041 session_deps_.socket_factory->ResetNextMockIndexes();
8043 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8044 scoped_ptr<HttpTransaction> trans(
8045 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8047 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8048 EXPECT_EQ(ERR_IO_PENDING, rv);
8050 rv = callback.WaitForResult();
8051 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8054 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8055 HttpRequestInfo request;
8056 request.method = "GET";
8057 request.url = GURL("http://www.google.com/");
8058 request.load_flags = 0;
8060 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8061 scoped_ptr<HttpTransaction> trans(
8062 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8064 MockRead data_reads[] = {
8065 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8066 MockRead(SYNCHRONOUS, OK),
8069 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8070 session_deps_.socket_factory->AddSocketDataProvider(&data);
8072 TestCompletionCallback callback;
8074 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8075 EXPECT_EQ(ERR_IO_PENDING, rv);
8077 EXPECT_EQ(OK, callback.WaitForResult());
8079 const HttpResponseInfo* response = trans->GetResponseInfo();
8080 ASSERT_TRUE(response != NULL);
8082 EXPECT_TRUE(response->headers.get() != NULL);
8083 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8085 std::string response_data;
8086 rv = ReadTransaction(trans.get(), &response_data);
8087 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8090 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8091 base::FilePath temp_file_path;
8092 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8093 const uint64 kFakeSize = 100000; // file is actually blank
8094 UploadFileElementReader::ScopedOverridingContentLengthForTests
8095 overriding_content_length(kFakeSize);
8097 ScopedVector<UploadElementReader> element_readers;
8098 element_readers.push_back(
8099 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8100 temp_file_path,
8102 kuint64max,
8103 base::Time()));
8104 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8106 HttpRequestInfo request;
8107 request.method = "POST";
8108 request.url = GURL("http://www.google.com/upload");
8109 request.upload_data_stream = &upload_data_stream;
8110 request.load_flags = 0;
8112 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8113 scoped_ptr<HttpTransaction> trans(
8114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8116 MockRead data_reads[] = {
8117 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8118 MockRead("hello world"),
8119 MockRead(SYNCHRONOUS, OK),
8121 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8122 session_deps_.socket_factory->AddSocketDataProvider(&data);
8124 TestCompletionCallback callback;
8126 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8127 EXPECT_EQ(ERR_IO_PENDING, rv);
8129 rv = callback.WaitForResult();
8130 EXPECT_EQ(OK, rv);
8132 const HttpResponseInfo* response = trans->GetResponseInfo();
8133 ASSERT_TRUE(response != NULL);
8135 EXPECT_TRUE(response->headers.get() != NULL);
8136 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8138 std::string response_data;
8139 rv = ReadTransaction(trans.get(), &response_data);
8140 EXPECT_EQ(OK, rv);
8141 EXPECT_EQ("hello world", response_data);
8143 base::DeleteFile(temp_file_path, false);
8146 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8147 base::FilePath temp_file;
8148 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8149 std::string temp_file_content("Unreadable file.");
8150 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8151 temp_file_content.length()));
8152 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
8154 ScopedVector<UploadElementReader> element_readers;
8155 element_readers.push_back(
8156 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8157 temp_file,
8159 kuint64max,
8160 base::Time()));
8161 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8163 HttpRequestInfo request;
8164 request.method = "POST";
8165 request.url = GURL("http://www.google.com/upload");
8166 request.upload_data_stream = &upload_data_stream;
8167 request.load_flags = 0;
8169 // If we try to upload an unreadable file, the transaction should fail.
8170 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8171 scoped_ptr<HttpTransaction> trans(
8172 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8174 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8175 session_deps_.socket_factory->AddSocketDataProvider(&data);
8177 TestCompletionCallback callback;
8179 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8180 EXPECT_EQ(ERR_IO_PENDING, rv);
8182 rv = callback.WaitForResult();
8183 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8185 const HttpResponseInfo* response = trans->GetResponseInfo();
8186 EXPECT_FALSE(response);
8188 base::DeleteFile(temp_file, false);
8191 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8192 class FakeUploadElementReader : public UploadElementReader {
8193 public:
8194 FakeUploadElementReader() {}
8195 virtual ~FakeUploadElementReader() {}
8197 const CompletionCallback& callback() const { return callback_; }
8199 // UploadElementReader overrides:
8200 virtual int Init(const CompletionCallback& callback) OVERRIDE {
8201 callback_ = callback;
8202 return ERR_IO_PENDING;
8204 virtual uint64 GetContentLength() const OVERRIDE { return 0; }
8205 virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
8206 virtual int Read(IOBuffer* buf,
8207 int buf_length,
8208 const CompletionCallback& callback) OVERRIDE {
8209 return ERR_FAILED;
8212 private:
8213 CompletionCallback callback_;
8216 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8217 ScopedVector<UploadElementReader> element_readers;
8218 element_readers.push_back(fake_reader);
8219 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8221 HttpRequestInfo request;
8222 request.method = "POST";
8223 request.url = GURL("http://www.google.com/upload");
8224 request.upload_data_stream = &upload_data_stream;
8225 request.load_flags = 0;
8227 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8228 scoped_ptr<HttpTransaction> trans(
8229 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8231 StaticSocketDataProvider data;
8232 session_deps_.socket_factory->AddSocketDataProvider(&data);
8234 TestCompletionCallback callback;
8235 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8236 EXPECT_EQ(ERR_IO_PENDING, rv);
8237 base::MessageLoop::current()->RunUntilIdle();
8239 // Transaction is pending on request body initialization.
8240 ASSERT_FALSE(fake_reader->callback().is_null());
8242 // Return Init()'s result after the transaction gets destroyed.
8243 trans.reset();
8244 fake_reader->callback().Run(OK); // Should not crash.
8247 // Tests that changes to Auth realms are treated like auth rejections.
8248 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8250 HttpRequestInfo request;
8251 request.method = "GET";
8252 request.url = GURL("http://www.google.com/");
8253 request.load_flags = 0;
8255 // First transaction will request a resource and receive a Basic challenge
8256 // with realm="first_realm".
8257 MockWrite data_writes1[] = {
8258 MockWrite("GET / HTTP/1.1\r\n"
8259 "Host: www.google.com\r\n"
8260 "Connection: keep-alive\r\n"
8261 "\r\n"),
8263 MockRead data_reads1[] = {
8264 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8265 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8266 "\r\n"),
8269 // After calling trans->RestartWithAuth(), provide an Authentication header
8270 // for first_realm. The server will reject and provide a challenge with
8271 // second_realm.
8272 MockWrite data_writes2[] = {
8273 MockWrite("GET / HTTP/1.1\r\n"
8274 "Host: www.google.com\r\n"
8275 "Connection: keep-alive\r\n"
8276 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8277 "\r\n"),
8279 MockRead data_reads2[] = {
8280 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8281 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8282 "\r\n"),
8285 // This again fails, and goes back to first_realm. Make sure that the
8286 // entry is removed from cache.
8287 MockWrite data_writes3[] = {
8288 MockWrite("GET / HTTP/1.1\r\n"
8289 "Host: www.google.com\r\n"
8290 "Connection: keep-alive\r\n"
8291 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8292 "\r\n"),
8294 MockRead data_reads3[] = {
8295 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8296 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8297 "\r\n"),
8300 // Try one last time (with the correct password) and get the resource.
8301 MockWrite data_writes4[] = {
8302 MockWrite("GET / HTTP/1.1\r\n"
8303 "Host: www.google.com\r\n"
8304 "Connection: keep-alive\r\n"
8305 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8306 "\r\n"),
8308 MockRead data_reads4[] = {
8309 MockRead("HTTP/1.1 200 OK\r\n"
8310 "Content-Type: text/html; charset=iso-8859-1\r\n"
8311 "Content-Length: 5\r\n"
8312 "\r\n"
8313 "hello"),
8316 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8317 data_writes1, arraysize(data_writes1));
8318 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8319 data_writes2, arraysize(data_writes2));
8320 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8321 data_writes3, arraysize(data_writes3));
8322 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8323 data_writes4, arraysize(data_writes4));
8324 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8325 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8326 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8327 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8329 TestCompletionCallback callback1;
8331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8332 scoped_ptr<HttpTransaction> trans(
8333 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8335 // Issue the first request with Authorize headers. There should be a
8336 // password prompt for first_realm waiting to be filled in after the
8337 // transaction completes.
8338 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8339 EXPECT_EQ(ERR_IO_PENDING, rv);
8340 rv = callback1.WaitForResult();
8341 EXPECT_EQ(OK, rv);
8342 const HttpResponseInfo* response = trans->GetResponseInfo();
8343 ASSERT_TRUE(response != NULL);
8344 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8345 ASSERT_FALSE(challenge == NULL);
8346 EXPECT_FALSE(challenge->is_proxy);
8347 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8348 EXPECT_EQ("first_realm", challenge->realm);
8349 EXPECT_EQ("basic", challenge->scheme);
8351 // Issue the second request with an incorrect password. There should be a
8352 // password prompt for second_realm waiting to be filled in after the
8353 // transaction completes.
8354 TestCompletionCallback callback2;
8355 rv = trans->RestartWithAuth(
8356 AuthCredentials(kFirst, kBaz), callback2.callback());
8357 EXPECT_EQ(ERR_IO_PENDING, rv);
8358 rv = callback2.WaitForResult();
8359 EXPECT_EQ(OK, rv);
8360 response = trans->GetResponseInfo();
8361 ASSERT_TRUE(response != NULL);
8362 challenge = response->auth_challenge.get();
8363 ASSERT_FALSE(challenge == NULL);
8364 EXPECT_FALSE(challenge->is_proxy);
8365 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8366 EXPECT_EQ("second_realm", challenge->realm);
8367 EXPECT_EQ("basic", challenge->scheme);
8369 // Issue the third request with another incorrect password. There should be
8370 // a password prompt for first_realm waiting to be filled in. If the password
8371 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8372 // first_realm was not correctly removed.
8373 TestCompletionCallback callback3;
8374 rv = trans->RestartWithAuth(
8375 AuthCredentials(kSecond, kFou), callback3.callback());
8376 EXPECT_EQ(ERR_IO_PENDING, rv);
8377 rv = callback3.WaitForResult();
8378 EXPECT_EQ(OK, rv);
8379 response = trans->GetResponseInfo();
8380 ASSERT_TRUE(response != NULL);
8381 challenge = response->auth_challenge.get();
8382 ASSERT_FALSE(challenge == NULL);
8383 EXPECT_FALSE(challenge->is_proxy);
8384 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8385 EXPECT_EQ("first_realm", challenge->realm);
8386 EXPECT_EQ("basic", challenge->scheme);
8388 // Issue the fourth request with the correct password and username.
8389 TestCompletionCallback callback4;
8390 rv = trans->RestartWithAuth(
8391 AuthCredentials(kFirst, kBar), callback4.callback());
8392 EXPECT_EQ(ERR_IO_PENDING, rv);
8393 rv = callback4.WaitForResult();
8394 EXPECT_EQ(OK, rv);
8395 response = trans->GetResponseInfo();
8396 ASSERT_TRUE(response != NULL);
8397 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8400 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8401 session_deps_.next_protos = SpdyNextProtos();
8402 session_deps_.use_alternate_protocols = true;
8404 std::string alternate_protocol_http_header =
8405 GetAlternateProtocolHttpHeader();
8407 MockRead data_reads[] = {
8408 MockRead("HTTP/1.1 200 OK\r\n"),
8409 MockRead(alternate_protocol_http_header.c_str()),
8410 MockRead("hello world"),
8411 MockRead(SYNCHRONOUS, OK),
8414 HttpRequestInfo request;
8415 request.method = "GET";
8416 request.url = GURL("http://www.google.com/");
8417 request.load_flags = 0;
8419 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8421 session_deps_.socket_factory->AddSocketDataProvider(&data);
8423 TestCompletionCallback callback;
8425 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8426 scoped_ptr<HttpTransaction> trans(
8427 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8429 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8430 EXPECT_EQ(ERR_IO_PENDING, rv);
8432 HostPortPair http_host_port_pair("www.google.com", 80);
8433 HttpServerProperties& http_server_properties =
8434 *session->http_server_properties();
8435 EXPECT_FALSE(
8436 http_server_properties.HasAlternateProtocol(http_host_port_pair));
8438 EXPECT_EQ(OK, callback.WaitForResult());
8440 const HttpResponseInfo* response = trans->GetResponseInfo();
8441 ASSERT_TRUE(response != NULL);
8442 ASSERT_TRUE(response->headers.get() != NULL);
8443 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8444 EXPECT_FALSE(response->was_fetched_via_spdy);
8445 EXPECT_FALSE(response->was_npn_negotiated);
8447 std::string response_data;
8448 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8449 EXPECT_EQ("hello world", response_data);
8451 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
8452 const AlternateProtocolInfo alternate =
8453 http_server_properties.GetAlternateProtocol(http_host_port_pair);
8454 AlternateProtocolInfo expected_alternate(
8455 443, AlternateProtocolFromNextProto(GetParam()), 1);
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()), 1);
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 AlternateProtocolInfo 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()), 1);
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()), 1);
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()), 1);
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()), 1);
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()), 1);
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()), 1);
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.get());
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.get()));
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.get());
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.get()));
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.get());
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get());
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.get());
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.get());
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.get());
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.get()));
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.get()));
12647 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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.get()));
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