WebViewGuest: Add missing break statement.
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blob6bac6db28c80f2978e4f0fcd3170c2ebb8d0e43e
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
8 #include <stdarg.h>
9 #include <string>
10 #include <vector>
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/json/json_writer.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/test/test_file_util.h"
23 #include "net/base/auth.h"
24 #include "net/base/capturing_net_log.h"
25 #include "net/base/completion_callback.h"
26 #include "net/base/load_timing_info.h"
27 #include "net/base/load_timing_info_test_util.h"
28 #include "net/base/net_log.h"
29 #include "net/base/net_log_unittest.h"
30 #include "net/base/request_priority.h"
31 #include "net/base/test_completion_callback.h"
32 #include "net/base/test_data_directory.h"
33 #include "net/base/upload_bytes_element_reader.h"
34 #include "net/base/upload_data_stream.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_stream.h"
44 #include "net/http/http_network_session.h"
45 #include "net/http/http_network_session_peer.h"
46 #include "net/http/http_server_properties_impl.h"
47 #include "net/http/http_stream.h"
48 #include "net/http/http_stream_factory.h"
49 #include "net/http/http_transaction_test_util.h"
50 #include "net/proxy/proxy_config_service_fixed.h"
51 #include "net/proxy/proxy_info.h"
52 #include "net/proxy/proxy_resolver.h"
53 #include "net/proxy/proxy_service.h"
54 #include "net/socket/client_socket_factory.h"
55 #include "net/socket/client_socket_pool_manager.h"
56 #include "net/socket/mock_client_socket_pool_manager.h"
57 #include "net/socket/next_proto.h"
58 #include "net/socket/socket_test_util.h"
59 #include "net/socket/ssl_client_socket.h"
60 #include "net/spdy/spdy_framer.h"
61 #include "net/spdy/spdy_session.h"
62 #include "net/spdy/spdy_session_pool.h"
63 #include "net/spdy/spdy_test_util_common.h"
64 #include "net/ssl/ssl_cert_request_info.h"
65 #include "net/ssl/ssl_config_service.h"
66 #include "net/ssl/ssl_config_service_defaults.h"
67 #include "net/ssl/ssl_info.h"
68 #include "net/test/cert_test_util.h"
69 #include "net/websockets/websocket_handshake_stream_base.h"
70 #include "testing/gtest/include/gtest/gtest.h"
71 #include "testing/platform_test.h"
72 #include "url/gurl.h"
74 using base::ASCIIToUTF16;
76 //-----------------------------------------------------------------------------
78 namespace {
80 const base::string16 kBar(ASCIIToUTF16("bar"));
81 const base::string16 kBar2(ASCIIToUTF16("bar2"));
82 const base::string16 kBar3(ASCIIToUTF16("bar3"));
83 const base::string16 kBaz(ASCIIToUTF16("baz"));
84 const base::string16 kFirst(ASCIIToUTF16("first"));
85 const base::string16 kFoo(ASCIIToUTF16("foo"));
86 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
87 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
88 const base::string16 kFou(ASCIIToUTF16("fou"));
89 const base::string16 kSecond(ASCIIToUTF16("second"));
90 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
91 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
93 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
94 return session->GetTransportSocketPool(
95 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
98 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
99 return session->GetSSLSocketPool(
100 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
103 bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) {
104 return session->GetTransportSocketPool(
105 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled();
108 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
109 // a JSONified list of headers as a single string. Uses single quotes instead
110 // of double quotes for easier comparison. Returns false on failure.
111 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
112 if (!params)
113 return false;
114 base::ListValue* header_list;
115 if (!params->GetList("headers", &header_list))
116 return false;
117 std::string double_quote_headers;
118 base::JSONWriter::Write(header_list, &double_quote_headers);
119 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
120 return true;
123 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
124 // used.
125 void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
126 EXPECT_TRUE(load_timing_info.socket_reused);
127 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
129 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
130 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
132 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
133 EXPECT_FALSE(load_timing_info.send_start.is_null());
135 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
137 // Set at a higher level.
138 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
139 EXPECT_TRUE(load_timing_info.request_start.is_null());
140 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
143 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
144 // used.
145 void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
146 int connect_timing_flags) {
147 EXPECT_FALSE(load_timing_info.socket_reused);
148 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
150 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
151 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
153 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
154 connect_timing_flags);
155 EXPECT_LE(load_timing_info.connect_timing.connect_end,
156 load_timing_info.send_start);
158 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
160 // Set at a higher level.
161 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
162 EXPECT_TRUE(load_timing_info.request_start.is_null());
163 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
166 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
167 // used.
168 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
169 EXPECT_TRUE(load_timing_info.socket_reused);
170 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
172 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
174 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
175 EXPECT_LE(load_timing_info.proxy_resolve_start,
176 load_timing_info.proxy_resolve_end);
177 EXPECT_LE(load_timing_info.proxy_resolve_end,
178 load_timing_info.send_start);
179 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
181 // Set at a higher level.
182 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
183 EXPECT_TRUE(load_timing_info.request_start.is_null());
184 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
187 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
188 // used.
189 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
190 int connect_timing_flags) {
191 EXPECT_FALSE(load_timing_info.socket_reused);
192 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
194 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
195 EXPECT_LE(load_timing_info.proxy_resolve_start,
196 load_timing_info.proxy_resolve_end);
197 EXPECT_LE(load_timing_info.proxy_resolve_end,
198 load_timing_info.connect_timing.connect_start);
199 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
200 connect_timing_flags);
201 EXPECT_LE(load_timing_info.connect_timing.connect_end,
202 load_timing_info.send_start);
204 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
206 // Set at a higher level.
207 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
208 EXPECT_TRUE(load_timing_info.request_start.is_null());
209 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
212 } // namespace
214 namespace net {
216 namespace {
218 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
219 return SpdySessionDependencies::SpdyCreateSession(session_deps);
222 } // namespace
224 class HttpNetworkTransactionTest
225 : public PlatformTest,
226 public ::testing::WithParamInterface<NextProto> {
227 public:
228 virtual ~HttpNetworkTransactionTest() {
229 // Important to restore the per-pool limit first, since the pool limit must
230 // always be greater than group limit, and the tests reduce both limits.
231 ClientSocketPoolManager::set_max_sockets_per_pool(
232 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
233 ClientSocketPoolManager::set_max_sockets_per_group(
234 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
237 protected:
238 HttpNetworkTransactionTest()
239 : spdy_util_(GetParam()),
240 session_deps_(GetParam()),
241 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
242 HttpNetworkSession::NORMAL_SOCKET_POOL)),
243 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
244 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
247 struct SimpleGetHelperResult {
248 int rv;
249 std::string status_line;
250 std::string response_data;
251 int64 totalReceivedBytes;
252 LoadTimingInfo load_timing_info;
255 virtual void SetUp() {
256 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
257 base::MessageLoop::current()->RunUntilIdle();
260 virtual void TearDown() {
261 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
262 base::MessageLoop::current()->RunUntilIdle();
263 // Empty the current queue.
264 base::MessageLoop::current()->RunUntilIdle();
265 PlatformTest::TearDown();
266 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
267 base::MessageLoop::current()->RunUntilIdle();
270 // This is the expected return from a current server advertising SPDY.
271 std::string GetAlternateProtocolHttpHeader() {
272 return
273 std::string("Alternate-Protocol: 443:") +
274 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
275 "\r\n\r\n";
278 // Either |write_failure| specifies a write failure or |read_failure|
279 // specifies a read failure when using a reused socket. In either case, the
280 // failure should cause the network transaction to resend the request, and the
281 // other argument should be NULL.
282 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
283 const MockRead* read_failure);
285 // Either |write_failure| specifies a write failure or |read_failure|
286 // specifies a read failure when using a reused socket. In either case, the
287 // failure should cause the network transaction to resend the request, and the
288 // other argument should be NULL.
289 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
290 const MockRead* read_failure,
291 bool use_spdy);
293 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
294 size_t data_count) {
295 SimpleGetHelperResult out;
297 HttpRequestInfo request;
298 request.method = "GET";
299 request.url = GURL("http://www.google.com/");
300 request.load_flags = 0;
302 CapturingBoundNetLog log;
303 session_deps_.net_log = log.bound().net_log();
304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
305 scoped_ptr<HttpTransaction> trans(
306 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
308 for (size_t i = 0; i < data_count; ++i) {
309 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
312 TestCompletionCallback callback;
314 EXPECT_TRUE(log.bound().IsLogging());
315 int rv = trans->Start(&request, callback.callback(), log.bound());
316 EXPECT_EQ(ERR_IO_PENDING, rv);
318 out.rv = callback.WaitForResult();
320 // Even in the failure cases that use this function, connections are always
321 // successfully established before the error.
322 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
323 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
325 if (out.rv != OK)
326 return out;
328 const HttpResponseInfo* response = trans->GetResponseInfo();
329 // Can't use ASSERT_* inside helper functions like this, so
330 // return an error.
331 if (response == NULL || response->headers.get() == NULL) {
332 out.rv = ERR_UNEXPECTED;
333 return out;
335 out.status_line = response->headers->GetStatusLine();
337 EXPECT_EQ("127.0.0.1", response->socket_address.host());
338 EXPECT_EQ(80, response->socket_address.port());
340 rv = ReadTransaction(trans.get(), &out.response_data);
341 EXPECT_EQ(OK, rv);
343 net::CapturingNetLog::CapturedEntryList entries;
344 log.GetEntries(&entries);
345 size_t pos = ExpectLogContainsSomewhere(
346 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
347 NetLog::PHASE_NONE);
348 ExpectLogContainsSomewhere(
349 entries, pos,
350 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
351 NetLog::PHASE_NONE);
353 std::string line;
354 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
355 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
357 HttpRequestHeaders request_headers;
358 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
359 std::string value;
360 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
361 EXPECT_EQ("www.google.com", value);
362 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
363 EXPECT_EQ("keep-alive", value);
365 std::string response_headers;
366 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
367 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
368 response_headers);
370 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
371 return out;
374 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
375 size_t reads_count) {
376 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
377 StaticSocketDataProvider* data[] = { &reads };
378 return SimpleGetHelperForData(data, 1);
381 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
382 int64 size = 0;
383 for (size_t i = 0; i < reads_count; ++i)
384 size += data_reads[i].data_len;
385 return size;
388 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
389 int expected_status);
391 void ConnectStatusHelper(const MockRead& status);
393 void BypassHostCacheOnRefreshHelper(int load_flags);
395 void CheckErrorIsPassedBack(int error, IoMode mode);
397 SpdyTestUtil spdy_util_;
398 SpdySessionDependencies session_deps_;
400 // Original socket limits. Some tests set these. Safest to always restore
401 // them once each test has been run.
402 int old_max_group_sockets_;
403 int old_max_pool_sockets_;
406 INSTANTIATE_TEST_CASE_P(
407 NextProto,
408 HttpNetworkTransactionTest,
409 testing::Values(kProtoDeprecatedSPDY2,
410 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
412 namespace {
414 class BeforeNetworkStartHandler {
415 public:
416 explicit BeforeNetworkStartHandler(bool defer)
417 : defer_on_before_network_start_(defer),
418 observed_before_network_start_(false) {}
420 void OnBeforeNetworkStart(bool* defer) {
421 *defer = defer_on_before_network_start_;
422 observed_before_network_start_ = true;
425 bool observed_before_network_start() const {
426 return observed_before_network_start_;
429 private:
430 const bool defer_on_before_network_start_;
431 bool observed_before_network_start_;
433 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
436 // Fill |str| with a long header list that consumes >= |size| bytes.
437 void FillLargeHeadersString(std::string* str, int size) {
438 const char* row =
439 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
440 const int sizeof_row = strlen(row);
441 const int num_rows = static_cast<int>(
442 ceil(static_cast<float>(size) / sizeof_row));
443 const int sizeof_data = num_rows * sizeof_row;
444 DCHECK(sizeof_data >= size);
445 str->reserve(sizeof_data);
447 for (int i = 0; i < num_rows; ++i)
448 str->append(row, sizeof_row);
451 // Alternative functions that eliminate randomness and dependency on the local
452 // host name so that the generated NTLM messages are reproducible.
453 void MockGenerateRandom1(uint8* output, size_t n) {
454 static const uint8 bytes[] = {
455 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
457 static size_t current_byte = 0;
458 for (size_t i = 0; i < n; ++i) {
459 output[i] = bytes[current_byte++];
460 current_byte %= arraysize(bytes);
464 void MockGenerateRandom2(uint8* output, size_t n) {
465 static const uint8 bytes[] = {
466 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
467 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
469 static size_t current_byte = 0;
470 for (size_t i = 0; i < n; ++i) {
471 output[i] = bytes[current_byte++];
472 current_byte %= arraysize(bytes);
476 std::string MockGetHostName() {
477 return "WTC-WIN7";
480 template<typename ParentPool>
481 class CaptureGroupNameSocketPool : public ParentPool {
482 public:
483 CaptureGroupNameSocketPool(HostResolver* host_resolver,
484 CertVerifier* cert_verifier);
486 const std::string last_group_name_received() const {
487 return last_group_name_;
490 virtual int RequestSocket(const std::string& group_name,
491 const void* socket_params,
492 RequestPriority priority,
493 ClientSocketHandle* handle,
494 const CompletionCallback& callback,
495 const BoundNetLog& net_log) {
496 last_group_name_ = group_name;
497 return ERR_IO_PENDING;
499 virtual void CancelRequest(const std::string& group_name,
500 ClientSocketHandle* handle) {}
501 virtual void ReleaseSocket(const std::string& group_name,
502 scoped_ptr<StreamSocket> socket,
503 int id) {}
504 virtual void CloseIdleSockets() {}
505 virtual int IdleSocketCount() const {
506 return 0;
508 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
509 return 0;
511 virtual LoadState GetLoadState(const std::string& group_name,
512 const ClientSocketHandle* handle) const {
513 return LOAD_STATE_IDLE;
515 virtual base::TimeDelta ConnectionTimeout() const {
516 return base::TimeDelta();
519 private:
520 std::string last_group_name_;
523 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
524 CaptureGroupNameTransportSocketPool;
525 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
526 CaptureGroupNameHttpProxySocketPool;
527 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
528 CaptureGroupNameSOCKSSocketPool;
529 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
530 CaptureGroupNameSSLSocketPool;
532 template<typename ParentPool>
533 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
534 HostResolver* host_resolver,
535 CertVerifier* /* cert_verifier */)
536 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
538 template<>
539 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
540 HostResolver* host_resolver,
541 CertVerifier* /* cert_verifier */)
542 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
544 template <>
545 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
546 HostResolver* host_resolver,
547 CertVerifier* cert_verifier)
548 : SSLClientSocketPool(0,
550 NULL,
551 host_resolver,
552 cert_verifier,
553 NULL,
554 NULL,
555 NULL,
556 std::string(),
557 NULL,
558 NULL,
559 NULL,
560 NULL,
561 NULL,
562 NULL) {}
564 //-----------------------------------------------------------------------------
566 // Helper functions for validating that AuthChallengeInfo's are correctly
567 // configured for common cases.
568 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
569 if (!auth_challenge)
570 return false;
571 EXPECT_FALSE(auth_challenge->is_proxy);
572 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
573 EXPECT_EQ("MyRealm1", auth_challenge->realm);
574 EXPECT_EQ("basic", auth_challenge->scheme);
575 return true;
578 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
579 if (!auth_challenge)
580 return false;
581 EXPECT_TRUE(auth_challenge->is_proxy);
582 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
583 EXPECT_EQ("MyRealm1", auth_challenge->realm);
584 EXPECT_EQ("basic", auth_challenge->scheme);
585 return true;
588 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
589 if (!auth_challenge)
590 return false;
591 EXPECT_FALSE(auth_challenge->is_proxy);
592 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
593 EXPECT_EQ("digestive", auth_challenge->realm);
594 EXPECT_EQ("digest", auth_challenge->scheme);
595 return true;
598 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
599 if (!auth_challenge)
600 return false;
601 EXPECT_FALSE(auth_challenge->is_proxy);
602 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
603 EXPECT_EQ(std::string(), auth_challenge->realm);
604 EXPECT_EQ("ntlm", auth_challenge->scheme);
605 return true;
608 } // namespace
610 TEST_P(HttpNetworkTransactionTest, Basic) {
611 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
612 scoped_ptr<HttpTransaction> trans(
613 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
616 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
617 MockRead data_reads[] = {
618 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
619 MockRead("hello world"),
620 MockRead(SYNCHRONOUS, OK),
622 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
623 arraysize(data_reads));
624 EXPECT_EQ(OK, out.rv);
625 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
626 EXPECT_EQ("hello world", out.response_data);
627 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
628 EXPECT_EQ(reads_size, out.totalReceivedBytes);
631 // Response with no status line.
632 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
633 MockRead data_reads[] = {
634 MockRead("hello world"),
635 MockRead(SYNCHRONOUS, OK),
637 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
638 arraysize(data_reads));
639 EXPECT_EQ(OK, out.rv);
640 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
641 EXPECT_EQ("hello world", out.response_data);
642 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
643 EXPECT_EQ(reads_size, out.totalReceivedBytes);
646 // Allow up to 4 bytes of junk to precede status line.
647 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
648 MockRead data_reads[] = {
649 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
650 MockRead(SYNCHRONOUS, OK),
652 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
653 arraysize(data_reads));
654 EXPECT_EQ(OK, out.rv);
655 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
656 EXPECT_EQ("DATA", out.response_data);
657 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
658 EXPECT_EQ(reads_size, out.totalReceivedBytes);
661 // Allow up to 4 bytes of junk to precede status line.
662 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
663 MockRead data_reads[] = {
664 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
665 MockRead(SYNCHRONOUS, OK),
667 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
668 arraysize(data_reads));
669 EXPECT_EQ(OK, out.rv);
670 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
671 EXPECT_EQ("DATA", out.response_data);
672 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
673 EXPECT_EQ(reads_size, out.totalReceivedBytes);
676 // Beyond 4 bytes of slop and it should fail to find a status line.
677 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
678 MockRead data_reads[] = {
679 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
680 MockRead(SYNCHRONOUS, OK),
682 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
683 arraysize(data_reads));
684 EXPECT_EQ(OK, out.rv);
685 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
686 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
687 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
688 EXPECT_EQ(reads_size, out.totalReceivedBytes);
691 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
692 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
693 MockRead data_reads[] = {
694 MockRead("\n"),
695 MockRead("\n"),
696 MockRead("Q"),
697 MockRead("J"),
698 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
699 MockRead(SYNCHRONOUS, OK),
701 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
702 arraysize(data_reads));
703 EXPECT_EQ(OK, out.rv);
704 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
705 EXPECT_EQ("DATA", out.response_data);
706 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
707 EXPECT_EQ(reads_size, out.totalReceivedBytes);
710 // Close the connection before enough bytes to have a status line.
711 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
712 MockRead data_reads[] = {
713 MockRead("HTT"),
714 MockRead(SYNCHRONOUS, OK),
716 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
717 arraysize(data_reads));
718 EXPECT_EQ(OK, out.rv);
719 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
720 EXPECT_EQ("HTT", out.response_data);
721 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
722 EXPECT_EQ(reads_size, out.totalReceivedBytes);
725 // Simulate a 204 response, lacking a Content-Length header, sent over a
726 // persistent connection. The response should still terminate since a 204
727 // cannot have a response body.
728 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
729 char junk[] = "junk";
730 MockRead data_reads[] = {
731 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
732 MockRead(junk), // Should not be read!!
733 MockRead(SYNCHRONOUS, OK),
735 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
736 arraysize(data_reads));
737 EXPECT_EQ(OK, out.rv);
738 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
739 EXPECT_EQ("", out.response_data);
740 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
741 int64 response_size = reads_size - strlen(junk);
742 EXPECT_EQ(response_size, out.totalReceivedBytes);
745 // A simple request using chunked encoding with some extra data after.
746 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
747 std::string final_chunk = "0\r\n\r\n";
748 std::string extra_data = "HTTP/1.1 200 OK\r\n";
749 std::string last_read = final_chunk + extra_data;
750 MockRead data_reads[] = {
751 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
752 MockRead("5\r\nHello\r\n"),
753 MockRead("1\r\n"),
754 MockRead(" \r\n"),
755 MockRead("5\r\nworld\r\n"),
756 MockRead(last_read.data()),
757 MockRead(SYNCHRONOUS, OK),
759 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
760 arraysize(data_reads));
761 EXPECT_EQ(OK, out.rv);
762 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
763 EXPECT_EQ("Hello world", out.response_data);
764 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
765 int64 response_size = reads_size - extra_data.size();
766 EXPECT_EQ(response_size, out.totalReceivedBytes);
769 // Next tests deal with http://crbug.com/56344.
771 TEST_P(HttpNetworkTransactionTest,
772 MultipleContentLengthHeadersNoTransferEncoding) {
773 MockRead data_reads[] = {
774 MockRead("HTTP/1.1 200 OK\r\n"),
775 MockRead("Content-Length: 10\r\n"),
776 MockRead("Content-Length: 5\r\n\r\n"),
778 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
779 arraysize(data_reads));
780 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
783 TEST_P(HttpNetworkTransactionTest,
784 DuplicateContentLengthHeadersNoTransferEncoding) {
785 MockRead data_reads[] = {
786 MockRead("HTTP/1.1 200 OK\r\n"),
787 MockRead("Content-Length: 5\r\n"),
788 MockRead("Content-Length: 5\r\n\r\n"),
789 MockRead("Hello"),
791 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
792 arraysize(data_reads));
793 EXPECT_EQ(OK, out.rv);
794 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
795 EXPECT_EQ("Hello", out.response_data);
798 TEST_P(HttpNetworkTransactionTest,
799 ComplexContentLengthHeadersNoTransferEncoding) {
800 // More than 2 dupes.
802 MockRead data_reads[] = {
803 MockRead("HTTP/1.1 200 OK\r\n"),
804 MockRead("Content-Length: 5\r\n"),
805 MockRead("Content-Length: 5\r\n"),
806 MockRead("Content-Length: 5\r\n\r\n"),
807 MockRead("Hello"),
809 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
810 arraysize(data_reads));
811 EXPECT_EQ(OK, out.rv);
812 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
813 EXPECT_EQ("Hello", out.response_data);
815 // HTTP/1.0
817 MockRead data_reads[] = {
818 MockRead("HTTP/1.0 200 OK\r\n"),
819 MockRead("Content-Length: 5\r\n"),
820 MockRead("Content-Length: 5\r\n"),
821 MockRead("Content-Length: 5\r\n\r\n"),
822 MockRead("Hello"),
824 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
825 arraysize(data_reads));
826 EXPECT_EQ(OK, out.rv);
827 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
828 EXPECT_EQ("Hello", out.response_data);
830 // 2 dupes and one mismatched.
832 MockRead data_reads[] = {
833 MockRead("HTTP/1.1 200 OK\r\n"),
834 MockRead("Content-Length: 10\r\n"),
835 MockRead("Content-Length: 10\r\n"),
836 MockRead("Content-Length: 5\r\n\r\n"),
838 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
839 arraysize(data_reads));
840 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
844 TEST_P(HttpNetworkTransactionTest,
845 MultipleContentLengthHeadersTransferEncoding) {
846 MockRead data_reads[] = {
847 MockRead("HTTP/1.1 200 OK\r\n"),
848 MockRead("Content-Length: 666\r\n"),
849 MockRead("Content-Length: 1337\r\n"),
850 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
851 MockRead("5\r\nHello\r\n"),
852 MockRead("1\r\n"),
853 MockRead(" \r\n"),
854 MockRead("5\r\nworld\r\n"),
855 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
856 MockRead(SYNCHRONOUS, OK),
858 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
859 arraysize(data_reads));
860 EXPECT_EQ(OK, out.rv);
861 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
862 EXPECT_EQ("Hello world", out.response_data);
865 // Next tests deal with http://crbug.com/98895.
867 // Checks that a single Content-Disposition header results in no error.
868 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
869 MockRead data_reads[] = {
870 MockRead("HTTP/1.1 200 OK\r\n"),
871 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
872 MockRead("Content-Length: 5\r\n\r\n"),
873 MockRead("Hello"),
875 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
876 arraysize(data_reads));
877 EXPECT_EQ(OK, out.rv);
878 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
879 EXPECT_EQ("Hello", out.response_data);
882 // Checks that two identical Content-Disposition headers result in no error.
883 TEST_P(HttpNetworkTransactionTest,
884 TwoIdenticalContentDispositionHeaders) {
885 MockRead data_reads[] = {
886 MockRead("HTTP/1.1 200 OK\r\n"),
887 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
888 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
889 MockRead("Content-Length: 5\r\n\r\n"),
890 MockRead("Hello"),
892 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
893 arraysize(data_reads));
894 EXPECT_EQ(OK, out.rv);
895 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
896 EXPECT_EQ("Hello", out.response_data);
899 // Checks that two distinct Content-Disposition headers result in an error.
900 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
901 MockRead data_reads[] = {
902 MockRead("HTTP/1.1 200 OK\r\n"),
903 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
904 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
905 MockRead("Content-Length: 5\r\n\r\n"),
906 MockRead("Hello"),
908 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
909 arraysize(data_reads));
910 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
913 // Checks that two identical Location headers result in no error.
914 // Also tests Location header behavior.
915 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
916 MockRead data_reads[] = {
917 MockRead("HTTP/1.1 302 Redirect\r\n"),
918 MockRead("Location: http://good.com/\r\n"),
919 MockRead("Location: http://good.com/\r\n"),
920 MockRead("Content-Length: 0\r\n\r\n"),
921 MockRead(SYNCHRONOUS, OK),
924 HttpRequestInfo request;
925 request.method = "GET";
926 request.url = GURL("http://redirect.com/");
927 request.load_flags = 0;
929 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
930 scoped_ptr<HttpTransaction> trans(
931 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
933 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
934 session_deps_.socket_factory->AddSocketDataProvider(&data);
936 TestCompletionCallback callback;
938 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
939 EXPECT_EQ(ERR_IO_PENDING, rv);
941 EXPECT_EQ(OK, callback.WaitForResult());
943 const HttpResponseInfo* response = trans->GetResponseInfo();
944 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
945 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
946 std::string url;
947 EXPECT_TRUE(response->headers->IsRedirect(&url));
948 EXPECT_EQ("http://good.com/", url);
951 // Checks that two distinct Location headers result in an error.
952 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
953 MockRead data_reads[] = {
954 MockRead("HTTP/1.1 302 Redirect\r\n"),
955 MockRead("Location: http://good.com/\r\n"),
956 MockRead("Location: http://evil.com/\r\n"),
957 MockRead("Content-Length: 0\r\n\r\n"),
958 MockRead(SYNCHRONOUS, OK),
960 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
961 arraysize(data_reads));
962 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
965 // Do a request using the HEAD method. Verify that we don't try to read the
966 // message body (since HEAD has none).
967 TEST_P(HttpNetworkTransactionTest, Head) {
968 HttpRequestInfo request;
969 request.method = "HEAD";
970 request.url = GURL("http://www.google.com/");
971 request.load_flags = 0;
973 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
974 scoped_ptr<HttpTransaction> trans(
975 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
977 MockWrite data_writes1[] = {
978 MockWrite("HEAD / HTTP/1.1\r\n"
979 "Host: www.google.com\r\n"
980 "Connection: keep-alive\r\n"
981 "Content-Length: 0\r\n\r\n"),
983 MockRead data_reads1[] = {
984 MockRead("HTTP/1.1 404 Not Found\r\n"),
985 MockRead("Server: Blah\r\n"),
986 MockRead("Content-Length: 1234\r\n\r\n"),
988 // No response body because the test stops reading here.
989 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
992 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
993 data_writes1, arraysize(data_writes1));
994 session_deps_.socket_factory->AddSocketDataProvider(&data1);
996 TestCompletionCallback callback1;
998 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
999 EXPECT_EQ(ERR_IO_PENDING, rv);
1001 rv = callback1.WaitForResult();
1002 EXPECT_EQ(OK, rv);
1004 const HttpResponseInfo* response = trans->GetResponseInfo();
1005 ASSERT_TRUE(response != NULL);
1007 // Check that the headers got parsed.
1008 EXPECT_TRUE(response->headers.get() != NULL);
1009 EXPECT_EQ(1234, response->headers->GetContentLength());
1010 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1012 std::string server_header;
1013 void* iter = NULL;
1014 bool has_server_header = response->headers->EnumerateHeader(
1015 &iter, "Server", &server_header);
1016 EXPECT_TRUE(has_server_header);
1017 EXPECT_EQ("Blah", server_header);
1019 // Reading should give EOF right away, since there is no message body
1020 // (despite non-zero content-length).
1021 std::string response_data;
1022 rv = ReadTransaction(trans.get(), &response_data);
1023 EXPECT_EQ(OK, rv);
1024 EXPECT_EQ("", response_data);
1027 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1028 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1030 MockRead data_reads[] = {
1031 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1032 MockRead("hello"),
1033 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1034 MockRead("world"),
1035 MockRead(SYNCHRONOUS, OK),
1037 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1038 session_deps_.socket_factory->AddSocketDataProvider(&data);
1040 const char* const kExpectedResponseData[] = {
1041 "hello", "world"
1044 for (int i = 0; i < 2; ++i) {
1045 HttpRequestInfo request;
1046 request.method = "GET";
1047 request.url = GURL("http://www.google.com/");
1048 request.load_flags = 0;
1050 scoped_ptr<HttpTransaction> trans(
1051 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1053 TestCompletionCallback callback;
1055 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1056 EXPECT_EQ(ERR_IO_PENDING, rv);
1058 rv = callback.WaitForResult();
1059 EXPECT_EQ(OK, rv);
1061 const HttpResponseInfo* response = trans->GetResponseInfo();
1062 ASSERT_TRUE(response != NULL);
1064 EXPECT_TRUE(response->headers.get() != NULL);
1065 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1067 std::string response_data;
1068 rv = ReadTransaction(trans.get(), &response_data);
1069 EXPECT_EQ(OK, rv);
1070 EXPECT_EQ(kExpectedResponseData[i], response_data);
1074 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1075 ScopedVector<UploadElementReader> element_readers;
1076 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1077 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1079 HttpRequestInfo request;
1080 request.method = "POST";
1081 request.url = GURL("http://www.foo.com/");
1082 request.upload_data_stream = &upload_data_stream;
1083 request.load_flags = 0;
1085 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1086 scoped_ptr<HttpTransaction> trans(
1087 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1089 MockRead data_reads[] = {
1090 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1091 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1092 MockRead("hello world"),
1093 MockRead(SYNCHRONOUS, OK),
1095 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1096 session_deps_.socket_factory->AddSocketDataProvider(&data);
1098 TestCompletionCallback callback;
1100 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1101 EXPECT_EQ(ERR_IO_PENDING, rv);
1103 rv = callback.WaitForResult();
1104 EXPECT_EQ(OK, rv);
1106 const HttpResponseInfo* response = trans->GetResponseInfo();
1107 ASSERT_TRUE(response != NULL);
1109 EXPECT_TRUE(response->headers.get() != NULL);
1110 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1112 std::string response_data;
1113 rv = ReadTransaction(trans.get(), &response_data);
1114 EXPECT_EQ(OK, rv);
1115 EXPECT_EQ("hello world", response_data);
1118 // This test is almost the same as Ignores100 above, but the response contains
1119 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1120 // HTTP/1.1 and the two status headers are read in one read.
1121 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1122 HttpRequestInfo request;
1123 request.method = "GET";
1124 request.url = GURL("http://www.foo.com/");
1125 request.load_flags = 0;
1127 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1128 scoped_ptr<HttpTransaction> trans(
1129 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1131 MockRead data_reads[] = {
1132 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1133 "HTTP/1.1 200 OK\r\n\r\n"),
1134 MockRead("hello world"),
1135 MockRead(SYNCHRONOUS, OK),
1137 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1138 session_deps_.socket_factory->AddSocketDataProvider(&data);
1140 TestCompletionCallback callback;
1142 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1143 EXPECT_EQ(ERR_IO_PENDING, rv);
1145 rv = callback.WaitForResult();
1146 EXPECT_EQ(OK, rv);
1148 const HttpResponseInfo* response = trans->GetResponseInfo();
1149 ASSERT_TRUE(response != NULL);
1151 EXPECT_TRUE(response->headers.get() != NULL);
1152 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1154 std::string response_data;
1155 rv = ReadTransaction(trans.get(), &response_data);
1156 EXPECT_EQ(OK, rv);
1157 EXPECT_EQ("hello world", response_data);
1160 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1161 HttpRequestInfo request;
1162 request.method = "POST";
1163 request.url = GURL("http://www.foo.com/");
1164 request.load_flags = 0;
1166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1167 scoped_ptr<HttpTransaction> trans(
1168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1170 MockRead data_reads[] = {
1171 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1172 MockRead(ASYNC, 0),
1174 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1175 session_deps_.socket_factory->AddSocketDataProvider(&data);
1177 TestCompletionCallback callback;
1179 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1180 EXPECT_EQ(ERR_IO_PENDING, rv);
1182 rv = callback.WaitForResult();
1183 EXPECT_EQ(OK, rv);
1185 std::string response_data;
1186 rv = ReadTransaction(trans.get(), &response_data);
1187 EXPECT_EQ(OK, rv);
1188 EXPECT_EQ("", response_data);
1191 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1192 HttpRequestInfo request;
1193 request.method = "POST";
1194 request.url = GURL("http://www.foo.com/");
1195 request.load_flags = 0;
1197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1198 scoped_ptr<HttpTransaction> trans(
1199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1202 MockRead data_reads[] = {
1203 MockRead(ASYNC, 0),
1205 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1206 session_deps_.socket_factory->AddSocketDataProvider(&data);
1208 TestCompletionCallback callback;
1210 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1211 EXPECT_EQ(ERR_IO_PENDING, rv);
1213 rv = callback.WaitForResult();
1214 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1217 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1218 const MockWrite* write_failure,
1219 const MockRead* read_failure) {
1220 HttpRequestInfo request;
1221 request.method = "GET";
1222 request.url = GURL("http://www.foo.com/");
1223 request.load_flags = 0;
1225 CapturingNetLog net_log;
1226 session_deps_.net_log = &net_log;
1227 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1229 // Written data for successfully sending both requests.
1230 MockWrite data1_writes[] = {
1231 MockWrite("GET / HTTP/1.1\r\n"
1232 "Host: www.foo.com\r\n"
1233 "Connection: keep-alive\r\n\r\n"),
1234 MockWrite("GET / HTTP/1.1\r\n"
1235 "Host: www.foo.com\r\n"
1236 "Connection: keep-alive\r\n\r\n")
1239 // Read results for the first request.
1240 MockRead data1_reads[] = {
1241 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1242 MockRead("hello"),
1243 MockRead(ASYNC, OK),
1246 if (write_failure) {
1247 ASSERT_FALSE(read_failure);
1248 data1_writes[1] = *write_failure;
1249 } else {
1250 ASSERT_TRUE(read_failure);
1251 data1_reads[2] = *read_failure;
1254 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1255 data1_writes, arraysize(data1_writes));
1256 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1258 MockRead data2_reads[] = {
1259 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1260 MockRead("world"),
1261 MockRead(ASYNC, OK),
1263 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1264 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1266 const char* kExpectedResponseData[] = {
1267 "hello", "world"
1270 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1271 for (int i = 0; i < 2; ++i) {
1272 TestCompletionCallback callback;
1274 scoped_ptr<HttpTransaction> trans(
1275 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1277 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1278 EXPECT_EQ(ERR_IO_PENDING, rv);
1280 rv = callback.WaitForResult();
1281 EXPECT_EQ(OK, rv);
1283 LoadTimingInfo load_timing_info;
1284 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1285 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1286 if (i == 0) {
1287 first_socket_log_id = load_timing_info.socket_log_id;
1288 } else {
1289 // The second request should be using a new socket.
1290 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1293 const HttpResponseInfo* response = trans->GetResponseInfo();
1294 ASSERT_TRUE(response != NULL);
1296 EXPECT_TRUE(response->headers.get() != NULL);
1297 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1299 std::string response_data;
1300 rv = ReadTransaction(trans.get(), &response_data);
1301 EXPECT_EQ(OK, rv);
1302 EXPECT_EQ(kExpectedResponseData[i], response_data);
1306 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1307 const MockWrite* write_failure,
1308 const MockRead* read_failure,
1309 bool use_spdy) {
1310 HttpRequestInfo request;
1311 request.method = "GET";
1312 request.url = GURL("https://www.foo.com/");
1313 request.load_flags = 0;
1315 CapturingNetLog net_log;
1316 session_deps_.net_log = &net_log;
1317 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1319 SSLSocketDataProvider ssl1(ASYNC, OK);
1320 SSLSocketDataProvider ssl2(ASYNC, OK);
1321 if (use_spdy) {
1322 ssl1.SetNextProto(GetParam());
1323 ssl2.SetNextProto(GetParam());
1325 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1326 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1328 // SPDY versions of the request and response.
1329 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1330 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1331 scoped_ptr<SpdyFrame> spdy_response(
1332 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1333 scoped_ptr<SpdyFrame> spdy_data(
1334 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1336 // HTTP/1.1 versions of the request and response.
1337 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1338 "Host: www.foo.com\r\n"
1339 "Connection: keep-alive\r\n\r\n";
1340 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1341 const char kHttpData[] = "hello";
1343 std::vector<MockRead> data1_reads;
1344 std::vector<MockWrite> data1_writes;
1345 if (write_failure) {
1346 ASSERT_FALSE(read_failure);
1347 data1_writes.push_back(*write_failure);
1348 data1_reads.push_back(MockRead(ASYNC, OK));
1349 } else {
1350 ASSERT_TRUE(read_failure);
1351 if (use_spdy) {
1352 data1_writes.push_back(CreateMockWrite(*spdy_request));
1353 } else {
1354 data1_writes.push_back(MockWrite(kHttpRequest));
1356 data1_reads.push_back(*read_failure);
1359 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1360 &data1_writes[0], data1_writes.size());
1361 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1363 std::vector<MockRead> data2_reads;
1364 std::vector<MockWrite> data2_writes;
1366 if (use_spdy) {
1367 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1369 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1370 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1371 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1372 } else {
1373 data2_writes.push_back(
1374 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1376 data2_reads.push_back(
1377 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1378 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1379 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1381 OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
1382 &data2_writes[0], data2_writes.size());
1383 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1385 // Preconnect a socket.
1386 net::SSLConfig ssl_config;
1387 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1388 session->GetNextProtos(&ssl_config.next_protos);
1389 session->http_stream_factory()->PreconnectStreams(
1390 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1391 // Wait for the preconnect to complete.
1392 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1393 base::RunLoop().RunUntilIdle();
1394 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1396 // Make the request.
1397 TestCompletionCallback callback;
1399 scoped_ptr<HttpTransaction> trans(
1400 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1402 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1403 EXPECT_EQ(ERR_IO_PENDING, rv);
1405 rv = callback.WaitForResult();
1406 EXPECT_EQ(OK, rv);
1408 LoadTimingInfo load_timing_info;
1409 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1410 TestLoadTimingNotReused(
1411 load_timing_info,
1412 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1414 const HttpResponseInfo* response = trans->GetResponseInfo();
1415 ASSERT_TRUE(response != NULL);
1417 EXPECT_TRUE(response->headers.get() != NULL);
1418 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1420 std::string response_data;
1421 rv = ReadTransaction(trans.get(), &response_data);
1422 EXPECT_EQ(OK, rv);
1423 EXPECT_EQ(kHttpData, response_data);
1426 TEST_P(HttpNetworkTransactionTest,
1427 KeepAliveConnectionNotConnectedOnWrite) {
1428 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1429 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1432 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1433 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1434 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1437 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1438 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1439 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1442 TEST_P(HttpNetworkTransactionTest,
1443 PreconnectErrorNotConnectedOnWrite) {
1444 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1445 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1448 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1449 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1450 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1453 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1454 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1455 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1458 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1459 MockRead read_failure(ASYNC, OK); // EOF
1460 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1463 TEST_P(HttpNetworkTransactionTest,
1464 SpdyPreconnectErrorNotConnectedOnWrite) {
1465 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1466 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1469 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1470 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1471 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1474 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1475 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1476 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1479 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1480 MockRead read_failure(ASYNC, OK); // EOF
1481 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1484 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1485 HttpRequestInfo request;
1486 request.method = "GET";
1487 request.url = GURL("http://www.google.com/");
1488 request.load_flags = 0;
1490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1491 scoped_ptr<HttpTransaction> trans(
1492 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1494 MockRead data_reads[] = {
1495 MockRead(ASYNC, ERR_CONNECTION_RESET),
1496 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1497 MockRead("hello world"),
1498 MockRead(SYNCHRONOUS, OK),
1500 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1501 session_deps_.socket_factory->AddSocketDataProvider(&data);
1503 TestCompletionCallback callback;
1505 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1506 EXPECT_EQ(ERR_IO_PENDING, rv);
1508 rv = callback.WaitForResult();
1509 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1511 const HttpResponseInfo* response = trans->GetResponseInfo();
1512 EXPECT_TRUE(response == NULL);
1515 // What do various browsers do when the server closes a non-keepalive
1516 // connection without sending any response header or body?
1518 // IE7: error page
1519 // Safari 3.1.2 (Windows): error page
1520 // Firefox 3.0.1: blank page
1521 // Opera 9.52: after five attempts, blank page
1522 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1523 // Us: error page (EMPTY_RESPONSE)
1524 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1525 MockRead data_reads[] = {
1526 MockRead(SYNCHRONOUS, OK), // EOF
1527 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1528 MockRead("hello world"),
1529 MockRead(SYNCHRONOUS, OK),
1531 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1532 arraysize(data_reads));
1533 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1536 // Test that network access can be deferred and resumed.
1537 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1538 HttpRequestInfo request;
1539 request.method = "GET";
1540 request.url = GURL("http://www.google.com/");
1541 request.load_flags = 0;
1543 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1544 scoped_ptr<HttpTransaction> trans(
1545 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1547 // Defer on OnBeforeNetworkStart.
1548 BeforeNetworkStartHandler net_start_handler(true); // defer
1549 trans->SetBeforeNetworkStartCallback(
1550 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1551 base::Unretained(&net_start_handler)));
1553 MockRead data_reads[] = {
1554 MockRead("HTTP/1.0 200 OK\r\n"),
1555 MockRead("Content-Length: 5\r\n\r\n"),
1556 MockRead("hello"),
1557 MockRead(SYNCHRONOUS, 0),
1559 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1560 session_deps_.socket_factory->AddSocketDataProvider(&data);
1562 TestCompletionCallback callback;
1564 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1565 EXPECT_EQ(ERR_IO_PENDING, rv);
1566 base::MessageLoop::current()->RunUntilIdle();
1568 // Should have deferred for network start.
1569 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1570 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1571 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1573 trans->ResumeNetworkStart();
1574 rv = callback.WaitForResult();
1575 EXPECT_EQ(OK, rv);
1576 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1578 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1579 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1580 if (rv == ERR_IO_PENDING)
1581 rv = callback.WaitForResult();
1582 EXPECT_EQ(5, rv);
1583 trans.reset();
1586 // Test that network use can be deferred and canceled.
1587 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1588 HttpRequestInfo request;
1589 request.method = "GET";
1590 request.url = GURL("http://www.google.com/");
1591 request.load_flags = 0;
1593 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1594 scoped_ptr<HttpTransaction> trans(
1595 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1597 // Defer on OnBeforeNetworkStart.
1598 BeforeNetworkStartHandler net_start_handler(true); // defer
1599 trans->SetBeforeNetworkStartCallback(
1600 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1601 base::Unretained(&net_start_handler)));
1603 TestCompletionCallback callback;
1605 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1606 EXPECT_EQ(ERR_IO_PENDING, rv);
1607 base::MessageLoop::current()->RunUntilIdle();
1609 // Should have deferred for network start.
1610 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1611 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1612 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1615 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1616 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1617 // destructor in such situations.
1618 // See http://crbug.com/154712 and http://crbug.com/156609.
1619 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1620 HttpRequestInfo request;
1621 request.method = "GET";
1622 request.url = GURL("http://www.google.com/");
1623 request.load_flags = 0;
1625 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1626 scoped_ptr<HttpTransaction> trans(
1627 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1629 MockRead data_reads[] = {
1630 MockRead("HTTP/1.0 200 OK\r\n"),
1631 MockRead("Connection: keep-alive\r\n"),
1632 MockRead("Content-Length: 100\r\n\r\n"),
1633 MockRead("hello"),
1634 MockRead(SYNCHRONOUS, 0),
1636 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1637 session_deps_.socket_factory->AddSocketDataProvider(&data);
1639 TestCompletionCallback callback;
1641 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1642 EXPECT_EQ(ERR_IO_PENDING, rv);
1644 rv = callback.WaitForResult();
1645 EXPECT_EQ(OK, rv);
1647 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1648 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1649 if (rv == ERR_IO_PENDING)
1650 rv = callback.WaitForResult();
1651 EXPECT_EQ(5, rv);
1652 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1653 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1655 trans.reset();
1656 base::MessageLoop::current()->RunUntilIdle();
1657 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1660 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1661 HttpRequestInfo request;
1662 request.method = "GET";
1663 request.url = GURL("http://www.google.com/");
1664 request.load_flags = 0;
1666 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1667 scoped_ptr<HttpTransaction> trans(
1668 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1670 MockRead data_reads[] = {
1671 MockRead("HTTP/1.0 200 OK\r\n"),
1672 MockRead("Connection: keep-alive\r\n"),
1673 MockRead("Content-Length: 100\r\n\r\n"),
1674 MockRead(SYNCHRONOUS, 0),
1676 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1677 session_deps_.socket_factory->AddSocketDataProvider(&data);
1679 TestCompletionCallback callback;
1681 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1682 EXPECT_EQ(ERR_IO_PENDING, rv);
1684 rv = callback.WaitForResult();
1685 EXPECT_EQ(OK, rv);
1687 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1688 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1689 if (rv == ERR_IO_PENDING)
1690 rv = callback.WaitForResult();
1691 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1693 trans.reset();
1694 base::MessageLoop::current()->RunUntilIdle();
1695 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1698 // Test that we correctly reuse a keep-alive connection after not explicitly
1699 // reading the body.
1700 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1701 HttpRequestInfo request;
1702 request.method = "GET";
1703 request.url = GURL("http://www.foo.com/");
1704 request.load_flags = 0;
1706 CapturingNetLog net_log;
1707 session_deps_.net_log = &net_log;
1708 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1710 // Note that because all these reads happen in the same
1711 // StaticSocketDataProvider, it shows that the same socket is being reused for
1712 // all transactions.
1713 MockRead data1_reads[] = {
1714 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1715 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1716 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1717 MockRead("HTTP/1.1 302 Found\r\n"
1718 "Content-Length: 0\r\n\r\n"),
1719 MockRead("HTTP/1.1 302 Found\r\n"
1720 "Content-Length: 5\r\n\r\n"
1721 "hello"),
1722 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1723 "Content-Length: 0\r\n\r\n"),
1724 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1725 "Content-Length: 5\r\n\r\n"
1726 "hello"),
1727 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1728 MockRead("hello"),
1730 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1731 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1733 MockRead data2_reads[] = {
1734 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1736 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1737 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1739 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1740 std::string response_lines[kNumUnreadBodies];
1742 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1743 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1744 TestCompletionCallback callback;
1746 scoped_ptr<HttpTransaction> trans(
1747 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1749 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1750 EXPECT_EQ(ERR_IO_PENDING, rv);
1752 rv = callback.WaitForResult();
1753 EXPECT_EQ(OK, rv);
1755 LoadTimingInfo load_timing_info;
1756 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1757 if (i == 0) {
1758 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1759 first_socket_log_id = load_timing_info.socket_log_id;
1760 } else {
1761 TestLoadTimingReused(load_timing_info);
1762 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1765 const HttpResponseInfo* response = trans->GetResponseInfo();
1766 ASSERT_TRUE(response != NULL);
1768 ASSERT_TRUE(response->headers.get() != NULL);
1769 response_lines[i] = response->headers->GetStatusLine();
1771 // We intentionally don't read the response bodies.
1774 const char* const kStatusLines[] = {
1775 "HTTP/1.1 204 No Content",
1776 "HTTP/1.1 205 Reset Content",
1777 "HTTP/1.1 304 Not Modified",
1778 "HTTP/1.1 302 Found",
1779 "HTTP/1.1 302 Found",
1780 "HTTP/1.1 301 Moved Permanently",
1781 "HTTP/1.1 301 Moved Permanently",
1784 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1785 forgot_to_update_kStatusLines);
1787 for (int i = 0; i < kNumUnreadBodies; ++i)
1788 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1790 TestCompletionCallback callback;
1791 scoped_ptr<HttpTransaction> trans(
1792 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1793 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1794 EXPECT_EQ(ERR_IO_PENDING, rv);
1795 rv = callback.WaitForResult();
1796 EXPECT_EQ(OK, rv);
1797 const HttpResponseInfo* response = trans->GetResponseInfo();
1798 ASSERT_TRUE(response != NULL);
1799 ASSERT_TRUE(response->headers.get() != NULL);
1800 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1801 std::string response_data;
1802 rv = ReadTransaction(trans.get(), &response_data);
1803 EXPECT_EQ(OK, rv);
1804 EXPECT_EQ("hello", response_data);
1807 // Test the request-challenge-retry sequence for basic auth.
1808 // (basic auth is the easiest to mock, because it has no randomness).
1809 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1810 HttpRequestInfo request;
1811 request.method = "GET";
1812 request.url = GURL("http://www.google.com/");
1813 request.load_flags = 0;
1815 CapturingNetLog log;
1816 session_deps_.net_log = &log;
1817 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1818 scoped_ptr<HttpTransaction> trans(
1819 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1821 MockWrite data_writes1[] = {
1822 MockWrite("GET / HTTP/1.1\r\n"
1823 "Host: www.google.com\r\n"
1824 "Connection: keep-alive\r\n\r\n"),
1827 MockRead data_reads1[] = {
1828 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1829 // Give a couple authenticate options (only the middle one is actually
1830 // supported).
1831 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1832 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1833 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1834 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1835 // Large content-length -- won't matter, as connection will be reset.
1836 MockRead("Content-Length: 10000\r\n\r\n"),
1837 MockRead(SYNCHRONOUS, ERR_FAILED),
1840 // After calling trans->RestartWithAuth(), this is the request we should
1841 // be issuing -- the final header line contains the credentials.
1842 MockWrite data_writes2[] = {
1843 MockWrite("GET / HTTP/1.1\r\n"
1844 "Host: www.google.com\r\n"
1845 "Connection: keep-alive\r\n"
1846 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1849 // Lastly, the server responds with the actual content.
1850 MockRead data_reads2[] = {
1851 MockRead("HTTP/1.0 200 OK\r\n"),
1852 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1853 MockRead("Content-Length: 100\r\n\r\n"),
1854 MockRead(SYNCHRONOUS, OK),
1857 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1858 data_writes1, arraysize(data_writes1));
1859 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1860 data_writes2, arraysize(data_writes2));
1861 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1862 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1864 TestCompletionCallback callback1;
1866 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1867 EXPECT_EQ(ERR_IO_PENDING, rv);
1869 rv = callback1.WaitForResult();
1870 EXPECT_EQ(OK, rv);
1872 LoadTimingInfo load_timing_info1;
1873 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1874 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1876 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1877 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1879 const HttpResponseInfo* response = trans->GetResponseInfo();
1880 ASSERT_TRUE(response != NULL);
1881 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1883 TestCompletionCallback callback2;
1885 rv = trans->RestartWithAuth(
1886 AuthCredentials(kFoo, kBar), callback2.callback());
1887 EXPECT_EQ(ERR_IO_PENDING, rv);
1889 rv = callback2.WaitForResult();
1890 EXPECT_EQ(OK, rv);
1892 LoadTimingInfo load_timing_info2;
1893 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1894 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1895 // The load timing after restart should have a new socket ID, and times after
1896 // those of the first load timing.
1897 EXPECT_LE(load_timing_info1.receive_headers_end,
1898 load_timing_info2.connect_timing.connect_start);
1899 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1901 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1902 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1904 response = trans->GetResponseInfo();
1905 ASSERT_TRUE(response != NULL);
1906 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1907 EXPECT_EQ(100, response->headers->GetContentLength());
1910 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1911 HttpRequestInfo request;
1912 request.method = "GET";
1913 request.url = GURL("http://www.google.com/");
1914 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1916 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1917 scoped_ptr<HttpTransaction> trans(
1918 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1920 MockWrite data_writes[] = {
1921 MockWrite("GET / HTTP/1.1\r\n"
1922 "Host: www.google.com\r\n"
1923 "Connection: keep-alive\r\n\r\n"),
1926 MockRead data_reads[] = {
1927 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1928 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1930 // Large content-length -- won't matter, as connection will be reset.
1931 MockRead("Content-Length: 10000\r\n\r\n"),
1932 MockRead(SYNCHRONOUS, ERR_FAILED),
1935 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1936 data_writes, arraysize(data_writes));
1937 session_deps_.socket_factory->AddSocketDataProvider(&data);
1938 TestCompletionCallback callback;
1940 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1941 EXPECT_EQ(ERR_IO_PENDING, rv);
1943 rv = callback.WaitForResult();
1944 EXPECT_EQ(0, rv);
1946 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
1947 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
1949 const HttpResponseInfo* response = trans->GetResponseInfo();
1950 ASSERT_TRUE(response != NULL);
1951 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1954 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1955 // connection.
1956 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1957 HttpRequestInfo request;
1958 request.method = "GET";
1959 request.url = GURL("http://www.google.com/");
1960 request.load_flags = 0;
1962 CapturingNetLog log;
1963 session_deps_.net_log = &log;
1964 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1966 MockWrite data_writes1[] = {
1967 MockWrite("GET / HTTP/1.1\r\n"
1968 "Host: www.google.com\r\n"
1969 "Connection: keep-alive\r\n\r\n"),
1971 // After calling trans->RestartWithAuth(), this is the request we should
1972 // be issuing -- the final header line contains the credentials.
1973 MockWrite("GET / HTTP/1.1\r\n"
1974 "Host: www.google.com\r\n"
1975 "Connection: keep-alive\r\n"
1976 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1979 MockRead data_reads1[] = {
1980 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1981 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1982 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1983 MockRead("Content-Length: 14\r\n\r\n"),
1984 MockRead("Unauthorized\r\n"),
1986 // Lastly, the server responds with the actual content.
1987 MockRead("HTTP/1.1 200 OK\r\n"),
1988 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1989 MockRead("Content-Length: 5\r\n\r\n"),
1990 MockRead("Hello"),
1993 // If there is a regression where we disconnect a Keep-Alive
1994 // connection during an auth roundtrip, we'll end up reading this.
1995 MockRead data_reads2[] = {
1996 MockRead(SYNCHRONOUS, ERR_FAILED),
1999 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2000 data_writes1, arraysize(data_writes1));
2001 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2002 NULL, 0);
2003 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2004 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2006 TestCompletionCallback callback1;
2008 scoped_ptr<HttpTransaction> trans(
2009 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2010 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2011 EXPECT_EQ(ERR_IO_PENDING, rv);
2013 rv = callback1.WaitForResult();
2014 EXPECT_EQ(OK, rv);
2016 LoadTimingInfo load_timing_info1;
2017 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2018 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2020 const HttpResponseInfo* response = trans->GetResponseInfo();
2021 ASSERT_TRUE(response != NULL);
2022 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2024 TestCompletionCallback callback2;
2026 rv = trans->RestartWithAuth(
2027 AuthCredentials(kFoo, kBar), callback2.callback());
2028 EXPECT_EQ(ERR_IO_PENDING, rv);
2030 rv = callback2.WaitForResult();
2031 EXPECT_EQ(OK, rv);
2033 LoadTimingInfo load_timing_info2;
2034 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2035 TestLoadTimingReused(load_timing_info2);
2036 // The load timing after restart should have the same socket ID, and times
2037 // those of the first load timing.
2038 EXPECT_LE(load_timing_info1.receive_headers_end,
2039 load_timing_info2.send_start);
2040 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2042 response = trans->GetResponseInfo();
2043 ASSERT_TRUE(response != NULL);
2044 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2045 EXPECT_EQ(5, response->headers->GetContentLength());
2047 std::string response_data;
2048 rv = ReadTransaction(trans.get(), &response_data);
2049 EXPECT_EQ(OK, rv);
2050 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2051 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2054 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2055 // connection and with no response body to drain.
2056 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2057 HttpRequestInfo request;
2058 request.method = "GET";
2059 request.url = GURL("http://www.google.com/");
2060 request.load_flags = 0;
2062 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2064 MockWrite data_writes1[] = {
2065 MockWrite("GET / HTTP/1.1\r\n"
2066 "Host: www.google.com\r\n"
2067 "Connection: keep-alive\r\n\r\n"),
2069 // After calling trans->RestartWithAuth(), this is the request we should
2070 // be issuing -- the final header line contains the credentials.
2071 MockWrite("GET / HTTP/1.1\r\n"
2072 "Host: www.google.com\r\n"
2073 "Connection: keep-alive\r\n"
2074 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2077 MockRead data_reads1[] = {
2078 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2079 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2080 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2082 // Lastly, the server responds with the actual content.
2083 MockRead("HTTP/1.1 200 OK\r\n"),
2084 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2085 MockRead("Content-Length: 5\r\n\r\n"),
2086 MockRead("hello"),
2089 // An incorrect reconnect would cause this to be read.
2090 MockRead data_reads2[] = {
2091 MockRead(SYNCHRONOUS, ERR_FAILED),
2094 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2095 data_writes1, arraysize(data_writes1));
2096 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2097 NULL, 0);
2098 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2099 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2101 TestCompletionCallback callback1;
2103 scoped_ptr<HttpTransaction> trans(
2104 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2105 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2106 EXPECT_EQ(ERR_IO_PENDING, rv);
2108 rv = callback1.WaitForResult();
2109 EXPECT_EQ(OK, rv);
2111 const HttpResponseInfo* response = trans->GetResponseInfo();
2112 ASSERT_TRUE(response != NULL);
2113 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2115 TestCompletionCallback callback2;
2117 rv = trans->RestartWithAuth(
2118 AuthCredentials(kFoo, kBar), callback2.callback());
2119 EXPECT_EQ(ERR_IO_PENDING, rv);
2121 rv = callback2.WaitForResult();
2122 EXPECT_EQ(OK, rv);
2124 response = trans->GetResponseInfo();
2125 ASSERT_TRUE(response != NULL);
2126 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2127 EXPECT_EQ(5, response->headers->GetContentLength());
2130 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2131 // connection and with a large response body to drain.
2132 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2133 HttpRequestInfo request;
2134 request.method = "GET";
2135 request.url = GURL("http://www.google.com/");
2136 request.load_flags = 0;
2138 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2140 MockWrite data_writes1[] = {
2141 MockWrite("GET / HTTP/1.1\r\n"
2142 "Host: www.google.com\r\n"
2143 "Connection: keep-alive\r\n\r\n"),
2145 // After calling trans->RestartWithAuth(), this is the request we should
2146 // be issuing -- the final header line contains the credentials.
2147 MockWrite("GET / HTTP/1.1\r\n"
2148 "Host: www.google.com\r\n"
2149 "Connection: keep-alive\r\n"
2150 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2153 // Respond with 5 kb of response body.
2154 std::string large_body_string("Unauthorized");
2155 large_body_string.append(5 * 1024, ' ');
2156 large_body_string.append("\r\n");
2158 MockRead data_reads1[] = {
2159 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2160 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2161 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2162 // 5134 = 12 + 5 * 1024 + 2
2163 MockRead("Content-Length: 5134\r\n\r\n"),
2164 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2166 // Lastly, the server responds with the actual content.
2167 MockRead("HTTP/1.1 200 OK\r\n"),
2168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2169 MockRead("Content-Length: 5\r\n\r\n"),
2170 MockRead("hello"),
2173 // An incorrect reconnect would cause this to be read.
2174 MockRead data_reads2[] = {
2175 MockRead(SYNCHRONOUS, ERR_FAILED),
2178 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2179 data_writes1, arraysize(data_writes1));
2180 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2181 NULL, 0);
2182 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2183 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2185 TestCompletionCallback callback1;
2187 scoped_ptr<HttpTransaction> trans(
2188 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2189 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2190 EXPECT_EQ(ERR_IO_PENDING, rv);
2192 rv = callback1.WaitForResult();
2193 EXPECT_EQ(OK, rv);
2195 const HttpResponseInfo* response = trans->GetResponseInfo();
2196 ASSERT_TRUE(response != NULL);
2197 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2199 TestCompletionCallback callback2;
2201 rv = trans->RestartWithAuth(
2202 AuthCredentials(kFoo, kBar), callback2.callback());
2203 EXPECT_EQ(ERR_IO_PENDING, rv);
2205 rv = callback2.WaitForResult();
2206 EXPECT_EQ(OK, rv);
2208 response = trans->GetResponseInfo();
2209 ASSERT_TRUE(response != NULL);
2210 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2211 EXPECT_EQ(5, response->headers->GetContentLength());
2214 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2215 // connection, but the server gets impatient and closes the connection.
2216 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2217 HttpRequestInfo request;
2218 request.method = "GET";
2219 request.url = GURL("http://www.google.com/");
2220 request.load_flags = 0;
2222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2224 MockWrite data_writes1[] = {
2225 MockWrite("GET / HTTP/1.1\r\n"
2226 "Host: www.google.com\r\n"
2227 "Connection: keep-alive\r\n\r\n"),
2228 // This simulates the seemingly successful write to a closed connection
2229 // if the bug is not fixed.
2230 MockWrite("GET / HTTP/1.1\r\n"
2231 "Host: www.google.com\r\n"
2232 "Connection: keep-alive\r\n"
2233 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2236 MockRead data_reads1[] = {
2237 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2238 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2239 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2240 MockRead("Content-Length: 14\r\n\r\n"),
2241 // Tell MockTCPClientSocket to simulate the server closing the connection.
2242 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2243 MockRead("Unauthorized\r\n"),
2244 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2247 // After calling trans->RestartWithAuth(), this is the request we should
2248 // be issuing -- the final header line contains the credentials.
2249 MockWrite data_writes2[] = {
2250 MockWrite("GET / HTTP/1.1\r\n"
2251 "Host: www.google.com\r\n"
2252 "Connection: keep-alive\r\n"
2253 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2256 // Lastly, the server responds with the actual content.
2257 MockRead data_reads2[] = {
2258 MockRead("HTTP/1.1 200 OK\r\n"),
2259 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2260 MockRead("Content-Length: 5\r\n\r\n"),
2261 MockRead("hello"),
2264 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2265 data_writes1, arraysize(data_writes1));
2266 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2267 data_writes2, arraysize(data_writes2));
2268 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2269 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2271 TestCompletionCallback callback1;
2273 scoped_ptr<HttpTransaction> trans(
2274 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2275 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2276 EXPECT_EQ(ERR_IO_PENDING, rv);
2278 rv = callback1.WaitForResult();
2279 EXPECT_EQ(OK, rv);
2281 const HttpResponseInfo* response = trans->GetResponseInfo();
2282 ASSERT_TRUE(response != NULL);
2283 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2285 TestCompletionCallback callback2;
2287 rv = trans->RestartWithAuth(
2288 AuthCredentials(kFoo, kBar), callback2.callback());
2289 EXPECT_EQ(ERR_IO_PENDING, rv);
2291 rv = callback2.WaitForResult();
2292 EXPECT_EQ(OK, rv);
2294 response = trans->GetResponseInfo();
2295 ASSERT_TRUE(response != NULL);
2296 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2297 EXPECT_EQ(5, response->headers->GetContentLength());
2300 // Test the request-challenge-retry sequence for basic auth, over a connection
2301 // that requires a restart when setting up an SSL tunnel.
2302 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
2303 HttpRequestInfo request;
2304 request.method = "GET";
2305 request.url = GURL("https://www.google.com/");
2306 // when the no authentication data flag is set.
2307 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2309 // Configure against proxy server "myproxy:70".
2310 session_deps_.proxy_service.reset(
2311 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2312 CapturingBoundNetLog log;
2313 session_deps_.net_log = log.bound().net_log();
2314 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2316 // Since we have proxy, should try to establish tunnel.
2317 MockWrite data_writes1[] = {
2318 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2319 "Host: www.google.com\r\n"
2320 "Proxy-Connection: keep-alive\r\n\r\n"),
2322 // After calling trans->RestartWithAuth(), this is the request we should
2323 // be issuing -- the final header line contains the credentials.
2324 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2325 "Host: www.google.com\r\n"
2326 "Proxy-Connection: keep-alive\r\n"
2327 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2329 MockWrite("GET / HTTP/1.1\r\n"
2330 "Host: www.google.com\r\n"
2331 "Connection: keep-alive\r\n\r\n"),
2334 // The proxy responds to the connect with a 407, using a persistent
2335 // connection.
2336 MockRead data_reads1[] = {
2337 // No credentials.
2338 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2339 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2340 MockRead("Proxy-Connection: close\r\n\r\n"),
2342 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2344 MockRead("HTTP/1.1 200 OK\r\n"),
2345 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2346 MockRead("Content-Length: 5\r\n\r\n"),
2347 MockRead(SYNCHRONOUS, "hello"),
2350 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2351 data_writes1, arraysize(data_writes1));
2352 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2353 SSLSocketDataProvider ssl(ASYNC, OK);
2354 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2356 TestCompletionCallback callback1;
2358 scoped_ptr<HttpTransaction> trans(
2359 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2361 int rv = trans->Start(&request, callback1.callback(), log.bound());
2362 EXPECT_EQ(ERR_IO_PENDING, rv);
2364 rv = callback1.WaitForResult();
2365 EXPECT_EQ(OK, rv);
2366 net::CapturingNetLog::CapturedEntryList entries;
2367 log.GetEntries(&entries);
2368 size_t pos = ExpectLogContainsSomewhere(
2369 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2370 NetLog::PHASE_NONE);
2371 ExpectLogContainsSomewhere(
2372 entries, pos,
2373 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2374 NetLog::PHASE_NONE);
2376 const HttpResponseInfo* response = trans->GetResponseInfo();
2377 ASSERT_TRUE(response != NULL);
2378 ASSERT_FALSE(response->headers.get() == NULL);
2379 EXPECT_EQ(407, response->headers->response_code());
2380 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2381 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2383 LoadTimingInfo load_timing_info;
2384 // CONNECT requests and responses are handled at the connect job level, so
2385 // the transaction does not yet have a connection.
2386 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2388 TestCompletionCallback callback2;
2390 rv = trans->RestartWithAuth(
2391 AuthCredentials(kFoo, kBar), callback2.callback());
2392 EXPECT_EQ(ERR_IO_PENDING, rv);
2394 rv = callback2.WaitForResult();
2395 EXPECT_EQ(OK, rv);
2397 response = trans->GetResponseInfo();
2398 ASSERT_TRUE(response != NULL);
2400 EXPECT_TRUE(response->headers->IsKeepAlive());
2401 EXPECT_EQ(200, response->headers->response_code());
2402 EXPECT_EQ(5, response->headers->GetContentLength());
2403 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2405 // The password prompt info should not be set.
2406 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2408 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2409 TestLoadTimingNotReusedWithPac(load_timing_info,
2410 CONNECT_TIMING_HAS_SSL_TIMES);
2412 trans.reset();
2413 session->CloseAllConnections();
2416 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2417 // proxy connection, when setting up an SSL tunnel.
2418 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2419 HttpRequestInfo request;
2420 request.method = "GET";
2421 request.url = GURL("https://www.google.com/");
2422 // Ensure that proxy authentication is attempted even
2423 // when the no authentication data flag is set.
2424 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2426 // Configure against proxy server "myproxy:70".
2427 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2428 CapturingBoundNetLog log;
2429 session_deps_.net_log = log.bound().net_log();
2430 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2432 scoped_ptr<HttpTransaction> trans(
2433 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2435 // Since we have proxy, should try to establish tunnel.
2436 MockWrite data_writes1[] = {
2437 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2438 "Host: www.google.com\r\n"
2439 "Proxy-Connection: keep-alive\r\n\r\n"),
2441 // After calling trans->RestartWithAuth(), this is the request we should
2442 // be issuing -- the final header line contains the credentials.
2443 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2444 "Host: www.google.com\r\n"
2445 "Proxy-Connection: keep-alive\r\n"
2446 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2449 // The proxy responds to the connect with a 407, using a persistent
2450 // connection.
2451 MockRead data_reads1[] = {
2452 // No credentials.
2453 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2454 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2455 MockRead("Content-Length: 10\r\n\r\n"),
2456 MockRead("0123456789"),
2458 // Wrong credentials (wrong password).
2459 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2460 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2461 MockRead("Content-Length: 10\r\n\r\n"),
2462 // No response body because the test stops reading here.
2463 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2466 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2467 data_writes1, arraysize(data_writes1));
2468 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2470 TestCompletionCallback callback1;
2472 int rv = trans->Start(&request, callback1.callback(), log.bound());
2473 EXPECT_EQ(ERR_IO_PENDING, rv);
2475 rv = callback1.WaitForResult();
2476 EXPECT_EQ(OK, rv);
2477 net::CapturingNetLog::CapturedEntryList entries;
2478 log.GetEntries(&entries);
2479 size_t pos = ExpectLogContainsSomewhere(
2480 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2481 NetLog::PHASE_NONE);
2482 ExpectLogContainsSomewhere(
2483 entries, pos,
2484 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2485 NetLog::PHASE_NONE);
2487 const HttpResponseInfo* response = trans->GetResponseInfo();
2488 ASSERT_TRUE(response != NULL);
2489 ASSERT_FALSE(response->headers.get() == NULL);
2490 EXPECT_TRUE(response->headers->IsKeepAlive());
2491 EXPECT_EQ(407, response->headers->response_code());
2492 EXPECT_EQ(10, response->headers->GetContentLength());
2493 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2494 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2496 TestCompletionCallback callback2;
2498 // Wrong password (should be "bar").
2499 rv = trans->RestartWithAuth(
2500 AuthCredentials(kFoo, kBaz), callback2.callback());
2501 EXPECT_EQ(ERR_IO_PENDING, rv);
2503 rv = callback2.WaitForResult();
2504 EXPECT_EQ(OK, rv);
2506 response = trans->GetResponseInfo();
2507 ASSERT_TRUE(response != NULL);
2508 ASSERT_FALSE(response->headers.get() == NULL);
2509 EXPECT_TRUE(response->headers->IsKeepAlive());
2510 EXPECT_EQ(407, response->headers->response_code());
2511 EXPECT_EQ(10, response->headers->GetContentLength());
2512 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2513 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2515 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2516 // out of scope.
2517 session->CloseAllConnections();
2520 // Test that we don't read the response body when we fail to establish a tunnel,
2521 // even if the user cancels the proxy's auth attempt.
2522 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2523 HttpRequestInfo request;
2524 request.method = "GET";
2525 request.url = GURL("https://www.google.com/");
2526 request.load_flags = 0;
2528 // Configure against proxy server "myproxy:70".
2529 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2531 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2533 scoped_ptr<HttpTransaction> trans(
2534 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2536 // Since we have proxy, should try to establish tunnel.
2537 MockWrite data_writes[] = {
2538 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2539 "Host: www.google.com\r\n"
2540 "Proxy-Connection: keep-alive\r\n\r\n"),
2543 // The proxy responds to the connect with a 407.
2544 MockRead data_reads[] = {
2545 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2546 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2547 MockRead("Content-Length: 10\r\n\r\n"),
2548 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2551 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2552 data_writes, arraysize(data_writes));
2553 session_deps_.socket_factory->AddSocketDataProvider(&data);
2555 TestCompletionCallback callback;
2557 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2558 EXPECT_EQ(ERR_IO_PENDING, rv);
2560 rv = callback.WaitForResult();
2561 EXPECT_EQ(OK, rv);
2563 const HttpResponseInfo* response = trans->GetResponseInfo();
2564 ASSERT_TRUE(response != NULL);
2566 EXPECT_TRUE(response->headers->IsKeepAlive());
2567 EXPECT_EQ(407, response->headers->response_code());
2568 EXPECT_EQ(10, response->headers->GetContentLength());
2569 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2571 std::string response_data;
2572 rv = ReadTransaction(trans.get(), &response_data);
2573 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2575 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2576 session->CloseAllConnections();
2579 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2580 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2581 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2582 HttpRequestInfo request;
2583 request.method = "GET";
2584 request.url = GURL("http://www.google.com/");
2585 request.load_flags = 0;
2587 // We are using a DIRECT connection (i.e. no proxy) for this session.
2588 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2589 scoped_ptr<HttpTransaction> trans(
2590 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
2592 MockWrite data_writes1[] = {
2593 MockWrite("GET / HTTP/1.1\r\n"
2594 "Host: www.google.com\r\n"
2595 "Connection: keep-alive\r\n\r\n"),
2598 MockRead data_reads1[] = {
2599 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2600 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2601 // Large content-length -- won't matter, as connection will be reset.
2602 MockRead("Content-Length: 10000\r\n\r\n"),
2603 MockRead(SYNCHRONOUS, ERR_FAILED),
2606 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2607 data_writes1, arraysize(data_writes1));
2608 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2610 TestCompletionCallback callback;
2612 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2613 EXPECT_EQ(ERR_IO_PENDING, rv);
2615 rv = callback.WaitForResult();
2616 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2619 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2620 // through a non-authenticating proxy. The request should fail with
2621 // ERR_UNEXPECTED_PROXY_AUTH.
2622 // Note that it is impossible to detect if an HTTP server returns a 407 through
2623 // a non-authenticating proxy - there is nothing to indicate whether the
2624 // response came from the proxy or the server, so it is treated as if the proxy
2625 // issued the challenge.
2626 TEST_P(HttpNetworkTransactionTest,
2627 HttpsServerRequestsProxyAuthThroughProxy) {
2628 HttpRequestInfo request;
2629 request.method = "GET";
2630 request.url = GURL("https://www.google.com/");
2632 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2633 CapturingBoundNetLog log;
2634 session_deps_.net_log = log.bound().net_log();
2635 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2637 // Since we have proxy, should try to establish tunnel.
2638 MockWrite data_writes1[] = {
2639 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2640 "Host: www.google.com\r\n"
2641 "Proxy-Connection: keep-alive\r\n\r\n"),
2643 MockWrite("GET / HTTP/1.1\r\n"
2644 "Host: www.google.com\r\n"
2645 "Connection: keep-alive\r\n\r\n"),
2648 MockRead data_reads1[] = {
2649 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2651 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2652 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2653 MockRead("\r\n"),
2654 MockRead(SYNCHRONOUS, OK),
2657 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2658 data_writes1, arraysize(data_writes1));
2659 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2660 SSLSocketDataProvider ssl(ASYNC, OK);
2661 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2663 TestCompletionCallback callback1;
2665 scoped_ptr<HttpTransaction> trans(
2666 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2668 int rv = trans->Start(&request, callback1.callback(), log.bound());
2669 EXPECT_EQ(ERR_IO_PENDING, rv);
2671 rv = callback1.WaitForResult();
2672 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2673 net::CapturingNetLog::CapturedEntryList entries;
2674 log.GetEntries(&entries);
2675 size_t pos = ExpectLogContainsSomewhere(
2676 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2677 NetLog::PHASE_NONE);
2678 ExpectLogContainsSomewhere(
2679 entries, pos,
2680 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2681 NetLog::PHASE_NONE);
2684 // Test the load timing for HTTPS requests with an HTTP proxy.
2685 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2686 HttpRequestInfo request1;
2687 request1.method = "GET";
2688 request1.url = GURL("https://www.google.com/1");
2690 HttpRequestInfo request2;
2691 request2.method = "GET";
2692 request2.url = GURL("https://www.google.com/2");
2694 // Configure against proxy server "myproxy:70".
2695 session_deps_.proxy_service.reset(
2696 ProxyService::CreateFixed("PROXY myproxy:70"));
2697 CapturingBoundNetLog log;
2698 session_deps_.net_log = log.bound().net_log();
2699 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2701 // Since we have proxy, should try to establish tunnel.
2702 MockWrite data_writes1[] = {
2703 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2704 "Host: www.google.com\r\n"
2705 "Proxy-Connection: keep-alive\r\n\r\n"),
2707 MockWrite("GET /1 HTTP/1.1\r\n"
2708 "Host: www.google.com\r\n"
2709 "Connection: keep-alive\r\n\r\n"),
2711 MockWrite("GET /2 HTTP/1.1\r\n"
2712 "Host: www.google.com\r\n"
2713 "Connection: keep-alive\r\n\r\n"),
2716 // The proxy responds to the connect with a 407, using a persistent
2717 // connection.
2718 MockRead data_reads1[] = {
2719 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2721 MockRead("HTTP/1.1 200 OK\r\n"),
2722 MockRead("Content-Length: 1\r\n\r\n"),
2723 MockRead(SYNCHRONOUS, "1"),
2725 MockRead("HTTP/1.1 200 OK\r\n"),
2726 MockRead("Content-Length: 2\r\n\r\n"),
2727 MockRead(SYNCHRONOUS, "22"),
2730 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2731 data_writes1, arraysize(data_writes1));
2732 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2733 SSLSocketDataProvider ssl(ASYNC, OK);
2734 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2736 TestCompletionCallback callback1;
2737 scoped_ptr<HttpTransaction> trans1(
2738 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2740 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2741 EXPECT_EQ(ERR_IO_PENDING, rv);
2743 rv = callback1.WaitForResult();
2744 EXPECT_EQ(OK, rv);
2746 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2747 ASSERT_TRUE(response1 != NULL);
2748 ASSERT_TRUE(response1->headers.get() != NULL);
2749 EXPECT_EQ(1, response1->headers->GetContentLength());
2751 LoadTimingInfo load_timing_info1;
2752 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2753 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2755 trans1.reset();
2757 TestCompletionCallback callback2;
2758 scoped_ptr<HttpTransaction> trans2(
2759 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2761 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2762 EXPECT_EQ(ERR_IO_PENDING, rv);
2764 rv = callback2.WaitForResult();
2765 EXPECT_EQ(OK, rv);
2767 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2768 ASSERT_TRUE(response2 != NULL);
2769 ASSERT_TRUE(response2->headers.get() != NULL);
2770 EXPECT_EQ(2, response2->headers->GetContentLength());
2772 LoadTimingInfo load_timing_info2;
2773 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2774 TestLoadTimingReused(load_timing_info2);
2776 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2778 trans2.reset();
2779 session->CloseAllConnections();
2782 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2783 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2784 HttpRequestInfo request1;
2785 request1.method = "GET";
2786 request1.url = GURL("https://www.google.com/1");
2788 HttpRequestInfo request2;
2789 request2.method = "GET";
2790 request2.url = GURL("https://www.google.com/2");
2792 // Configure against proxy server "myproxy:70".
2793 session_deps_.proxy_service.reset(
2794 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2795 CapturingBoundNetLog log;
2796 session_deps_.net_log = log.bound().net_log();
2797 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2799 // Since we have proxy, should try to establish tunnel.
2800 MockWrite data_writes1[] = {
2801 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2802 "Host: www.google.com\r\n"
2803 "Proxy-Connection: keep-alive\r\n\r\n"),
2805 MockWrite("GET /1 HTTP/1.1\r\n"
2806 "Host: www.google.com\r\n"
2807 "Connection: keep-alive\r\n\r\n"),
2809 MockWrite("GET /2 HTTP/1.1\r\n"
2810 "Host: www.google.com\r\n"
2811 "Connection: keep-alive\r\n\r\n"),
2814 // The proxy responds to the connect with a 407, using a persistent
2815 // connection.
2816 MockRead data_reads1[] = {
2817 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2819 MockRead("HTTP/1.1 200 OK\r\n"),
2820 MockRead("Content-Length: 1\r\n\r\n"),
2821 MockRead(SYNCHRONOUS, "1"),
2823 MockRead("HTTP/1.1 200 OK\r\n"),
2824 MockRead("Content-Length: 2\r\n\r\n"),
2825 MockRead(SYNCHRONOUS, "22"),
2828 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2829 data_writes1, arraysize(data_writes1));
2830 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2831 SSLSocketDataProvider ssl(ASYNC, OK);
2832 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2834 TestCompletionCallback callback1;
2835 scoped_ptr<HttpTransaction> trans1(
2836 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2838 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2839 EXPECT_EQ(ERR_IO_PENDING, rv);
2841 rv = callback1.WaitForResult();
2842 EXPECT_EQ(OK, rv);
2844 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2845 ASSERT_TRUE(response1 != NULL);
2846 ASSERT_TRUE(response1->headers.get() != NULL);
2847 EXPECT_EQ(1, response1->headers->GetContentLength());
2849 LoadTimingInfo load_timing_info1;
2850 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2851 TestLoadTimingNotReusedWithPac(load_timing_info1,
2852 CONNECT_TIMING_HAS_SSL_TIMES);
2854 trans1.reset();
2856 TestCompletionCallback callback2;
2857 scoped_ptr<HttpTransaction> trans2(
2858 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2860 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2861 EXPECT_EQ(ERR_IO_PENDING, rv);
2863 rv = callback2.WaitForResult();
2864 EXPECT_EQ(OK, rv);
2866 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2867 ASSERT_TRUE(response2 != NULL);
2868 ASSERT_TRUE(response2->headers.get() != NULL);
2869 EXPECT_EQ(2, response2->headers->GetContentLength());
2871 LoadTimingInfo load_timing_info2;
2872 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2873 TestLoadTimingReusedWithPac(load_timing_info2);
2875 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2877 trans2.reset();
2878 session->CloseAllConnections();
2881 // Test a simple get through an HTTPS Proxy.
2882 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2883 HttpRequestInfo request;
2884 request.method = "GET";
2885 request.url = GURL("http://www.google.com/");
2887 // Configure against https proxy server "proxy:70".
2888 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2889 "https://proxy:70"));
2890 CapturingBoundNetLog log;
2891 session_deps_.net_log = log.bound().net_log();
2892 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2894 // Since we have proxy, should use full url
2895 MockWrite data_writes1[] = {
2896 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2897 "Host: www.google.com\r\n"
2898 "Proxy-Connection: keep-alive\r\n\r\n"),
2901 MockRead data_reads1[] = {
2902 MockRead("HTTP/1.1 200 OK\r\n"),
2903 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2904 MockRead("Content-Length: 100\r\n\r\n"),
2905 MockRead(SYNCHRONOUS, OK),
2908 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2909 data_writes1, arraysize(data_writes1));
2910 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2911 SSLSocketDataProvider ssl(ASYNC, OK);
2912 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2914 TestCompletionCallback callback1;
2916 scoped_ptr<HttpTransaction> trans(
2917 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2919 int rv = trans->Start(&request, callback1.callback(), log.bound());
2920 EXPECT_EQ(ERR_IO_PENDING, rv);
2922 rv = callback1.WaitForResult();
2923 EXPECT_EQ(OK, rv);
2925 LoadTimingInfo load_timing_info;
2926 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2927 TestLoadTimingNotReused(load_timing_info,
2928 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2930 const HttpResponseInfo* response = trans->GetResponseInfo();
2931 ASSERT_TRUE(response != NULL);
2933 EXPECT_TRUE(response->headers->IsKeepAlive());
2934 EXPECT_EQ(200, response->headers->response_code());
2935 EXPECT_EQ(100, response->headers->GetContentLength());
2936 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2938 // The password prompt info should not be set.
2939 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2942 // Test a SPDY get through an HTTPS Proxy.
2943 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2944 HttpRequestInfo request;
2945 request.method = "GET";
2946 request.url = GURL("http://www.google.com/");
2947 request.load_flags = 0;
2949 // Configure against https proxy server "proxy:70".
2950 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2951 "https://proxy:70"));
2952 CapturingBoundNetLog log;
2953 session_deps_.net_log = log.bound().net_log();
2954 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2956 // fetch http://www.google.com/ via SPDY
2957 scoped_ptr<SpdyFrame> req(
2958 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2959 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2961 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2962 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2963 MockRead spdy_reads[] = {
2964 CreateMockRead(*resp),
2965 CreateMockRead(*data),
2966 MockRead(ASYNC, 0, 0),
2969 DelayedSocketData spdy_data(
2970 1, // wait for one write to finish before reading.
2971 spdy_reads, arraysize(spdy_reads),
2972 spdy_writes, arraysize(spdy_writes));
2973 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2975 SSLSocketDataProvider ssl(ASYNC, OK);
2976 ssl.SetNextProto(GetParam());
2977 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2979 TestCompletionCallback callback1;
2981 scoped_ptr<HttpTransaction> trans(
2982 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2984 int rv = trans->Start(&request, callback1.callback(), log.bound());
2985 EXPECT_EQ(ERR_IO_PENDING, rv);
2987 rv = callback1.WaitForResult();
2988 EXPECT_EQ(OK, rv);
2990 LoadTimingInfo load_timing_info;
2991 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2992 TestLoadTimingNotReused(load_timing_info,
2993 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2995 const HttpResponseInfo* response = trans->GetResponseInfo();
2996 ASSERT_TRUE(response != NULL);
2997 ASSERT_TRUE(response->headers.get() != NULL);
2998 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3000 std::string response_data;
3001 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3002 EXPECT_EQ(kUploadData, response_data);
3005 // Test a SPDY get through an HTTPS Proxy.
3006 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3007 HttpRequestInfo request;
3008 request.method = "GET";
3009 request.url = GURL("http://www.google.com/");
3010 request.load_flags = 0;
3012 // Configure against https proxy server "myproxy:70".
3013 session_deps_.proxy_service.reset(
3014 ProxyService::CreateFixed("https://myproxy:70"));
3015 CapturingBoundNetLog log;
3016 session_deps_.net_log = log.bound().net_log();
3017 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3019 // The first request will be a bare GET, the second request will be a
3020 // GET with a Proxy-Authorization header.
3021 scoped_ptr<SpdyFrame> req_get(
3022 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3023 const char* const kExtraAuthorizationHeaders[] = {
3024 "proxy-authorization", "Basic Zm9vOmJhcg=="
3026 scoped_ptr<SpdyFrame> req_get_authorization(
3027 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3028 arraysize(kExtraAuthorizationHeaders) / 2,
3029 false,
3031 LOWEST,
3032 false));
3033 MockWrite spdy_writes[] = {
3034 CreateMockWrite(*req_get, 1),
3035 CreateMockWrite(*req_get_authorization, 4),
3038 // The first response is a 407 proxy authentication challenge, and the second
3039 // response will be a 200 response since the second request includes a valid
3040 // Authorization header.
3041 const char* const kExtraAuthenticationHeaders[] = {
3042 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3044 scoped_ptr<SpdyFrame> resp_authentication(
3045 spdy_util_.ConstructSpdySynReplyError(
3046 "407 Proxy Authentication Required",
3047 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3048 1));
3049 scoped_ptr<SpdyFrame> body_authentication(
3050 spdy_util_.ConstructSpdyBodyFrame(1, true));
3051 scoped_ptr<SpdyFrame> resp_data(
3052 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3053 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3054 MockRead spdy_reads[] = {
3055 CreateMockRead(*resp_authentication, 2),
3056 CreateMockRead(*body_authentication, 3),
3057 CreateMockRead(*resp_data, 5),
3058 CreateMockRead(*body_data, 6),
3059 MockRead(ASYNC, 0, 7),
3062 OrderedSocketData data(
3063 spdy_reads, arraysize(spdy_reads),
3064 spdy_writes, arraysize(spdy_writes));
3065 session_deps_.socket_factory->AddSocketDataProvider(&data);
3067 SSLSocketDataProvider ssl(ASYNC, OK);
3068 ssl.SetNextProto(GetParam());
3069 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3071 TestCompletionCallback callback1;
3073 scoped_ptr<HttpTransaction> trans(
3074 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3076 int rv = trans->Start(&request, callback1.callback(), log.bound());
3077 EXPECT_EQ(ERR_IO_PENDING, rv);
3079 rv = callback1.WaitForResult();
3080 EXPECT_EQ(OK, rv);
3082 const HttpResponseInfo* const response = trans->GetResponseInfo();
3084 ASSERT_TRUE(response != NULL);
3085 ASSERT_TRUE(response->headers.get() != NULL);
3086 EXPECT_EQ(407, response->headers->response_code());
3087 EXPECT_TRUE(response->was_fetched_via_spdy);
3088 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3090 TestCompletionCallback callback2;
3092 rv = trans->RestartWithAuth(
3093 AuthCredentials(kFoo, kBar), callback2.callback());
3094 EXPECT_EQ(ERR_IO_PENDING, rv);
3096 rv = callback2.WaitForResult();
3097 EXPECT_EQ(OK, rv);
3099 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3101 ASSERT_TRUE(response_restart != NULL);
3102 ASSERT_TRUE(response_restart->headers.get() != NULL);
3103 EXPECT_EQ(200, response_restart->headers->response_code());
3104 // The password prompt info should not be set.
3105 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3108 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3109 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3110 HttpRequestInfo request;
3111 request.method = "GET";
3112 request.url = GURL("https://www.google.com/");
3113 request.load_flags = 0;
3115 // Configure against https proxy server "proxy:70".
3116 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3117 "https://proxy:70"));
3118 CapturingBoundNetLog log;
3119 session_deps_.net_log = log.bound().net_log();
3120 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3122 scoped_ptr<HttpTransaction> trans(
3123 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3125 // CONNECT to www.google.com:443 via SPDY
3126 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3127 LOWEST));
3128 // fetch https://www.google.com/ via HTTP
3130 const char get[] = "GET / HTTP/1.1\r\n"
3131 "Host: www.google.com\r\n"
3132 "Connection: keep-alive\r\n\r\n";
3133 scoped_ptr<SpdyFrame> wrapped_get(
3134 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3135 scoped_ptr<SpdyFrame> conn_resp(
3136 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3137 const char resp[] = "HTTP/1.1 200 OK\r\n"
3138 "Content-Length: 10\r\n\r\n";
3139 scoped_ptr<SpdyFrame> wrapped_get_resp(
3140 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3141 scoped_ptr<SpdyFrame> wrapped_body(
3142 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3143 scoped_ptr<SpdyFrame> window_update(
3144 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3146 MockWrite spdy_writes[] = {
3147 CreateMockWrite(*connect, 1),
3148 CreateMockWrite(*wrapped_get, 3),
3149 CreateMockWrite(*window_update, 5),
3152 MockRead spdy_reads[] = {
3153 CreateMockRead(*conn_resp, 2, ASYNC),
3154 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3155 CreateMockRead(*wrapped_body, 6, ASYNC),
3156 CreateMockRead(*wrapped_body, 7, ASYNC),
3157 MockRead(ASYNC, 0, 8),
3160 OrderedSocketData spdy_data(
3161 spdy_reads, arraysize(spdy_reads),
3162 spdy_writes, arraysize(spdy_writes));
3163 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3165 SSLSocketDataProvider ssl(ASYNC, OK);
3166 ssl.SetNextProto(GetParam());
3167 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3168 SSLSocketDataProvider ssl2(ASYNC, OK);
3169 ssl2.was_npn_negotiated = false;
3170 ssl2.protocol_negotiated = kProtoUnknown;
3171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3173 TestCompletionCallback callback1;
3175 int rv = trans->Start(&request, callback1.callback(), log.bound());
3176 EXPECT_EQ(ERR_IO_PENDING, rv);
3178 rv = callback1.WaitForResult();
3179 EXPECT_EQ(OK, rv);
3181 LoadTimingInfo load_timing_info;
3182 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3183 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3185 const HttpResponseInfo* response = trans->GetResponseInfo();
3186 ASSERT_TRUE(response != NULL);
3187 ASSERT_TRUE(response->headers.get() != NULL);
3188 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3190 std::string response_data;
3191 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3192 EXPECT_EQ("1234567890", response_data);
3195 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3196 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3197 HttpRequestInfo request;
3198 request.method = "GET";
3199 request.url = GURL("https://www.google.com/");
3200 request.load_flags = 0;
3202 // Configure against https proxy server "proxy:70".
3203 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3204 "https://proxy:70"));
3205 CapturingBoundNetLog log;
3206 session_deps_.net_log = log.bound().net_log();
3207 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3209 scoped_ptr<HttpTransaction> trans(
3210 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3212 // CONNECT to www.google.com:443 via SPDY
3213 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3214 LOWEST));
3215 // fetch https://www.google.com/ via SPDY
3216 const char* const kMyUrl = "https://www.google.com/";
3217 scoped_ptr<SpdyFrame> get(
3218 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3219 scoped_ptr<SpdyFrame> wrapped_get(
3220 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3221 scoped_ptr<SpdyFrame> conn_resp(
3222 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3223 scoped_ptr<SpdyFrame> get_resp(
3224 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3225 scoped_ptr<SpdyFrame> wrapped_get_resp(
3226 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3227 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3228 scoped_ptr<SpdyFrame> wrapped_body(
3229 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3230 scoped_ptr<SpdyFrame> window_update_get_resp(
3231 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3232 scoped_ptr<SpdyFrame> window_update_body(
3233 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3235 MockWrite spdy_writes[] = {
3236 CreateMockWrite(*connect, 1),
3237 CreateMockWrite(*wrapped_get, 3),
3238 CreateMockWrite(*window_update_get_resp, 5),
3239 CreateMockWrite(*window_update_body, 7),
3242 MockRead spdy_reads[] = {
3243 CreateMockRead(*conn_resp, 2, ASYNC),
3244 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3245 CreateMockRead(*wrapped_body, 6, ASYNC),
3246 MockRead(ASYNC, 0, 8),
3249 OrderedSocketData spdy_data(
3250 spdy_reads, arraysize(spdy_reads),
3251 spdy_writes, arraysize(spdy_writes));
3252 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3254 SSLSocketDataProvider ssl(ASYNC, OK);
3255 ssl.SetNextProto(GetParam());
3256 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3257 SSLSocketDataProvider ssl2(ASYNC, OK);
3258 ssl2.SetNextProto(GetParam());
3259 ssl2.protocol_negotiated = GetParam();
3260 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3262 TestCompletionCallback callback1;
3264 int rv = trans->Start(&request, callback1.callback(), log.bound());
3265 EXPECT_EQ(ERR_IO_PENDING, rv);
3267 rv = callback1.WaitForResult();
3268 EXPECT_EQ(OK, rv);
3270 LoadTimingInfo load_timing_info;
3271 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3272 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3274 const HttpResponseInfo* response = trans->GetResponseInfo();
3275 ASSERT_TRUE(response != NULL);
3276 ASSERT_TRUE(response->headers.get() != NULL);
3277 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3279 std::string response_data;
3280 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3281 EXPECT_EQ(kUploadData, response_data);
3284 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3285 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3286 HttpRequestInfo request;
3287 request.method = "GET";
3288 request.url = GURL("https://www.google.com/");
3289 request.load_flags = 0;
3291 // Configure against https proxy server "proxy:70".
3292 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3293 "https://proxy:70"));
3294 CapturingBoundNetLog log;
3295 session_deps_.net_log = log.bound().net_log();
3296 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3298 scoped_ptr<HttpTransaction> trans(
3299 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3301 // CONNECT to www.google.com:443 via SPDY
3302 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3303 LOWEST));
3304 scoped_ptr<SpdyFrame> get(
3305 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3307 MockWrite spdy_writes[] = {
3308 CreateMockWrite(*connect, 1),
3309 CreateMockWrite(*get, 3),
3312 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3313 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3314 MockRead spdy_reads[] = {
3315 CreateMockRead(*resp, 2, ASYNC),
3316 MockRead(ASYNC, 0, 4),
3319 OrderedSocketData spdy_data(
3320 spdy_reads, arraysize(spdy_reads),
3321 spdy_writes, arraysize(spdy_writes));
3322 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3324 SSLSocketDataProvider ssl(ASYNC, OK);
3325 ssl.SetNextProto(GetParam());
3326 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3327 SSLSocketDataProvider ssl2(ASYNC, OK);
3328 ssl2.SetNextProto(GetParam());
3329 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3331 TestCompletionCallback callback1;
3333 int rv = trans->Start(&request, callback1.callback(), log.bound());
3334 EXPECT_EQ(ERR_IO_PENDING, rv);
3336 rv = callback1.WaitForResult();
3337 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3339 // TODO(ttuttle): Anything else to check here?
3342 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3343 // HTTPS Proxy to different servers.
3344 TEST_P(HttpNetworkTransactionTest,
3345 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3346 // Configure against https proxy server "proxy:70".
3347 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3348 "https://proxy:70"));
3349 CapturingBoundNetLog log;
3350 session_deps_.net_log = log.bound().net_log();
3351 scoped_refptr<HttpNetworkSession> session(
3352 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3354 HttpRequestInfo request1;
3355 request1.method = "GET";
3356 request1.url = GURL("https://www.google.com/");
3357 request1.load_flags = 0;
3359 HttpRequestInfo request2;
3360 request2.method = "GET";
3361 request2.url = GURL("https://news.google.com/");
3362 request2.load_flags = 0;
3364 // CONNECT to www.google.com:443 via SPDY.
3365 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3366 LOWEST));
3367 scoped_ptr<SpdyFrame> conn_resp1(
3368 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3370 // Fetch https://www.google.com/ via HTTP.
3371 const char get1[] = "GET / HTTP/1.1\r\n"
3372 "Host: www.google.com\r\n"
3373 "Connection: keep-alive\r\n\r\n";
3374 scoped_ptr<SpdyFrame> wrapped_get1(
3375 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3376 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3377 "Content-Length: 1\r\n\r\n";
3378 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3379 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3380 scoped_ptr<SpdyFrame> wrapped_body1(
3381 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3382 scoped_ptr<SpdyFrame> window_update(
3383 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3385 // CONNECT to news.google.com:443 via SPDY.
3386 SpdySynStreamIR connect2_ir(3);
3387 spdy_util_.SetPriority(LOWEST, &connect2_ir);
3388 connect2_ir.SetHeader(spdy_util_.GetMethodKey(), "CONNECT");
3389 connect2_ir.SetHeader(spdy_util_.GetPathKey(), "news.google.com:443");
3390 connect2_ir.SetHeader(spdy_util_.GetHostKey(), "news.google.com");
3391 spdy_util_.MaybeAddVersionHeader(&connect2_ir);
3392 scoped_ptr<SpdyFrame> connect2(
3393 spdy_util_.CreateFramer(false)->SerializeFrame(connect2_ir));
3395 scoped_ptr<SpdyFrame> conn_resp2(
3396 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3398 // Fetch https://news.google.com/ via HTTP.
3399 const char get2[] = "GET / HTTP/1.1\r\n"
3400 "Host: news.google.com\r\n"
3401 "Connection: keep-alive\r\n\r\n";
3402 scoped_ptr<SpdyFrame> wrapped_get2(
3403 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3404 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3405 "Content-Length: 2\r\n\r\n";
3406 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3407 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3408 scoped_ptr<SpdyFrame> wrapped_body2(
3409 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3411 MockWrite spdy_writes[] = {
3412 CreateMockWrite(*connect1, 0),
3413 CreateMockWrite(*wrapped_get1, 2),
3414 CreateMockWrite(*connect2, 5),
3415 CreateMockWrite(*wrapped_get2, 7),
3418 MockRead spdy_reads[] = {
3419 CreateMockRead(*conn_resp1, 1, ASYNC),
3420 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3421 CreateMockRead(*wrapped_body1, 4, ASYNC),
3422 CreateMockRead(*conn_resp2, 6, ASYNC),
3423 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3424 CreateMockRead(*wrapped_body2, 9, ASYNC),
3425 MockRead(ASYNC, 0, 10),
3428 DeterministicSocketData spdy_data(
3429 spdy_reads, arraysize(spdy_reads),
3430 spdy_writes, arraysize(spdy_writes));
3431 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3433 SSLSocketDataProvider ssl(ASYNC, OK);
3434 ssl.SetNextProto(GetParam());
3435 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3436 SSLSocketDataProvider ssl2(ASYNC, OK);
3437 ssl2.was_npn_negotiated = false;
3438 ssl2.protocol_negotiated = kProtoUnknown;
3439 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3440 SSLSocketDataProvider ssl3(ASYNC, OK);
3441 ssl3.was_npn_negotiated = false;
3442 ssl3.protocol_negotiated = kProtoUnknown;
3443 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3445 TestCompletionCallback callback;
3447 scoped_ptr<HttpTransaction> trans(
3448 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3449 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3450 EXPECT_EQ(ERR_IO_PENDING, rv);
3451 // The first connect and request, each of their responses, and the body.
3452 spdy_data.RunFor(5);
3454 rv = callback.WaitForResult();
3455 EXPECT_EQ(OK, rv);
3457 LoadTimingInfo load_timing_info;
3458 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3459 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3461 const HttpResponseInfo* response = trans->GetResponseInfo();
3462 ASSERT_TRUE(response != NULL);
3463 ASSERT_TRUE(response->headers.get() != NULL);
3464 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3466 std::string response_data;
3467 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3468 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3470 scoped_ptr<HttpTransaction> trans2(
3471 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3472 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3473 EXPECT_EQ(ERR_IO_PENDING, rv);
3475 // The second connect and request, each of their responses, and the body.
3476 spdy_data.RunFor(5);
3477 rv = callback.WaitForResult();
3478 EXPECT_EQ(OK, rv);
3480 LoadTimingInfo load_timing_info2;
3481 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3482 // Even though the SPDY connection is reused, a new tunnelled connection has
3483 // to be created, so the socket's load timing looks like a fresh connection.
3484 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3486 // The requests should have different IDs, since they each are using their own
3487 // separate stream.
3488 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3490 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3493 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3494 // HTTPS Proxy to the same server.
3495 TEST_P(HttpNetworkTransactionTest,
3496 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3497 // Configure against https proxy server "proxy:70".
3498 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3499 "https://proxy:70"));
3500 CapturingBoundNetLog log;
3501 session_deps_.net_log = log.bound().net_log();
3502 scoped_refptr<HttpNetworkSession> session(
3503 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3505 HttpRequestInfo request1;
3506 request1.method = "GET";
3507 request1.url = GURL("https://www.google.com/");
3508 request1.load_flags = 0;
3510 HttpRequestInfo request2;
3511 request2.method = "GET";
3512 request2.url = GURL("https://www.google.com/2");
3513 request2.load_flags = 0;
3515 // CONNECT to www.google.com:443 via SPDY.
3516 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3517 LOWEST));
3518 scoped_ptr<SpdyFrame> conn_resp1(
3519 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3521 // Fetch https://www.google.com/ via HTTP.
3522 const char get1[] = "GET / HTTP/1.1\r\n"
3523 "Host: www.google.com\r\n"
3524 "Connection: keep-alive\r\n\r\n";
3525 scoped_ptr<SpdyFrame> wrapped_get1(
3526 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3527 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3528 "Content-Length: 1\r\n\r\n";
3529 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3530 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3531 scoped_ptr<SpdyFrame> wrapped_body1(
3532 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3533 scoped_ptr<SpdyFrame> window_update(
3534 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3536 // Fetch https://www.google.com/2 via HTTP.
3537 const char get2[] = "GET /2 HTTP/1.1\r\n"
3538 "Host: www.google.com\r\n"
3539 "Connection: keep-alive\r\n\r\n";
3540 scoped_ptr<SpdyFrame> wrapped_get2(
3541 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3542 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3543 "Content-Length: 2\r\n\r\n";
3544 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3545 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3546 scoped_ptr<SpdyFrame> wrapped_body2(
3547 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3549 MockWrite spdy_writes[] = {
3550 CreateMockWrite(*connect1, 0),
3551 CreateMockWrite(*wrapped_get1, 2),
3552 CreateMockWrite(*wrapped_get2, 5),
3555 MockRead spdy_reads[] = {
3556 CreateMockRead(*conn_resp1, 1, ASYNC),
3557 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3558 CreateMockRead(*wrapped_body1, 4, ASYNC),
3559 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3560 CreateMockRead(*wrapped_body2, 7, ASYNC),
3561 MockRead(ASYNC, 0, 8),
3564 DeterministicSocketData spdy_data(
3565 spdy_reads, arraysize(spdy_reads),
3566 spdy_writes, arraysize(spdy_writes));
3567 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3569 SSLSocketDataProvider ssl(ASYNC, OK);
3570 ssl.SetNextProto(GetParam());
3571 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3572 SSLSocketDataProvider ssl2(ASYNC, OK);
3573 ssl2.was_npn_negotiated = false;
3574 ssl2.protocol_negotiated = kProtoUnknown;
3575 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3577 TestCompletionCallback callback;
3579 scoped_ptr<HttpTransaction> trans(
3580 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3581 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3582 EXPECT_EQ(ERR_IO_PENDING, rv);
3583 // The first connect and request, each of their responses, and the body.
3584 spdy_data.RunFor(5);
3586 rv = callback.WaitForResult();
3587 EXPECT_EQ(OK, rv);
3589 LoadTimingInfo load_timing_info;
3590 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3591 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3593 const HttpResponseInfo* response = trans->GetResponseInfo();
3594 ASSERT_TRUE(response != NULL);
3595 ASSERT_TRUE(response->headers.get() != NULL);
3596 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3598 std::string response_data;
3599 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3600 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3601 trans.reset();
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 request, response, and body. There should not be a second
3609 // connect.
3610 spdy_data.RunFor(3);
3611 rv = callback.WaitForResult();
3612 EXPECT_EQ(OK, rv);
3614 LoadTimingInfo load_timing_info2;
3615 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3616 TestLoadTimingReused(load_timing_info2);
3618 // The requests should have the same ID.
3619 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3621 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3624 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3625 // Proxy to different servers.
3626 TEST_P(HttpNetworkTransactionTest,
3627 HttpsProxySpdyLoadTimingTwoHttpRequests) {
3628 // Configure against https proxy server "proxy:70".
3629 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3630 "https://proxy:70"));
3631 CapturingBoundNetLog log;
3632 session_deps_.net_log = log.bound().net_log();
3633 scoped_refptr<HttpNetworkSession> session(
3634 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3636 HttpRequestInfo request1;
3637 request1.method = "GET";
3638 request1.url = GURL("http://www.google.com/");
3639 request1.load_flags = 0;
3641 HttpRequestInfo request2;
3642 request2.method = "GET";
3643 request2.url = GURL("http://news.google.com/");
3644 request2.load_flags = 0;
3646 // http://www.google.com/
3647 scoped_ptr<SpdyHeaderBlock> headers(
3648 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3649 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
3650 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3651 scoped_ptr<SpdyFrame> get_resp1(
3652 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3653 scoped_ptr<SpdyFrame> body1(
3654 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3656 // http://news.google.com/
3657 scoped_ptr<SpdyHeaderBlock> headers2(
3658 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3659 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
3660 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3661 scoped_ptr<SpdyFrame> get_resp2(
3662 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3663 scoped_ptr<SpdyFrame> body2(
3664 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3666 MockWrite spdy_writes[] = {
3667 CreateMockWrite(*get1, 0),
3668 CreateMockWrite(*get2, 3),
3671 MockRead spdy_reads[] = {
3672 CreateMockRead(*get_resp1, 1, ASYNC),
3673 CreateMockRead(*body1, 2, ASYNC),
3674 CreateMockRead(*get_resp2, 4, ASYNC),
3675 CreateMockRead(*body2, 5, ASYNC),
3676 MockRead(ASYNC, 0, 6),
3679 DeterministicSocketData spdy_data(
3680 spdy_reads, arraysize(spdy_reads),
3681 spdy_writes, arraysize(spdy_writes));
3682 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3684 SSLSocketDataProvider ssl(ASYNC, OK);
3685 ssl.SetNextProto(GetParam());
3686 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3688 TestCompletionCallback callback;
3690 scoped_ptr<HttpTransaction> trans(
3691 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3692 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3693 EXPECT_EQ(ERR_IO_PENDING, rv);
3694 spdy_data.RunFor(2);
3696 rv = callback.WaitForResult();
3697 EXPECT_EQ(OK, rv);
3699 LoadTimingInfo load_timing_info;
3700 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3701 TestLoadTimingNotReused(load_timing_info,
3702 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3704 const HttpResponseInfo* response = trans->GetResponseInfo();
3705 ASSERT_TRUE(response != NULL);
3706 ASSERT_TRUE(response->headers.get() != NULL);
3707 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3709 std::string response_data;
3710 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3711 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3712 spdy_data.RunFor(1);
3713 EXPECT_EQ(1, callback.WaitForResult());
3714 // Delete the first request, so the second one can reuse the socket.
3715 trans.reset();
3717 scoped_ptr<HttpTransaction> trans2(
3718 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3719 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3720 EXPECT_EQ(ERR_IO_PENDING, rv);
3722 spdy_data.RunFor(2);
3723 rv = callback.WaitForResult();
3724 EXPECT_EQ(OK, rv);
3726 LoadTimingInfo load_timing_info2;
3727 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3728 TestLoadTimingReused(load_timing_info2);
3730 // The requests should have the same ID.
3731 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3733 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3734 spdy_data.RunFor(1);
3735 EXPECT_EQ(2, callback.WaitForResult());
3738 // Test the challenge-response-retry sequence through an HTTPS Proxy
3739 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3740 HttpRequestInfo request;
3741 request.method = "GET";
3742 request.url = GURL("http://www.google.com/");
3743 // when the no authentication data flag is set.
3744 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3746 // Configure against https proxy server "myproxy:70".
3747 session_deps_.proxy_service.reset(
3748 ProxyService::CreateFixed("https://myproxy:70"));
3749 CapturingBoundNetLog log;
3750 session_deps_.net_log = log.bound().net_log();
3751 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3753 // Since we have proxy, should use full url
3754 MockWrite data_writes1[] = {
3755 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3756 "Host: www.google.com\r\n"
3757 "Proxy-Connection: keep-alive\r\n\r\n"),
3759 // After calling trans->RestartWithAuth(), this is the request we should
3760 // be issuing -- the final header line contains the credentials.
3761 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3762 "Host: www.google.com\r\n"
3763 "Proxy-Connection: keep-alive\r\n"
3764 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3767 // The proxy responds to the GET with a 407, using a persistent
3768 // connection.
3769 MockRead data_reads1[] = {
3770 // No credentials.
3771 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3772 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3773 MockRead("Proxy-Connection: keep-alive\r\n"),
3774 MockRead("Content-Length: 0\r\n\r\n"),
3776 MockRead("HTTP/1.1 200 OK\r\n"),
3777 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3778 MockRead("Content-Length: 100\r\n\r\n"),
3779 MockRead(SYNCHRONOUS, OK),
3782 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3783 data_writes1, arraysize(data_writes1));
3784 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3785 SSLSocketDataProvider ssl(ASYNC, OK);
3786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3788 TestCompletionCallback callback1;
3790 scoped_ptr<HttpTransaction> trans(
3791 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3793 int rv = trans->Start(&request, callback1.callback(), log.bound());
3794 EXPECT_EQ(ERR_IO_PENDING, rv);
3796 rv = callback1.WaitForResult();
3797 EXPECT_EQ(OK, rv);
3799 LoadTimingInfo load_timing_info;
3800 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3801 TestLoadTimingNotReused(load_timing_info,
3802 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3804 const HttpResponseInfo* response = trans->GetResponseInfo();
3805 ASSERT_TRUE(response != NULL);
3806 ASSERT_FALSE(response->headers.get() == NULL);
3807 EXPECT_EQ(407, response->headers->response_code());
3808 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3809 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3811 TestCompletionCallback callback2;
3813 rv = trans->RestartWithAuth(
3814 AuthCredentials(kFoo, kBar), callback2.callback());
3815 EXPECT_EQ(ERR_IO_PENDING, rv);
3817 rv = callback2.WaitForResult();
3818 EXPECT_EQ(OK, rv);
3820 load_timing_info = LoadTimingInfo();
3821 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3822 // Retrying with HTTP AUTH is considered to be reusing a socket.
3823 TestLoadTimingReused(load_timing_info);
3825 response = trans->GetResponseInfo();
3826 ASSERT_TRUE(response != NULL);
3828 EXPECT_TRUE(response->headers->IsKeepAlive());
3829 EXPECT_EQ(200, response->headers->response_code());
3830 EXPECT_EQ(100, response->headers->GetContentLength());
3831 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3833 // The password prompt info should not be set.
3834 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3837 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3838 const MockRead& status, int expected_status) {
3839 HttpRequestInfo request;
3840 request.method = "GET";
3841 request.url = GURL("https://www.google.com/");
3842 request.load_flags = 0;
3844 // Configure against proxy server "myproxy:70".
3845 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3846 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3848 // Since we have proxy, should try to establish tunnel.
3849 MockWrite data_writes[] = {
3850 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3851 "Host: www.google.com\r\n"
3852 "Proxy-Connection: keep-alive\r\n\r\n"),
3855 MockRead data_reads[] = {
3856 status,
3857 MockRead("Content-Length: 10\r\n\r\n"),
3858 // No response body because the test stops reading here.
3859 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3862 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3863 data_writes, arraysize(data_writes));
3864 session_deps_.socket_factory->AddSocketDataProvider(&data);
3866 TestCompletionCallback callback;
3868 scoped_ptr<HttpTransaction> trans(
3869 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3871 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3872 EXPECT_EQ(ERR_IO_PENDING, rv);
3874 rv = callback.WaitForResult();
3875 EXPECT_EQ(expected_status, rv);
3878 void HttpNetworkTransactionTest::ConnectStatusHelper(
3879 const MockRead& status) {
3880 ConnectStatusHelperWithExpectedStatus(
3881 status, ERR_TUNNEL_CONNECTION_FAILED);
3884 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3885 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3888 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3889 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3892 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3893 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3896 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3897 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3900 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
3901 ConnectStatusHelper(
3902 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3905 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
3906 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3909 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
3910 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3913 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
3914 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3917 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
3918 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3921 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
3922 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3925 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
3926 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3929 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
3930 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3933 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
3934 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3937 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
3938 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3941 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
3942 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3945 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
3946 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3949 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
3950 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
3953 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
3954 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3957 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
3958 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3961 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
3962 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3965 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
3966 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3969 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
3970 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3973 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
3974 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3977 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
3978 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3981 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
3982 ConnectStatusHelperWithExpectedStatus(
3983 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3984 ERR_PROXY_AUTH_UNSUPPORTED);
3987 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
3988 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3991 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
3992 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3995 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
3996 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
3999 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4000 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4003 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4004 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4007 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4008 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4011 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4012 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4015 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4016 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4019 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4020 ConnectStatusHelper(
4021 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4024 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4025 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4028 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4029 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4032 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4033 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4036 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4037 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4040 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4041 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4044 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4045 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4048 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4049 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4052 // Test the flow when both the proxy server AND origin server require
4053 // authentication. Again, this uses basic auth for both since that is
4054 // the simplest to mock.
4055 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4056 HttpRequestInfo request;
4057 request.method = "GET";
4058 request.url = GURL("http://www.google.com/");
4059 request.load_flags = 0;
4061 // Configure against proxy server "myproxy:70".
4062 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4063 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4065 scoped_ptr<HttpTransaction> trans(
4066 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4068 MockWrite data_writes1[] = {
4069 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4070 "Host: www.google.com\r\n"
4071 "Proxy-Connection: keep-alive\r\n\r\n"),
4074 MockRead data_reads1[] = {
4075 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4076 // Give a couple authenticate options (only the middle one is actually
4077 // supported).
4078 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4079 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4080 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4081 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4082 // Large content-length -- won't matter, as connection will be reset.
4083 MockRead("Content-Length: 10000\r\n\r\n"),
4084 MockRead(SYNCHRONOUS, ERR_FAILED),
4087 // After calling trans->RestartWithAuth() the first time, this is the
4088 // request we should be issuing -- the final header line contains the
4089 // proxy's credentials.
4090 MockWrite data_writes2[] = {
4091 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4092 "Host: www.google.com\r\n"
4093 "Proxy-Connection: keep-alive\r\n"
4094 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4097 // Now the proxy server lets the request pass through to origin server.
4098 // The origin server responds with a 401.
4099 MockRead data_reads2[] = {
4100 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4101 // Note: We are using the same realm-name as the proxy server. This is
4102 // completely valid, as realms are unique across hosts.
4103 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4104 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4105 MockRead("Content-Length: 2000\r\n\r\n"),
4106 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4109 // After calling trans->RestartWithAuth() the second time, we should send
4110 // the credentials for both the proxy and origin server.
4111 MockWrite data_writes3[] = {
4112 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4113 "Host: www.google.com\r\n"
4114 "Proxy-Connection: keep-alive\r\n"
4115 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4116 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4119 // Lastly we get the desired content.
4120 MockRead data_reads3[] = {
4121 MockRead("HTTP/1.0 200 OK\r\n"),
4122 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4123 MockRead("Content-Length: 100\r\n\r\n"),
4124 MockRead(SYNCHRONOUS, OK),
4127 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4128 data_writes1, arraysize(data_writes1));
4129 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4130 data_writes2, arraysize(data_writes2));
4131 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4132 data_writes3, arraysize(data_writes3));
4133 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4134 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4135 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4137 TestCompletionCallback callback1;
4139 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4140 EXPECT_EQ(ERR_IO_PENDING, rv);
4142 rv = callback1.WaitForResult();
4143 EXPECT_EQ(OK, rv);
4145 const HttpResponseInfo* response = trans->GetResponseInfo();
4146 ASSERT_TRUE(response != NULL);
4147 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4149 TestCompletionCallback callback2;
4151 rv = trans->RestartWithAuth(
4152 AuthCredentials(kFoo, kBar), callback2.callback());
4153 EXPECT_EQ(ERR_IO_PENDING, rv);
4155 rv = callback2.WaitForResult();
4156 EXPECT_EQ(OK, rv);
4158 response = trans->GetResponseInfo();
4159 ASSERT_TRUE(response != NULL);
4160 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4162 TestCompletionCallback callback3;
4164 rv = trans->RestartWithAuth(
4165 AuthCredentials(kFoo2, kBar2), callback3.callback());
4166 EXPECT_EQ(ERR_IO_PENDING, rv);
4168 rv = callback3.WaitForResult();
4169 EXPECT_EQ(OK, rv);
4171 response = trans->GetResponseInfo();
4172 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4173 EXPECT_EQ(100, response->headers->GetContentLength());
4176 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4177 // can't hook into its internals to cause it to generate predictable NTLM
4178 // authorization headers.
4179 #if defined(NTLM_PORTABLE)
4180 // The NTLM authentication unit tests were generated by capturing the HTTP
4181 // requests and responses using Fiddler 2 and inspecting the generated random
4182 // bytes in the debugger.
4184 // Enter the correct password and authenticate successfully.
4185 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4186 HttpRequestInfo request;
4187 request.method = "GET";
4188 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4190 // Ensure load is not disrupted by flags which suppress behaviour specific
4191 // to other auth schemes.
4192 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4194 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4195 MockGetHostName);
4196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4198 MockWrite data_writes1[] = {
4199 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4200 "Host: 172.22.68.17\r\n"
4201 "Connection: keep-alive\r\n\r\n"),
4204 MockRead data_reads1[] = {
4205 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4206 // Negotiate and NTLM are often requested together. However, we only want
4207 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4208 // the header that requests Negotiate for this test.
4209 MockRead("WWW-Authenticate: NTLM\r\n"),
4210 MockRead("Connection: close\r\n"),
4211 MockRead("Content-Length: 42\r\n"),
4212 MockRead("Content-Type: text/html\r\n\r\n"),
4213 // Missing content -- won't matter, as connection will be reset.
4214 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4217 MockWrite data_writes2[] = {
4218 // After restarting with a null identity, this is the
4219 // request we should be issuing -- the final header line contains a Type
4220 // 1 message.
4221 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4222 "Host: 172.22.68.17\r\n"
4223 "Connection: keep-alive\r\n"
4224 "Authorization: NTLM "
4225 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4227 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4228 // (the credentials for the origin server). The second request continues
4229 // on the same connection.
4230 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4231 "Host: 172.22.68.17\r\n"
4232 "Connection: keep-alive\r\n"
4233 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4234 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4235 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4236 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4237 "ahlhx5I=\r\n\r\n"),
4240 MockRead data_reads2[] = {
4241 // The origin server responds with a Type 2 message.
4242 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4243 MockRead("WWW-Authenticate: NTLM "
4244 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4245 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4246 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4247 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4248 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4249 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4250 "BtAAAAAAA=\r\n"),
4251 MockRead("Content-Length: 42\r\n"),
4252 MockRead("Content-Type: text/html\r\n\r\n"),
4253 MockRead("You are not authorized to view this page\r\n"),
4255 // Lastly we get the desired content.
4256 MockRead("HTTP/1.1 200 OK\r\n"),
4257 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4258 MockRead("Content-Length: 13\r\n\r\n"),
4259 MockRead("Please Login\r\n"),
4260 MockRead(SYNCHRONOUS, OK),
4263 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4264 data_writes1, arraysize(data_writes1));
4265 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4266 data_writes2, arraysize(data_writes2));
4267 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4268 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4270 TestCompletionCallback callback1;
4272 scoped_ptr<HttpTransaction> trans(
4273 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4275 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4276 EXPECT_EQ(ERR_IO_PENDING, rv);
4278 rv = callback1.WaitForResult();
4279 EXPECT_EQ(OK, rv);
4281 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4283 const HttpResponseInfo* response = trans->GetResponseInfo();
4284 ASSERT_FALSE(response == NULL);
4285 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4287 TestCompletionCallback callback2;
4289 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4290 callback2.callback());
4291 EXPECT_EQ(ERR_IO_PENDING, rv);
4293 rv = callback2.WaitForResult();
4294 EXPECT_EQ(OK, rv);
4296 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4298 response = trans->GetResponseInfo();
4299 ASSERT_TRUE(response != NULL);
4300 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4302 TestCompletionCallback callback3;
4304 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4305 EXPECT_EQ(ERR_IO_PENDING, rv);
4307 rv = callback3.WaitForResult();
4308 EXPECT_EQ(OK, rv);
4310 response = trans->GetResponseInfo();
4311 ASSERT_TRUE(response != NULL);
4312 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4313 EXPECT_EQ(13, response->headers->GetContentLength());
4316 // Enter a wrong password, and then the correct one.
4317 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4318 HttpRequestInfo request;
4319 request.method = "GET";
4320 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4321 request.load_flags = 0;
4323 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4324 MockGetHostName);
4325 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4327 MockWrite data_writes1[] = {
4328 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4329 "Host: 172.22.68.17\r\n"
4330 "Connection: keep-alive\r\n\r\n"),
4333 MockRead data_reads1[] = {
4334 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4335 // Negotiate and NTLM are often requested together. However, we only want
4336 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4337 // the header that requests Negotiate for this test.
4338 MockRead("WWW-Authenticate: NTLM\r\n"),
4339 MockRead("Connection: close\r\n"),
4340 MockRead("Content-Length: 42\r\n"),
4341 MockRead("Content-Type: text/html\r\n\r\n"),
4342 // Missing content -- won't matter, as connection will be reset.
4343 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4346 MockWrite data_writes2[] = {
4347 // After restarting with a null identity, this is the
4348 // request we should be issuing -- the final header line contains a Type
4349 // 1 message.
4350 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4351 "Host: 172.22.68.17\r\n"
4352 "Connection: keep-alive\r\n"
4353 "Authorization: NTLM "
4354 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4356 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4357 // (the credentials for the origin server). The second request continues
4358 // on the same connection.
4359 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4360 "Host: 172.22.68.17\r\n"
4361 "Connection: keep-alive\r\n"
4362 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4363 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4364 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4365 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4366 "4Ww7b7E=\r\n\r\n"),
4369 MockRead data_reads2[] = {
4370 // The origin server responds with a Type 2 message.
4371 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4372 MockRead("WWW-Authenticate: NTLM "
4373 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4374 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4375 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4376 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4377 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4378 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4379 "BtAAAAAAA=\r\n"),
4380 MockRead("Content-Length: 42\r\n"),
4381 MockRead("Content-Type: text/html\r\n\r\n"),
4382 MockRead("You are not authorized to view this page\r\n"),
4384 // Wrong password.
4385 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4386 MockRead("WWW-Authenticate: NTLM\r\n"),
4387 MockRead("Connection: close\r\n"),
4388 MockRead("Content-Length: 42\r\n"),
4389 MockRead("Content-Type: text/html\r\n\r\n"),
4390 // Missing content -- won't matter, as connection will be reset.
4391 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4394 MockWrite data_writes3[] = {
4395 // After restarting with a null identity, this is the
4396 // request we should be issuing -- the final header line contains a Type
4397 // 1 message.
4398 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4399 "Host: 172.22.68.17\r\n"
4400 "Connection: keep-alive\r\n"
4401 "Authorization: NTLM "
4402 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4404 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4405 // (the credentials for the origin server). The second request continues
4406 // on the same connection.
4407 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4408 "Host: 172.22.68.17\r\n"
4409 "Connection: keep-alive\r\n"
4410 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4411 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4412 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4413 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4414 "+4MUm7c=\r\n\r\n"),
4417 MockRead data_reads3[] = {
4418 // The origin server responds with a Type 2 message.
4419 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4420 MockRead("WWW-Authenticate: NTLM "
4421 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4422 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4423 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4424 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4425 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4426 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4427 "BtAAAAAAA=\r\n"),
4428 MockRead("Content-Length: 42\r\n"),
4429 MockRead("Content-Type: text/html\r\n\r\n"),
4430 MockRead("You are not authorized to view this page\r\n"),
4432 // Lastly we get the desired content.
4433 MockRead("HTTP/1.1 200 OK\r\n"),
4434 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4435 MockRead("Content-Length: 13\r\n\r\n"),
4436 MockRead("Please Login\r\n"),
4437 MockRead(SYNCHRONOUS, OK),
4440 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4441 data_writes1, arraysize(data_writes1));
4442 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4443 data_writes2, arraysize(data_writes2));
4444 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4445 data_writes3, arraysize(data_writes3));
4446 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4447 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4448 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4450 TestCompletionCallback callback1;
4452 scoped_ptr<HttpTransaction> trans(
4453 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4455 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4456 EXPECT_EQ(ERR_IO_PENDING, rv);
4458 rv = callback1.WaitForResult();
4459 EXPECT_EQ(OK, rv);
4461 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4463 const HttpResponseInfo* response = trans->GetResponseInfo();
4464 ASSERT_TRUE(response != NULL);
4465 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4467 TestCompletionCallback callback2;
4469 // Enter the wrong password.
4470 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4471 callback2.callback());
4472 EXPECT_EQ(ERR_IO_PENDING, rv);
4474 rv = callback2.WaitForResult();
4475 EXPECT_EQ(OK, rv);
4477 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4478 TestCompletionCallback callback3;
4479 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4480 EXPECT_EQ(ERR_IO_PENDING, rv);
4481 rv = callback3.WaitForResult();
4482 EXPECT_EQ(OK, rv);
4483 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4485 response = trans->GetResponseInfo();
4486 ASSERT_FALSE(response == NULL);
4487 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4489 TestCompletionCallback callback4;
4491 // Now enter the right password.
4492 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4493 callback4.callback());
4494 EXPECT_EQ(ERR_IO_PENDING, rv);
4496 rv = callback4.WaitForResult();
4497 EXPECT_EQ(OK, rv);
4499 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4501 TestCompletionCallback callback5;
4503 // One more roundtrip
4504 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4505 EXPECT_EQ(ERR_IO_PENDING, rv);
4507 rv = callback5.WaitForResult();
4508 EXPECT_EQ(OK, rv);
4510 response = trans->GetResponseInfo();
4511 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4512 EXPECT_EQ(13, response->headers->GetContentLength());
4514 #endif // NTLM_PORTABLE
4516 // Test reading a server response which has only headers, and no body.
4517 // After some maximum number of bytes is consumed, the transaction should
4518 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4519 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4520 HttpRequestInfo request;
4521 request.method = "GET";
4522 request.url = GURL("http://www.google.com/");
4523 request.load_flags = 0;
4525 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4526 scoped_ptr<HttpTransaction> trans(
4527 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4529 // Respond with 300 kb of headers (we should fail after 256 kb).
4530 std::string large_headers_string;
4531 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4533 MockRead data_reads[] = {
4534 MockRead("HTTP/1.0 200 OK\r\n"),
4535 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4536 MockRead("\r\nBODY"),
4537 MockRead(SYNCHRONOUS, OK),
4539 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4540 session_deps_.socket_factory->AddSocketDataProvider(&data);
4542 TestCompletionCallback callback;
4544 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4545 EXPECT_EQ(ERR_IO_PENDING, rv);
4547 rv = callback.WaitForResult();
4548 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4550 const HttpResponseInfo* response = trans->GetResponseInfo();
4551 EXPECT_TRUE(response == NULL);
4554 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4555 // establish tunnel.
4556 // http://code.google.com/p/chromium/issues/detail?id=3772
4557 TEST_P(HttpNetworkTransactionTest,
4558 DontRecycleTransportSocketForSSLTunnel) {
4559 HttpRequestInfo request;
4560 request.method = "GET";
4561 request.url = GURL("https://www.google.com/");
4562 request.load_flags = 0;
4564 // Configure against proxy server "myproxy:70".
4565 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4567 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4569 scoped_ptr<HttpTransaction> trans(
4570 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4572 // Since we have proxy, should try to establish tunnel.
4573 MockWrite data_writes1[] = {
4574 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4575 "Host: www.google.com\r\n"
4576 "Proxy-Connection: keep-alive\r\n\r\n"),
4579 // The proxy responds to the connect with a 404, using a persistent
4580 // connection. Usually a proxy would return 501 (not implemented),
4581 // or 200 (tunnel established).
4582 MockRead data_reads1[] = {
4583 MockRead("HTTP/1.1 404 Not Found\r\n"),
4584 MockRead("Content-Length: 10\r\n\r\n"),
4585 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4588 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4589 data_writes1, arraysize(data_writes1));
4590 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4592 TestCompletionCallback callback1;
4594 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4595 EXPECT_EQ(ERR_IO_PENDING, rv);
4597 rv = callback1.WaitForResult();
4598 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4600 const HttpResponseInfo* response = trans->GetResponseInfo();
4601 EXPECT_TRUE(response == NULL);
4603 // Empty the current queue. This is necessary because idle sockets are
4604 // added to the connection pool asynchronously with a PostTask.
4605 base::MessageLoop::current()->RunUntilIdle();
4607 // We now check to make sure the TCPClientSocket was not added back to
4608 // the pool.
4609 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4610 trans.reset();
4611 base::MessageLoop::current()->RunUntilIdle();
4612 // Make sure that the socket didn't get recycled after calling the destructor.
4613 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4616 // Make sure that we recycle a socket after reading all of the response body.
4617 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4618 HttpRequestInfo request;
4619 request.method = "GET";
4620 request.url = GURL("http://www.google.com/");
4621 request.load_flags = 0;
4623 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4625 scoped_ptr<HttpTransaction> trans(
4626 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4628 MockRead data_reads[] = {
4629 // A part of the response body is received with the response headers.
4630 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4631 // The rest of the response body is received in two parts.
4632 MockRead("lo"),
4633 MockRead(" world"),
4634 MockRead("junk"), // Should not be read!!
4635 MockRead(SYNCHRONOUS, OK),
4638 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4639 session_deps_.socket_factory->AddSocketDataProvider(&data);
4641 TestCompletionCallback callback;
4643 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4644 EXPECT_EQ(ERR_IO_PENDING, rv);
4646 rv = callback.WaitForResult();
4647 EXPECT_EQ(OK, rv);
4649 const HttpResponseInfo* response = trans->GetResponseInfo();
4650 ASSERT_TRUE(response != NULL);
4652 EXPECT_TRUE(response->headers.get() != NULL);
4653 std::string status_line = response->headers->GetStatusLine();
4654 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4656 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4658 std::string response_data;
4659 rv = ReadTransaction(trans.get(), &response_data);
4660 EXPECT_EQ(OK, rv);
4661 EXPECT_EQ("hello world", response_data);
4663 // Empty the current queue. This is necessary because idle sockets are
4664 // added to the connection pool asynchronously with a PostTask.
4665 base::MessageLoop::current()->RunUntilIdle();
4667 // We now check to make sure the socket was added back to the pool.
4668 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4671 // Make sure that we recycle a SSL socket after reading all of the response
4672 // body.
4673 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4674 HttpRequestInfo request;
4675 request.method = "GET";
4676 request.url = GURL("https://www.google.com/");
4677 request.load_flags = 0;
4679 MockWrite data_writes[] = {
4680 MockWrite("GET / HTTP/1.1\r\n"
4681 "Host: www.google.com\r\n"
4682 "Connection: keep-alive\r\n\r\n"),
4685 MockRead data_reads[] = {
4686 MockRead("HTTP/1.1 200 OK\r\n"),
4687 MockRead("Content-Length: 11\r\n\r\n"),
4688 MockRead("hello world"),
4689 MockRead(SYNCHRONOUS, OK),
4692 SSLSocketDataProvider ssl(ASYNC, OK);
4693 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4695 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4696 data_writes, arraysize(data_writes));
4697 session_deps_.socket_factory->AddSocketDataProvider(&data);
4699 TestCompletionCallback callback;
4701 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4702 scoped_ptr<HttpTransaction> trans(
4703 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4705 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4707 EXPECT_EQ(ERR_IO_PENDING, rv);
4708 EXPECT_EQ(OK, callback.WaitForResult());
4710 const HttpResponseInfo* response = trans->GetResponseInfo();
4711 ASSERT_TRUE(response != NULL);
4712 ASSERT_TRUE(response->headers.get() != NULL);
4713 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4715 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4717 std::string response_data;
4718 rv = ReadTransaction(trans.get(), &response_data);
4719 EXPECT_EQ(OK, rv);
4720 EXPECT_EQ("hello world", response_data);
4722 // Empty the current queue. This is necessary because idle sockets are
4723 // added to the connection pool asynchronously with a PostTask.
4724 base::MessageLoop::current()->RunUntilIdle();
4726 // We now check to make sure the socket was added back to the pool.
4727 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4730 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4731 // from the pool and make sure that we recover okay.
4732 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4733 HttpRequestInfo request;
4734 request.method = "GET";
4735 request.url = GURL("https://www.google.com/");
4736 request.load_flags = 0;
4738 MockWrite data_writes[] = {
4739 MockWrite("GET / HTTP/1.1\r\n"
4740 "Host: www.google.com\r\n"
4741 "Connection: keep-alive\r\n\r\n"),
4742 MockWrite("GET / HTTP/1.1\r\n"
4743 "Host: www.google.com\r\n"
4744 "Connection: keep-alive\r\n\r\n"),
4747 MockRead data_reads[] = {
4748 MockRead("HTTP/1.1 200 OK\r\n"),
4749 MockRead("Content-Length: 11\r\n\r\n"),
4750 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4751 MockRead("hello world"),
4752 MockRead(ASYNC, 0, 0) // EOF
4755 SSLSocketDataProvider ssl(ASYNC, OK);
4756 SSLSocketDataProvider ssl2(ASYNC, OK);
4757 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4758 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4760 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4761 data_writes, arraysize(data_writes));
4762 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4763 data_writes, arraysize(data_writes));
4764 session_deps_.socket_factory->AddSocketDataProvider(&data);
4765 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4767 TestCompletionCallback callback;
4769 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4770 scoped_ptr<HttpTransaction> trans(
4771 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4773 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4775 EXPECT_EQ(ERR_IO_PENDING, rv);
4776 EXPECT_EQ(OK, callback.WaitForResult());
4778 const HttpResponseInfo* response = trans->GetResponseInfo();
4779 ASSERT_TRUE(response != NULL);
4780 ASSERT_TRUE(response->headers.get() != NULL);
4781 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4783 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4785 std::string response_data;
4786 rv = ReadTransaction(trans.get(), &response_data);
4787 EXPECT_EQ(OK, rv);
4788 EXPECT_EQ("hello world", response_data);
4790 // Empty the current queue. This is necessary because idle sockets are
4791 // added to the connection pool asynchronously with a PostTask.
4792 base::MessageLoop::current()->RunUntilIdle();
4794 // We now check to make sure the socket was added back to the pool.
4795 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4797 // Now start the second transaction, which should reuse the previous socket.
4799 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4801 rv = trans->Start(&request, callback.callback(), BoundNetLog());
4803 EXPECT_EQ(ERR_IO_PENDING, rv);
4804 EXPECT_EQ(OK, callback.WaitForResult());
4806 response = trans->GetResponseInfo();
4807 ASSERT_TRUE(response != NULL);
4808 ASSERT_TRUE(response->headers.get() != NULL);
4809 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4811 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4813 rv = ReadTransaction(trans.get(), &response_data);
4814 EXPECT_EQ(OK, rv);
4815 EXPECT_EQ("hello world", response_data);
4817 // Empty the current queue. This is necessary because idle sockets are
4818 // added to the connection pool asynchronously with a PostTask.
4819 base::MessageLoop::current()->RunUntilIdle();
4821 // We now check to make sure the socket was added back to the pool.
4822 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4825 // Make sure that we recycle a socket after a zero-length response.
4826 // http://crbug.com/9880
4827 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4828 HttpRequestInfo request;
4829 request.method = "GET";
4830 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4831 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4832 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4833 "rt=prt.2642,ol.2649,xjs.2951");
4834 request.load_flags = 0;
4836 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4838 scoped_ptr<HttpTransaction> trans(
4839 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4841 MockRead data_reads[] = {
4842 MockRead("HTTP/1.1 204 No Content\r\n"
4843 "Content-Length: 0\r\n"
4844 "Content-Type: text/html\r\n\r\n"),
4845 MockRead("junk"), // Should not be read!!
4846 MockRead(SYNCHRONOUS, OK),
4849 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4850 session_deps_.socket_factory->AddSocketDataProvider(&data);
4852 TestCompletionCallback callback;
4854 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4855 EXPECT_EQ(ERR_IO_PENDING, rv);
4857 rv = callback.WaitForResult();
4858 EXPECT_EQ(OK, rv);
4860 const HttpResponseInfo* response = trans->GetResponseInfo();
4861 ASSERT_TRUE(response != NULL);
4863 EXPECT_TRUE(response->headers.get() != NULL);
4864 std::string status_line = response->headers->GetStatusLine();
4865 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4867 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4869 std::string response_data;
4870 rv = ReadTransaction(trans.get(), &response_data);
4871 EXPECT_EQ(OK, rv);
4872 EXPECT_EQ("", response_data);
4874 // Empty the current queue. This is necessary because idle sockets are
4875 // added to the connection pool asynchronously with a PostTask.
4876 base::MessageLoop::current()->RunUntilIdle();
4878 // We now check to make sure the socket was added back to the pool.
4879 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4882 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
4883 ScopedVector<UploadElementReader> element_readers;
4884 element_readers.push_back(new UploadBytesElementReader("foo", 3));
4885 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
4887 HttpRequestInfo request[2];
4888 // Transaction 1: a GET request that succeeds. The socket is recycled
4889 // after use.
4890 request[0].method = "GET";
4891 request[0].url = GURL("http://www.google.com/");
4892 request[0].load_flags = 0;
4893 // Transaction 2: a POST request. Reuses the socket kept alive from
4894 // transaction 1. The first attempts fails when writing the POST data.
4895 // This causes the transaction to retry with a new socket. The second
4896 // attempt succeeds.
4897 request[1].method = "POST";
4898 request[1].url = GURL("http://www.google.com/login.cgi");
4899 request[1].upload_data_stream = &upload_data_stream;
4900 request[1].load_flags = 0;
4902 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4904 // The first socket is used for transaction 1 and the first attempt of
4905 // transaction 2.
4907 // The response of transaction 1.
4908 MockRead data_reads1[] = {
4909 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4910 MockRead("hello world"),
4911 MockRead(SYNCHRONOUS, OK),
4913 // The mock write results of transaction 1 and the first attempt of
4914 // transaction 2.
4915 MockWrite data_writes1[] = {
4916 MockWrite(SYNCHRONOUS, 64), // GET
4917 MockWrite(SYNCHRONOUS, 93), // POST
4918 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
4920 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4921 data_writes1, arraysize(data_writes1));
4923 // The second socket is used for the second attempt of transaction 2.
4925 // The response of transaction 2.
4926 MockRead data_reads2[] = {
4927 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4928 MockRead("welcome"),
4929 MockRead(SYNCHRONOUS, OK),
4931 // The mock write results of the second attempt of transaction 2.
4932 MockWrite data_writes2[] = {
4933 MockWrite(SYNCHRONOUS, 93), // POST
4934 MockWrite(SYNCHRONOUS, 3), // POST data
4936 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4937 data_writes2, arraysize(data_writes2));
4939 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4940 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4942 const char* kExpectedResponseData[] = {
4943 "hello world", "welcome"
4946 for (int i = 0; i < 2; ++i) {
4947 scoped_ptr<HttpTransaction> trans(
4948 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4950 TestCompletionCallback callback;
4952 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
4953 EXPECT_EQ(ERR_IO_PENDING, rv);
4955 rv = callback.WaitForResult();
4956 EXPECT_EQ(OK, rv);
4958 const HttpResponseInfo* response = trans->GetResponseInfo();
4959 ASSERT_TRUE(response != NULL);
4961 EXPECT_TRUE(response->headers.get() != NULL);
4962 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4964 std::string response_data;
4965 rv = ReadTransaction(trans.get(), &response_data);
4966 EXPECT_EQ(OK, rv);
4967 EXPECT_EQ(kExpectedResponseData[i], response_data);
4971 // Test the request-challenge-retry sequence for basic auth when there is
4972 // an identity in the URL. The request should be sent as normal, but when
4973 // it fails the identity from the URL is used to answer the challenge.
4974 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
4975 HttpRequestInfo request;
4976 request.method = "GET";
4977 request.url = GURL("http://foo:b@r@www.google.com/");
4978 request.load_flags = LOAD_NORMAL;
4980 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4981 scoped_ptr<HttpTransaction> trans(
4982 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4984 // The password contains an escaped character -- for this test to pass it
4985 // will need to be unescaped by HttpNetworkTransaction.
4986 EXPECT_EQ("b%40r", request.url.password());
4988 MockWrite data_writes1[] = {
4989 MockWrite("GET / HTTP/1.1\r\n"
4990 "Host: www.google.com\r\n"
4991 "Connection: keep-alive\r\n\r\n"),
4994 MockRead data_reads1[] = {
4995 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4996 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4997 MockRead("Content-Length: 10\r\n\r\n"),
4998 MockRead(SYNCHRONOUS, ERR_FAILED),
5001 // After the challenge above, the transaction will be restarted using the
5002 // identity from the url (foo, b@r) to answer the challenge.
5003 MockWrite data_writes2[] = {
5004 MockWrite("GET / HTTP/1.1\r\n"
5005 "Host: www.google.com\r\n"
5006 "Connection: keep-alive\r\n"
5007 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5010 MockRead data_reads2[] = {
5011 MockRead("HTTP/1.0 200 OK\r\n"),
5012 MockRead("Content-Length: 100\r\n\r\n"),
5013 MockRead(SYNCHRONOUS, OK),
5016 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5017 data_writes1, arraysize(data_writes1));
5018 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5019 data_writes2, arraysize(data_writes2));
5020 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5021 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5023 TestCompletionCallback callback1;
5024 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5025 EXPECT_EQ(ERR_IO_PENDING, rv);
5026 rv = callback1.WaitForResult();
5027 EXPECT_EQ(OK, rv);
5028 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5030 TestCompletionCallback callback2;
5031 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5032 EXPECT_EQ(ERR_IO_PENDING, rv);
5033 rv = callback2.WaitForResult();
5034 EXPECT_EQ(OK, rv);
5035 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5037 const HttpResponseInfo* response = trans->GetResponseInfo();
5038 ASSERT_TRUE(response != NULL);
5040 // There is no challenge info, since the identity in URL worked.
5041 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5043 EXPECT_EQ(100, response->headers->GetContentLength());
5045 // Empty the current queue.
5046 base::MessageLoop::current()->RunUntilIdle();
5049 // Test the request-challenge-retry sequence for basic auth when there is an
5050 // incorrect identity in the URL. The identity from the URL should be used only
5051 // once.
5052 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5053 HttpRequestInfo request;
5054 request.method = "GET";
5055 // Note: the URL has a username:password in it. The password "baz" is
5056 // wrong (should be "bar").
5057 request.url = GURL("http://foo:baz@www.google.com/");
5059 request.load_flags = LOAD_NORMAL;
5061 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5062 scoped_ptr<HttpTransaction> trans(
5063 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5065 MockWrite data_writes1[] = {
5066 MockWrite("GET / HTTP/1.1\r\n"
5067 "Host: www.google.com\r\n"
5068 "Connection: keep-alive\r\n\r\n"),
5071 MockRead data_reads1[] = {
5072 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5073 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5074 MockRead("Content-Length: 10\r\n\r\n"),
5075 MockRead(SYNCHRONOUS, ERR_FAILED),
5078 // After the challenge above, the transaction will be restarted using the
5079 // identity from the url (foo, baz) to answer the challenge.
5080 MockWrite data_writes2[] = {
5081 MockWrite("GET / HTTP/1.1\r\n"
5082 "Host: www.google.com\r\n"
5083 "Connection: keep-alive\r\n"
5084 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5087 MockRead data_reads2[] = {
5088 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5089 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5090 MockRead("Content-Length: 10\r\n\r\n"),
5091 MockRead(SYNCHRONOUS, ERR_FAILED),
5094 // After the challenge above, the transaction will be restarted using the
5095 // identity supplied by the user (foo, bar) to answer the challenge.
5096 MockWrite data_writes3[] = {
5097 MockWrite("GET / HTTP/1.1\r\n"
5098 "Host: www.google.com\r\n"
5099 "Connection: keep-alive\r\n"
5100 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5103 MockRead data_reads3[] = {
5104 MockRead("HTTP/1.0 200 OK\r\n"),
5105 MockRead("Content-Length: 100\r\n\r\n"),
5106 MockRead(SYNCHRONOUS, OK),
5109 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5110 data_writes1, arraysize(data_writes1));
5111 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5112 data_writes2, arraysize(data_writes2));
5113 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5114 data_writes3, arraysize(data_writes3));
5115 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5116 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5117 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5119 TestCompletionCallback callback1;
5121 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5122 EXPECT_EQ(ERR_IO_PENDING, rv);
5124 rv = callback1.WaitForResult();
5125 EXPECT_EQ(OK, rv);
5127 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5128 TestCompletionCallback callback2;
5129 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5130 EXPECT_EQ(ERR_IO_PENDING, rv);
5131 rv = callback2.WaitForResult();
5132 EXPECT_EQ(OK, rv);
5133 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5135 const HttpResponseInfo* response = trans->GetResponseInfo();
5136 ASSERT_TRUE(response != NULL);
5137 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5139 TestCompletionCallback callback3;
5140 rv = trans->RestartWithAuth(
5141 AuthCredentials(kFoo, kBar), callback3.callback());
5142 EXPECT_EQ(ERR_IO_PENDING, rv);
5143 rv = callback3.WaitForResult();
5144 EXPECT_EQ(OK, rv);
5145 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5147 response = trans->GetResponseInfo();
5148 ASSERT_TRUE(response != NULL);
5150 // There is no challenge info, since the identity worked.
5151 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5153 EXPECT_EQ(100, response->headers->GetContentLength());
5155 // Empty the current queue.
5156 base::MessageLoop::current()->RunUntilIdle();
5160 // Test the request-challenge-retry sequence for basic auth when there is a
5161 // correct identity in the URL, but its use is being suppressed. The identity
5162 // from the URL should never be used.
5163 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5164 HttpRequestInfo request;
5165 request.method = "GET";
5166 request.url = GURL("http://foo:bar@www.google.com/");
5167 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5169 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5170 scoped_ptr<HttpTransaction> trans(
5171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5173 MockWrite data_writes1[] = {
5174 MockWrite("GET / HTTP/1.1\r\n"
5175 "Host: www.google.com\r\n"
5176 "Connection: keep-alive\r\n\r\n"),
5179 MockRead data_reads1[] = {
5180 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5181 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5182 MockRead("Content-Length: 10\r\n\r\n"),
5183 MockRead(SYNCHRONOUS, ERR_FAILED),
5186 // After the challenge above, the transaction will be restarted using the
5187 // identity supplied by the user, not the one in the URL, to answer the
5188 // challenge.
5189 MockWrite data_writes3[] = {
5190 MockWrite("GET / HTTP/1.1\r\n"
5191 "Host: www.google.com\r\n"
5192 "Connection: keep-alive\r\n"
5193 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5196 MockRead data_reads3[] = {
5197 MockRead("HTTP/1.0 200 OK\r\n"),
5198 MockRead("Content-Length: 100\r\n\r\n"),
5199 MockRead(SYNCHRONOUS, OK),
5202 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5203 data_writes1, arraysize(data_writes1));
5204 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5205 data_writes3, arraysize(data_writes3));
5206 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5207 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5209 TestCompletionCallback callback1;
5210 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5211 EXPECT_EQ(ERR_IO_PENDING, rv);
5212 rv = callback1.WaitForResult();
5213 EXPECT_EQ(OK, rv);
5214 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5216 const HttpResponseInfo* response = trans->GetResponseInfo();
5217 ASSERT_TRUE(response != NULL);
5218 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5220 TestCompletionCallback callback3;
5221 rv = trans->RestartWithAuth(
5222 AuthCredentials(kFoo, kBar), callback3.callback());
5223 EXPECT_EQ(ERR_IO_PENDING, rv);
5224 rv = callback3.WaitForResult();
5225 EXPECT_EQ(OK, rv);
5226 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5228 response = trans->GetResponseInfo();
5229 ASSERT_TRUE(response != NULL);
5231 // There is no challenge info, since the identity worked.
5232 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5233 EXPECT_EQ(100, response->headers->GetContentLength());
5235 // Empty the current queue.
5236 base::MessageLoop::current()->RunUntilIdle();
5239 // Test that previously tried username/passwords for a realm get re-used.
5240 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5241 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5243 // Transaction 1: authenticate (foo, bar) on MyRealm1
5245 HttpRequestInfo request;
5246 request.method = "GET";
5247 request.url = GURL("http://www.google.com/x/y/z");
5248 request.load_flags = 0;
5250 scoped_ptr<HttpTransaction> trans(
5251 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5253 MockWrite data_writes1[] = {
5254 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5255 "Host: www.google.com\r\n"
5256 "Connection: keep-alive\r\n\r\n"),
5259 MockRead data_reads1[] = {
5260 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5261 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5262 MockRead("Content-Length: 10000\r\n\r\n"),
5263 MockRead(SYNCHRONOUS, ERR_FAILED),
5266 // Resend with authorization (username=foo, password=bar)
5267 MockWrite data_writes2[] = {
5268 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5269 "Host: www.google.com\r\n"
5270 "Connection: keep-alive\r\n"
5271 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5274 // Sever accepts the authorization.
5275 MockRead data_reads2[] = {
5276 MockRead("HTTP/1.0 200 OK\r\n"),
5277 MockRead("Content-Length: 100\r\n\r\n"),
5278 MockRead(SYNCHRONOUS, OK),
5281 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5282 data_writes1, arraysize(data_writes1));
5283 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5284 data_writes2, arraysize(data_writes2));
5285 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5286 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5288 TestCompletionCallback callback1;
5290 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5291 EXPECT_EQ(ERR_IO_PENDING, rv);
5293 rv = callback1.WaitForResult();
5294 EXPECT_EQ(OK, rv);
5296 const HttpResponseInfo* response = trans->GetResponseInfo();
5297 ASSERT_TRUE(response != NULL);
5298 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5300 TestCompletionCallback callback2;
5302 rv = trans->RestartWithAuth(
5303 AuthCredentials(kFoo, kBar), callback2.callback());
5304 EXPECT_EQ(ERR_IO_PENDING, rv);
5306 rv = callback2.WaitForResult();
5307 EXPECT_EQ(OK, rv);
5309 response = trans->GetResponseInfo();
5310 ASSERT_TRUE(response != NULL);
5311 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5312 EXPECT_EQ(100, response->headers->GetContentLength());
5315 // ------------------------------------------------------------------------
5317 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5319 HttpRequestInfo request;
5320 request.method = "GET";
5321 // Note that Transaction 1 was at /x/y/z, so this is in the same
5322 // protection space as MyRealm1.
5323 request.url = GURL("http://www.google.com/x/y/a/b");
5324 request.load_flags = 0;
5326 scoped_ptr<HttpTransaction> trans(
5327 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5329 MockWrite data_writes1[] = {
5330 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5331 "Host: www.google.com\r\n"
5332 "Connection: keep-alive\r\n"
5333 // Send preemptive authorization for MyRealm1
5334 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5337 // The server didn't like the preemptive authorization, and
5338 // challenges us for a different realm (MyRealm2).
5339 MockRead data_reads1[] = {
5340 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5341 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5342 MockRead("Content-Length: 10000\r\n\r\n"),
5343 MockRead(SYNCHRONOUS, ERR_FAILED),
5346 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5347 MockWrite data_writes2[] = {
5348 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5349 "Host: www.google.com\r\n"
5350 "Connection: keep-alive\r\n"
5351 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5354 // Sever accepts the authorization.
5355 MockRead data_reads2[] = {
5356 MockRead("HTTP/1.0 200 OK\r\n"),
5357 MockRead("Content-Length: 100\r\n\r\n"),
5358 MockRead(SYNCHRONOUS, OK),
5361 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5362 data_writes1, arraysize(data_writes1));
5363 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5364 data_writes2, arraysize(data_writes2));
5365 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5366 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5368 TestCompletionCallback callback1;
5370 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5371 EXPECT_EQ(ERR_IO_PENDING, rv);
5373 rv = callback1.WaitForResult();
5374 EXPECT_EQ(OK, rv);
5376 const HttpResponseInfo* response = trans->GetResponseInfo();
5377 ASSERT_TRUE(response != NULL);
5378 ASSERT_TRUE(response->auth_challenge.get());
5379 EXPECT_FALSE(response->auth_challenge->is_proxy);
5380 EXPECT_EQ("www.google.com:80",
5381 response->auth_challenge->challenger.ToString());
5382 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5383 EXPECT_EQ("basic", response->auth_challenge->scheme);
5385 TestCompletionCallback callback2;
5387 rv = trans->RestartWithAuth(
5388 AuthCredentials(kFoo2, kBar2), callback2.callback());
5389 EXPECT_EQ(ERR_IO_PENDING, rv);
5391 rv = callback2.WaitForResult();
5392 EXPECT_EQ(OK, rv);
5394 response = trans->GetResponseInfo();
5395 ASSERT_TRUE(response != NULL);
5396 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5397 EXPECT_EQ(100, response->headers->GetContentLength());
5400 // ------------------------------------------------------------------------
5402 // Transaction 3: Resend a request in MyRealm's protection space --
5403 // succeed with preemptive authorization.
5405 HttpRequestInfo request;
5406 request.method = "GET";
5407 request.url = GURL("http://www.google.com/x/y/z2");
5408 request.load_flags = 0;
5410 scoped_ptr<HttpTransaction> trans(
5411 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5413 MockWrite data_writes1[] = {
5414 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5415 "Host: www.google.com\r\n"
5416 "Connection: keep-alive\r\n"
5417 // The authorization for MyRealm1 gets sent preemptively
5418 // (since the url is in the same protection space)
5419 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5422 // Sever accepts the preemptive authorization
5423 MockRead data_reads1[] = {
5424 MockRead("HTTP/1.0 200 OK\r\n"),
5425 MockRead("Content-Length: 100\r\n\r\n"),
5426 MockRead(SYNCHRONOUS, OK),
5429 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5430 data_writes1, arraysize(data_writes1));
5431 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5433 TestCompletionCallback callback1;
5435 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5436 EXPECT_EQ(ERR_IO_PENDING, rv);
5438 rv = callback1.WaitForResult();
5439 EXPECT_EQ(OK, rv);
5441 const HttpResponseInfo* response = trans->GetResponseInfo();
5442 ASSERT_TRUE(response != NULL);
5444 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5445 EXPECT_EQ(100, response->headers->GetContentLength());
5448 // ------------------------------------------------------------------------
5450 // Transaction 4: request another URL in MyRealm (however the
5451 // url is not known to belong to the protection space, so no pre-auth).
5453 HttpRequestInfo request;
5454 request.method = "GET";
5455 request.url = GURL("http://www.google.com/x/1");
5456 request.load_flags = 0;
5458 scoped_ptr<HttpTransaction> trans(
5459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5461 MockWrite data_writes1[] = {
5462 MockWrite("GET /x/1 HTTP/1.1\r\n"
5463 "Host: www.google.com\r\n"
5464 "Connection: keep-alive\r\n\r\n"),
5467 MockRead data_reads1[] = {
5468 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5469 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5470 MockRead("Content-Length: 10000\r\n\r\n"),
5471 MockRead(SYNCHRONOUS, ERR_FAILED),
5474 // Resend with authorization from MyRealm's cache.
5475 MockWrite data_writes2[] = {
5476 MockWrite("GET /x/1 HTTP/1.1\r\n"
5477 "Host: www.google.com\r\n"
5478 "Connection: keep-alive\r\n"
5479 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5482 // Sever accepts the authorization.
5483 MockRead data_reads2[] = {
5484 MockRead("HTTP/1.0 200 OK\r\n"),
5485 MockRead("Content-Length: 100\r\n\r\n"),
5486 MockRead(SYNCHRONOUS, OK),
5489 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5490 data_writes1, arraysize(data_writes1));
5491 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5492 data_writes2, arraysize(data_writes2));
5493 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5494 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5496 TestCompletionCallback callback1;
5498 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5499 EXPECT_EQ(ERR_IO_PENDING, rv);
5501 rv = callback1.WaitForResult();
5502 EXPECT_EQ(OK, rv);
5504 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5505 TestCompletionCallback callback2;
5506 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5507 EXPECT_EQ(ERR_IO_PENDING, rv);
5508 rv = callback2.WaitForResult();
5509 EXPECT_EQ(OK, rv);
5510 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5512 const HttpResponseInfo* response = trans->GetResponseInfo();
5513 ASSERT_TRUE(response != NULL);
5514 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5515 EXPECT_EQ(100, response->headers->GetContentLength());
5518 // ------------------------------------------------------------------------
5520 // Transaction 5: request a URL in MyRealm, but the server rejects the
5521 // cached identity. Should invalidate and re-prompt.
5523 HttpRequestInfo request;
5524 request.method = "GET";
5525 request.url = GURL("http://www.google.com/p/q/t");
5526 request.load_flags = 0;
5528 scoped_ptr<HttpTransaction> trans(
5529 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5531 MockWrite data_writes1[] = {
5532 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5533 "Host: www.google.com\r\n"
5534 "Connection: keep-alive\r\n\r\n"),
5537 MockRead data_reads1[] = {
5538 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5539 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5540 MockRead("Content-Length: 10000\r\n\r\n"),
5541 MockRead(SYNCHRONOUS, ERR_FAILED),
5544 // Resend with authorization from cache for MyRealm.
5545 MockWrite data_writes2[] = {
5546 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5547 "Host: www.google.com\r\n"
5548 "Connection: keep-alive\r\n"
5549 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5552 // Sever rejects the authorization.
5553 MockRead data_reads2[] = {
5554 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5555 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5556 MockRead("Content-Length: 10000\r\n\r\n"),
5557 MockRead(SYNCHRONOUS, ERR_FAILED),
5560 // At this point we should prompt for new credentials for MyRealm.
5561 // Restart with username=foo3, password=foo4.
5562 MockWrite data_writes3[] = {
5563 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5564 "Host: www.google.com\r\n"
5565 "Connection: keep-alive\r\n"
5566 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5569 // Sever accepts the authorization.
5570 MockRead data_reads3[] = {
5571 MockRead("HTTP/1.0 200 OK\r\n"),
5572 MockRead("Content-Length: 100\r\n\r\n"),
5573 MockRead(SYNCHRONOUS, OK),
5576 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5577 data_writes1, arraysize(data_writes1));
5578 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5579 data_writes2, arraysize(data_writes2));
5580 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5581 data_writes3, arraysize(data_writes3));
5582 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5583 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5584 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5586 TestCompletionCallback callback1;
5588 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5589 EXPECT_EQ(ERR_IO_PENDING, rv);
5591 rv = callback1.WaitForResult();
5592 EXPECT_EQ(OK, rv);
5594 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5595 TestCompletionCallback callback2;
5596 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5597 EXPECT_EQ(ERR_IO_PENDING, rv);
5598 rv = callback2.WaitForResult();
5599 EXPECT_EQ(OK, rv);
5600 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5602 const HttpResponseInfo* response = trans->GetResponseInfo();
5603 ASSERT_TRUE(response != NULL);
5604 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5606 TestCompletionCallback callback3;
5608 rv = trans->RestartWithAuth(
5609 AuthCredentials(kFoo3, kBar3), callback3.callback());
5610 EXPECT_EQ(ERR_IO_PENDING, rv);
5612 rv = callback3.WaitForResult();
5613 EXPECT_EQ(OK, rv);
5615 response = trans->GetResponseInfo();
5616 ASSERT_TRUE(response != NULL);
5617 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5618 EXPECT_EQ(100, response->headers->GetContentLength());
5622 // Tests that nonce count increments when multiple auth attempts
5623 // are started with the same nonce.
5624 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5625 HttpAuthHandlerDigest::Factory* digest_factory =
5626 new HttpAuthHandlerDigest::Factory();
5627 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5628 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5629 digest_factory->set_nonce_generator(nonce_generator);
5630 session_deps_.http_auth_handler_factory.reset(digest_factory);
5631 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5633 // Transaction 1: authenticate (foo, bar) on MyRealm1
5635 HttpRequestInfo request;
5636 request.method = "GET";
5637 request.url = GURL("http://www.google.com/x/y/z");
5638 request.load_flags = 0;
5640 scoped_ptr<HttpTransaction> trans(
5641 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5643 MockWrite data_writes1[] = {
5644 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5645 "Host: www.google.com\r\n"
5646 "Connection: keep-alive\r\n\r\n"),
5649 MockRead data_reads1[] = {
5650 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5651 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5652 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5653 MockRead(SYNCHRONOUS, OK),
5656 // Resend with authorization (username=foo, password=bar)
5657 MockWrite data_writes2[] = {
5658 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5659 "Host: www.google.com\r\n"
5660 "Connection: keep-alive\r\n"
5661 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5662 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5663 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5664 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5667 // Sever accepts the authorization.
5668 MockRead data_reads2[] = {
5669 MockRead("HTTP/1.0 200 OK\r\n"),
5670 MockRead(SYNCHRONOUS, OK),
5673 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5674 data_writes1, arraysize(data_writes1));
5675 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5676 data_writes2, arraysize(data_writes2));
5677 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5678 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5680 TestCompletionCallback callback1;
5682 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5683 EXPECT_EQ(ERR_IO_PENDING, rv);
5685 rv = callback1.WaitForResult();
5686 EXPECT_EQ(OK, rv);
5688 const HttpResponseInfo* response = trans->GetResponseInfo();
5689 ASSERT_TRUE(response != NULL);
5690 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5692 TestCompletionCallback callback2;
5694 rv = trans->RestartWithAuth(
5695 AuthCredentials(kFoo, kBar), callback2.callback());
5696 EXPECT_EQ(ERR_IO_PENDING, rv);
5698 rv = callback2.WaitForResult();
5699 EXPECT_EQ(OK, rv);
5701 response = trans->GetResponseInfo();
5702 ASSERT_TRUE(response != NULL);
5703 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5706 // ------------------------------------------------------------------------
5708 // Transaction 2: Request another resource in digestive's protection space.
5709 // This will preemptively add an Authorization header which should have an
5710 // "nc" value of 2 (as compared to 1 in the first use.
5712 HttpRequestInfo request;
5713 request.method = "GET";
5714 // Note that Transaction 1 was at /x/y/z, so this is in the same
5715 // protection space as digest.
5716 request.url = GURL("http://www.google.com/x/y/a/b");
5717 request.load_flags = 0;
5719 scoped_ptr<HttpTransaction> trans(
5720 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5722 MockWrite data_writes1[] = {
5723 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5724 "Host: www.google.com\r\n"
5725 "Connection: keep-alive\r\n"
5726 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5727 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5728 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5729 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5732 // Sever accepts the authorization.
5733 MockRead data_reads1[] = {
5734 MockRead("HTTP/1.0 200 OK\r\n"),
5735 MockRead("Content-Length: 100\r\n\r\n"),
5736 MockRead(SYNCHRONOUS, OK),
5739 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5740 data_writes1, arraysize(data_writes1));
5741 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5743 TestCompletionCallback callback1;
5745 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5746 EXPECT_EQ(ERR_IO_PENDING, rv);
5748 rv = callback1.WaitForResult();
5749 EXPECT_EQ(OK, rv);
5751 const HttpResponseInfo* response = trans->GetResponseInfo();
5752 ASSERT_TRUE(response != NULL);
5753 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5757 // Test the ResetStateForRestart() private method.
5758 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5759 // Create a transaction (the dependencies aren't important).
5760 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5761 scoped_ptr<HttpNetworkTransaction> trans(
5762 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5764 // Setup some state (which we expect ResetStateForRestart() will clear).
5765 trans->read_buf_ = new IOBuffer(15);
5766 trans->read_buf_len_ = 15;
5767 trans->request_headers_.SetHeader("Authorization", "NTLM");
5769 // Setup state in response_
5770 HttpResponseInfo* response = &trans->response_;
5771 response->auth_challenge = new AuthChallengeInfo();
5772 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
5773 response->response_time = base::Time::Now();
5774 response->was_cached = true; // (Wouldn't ever actually be true...)
5776 { // Setup state for response_.vary_data
5777 HttpRequestInfo request;
5778 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5779 std::replace(temp.begin(), temp.end(), '\n', '\0');
5780 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5781 request.extra_headers.SetHeader("Foo", "1");
5782 request.extra_headers.SetHeader("bar", "23");
5783 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5786 // Cause the above state to be reset.
5787 trans->ResetStateForRestart();
5789 // Verify that the state that needed to be reset, has been reset.
5790 EXPECT_TRUE(trans->read_buf_.get() == NULL);
5791 EXPECT_EQ(0, trans->read_buf_len_);
5792 EXPECT_TRUE(trans->request_headers_.IsEmpty());
5793 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5794 EXPECT_TRUE(response->headers.get() == NULL);
5795 EXPECT_FALSE(response->was_cached);
5796 EXPECT_EQ(0U, response->ssl_info.cert_status);
5797 EXPECT_FALSE(response->vary_data.is_valid());
5800 // Test HTTPS connections to a site with a bad certificate
5801 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5802 HttpRequestInfo request;
5803 request.method = "GET";
5804 request.url = GURL("https://www.google.com/");
5805 request.load_flags = 0;
5807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5808 scoped_ptr<HttpTransaction> trans(
5809 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5811 MockWrite data_writes[] = {
5812 MockWrite("GET / HTTP/1.1\r\n"
5813 "Host: www.google.com\r\n"
5814 "Connection: keep-alive\r\n\r\n"),
5817 MockRead data_reads[] = {
5818 MockRead("HTTP/1.0 200 OK\r\n"),
5819 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5820 MockRead("Content-Length: 100\r\n\r\n"),
5821 MockRead(SYNCHRONOUS, OK),
5824 StaticSocketDataProvider ssl_bad_certificate;
5825 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5826 data_writes, arraysize(data_writes));
5827 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5828 SSLSocketDataProvider ssl(ASYNC, OK);
5830 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5831 session_deps_.socket_factory->AddSocketDataProvider(&data);
5832 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5833 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5835 TestCompletionCallback callback;
5837 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5838 EXPECT_EQ(ERR_IO_PENDING, rv);
5840 rv = callback.WaitForResult();
5841 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5843 rv = trans->RestartIgnoringLastError(callback.callback());
5844 EXPECT_EQ(ERR_IO_PENDING, rv);
5846 rv = callback.WaitForResult();
5847 EXPECT_EQ(OK, rv);
5849 const HttpResponseInfo* response = trans->GetResponseInfo();
5851 ASSERT_TRUE(response != NULL);
5852 EXPECT_EQ(100, response->headers->GetContentLength());
5855 // Test HTTPS connections to a site with a bad certificate, going through a
5856 // proxy
5857 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5858 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5860 HttpRequestInfo request;
5861 request.method = "GET";
5862 request.url = GURL("https://www.google.com/");
5863 request.load_flags = 0;
5865 MockWrite proxy_writes[] = {
5866 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5867 "Host: www.google.com\r\n"
5868 "Proxy-Connection: keep-alive\r\n\r\n"),
5871 MockRead proxy_reads[] = {
5872 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5873 MockRead(SYNCHRONOUS, OK)
5876 MockWrite data_writes[] = {
5877 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5878 "Host: www.google.com\r\n"
5879 "Proxy-Connection: keep-alive\r\n\r\n"),
5880 MockWrite("GET / HTTP/1.1\r\n"
5881 "Host: www.google.com\r\n"
5882 "Connection: keep-alive\r\n\r\n"),
5885 MockRead data_reads[] = {
5886 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5887 MockRead("HTTP/1.0 200 OK\r\n"),
5888 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5889 MockRead("Content-Length: 100\r\n\r\n"),
5890 MockRead(SYNCHRONOUS, OK),
5893 StaticSocketDataProvider ssl_bad_certificate(
5894 proxy_reads, arraysize(proxy_reads),
5895 proxy_writes, arraysize(proxy_writes));
5896 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5897 data_writes, arraysize(data_writes));
5898 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5899 SSLSocketDataProvider ssl(ASYNC, OK);
5901 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5902 session_deps_.socket_factory->AddSocketDataProvider(&data);
5903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5904 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5906 TestCompletionCallback callback;
5908 for (int i = 0; i < 2; i++) {
5909 session_deps_.socket_factory->ResetNextMockIndexes();
5911 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5912 scoped_ptr<HttpTransaction> trans(
5913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5915 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5916 EXPECT_EQ(ERR_IO_PENDING, rv);
5918 rv = callback.WaitForResult();
5919 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5921 rv = trans->RestartIgnoringLastError(callback.callback());
5922 EXPECT_EQ(ERR_IO_PENDING, rv);
5924 rv = callback.WaitForResult();
5925 EXPECT_EQ(OK, rv);
5927 const HttpResponseInfo* response = trans->GetResponseInfo();
5929 ASSERT_TRUE(response != NULL);
5930 EXPECT_EQ(100, response->headers->GetContentLength());
5935 // Test HTTPS connections to a site, going through an HTTPS proxy
5936 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
5937 session_deps_.proxy_service.reset(
5938 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5939 CapturingNetLog net_log;
5940 session_deps_.net_log = &net_log;
5942 HttpRequestInfo request;
5943 request.method = "GET";
5944 request.url = GURL("https://www.google.com/");
5945 request.load_flags = 0;
5947 MockWrite data_writes[] = {
5948 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5949 "Host: www.google.com\r\n"
5950 "Proxy-Connection: keep-alive\r\n\r\n"),
5951 MockWrite("GET / HTTP/1.1\r\n"
5952 "Host: www.google.com\r\n"
5953 "Connection: keep-alive\r\n\r\n"),
5956 MockRead data_reads[] = {
5957 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5958 MockRead("HTTP/1.1 200 OK\r\n"),
5959 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5960 MockRead("Content-Length: 100\r\n\r\n"),
5961 MockRead(SYNCHRONOUS, OK),
5964 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5965 data_writes, arraysize(data_writes));
5966 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5967 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
5969 session_deps_.socket_factory->AddSocketDataProvider(&data);
5970 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5971 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
5973 TestCompletionCallback callback;
5975 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5976 scoped_ptr<HttpTransaction> trans(
5977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5979 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5980 EXPECT_EQ(ERR_IO_PENDING, rv);
5982 rv = callback.WaitForResult();
5983 EXPECT_EQ(OK, rv);
5984 const HttpResponseInfo* response = trans->GetResponseInfo();
5986 ASSERT_TRUE(response != NULL);
5988 EXPECT_TRUE(response->headers->IsKeepAlive());
5989 EXPECT_EQ(200, response->headers->response_code());
5990 EXPECT_EQ(100, response->headers->GetContentLength());
5991 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5993 LoadTimingInfo load_timing_info;
5994 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5995 TestLoadTimingNotReusedWithPac(load_timing_info,
5996 CONNECT_TIMING_HAS_SSL_TIMES);
5999 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6000 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6001 session_deps_.proxy_service.reset(
6002 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6003 CapturingNetLog net_log;
6004 session_deps_.net_log = &net_log;
6006 HttpRequestInfo request;
6007 request.method = "GET";
6008 request.url = GURL("https://www.google.com/");
6009 request.load_flags = 0;
6011 MockWrite data_writes[] = {
6012 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6013 "Host: www.google.com\r\n"
6014 "Proxy-Connection: keep-alive\r\n\r\n"),
6017 MockRead data_reads[] = {
6018 MockRead("HTTP/1.1 302 Redirect\r\n"),
6019 MockRead("Location: http://login.example.com/\r\n"),
6020 MockRead("Content-Length: 0\r\n\r\n"),
6021 MockRead(SYNCHRONOUS, OK),
6024 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6025 data_writes, arraysize(data_writes));
6026 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6028 session_deps_.socket_factory->AddSocketDataProvider(&data);
6029 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6031 TestCompletionCallback callback;
6033 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6034 scoped_ptr<HttpTransaction> trans(
6035 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6037 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6038 EXPECT_EQ(ERR_IO_PENDING, rv);
6040 rv = callback.WaitForResult();
6041 EXPECT_EQ(OK, rv);
6042 const HttpResponseInfo* response = trans->GetResponseInfo();
6044 ASSERT_TRUE(response != NULL);
6046 EXPECT_EQ(302, response->headers->response_code());
6047 std::string url;
6048 EXPECT_TRUE(response->headers->IsRedirect(&url));
6049 EXPECT_EQ("http://login.example.com/", url);
6051 // In the case of redirects from proxies, HttpNetworkTransaction returns
6052 // timing for the proxy connection instead of the connection to the host,
6053 // and no send / receive times.
6054 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6055 LoadTimingInfo load_timing_info;
6056 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6058 EXPECT_FALSE(load_timing_info.socket_reused);
6059 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6061 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6062 EXPECT_LE(load_timing_info.proxy_resolve_start,
6063 load_timing_info.proxy_resolve_end);
6064 EXPECT_LE(load_timing_info.proxy_resolve_end,
6065 load_timing_info.connect_timing.connect_start);
6066 ExpectConnectTimingHasTimes(
6067 load_timing_info.connect_timing,
6068 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6070 EXPECT_TRUE(load_timing_info.send_start.is_null());
6071 EXPECT_TRUE(load_timing_info.send_end.is_null());
6072 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6075 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6076 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6077 session_deps_.proxy_service.reset(
6078 ProxyService::CreateFixed("https://proxy:70"));
6080 HttpRequestInfo request;
6081 request.method = "GET";
6082 request.url = GURL("https://www.google.com/");
6083 request.load_flags = 0;
6085 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6086 LOWEST));
6087 scoped_ptr<SpdyFrame> goaway(
6088 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6089 MockWrite data_writes[] = {
6090 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6091 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
6094 static const char* const kExtraHeaders[] = {
6095 "location",
6096 "http://login.example.com/",
6098 scoped_ptr<SpdyFrame> resp(
6099 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6100 arraysize(kExtraHeaders)/2, 1));
6101 MockRead data_reads[] = {
6102 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6103 MockRead(ASYNC, 0, 2), // EOF
6106 DelayedSocketData data(
6107 1, // wait for one write to finish before reading.
6108 data_reads, arraysize(data_reads),
6109 data_writes, arraysize(data_writes));
6110 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6111 proxy_ssl.SetNextProto(GetParam());
6113 session_deps_.socket_factory->AddSocketDataProvider(&data);
6114 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6116 TestCompletionCallback callback;
6118 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6119 scoped_ptr<HttpTransaction> trans(
6120 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6122 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6123 EXPECT_EQ(ERR_IO_PENDING, rv);
6125 rv = callback.WaitForResult();
6126 EXPECT_EQ(OK, rv);
6127 const HttpResponseInfo* response = trans->GetResponseInfo();
6129 ASSERT_TRUE(response != NULL);
6131 EXPECT_EQ(302, response->headers->response_code());
6132 std::string url;
6133 EXPECT_TRUE(response->headers->IsRedirect(&url));
6134 EXPECT_EQ("http://login.example.com/", url);
6137 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6138 TEST_P(HttpNetworkTransactionTest,
6139 ErrorResponseToHttpsConnectViaHttpsProxy) {
6140 session_deps_.proxy_service.reset(
6141 ProxyService::CreateFixed("https://proxy:70"));
6143 HttpRequestInfo request;
6144 request.method = "GET";
6145 request.url = GURL("https://www.google.com/");
6146 request.load_flags = 0;
6148 MockWrite data_writes[] = {
6149 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6150 "Host: www.google.com\r\n"
6151 "Proxy-Connection: keep-alive\r\n\r\n"),
6154 MockRead data_reads[] = {
6155 MockRead("HTTP/1.1 404 Not Found\r\n"),
6156 MockRead("Content-Length: 23\r\n\r\n"),
6157 MockRead("The host does not exist"),
6158 MockRead(SYNCHRONOUS, OK),
6161 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6162 data_writes, arraysize(data_writes));
6163 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6165 session_deps_.socket_factory->AddSocketDataProvider(&data);
6166 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6168 TestCompletionCallback callback;
6170 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6171 scoped_ptr<HttpTransaction> trans(
6172 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6174 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6175 EXPECT_EQ(ERR_IO_PENDING, rv);
6177 rv = callback.WaitForResult();
6178 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6180 // TODO(ttuttle): Anything else to check here?
6183 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6184 TEST_P(HttpNetworkTransactionTest,
6185 ErrorResponseToHttpsConnectViaSpdyProxy) {
6186 session_deps_.proxy_service.reset(
6187 ProxyService::CreateFixed("https://proxy:70"));
6189 HttpRequestInfo request;
6190 request.method = "GET";
6191 request.url = GURL("https://www.google.com/");
6192 request.load_flags = 0;
6194 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6195 LOWEST));
6196 scoped_ptr<SpdyFrame> rst(
6197 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6198 MockWrite data_writes[] = {
6199 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6200 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6203 static const char* const kExtraHeaders[] = {
6204 "location",
6205 "http://login.example.com/",
6207 scoped_ptr<SpdyFrame> resp(
6208 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6209 arraysize(kExtraHeaders)/2, 1));
6210 scoped_ptr<SpdyFrame> body(
6211 spdy_util_.ConstructSpdyBodyFrame(
6212 1, "The host does not exist", 23, true));
6213 MockRead data_reads[] = {
6214 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6215 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6216 MockRead(ASYNC, 0, 4), // EOF
6219 DelayedSocketData data(
6220 1, // wait for one write to finish before reading.
6221 data_reads, arraysize(data_reads),
6222 data_writes, arraysize(data_writes));
6223 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6224 proxy_ssl.SetNextProto(GetParam());
6226 session_deps_.socket_factory->AddSocketDataProvider(&data);
6227 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6229 TestCompletionCallback callback;
6231 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6232 scoped_ptr<HttpTransaction> trans(
6233 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6235 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6236 EXPECT_EQ(ERR_IO_PENDING, rv);
6238 rv = callback.WaitForResult();
6239 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6241 // TODO(ttuttle): Anything else to check here?
6244 // Test the request-challenge-retry sequence for basic auth, through
6245 // a SPDY proxy over a single SPDY session.
6246 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6247 HttpRequestInfo request;
6248 request.method = "GET";
6249 request.url = GURL("https://www.google.com/");
6250 // when the no authentication data flag is set.
6251 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
6253 // Configure against https proxy server "myproxy:70".
6254 session_deps_.proxy_service.reset(
6255 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6256 CapturingBoundNetLog log;
6257 session_deps_.net_log = log.bound().net_log();
6258 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6260 // Since we have proxy, should try to establish tunnel.
6261 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6262 LOWEST));
6263 scoped_ptr<SpdyFrame> rst(
6264 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6266 // After calling trans->RestartWithAuth(), this is the request we should
6267 // be issuing -- the final header line contains the credentials.
6268 const char* const kAuthCredentials[] = {
6269 "proxy-authorization", "Basic Zm9vOmJhcg==",
6271 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6272 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
6273 // fetch https://www.google.com/ via HTTP
6274 const char get[] = "GET / HTTP/1.1\r\n"
6275 "Host: www.google.com\r\n"
6276 "Connection: keep-alive\r\n\r\n";
6277 scoped_ptr<SpdyFrame> wrapped_get(
6278 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6280 MockWrite spdy_writes[] = {
6281 CreateMockWrite(*req, 1, ASYNC),
6282 CreateMockWrite(*rst, 4, ASYNC),
6283 CreateMockWrite(*connect2, 5),
6284 CreateMockWrite(*wrapped_get, 8),
6287 // The proxy responds to the connect with a 407, using a persistent
6288 // connection.
6289 const char* const kAuthChallenge[] = {
6290 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
6291 spdy_util_.GetVersionKey(), "HTTP/1.1",
6292 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6295 scoped_ptr<SpdyFrame> conn_auth_resp(
6296 spdy_util_.ConstructSpdyControlFrame(NULL,
6298 false,
6300 LOWEST,
6301 SYN_REPLY,
6302 CONTROL_FLAG_NONE,
6303 kAuthChallenge,
6304 arraysize(kAuthChallenge),
6305 0));
6307 scoped_ptr<SpdyFrame> conn_resp(
6308 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6309 const char resp[] = "HTTP/1.1 200 OK\r\n"
6310 "Content-Length: 5\r\n\r\n";
6312 scoped_ptr<SpdyFrame> wrapped_get_resp(
6313 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6314 scoped_ptr<SpdyFrame> wrapped_body(
6315 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6316 MockRead spdy_reads[] = {
6317 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6318 CreateMockRead(*conn_resp, 6, ASYNC),
6319 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6320 CreateMockRead(*wrapped_body, 10, ASYNC),
6321 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6324 OrderedSocketData spdy_data(
6325 spdy_reads, arraysize(spdy_reads),
6326 spdy_writes, arraysize(spdy_writes));
6327 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6328 // Negotiate SPDY to the proxy
6329 SSLSocketDataProvider proxy(ASYNC, OK);
6330 proxy.SetNextProto(GetParam());
6331 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6332 // Vanilla SSL to the server
6333 SSLSocketDataProvider server(ASYNC, OK);
6334 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6336 TestCompletionCallback callback1;
6338 scoped_ptr<HttpTransaction> trans(
6339 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6341 int rv = trans->Start(&request, callback1.callback(), log.bound());
6342 EXPECT_EQ(ERR_IO_PENDING, rv);
6344 rv = callback1.WaitForResult();
6345 EXPECT_EQ(OK, rv);
6346 net::CapturingNetLog::CapturedEntryList entries;
6347 log.GetEntries(&entries);
6348 size_t pos = ExpectLogContainsSomewhere(
6349 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6350 NetLog::PHASE_NONE);
6351 ExpectLogContainsSomewhere(
6352 entries, pos,
6353 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6354 NetLog::PHASE_NONE);
6356 const HttpResponseInfo* response = trans->GetResponseInfo();
6357 ASSERT_TRUE(response != NULL);
6358 ASSERT_FALSE(response->headers.get() == NULL);
6359 EXPECT_EQ(407, response->headers->response_code());
6360 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6361 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6362 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6364 TestCompletionCallback callback2;
6366 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6367 callback2.callback());
6368 EXPECT_EQ(ERR_IO_PENDING, rv);
6370 rv = callback2.WaitForResult();
6371 EXPECT_EQ(OK, rv);
6373 response = trans->GetResponseInfo();
6374 ASSERT_TRUE(response != NULL);
6376 EXPECT_TRUE(response->headers->IsKeepAlive());
6377 EXPECT_EQ(200, response->headers->response_code());
6378 EXPECT_EQ(5, response->headers->GetContentLength());
6379 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6381 // The password prompt info should not be set.
6382 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6384 LoadTimingInfo load_timing_info;
6385 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6386 TestLoadTimingNotReusedWithPac(load_timing_info,
6387 CONNECT_TIMING_HAS_SSL_TIMES);
6389 trans.reset();
6390 session->CloseAllConnections();
6393 // Test that an explicitly trusted SPDY proxy can push a resource from an
6394 // origin that is different from that of its associated resource.
6395 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6396 HttpRequestInfo request;
6397 HttpRequestInfo push_request;
6399 request.method = "GET";
6400 request.url = GURL("http://www.google.com/");
6401 push_request.method = "GET";
6402 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6404 // Configure against https proxy server "myproxy:70".
6405 session_deps_.proxy_service.reset(
6406 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6407 CapturingBoundNetLog log;
6408 session_deps_.net_log = log.bound().net_log();
6410 // Enable cross-origin push.
6411 session_deps_.trusted_spdy_proxy = "myproxy:70";
6413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6415 scoped_ptr<SpdyFrame> stream1_syn(
6416 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6418 MockWrite spdy_writes[] = {
6419 CreateMockWrite(*stream1_syn, 1, ASYNC),
6422 scoped_ptr<SpdyFrame>
6423 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6425 scoped_ptr<SpdyFrame>
6426 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6428 scoped_ptr<SpdyFrame>
6429 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6433 "http://www.another-origin.com/foo.dat"));
6434 const char kPushedData[] = "pushed";
6435 scoped_ptr<SpdyFrame> stream2_body(
6436 spdy_util_.ConstructSpdyBodyFrame(
6437 2, kPushedData, strlen(kPushedData), true));
6439 MockRead spdy_reads[] = {
6440 CreateMockRead(*stream1_reply, 2, ASYNC),
6441 CreateMockRead(*stream2_syn, 3, ASYNC),
6442 CreateMockRead(*stream1_body, 4, ASYNC),
6443 CreateMockRead(*stream2_body, 5, ASYNC),
6444 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6447 OrderedSocketData spdy_data(
6448 spdy_reads, arraysize(spdy_reads),
6449 spdy_writes, arraysize(spdy_writes));
6450 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6451 // Negotiate SPDY to the proxy
6452 SSLSocketDataProvider proxy(ASYNC, OK);
6453 proxy.SetNextProto(GetParam());
6454 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6456 scoped_ptr<HttpTransaction> trans(
6457 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6458 TestCompletionCallback callback;
6459 int rv = trans->Start(&request, callback.callback(), log.bound());
6460 EXPECT_EQ(ERR_IO_PENDING, rv);
6462 rv = callback.WaitForResult();
6463 EXPECT_EQ(OK, rv);
6464 const HttpResponseInfo* response = trans->GetResponseInfo();
6466 scoped_ptr<HttpTransaction> push_trans(
6467 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6468 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6469 EXPECT_EQ(ERR_IO_PENDING, rv);
6471 rv = callback.WaitForResult();
6472 EXPECT_EQ(OK, rv);
6473 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6475 ASSERT_TRUE(response != NULL);
6476 EXPECT_TRUE(response->headers->IsKeepAlive());
6478 EXPECT_EQ(200, response->headers->response_code());
6479 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6481 std::string response_data;
6482 rv = ReadTransaction(trans.get(), &response_data);
6483 EXPECT_EQ(OK, rv);
6484 EXPECT_EQ("hello!", response_data);
6486 LoadTimingInfo load_timing_info;
6487 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6488 TestLoadTimingNotReusedWithPac(load_timing_info,
6489 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6491 // Verify the pushed stream.
6492 EXPECT_TRUE(push_response->headers.get() != NULL);
6493 EXPECT_EQ(200, push_response->headers->response_code());
6495 rv = ReadTransaction(push_trans.get(), &response_data);
6496 EXPECT_EQ(OK, rv);
6497 EXPECT_EQ("pushed", response_data);
6499 LoadTimingInfo push_load_timing_info;
6500 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6501 TestLoadTimingReusedWithPac(push_load_timing_info);
6502 // The transactions should share a socket ID, despite being for different
6503 // origins.
6504 EXPECT_EQ(load_timing_info.socket_log_id,
6505 push_load_timing_info.socket_log_id);
6507 trans.reset();
6508 push_trans.reset();
6509 session->CloseAllConnections();
6512 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6513 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6514 HttpRequestInfo request;
6516 request.method = "GET";
6517 request.url = GURL("http://www.google.com/");
6519 // Configure against https proxy server "myproxy:70".
6520 session_deps_.proxy_service.reset(
6521 ProxyService::CreateFixed("https://myproxy:70"));
6522 CapturingBoundNetLog log;
6523 session_deps_.net_log = log.bound().net_log();
6525 // Enable cross-origin push.
6526 session_deps_.trusted_spdy_proxy = "myproxy:70";
6528 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6530 scoped_ptr<SpdyFrame> stream1_syn(
6531 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6533 scoped_ptr<SpdyFrame> push_rst(
6534 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6536 MockWrite spdy_writes[] = {
6537 CreateMockWrite(*stream1_syn, 1, ASYNC),
6538 CreateMockWrite(*push_rst, 4),
6541 scoped_ptr<SpdyFrame>
6542 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6544 scoped_ptr<SpdyFrame>
6545 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6547 scoped_ptr<SpdyFrame>
6548 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6552 "https://www.another-origin.com/foo.dat"));
6554 MockRead spdy_reads[] = {
6555 CreateMockRead(*stream1_reply, 2, ASYNC),
6556 CreateMockRead(*stream2_syn, 3, ASYNC),
6557 CreateMockRead(*stream1_body, 5, ASYNC),
6558 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6561 OrderedSocketData spdy_data(
6562 spdy_reads, arraysize(spdy_reads),
6563 spdy_writes, arraysize(spdy_writes));
6564 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6565 // Negotiate SPDY to the proxy
6566 SSLSocketDataProvider proxy(ASYNC, OK);
6567 proxy.SetNextProto(GetParam());
6568 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6570 scoped_ptr<HttpTransaction> trans(
6571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6572 TestCompletionCallback callback;
6573 int rv = trans->Start(&request, callback.callback(), log.bound());
6574 EXPECT_EQ(ERR_IO_PENDING, rv);
6576 rv = callback.WaitForResult();
6577 EXPECT_EQ(OK, rv);
6578 const HttpResponseInfo* response = trans->GetResponseInfo();
6580 ASSERT_TRUE(response != NULL);
6581 EXPECT_TRUE(response->headers->IsKeepAlive());
6583 EXPECT_EQ(200, response->headers->response_code());
6584 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6586 std::string response_data;
6587 rv = ReadTransaction(trans.get(), &response_data);
6588 EXPECT_EQ(OK, rv);
6589 EXPECT_EQ("hello!", response_data);
6591 trans.reset();
6592 session->CloseAllConnections();
6595 // Test HTTPS connections to a site with a bad certificate, going through an
6596 // HTTPS proxy
6597 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6598 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6599 "https://proxy:70"));
6601 HttpRequestInfo request;
6602 request.method = "GET";
6603 request.url = GURL("https://www.google.com/");
6604 request.load_flags = 0;
6606 // Attempt to fetch the URL from a server with a bad cert
6607 MockWrite bad_cert_writes[] = {
6608 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6609 "Host: www.google.com\r\n"
6610 "Proxy-Connection: keep-alive\r\n\r\n"),
6613 MockRead bad_cert_reads[] = {
6614 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6615 MockRead(SYNCHRONOUS, OK)
6618 // Attempt to fetch the URL with a good cert
6619 MockWrite good_data_writes[] = {
6620 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6621 "Host: www.google.com\r\n"
6622 "Proxy-Connection: keep-alive\r\n\r\n"),
6623 MockWrite("GET / HTTP/1.1\r\n"
6624 "Host: www.google.com\r\n"
6625 "Connection: keep-alive\r\n\r\n"),
6628 MockRead good_cert_reads[] = {
6629 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6630 MockRead("HTTP/1.0 200 OK\r\n"),
6631 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6632 MockRead("Content-Length: 100\r\n\r\n"),
6633 MockRead(SYNCHRONOUS, OK),
6636 StaticSocketDataProvider ssl_bad_certificate(
6637 bad_cert_reads, arraysize(bad_cert_reads),
6638 bad_cert_writes, arraysize(bad_cert_writes));
6639 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6640 good_data_writes, arraysize(good_data_writes));
6641 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6642 SSLSocketDataProvider ssl(ASYNC, OK);
6644 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6645 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6646 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6647 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6649 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6650 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6651 session_deps_.socket_factory->AddSocketDataProvider(&data);
6652 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6654 TestCompletionCallback callback;
6656 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6657 scoped_ptr<HttpTransaction> trans(
6658 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6660 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6661 EXPECT_EQ(ERR_IO_PENDING, rv);
6663 rv = callback.WaitForResult();
6664 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6666 rv = trans->RestartIgnoringLastError(callback.callback());
6667 EXPECT_EQ(ERR_IO_PENDING, rv);
6669 rv = callback.WaitForResult();
6670 EXPECT_EQ(OK, rv);
6672 const HttpResponseInfo* response = trans->GetResponseInfo();
6674 ASSERT_TRUE(response != NULL);
6675 EXPECT_EQ(100, response->headers->GetContentLength());
6678 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6679 HttpRequestInfo request;
6680 request.method = "GET";
6681 request.url = GURL("http://www.google.com/");
6682 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6683 "Chromium Ultra Awesome X Edition");
6685 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6686 scoped_ptr<HttpTransaction> trans(
6687 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6689 MockWrite data_writes[] = {
6690 MockWrite("GET / HTTP/1.1\r\n"
6691 "Host: www.google.com\r\n"
6692 "Connection: keep-alive\r\n"
6693 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6696 // Lastly, the server responds with the actual content.
6697 MockRead data_reads[] = {
6698 MockRead("HTTP/1.0 200 OK\r\n"),
6699 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6700 MockRead("Content-Length: 100\r\n\r\n"),
6701 MockRead(SYNCHRONOUS, OK),
6704 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6705 data_writes, arraysize(data_writes));
6706 session_deps_.socket_factory->AddSocketDataProvider(&data);
6708 TestCompletionCallback callback;
6710 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6711 EXPECT_EQ(ERR_IO_PENDING, rv);
6713 rv = callback.WaitForResult();
6714 EXPECT_EQ(OK, rv);
6717 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6718 HttpRequestInfo request;
6719 request.method = "GET";
6720 request.url = GURL("https://www.google.com/");
6721 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6722 "Chromium Ultra Awesome X Edition");
6724 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6725 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6726 scoped_ptr<HttpTransaction> trans(
6727 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6729 MockWrite data_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"
6733 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6735 MockRead data_reads[] = {
6736 // Return an error, so the transaction stops here (this test isn't
6737 // interested in the rest).
6738 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6739 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6740 MockRead("Proxy-Connection: close\r\n\r\n"),
6743 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6744 data_writes, arraysize(data_writes));
6745 session_deps_.socket_factory->AddSocketDataProvider(&data);
6747 TestCompletionCallback callback;
6749 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6750 EXPECT_EQ(ERR_IO_PENDING, rv);
6752 rv = callback.WaitForResult();
6753 EXPECT_EQ(OK, rv);
6756 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6757 HttpRequestInfo request;
6758 request.method = "GET";
6759 request.url = GURL("http://www.google.com/");
6760 request.load_flags = 0;
6761 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6762 "http://the.previous.site.com/");
6764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6765 scoped_ptr<HttpTransaction> trans(
6766 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6768 MockWrite data_writes[] = {
6769 MockWrite("GET / HTTP/1.1\r\n"
6770 "Host: www.google.com\r\n"
6771 "Connection: keep-alive\r\n"
6772 "Referer: http://the.previous.site.com/\r\n\r\n"),
6775 // Lastly, the server responds with the actual content.
6776 MockRead data_reads[] = {
6777 MockRead("HTTP/1.0 200 OK\r\n"),
6778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6779 MockRead("Content-Length: 100\r\n\r\n"),
6780 MockRead(SYNCHRONOUS, OK),
6783 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6784 data_writes, arraysize(data_writes));
6785 session_deps_.socket_factory->AddSocketDataProvider(&data);
6787 TestCompletionCallback callback;
6789 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6790 EXPECT_EQ(ERR_IO_PENDING, rv);
6792 rv = callback.WaitForResult();
6793 EXPECT_EQ(OK, rv);
6796 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6797 HttpRequestInfo request;
6798 request.method = "POST";
6799 request.url = GURL("http://www.google.com/");
6801 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6802 scoped_ptr<HttpTransaction> trans(
6803 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6805 MockWrite data_writes[] = {
6806 MockWrite("POST / HTTP/1.1\r\n"
6807 "Host: www.google.com\r\n"
6808 "Connection: keep-alive\r\n"
6809 "Content-Length: 0\r\n\r\n"),
6812 // Lastly, the server responds with the actual content.
6813 MockRead data_reads[] = {
6814 MockRead("HTTP/1.0 200 OK\r\n"),
6815 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6816 MockRead("Content-Length: 100\r\n\r\n"),
6817 MockRead(SYNCHRONOUS, OK),
6820 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6821 data_writes, arraysize(data_writes));
6822 session_deps_.socket_factory->AddSocketDataProvider(&data);
6824 TestCompletionCallback callback;
6826 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6827 EXPECT_EQ(ERR_IO_PENDING, rv);
6829 rv = callback.WaitForResult();
6830 EXPECT_EQ(OK, rv);
6833 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6834 HttpRequestInfo request;
6835 request.method = "PUT";
6836 request.url = GURL("http://www.google.com/");
6838 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6839 scoped_ptr<HttpTransaction> trans(
6840 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6842 MockWrite data_writes[] = {
6843 MockWrite("PUT / HTTP/1.1\r\n"
6844 "Host: www.google.com\r\n"
6845 "Connection: keep-alive\r\n"
6846 "Content-Length: 0\r\n\r\n"),
6849 // Lastly, the server responds with the actual content.
6850 MockRead data_reads[] = {
6851 MockRead("HTTP/1.0 200 OK\r\n"),
6852 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6853 MockRead("Content-Length: 100\r\n\r\n"),
6854 MockRead(SYNCHRONOUS, OK),
6857 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6858 data_writes, arraysize(data_writes));
6859 session_deps_.socket_factory->AddSocketDataProvider(&data);
6861 TestCompletionCallback callback;
6863 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6864 EXPECT_EQ(ERR_IO_PENDING, rv);
6866 rv = callback.WaitForResult();
6867 EXPECT_EQ(OK, rv);
6870 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6871 HttpRequestInfo request;
6872 request.method = "HEAD";
6873 request.url = GURL("http://www.google.com/");
6875 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6876 scoped_ptr<HttpTransaction> trans(
6877 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6879 MockWrite data_writes[] = {
6880 MockWrite("HEAD / HTTP/1.1\r\n"
6881 "Host: www.google.com\r\n"
6882 "Connection: keep-alive\r\n"
6883 "Content-Length: 0\r\n\r\n"),
6886 // Lastly, the server responds with the actual content.
6887 MockRead data_reads[] = {
6888 MockRead("HTTP/1.0 200 OK\r\n"),
6889 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6890 MockRead("Content-Length: 100\r\n\r\n"),
6891 MockRead(SYNCHRONOUS, OK),
6894 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6895 data_writes, arraysize(data_writes));
6896 session_deps_.socket_factory->AddSocketDataProvider(&data);
6898 TestCompletionCallback callback;
6900 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6901 EXPECT_EQ(ERR_IO_PENDING, rv);
6903 rv = callback.WaitForResult();
6904 EXPECT_EQ(OK, rv);
6907 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
6908 HttpRequestInfo request;
6909 request.method = "GET";
6910 request.url = GURL("http://www.google.com/");
6911 request.load_flags = LOAD_BYPASS_CACHE;
6913 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6914 scoped_ptr<HttpTransaction> trans(
6915 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6917 MockWrite data_writes[] = {
6918 MockWrite("GET / HTTP/1.1\r\n"
6919 "Host: www.google.com\r\n"
6920 "Connection: keep-alive\r\n"
6921 "Pragma: no-cache\r\n"
6922 "Cache-Control: no-cache\r\n\r\n"),
6925 // Lastly, the server responds with the actual content.
6926 MockRead data_reads[] = {
6927 MockRead("HTTP/1.0 200 OK\r\n"),
6928 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6929 MockRead("Content-Length: 100\r\n\r\n"),
6930 MockRead(SYNCHRONOUS, OK),
6933 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6934 data_writes, arraysize(data_writes));
6935 session_deps_.socket_factory->AddSocketDataProvider(&data);
6937 TestCompletionCallback callback;
6939 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6940 EXPECT_EQ(ERR_IO_PENDING, rv);
6942 rv = callback.WaitForResult();
6943 EXPECT_EQ(OK, rv);
6946 TEST_P(HttpNetworkTransactionTest,
6947 BuildRequest_CacheControlValidateCache) {
6948 HttpRequestInfo request;
6949 request.method = "GET";
6950 request.url = GURL("http://www.google.com/");
6951 request.load_flags = LOAD_VALIDATE_CACHE;
6953 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6954 scoped_ptr<HttpTransaction> trans(
6955 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6957 MockWrite data_writes[] = {
6958 MockWrite("GET / HTTP/1.1\r\n"
6959 "Host: www.google.com\r\n"
6960 "Connection: keep-alive\r\n"
6961 "Cache-Control: max-age=0\r\n\r\n"),
6964 // Lastly, the server responds with the actual content.
6965 MockRead data_reads[] = {
6966 MockRead("HTTP/1.0 200 OK\r\n"),
6967 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6968 MockRead("Content-Length: 100\r\n\r\n"),
6969 MockRead(SYNCHRONOUS, OK),
6972 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6973 data_writes, arraysize(data_writes));
6974 session_deps_.socket_factory->AddSocketDataProvider(&data);
6976 TestCompletionCallback callback;
6978 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6979 EXPECT_EQ(ERR_IO_PENDING, rv);
6981 rv = callback.WaitForResult();
6982 EXPECT_EQ(OK, rv);
6985 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
6986 HttpRequestInfo request;
6987 request.method = "GET";
6988 request.url = GURL("http://www.google.com/");
6989 request.extra_headers.SetHeader("FooHeader", "Bar");
6991 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6992 scoped_ptr<HttpTransaction> trans(
6993 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6995 MockWrite data_writes[] = {
6996 MockWrite("GET / HTTP/1.1\r\n"
6997 "Host: www.google.com\r\n"
6998 "Connection: keep-alive\r\n"
6999 "FooHeader: Bar\r\n\r\n"),
7002 // Lastly, the server responds with the actual content.
7003 MockRead data_reads[] = {
7004 MockRead("HTTP/1.0 200 OK\r\n"),
7005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7006 MockRead("Content-Length: 100\r\n\r\n"),
7007 MockRead(SYNCHRONOUS, OK),
7010 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7011 data_writes, arraysize(data_writes));
7012 session_deps_.socket_factory->AddSocketDataProvider(&data);
7014 TestCompletionCallback callback;
7016 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7017 EXPECT_EQ(ERR_IO_PENDING, rv);
7019 rv = callback.WaitForResult();
7020 EXPECT_EQ(OK, rv);
7023 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7024 HttpRequestInfo request;
7025 request.method = "GET";
7026 request.url = GURL("http://www.google.com/");
7027 request.extra_headers.SetHeader("referer", "www.foo.com");
7028 request.extra_headers.SetHeader("hEllo", "Kitty");
7029 request.extra_headers.SetHeader("FoO", "bar");
7031 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7032 scoped_ptr<HttpTransaction> trans(
7033 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7035 MockWrite data_writes[] = {
7036 MockWrite("GET / HTTP/1.1\r\n"
7037 "Host: www.google.com\r\n"
7038 "Connection: keep-alive\r\n"
7039 "referer: www.foo.com\r\n"
7040 "hEllo: Kitty\r\n"
7041 "FoO: bar\r\n\r\n"),
7044 // Lastly, the server responds with the actual content.
7045 MockRead data_reads[] = {
7046 MockRead("HTTP/1.0 200 OK\r\n"),
7047 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7048 MockRead("Content-Length: 100\r\n\r\n"),
7049 MockRead(SYNCHRONOUS, OK),
7052 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7053 data_writes, arraysize(data_writes));
7054 session_deps_.socket_factory->AddSocketDataProvider(&data);
7056 TestCompletionCallback callback;
7058 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7059 EXPECT_EQ(ERR_IO_PENDING, rv);
7061 rv = callback.WaitForResult();
7062 EXPECT_EQ(OK, rv);
7065 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7066 HttpRequestInfo request;
7067 request.method = "GET";
7068 request.url = GURL("http://www.google.com/");
7069 request.load_flags = 0;
7071 session_deps_.proxy_service.reset(
7072 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7073 CapturingNetLog net_log;
7074 session_deps_.net_log = &net_log;
7076 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7077 scoped_ptr<HttpTransaction> trans(
7078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7080 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7081 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7083 MockWrite data_writes[] = {
7084 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7085 MockWrite("GET / HTTP/1.1\r\n"
7086 "Host: www.google.com\r\n"
7087 "Connection: keep-alive\r\n\r\n")
7090 MockRead data_reads[] = {
7091 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7092 MockRead("HTTP/1.0 200 OK\r\n"),
7093 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7094 MockRead("Payload"),
7095 MockRead(SYNCHRONOUS, OK)
7098 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7099 data_writes, arraysize(data_writes));
7100 session_deps_.socket_factory->AddSocketDataProvider(&data);
7102 TestCompletionCallback callback;
7104 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7105 EXPECT_EQ(ERR_IO_PENDING, rv);
7107 rv = callback.WaitForResult();
7108 EXPECT_EQ(OK, rv);
7110 const HttpResponseInfo* response = trans->GetResponseInfo();
7111 ASSERT_TRUE(response != NULL);
7113 LoadTimingInfo load_timing_info;
7114 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7115 TestLoadTimingNotReusedWithPac(load_timing_info,
7116 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7118 std::string response_text;
7119 rv = ReadTransaction(trans.get(), &response_text);
7120 EXPECT_EQ(OK, rv);
7121 EXPECT_EQ("Payload", response_text);
7124 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7125 HttpRequestInfo request;
7126 request.method = "GET";
7127 request.url = GURL("https://www.google.com/");
7128 request.load_flags = 0;
7130 session_deps_.proxy_service.reset(
7131 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7132 CapturingNetLog net_log;
7133 session_deps_.net_log = &net_log;
7135 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7136 scoped_ptr<HttpTransaction> trans(
7137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7139 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7140 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7142 MockWrite data_writes[] = {
7143 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7144 arraysize(write_buffer)),
7145 MockWrite("GET / HTTP/1.1\r\n"
7146 "Host: www.google.com\r\n"
7147 "Connection: keep-alive\r\n\r\n")
7150 MockRead data_reads[] = {
7151 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7152 arraysize(read_buffer)),
7153 MockRead("HTTP/1.0 200 OK\r\n"),
7154 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7155 MockRead("Payload"),
7156 MockRead(SYNCHRONOUS, OK)
7159 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7160 data_writes, arraysize(data_writes));
7161 session_deps_.socket_factory->AddSocketDataProvider(&data);
7163 SSLSocketDataProvider ssl(ASYNC, OK);
7164 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7166 TestCompletionCallback callback;
7168 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7169 EXPECT_EQ(ERR_IO_PENDING, rv);
7171 rv = callback.WaitForResult();
7172 EXPECT_EQ(OK, rv);
7174 LoadTimingInfo load_timing_info;
7175 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7176 TestLoadTimingNotReusedWithPac(load_timing_info,
7177 CONNECT_TIMING_HAS_SSL_TIMES);
7179 const HttpResponseInfo* response = trans->GetResponseInfo();
7180 ASSERT_TRUE(response != NULL);
7182 std::string response_text;
7183 rv = ReadTransaction(trans.get(), &response_text);
7184 EXPECT_EQ(OK, rv);
7185 EXPECT_EQ("Payload", response_text);
7188 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7189 HttpRequestInfo request;
7190 request.method = "GET";
7191 request.url = GURL("http://www.google.com/");
7192 request.load_flags = 0;
7194 session_deps_.proxy_service.reset(
7195 ProxyService::CreateFixed("socks4://myproxy:1080"));
7196 CapturingNetLog net_log;
7197 session_deps_.net_log = &net_log;
7199 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7200 scoped_ptr<HttpTransaction> trans(
7201 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7203 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7204 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7206 MockWrite data_writes[] = {
7207 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7208 MockWrite("GET / HTTP/1.1\r\n"
7209 "Host: www.google.com\r\n"
7210 "Connection: keep-alive\r\n\r\n")
7213 MockRead data_reads[] = {
7214 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7215 MockRead("HTTP/1.0 200 OK\r\n"),
7216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7217 MockRead("Payload"),
7218 MockRead(SYNCHRONOUS, OK)
7221 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7222 data_writes, arraysize(data_writes));
7223 session_deps_.socket_factory->AddSocketDataProvider(&data);
7225 TestCompletionCallback callback;
7227 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7228 EXPECT_EQ(ERR_IO_PENDING, rv);
7230 rv = callback.WaitForResult();
7231 EXPECT_EQ(OK, rv);
7233 const HttpResponseInfo* response = trans->GetResponseInfo();
7234 ASSERT_TRUE(response != NULL);
7236 LoadTimingInfo load_timing_info;
7237 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7238 TestLoadTimingNotReused(load_timing_info,
7239 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7241 std::string response_text;
7242 rv = ReadTransaction(trans.get(), &response_text);
7243 EXPECT_EQ(OK, rv);
7244 EXPECT_EQ("Payload", response_text);
7247 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7248 HttpRequestInfo request;
7249 request.method = "GET";
7250 request.url = GURL("http://www.google.com/");
7251 request.load_flags = 0;
7253 session_deps_.proxy_service.reset(
7254 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7255 CapturingNetLog net_log;
7256 session_deps_.net_log = &net_log;
7258 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7259 scoped_ptr<HttpTransaction> trans(
7260 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7262 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7263 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7264 const char kSOCKS5OkRequest[] = {
7265 0x05, // Version
7266 0x01, // Command (CONNECT)
7267 0x00, // Reserved.
7268 0x03, // Address type (DOMAINNAME).
7269 0x0E, // Length of domain (14)
7270 // Domain string:
7271 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7272 0x00, 0x50, // 16-bit port (80)
7274 const char kSOCKS5OkResponse[] =
7275 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7277 MockWrite data_writes[] = {
7278 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7279 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7280 MockWrite("GET / HTTP/1.1\r\n"
7281 "Host: www.google.com\r\n"
7282 "Connection: keep-alive\r\n\r\n")
7285 MockRead data_reads[] = {
7286 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7287 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7288 MockRead("HTTP/1.0 200 OK\r\n"),
7289 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7290 MockRead("Payload"),
7291 MockRead(SYNCHRONOUS, OK)
7294 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7295 data_writes, arraysize(data_writes));
7296 session_deps_.socket_factory->AddSocketDataProvider(&data);
7298 TestCompletionCallback callback;
7300 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7301 EXPECT_EQ(ERR_IO_PENDING, rv);
7303 rv = callback.WaitForResult();
7304 EXPECT_EQ(OK, rv);
7306 const HttpResponseInfo* response = trans->GetResponseInfo();
7307 ASSERT_TRUE(response != NULL);
7309 LoadTimingInfo load_timing_info;
7310 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7311 TestLoadTimingNotReusedWithPac(load_timing_info,
7312 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7314 std::string response_text;
7315 rv = ReadTransaction(trans.get(), &response_text);
7316 EXPECT_EQ(OK, rv);
7317 EXPECT_EQ("Payload", response_text);
7320 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7321 HttpRequestInfo request;
7322 request.method = "GET";
7323 request.url = GURL("https://www.google.com/");
7324 request.load_flags = 0;
7326 session_deps_.proxy_service.reset(
7327 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7328 CapturingNetLog net_log;
7329 session_deps_.net_log = &net_log;
7331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7332 scoped_ptr<HttpTransaction> trans(
7333 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7335 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7336 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7337 const unsigned char kSOCKS5OkRequest[] = {
7338 0x05, // Version
7339 0x01, // Command (CONNECT)
7340 0x00, // Reserved.
7341 0x03, // Address type (DOMAINNAME).
7342 0x0E, // Length of domain (14)
7343 // Domain string:
7344 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7345 0x01, 0xBB, // 16-bit port (443)
7348 const char kSOCKS5OkResponse[] =
7349 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7351 MockWrite data_writes[] = {
7352 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7353 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7354 arraysize(kSOCKS5OkRequest)),
7355 MockWrite("GET / HTTP/1.1\r\n"
7356 "Host: www.google.com\r\n"
7357 "Connection: keep-alive\r\n\r\n")
7360 MockRead data_reads[] = {
7361 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7362 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7363 MockRead("HTTP/1.0 200 OK\r\n"),
7364 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7365 MockRead("Payload"),
7366 MockRead(SYNCHRONOUS, OK)
7369 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7370 data_writes, arraysize(data_writes));
7371 session_deps_.socket_factory->AddSocketDataProvider(&data);
7373 SSLSocketDataProvider ssl(ASYNC, OK);
7374 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7376 TestCompletionCallback callback;
7378 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7379 EXPECT_EQ(ERR_IO_PENDING, rv);
7381 rv = callback.WaitForResult();
7382 EXPECT_EQ(OK, rv);
7384 const HttpResponseInfo* response = trans->GetResponseInfo();
7385 ASSERT_TRUE(response != NULL);
7387 LoadTimingInfo load_timing_info;
7388 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7389 TestLoadTimingNotReusedWithPac(load_timing_info,
7390 CONNECT_TIMING_HAS_SSL_TIMES);
7392 std::string response_text;
7393 rv = ReadTransaction(trans.get(), &response_text);
7394 EXPECT_EQ(OK, rv);
7395 EXPECT_EQ("Payload", response_text);
7398 namespace {
7400 // Tests that for connection endpoints the group names are correctly set.
7402 struct GroupNameTest {
7403 std::string proxy_server;
7404 std::string url;
7405 std::string expected_group_name;
7406 bool ssl;
7409 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7410 NextProto next_proto,
7411 SpdySessionDependencies* session_deps_) {
7412 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7414 base::WeakPtr<HttpServerProperties> http_server_properties =
7415 session->http_server_properties();
7416 http_server_properties->SetAlternateProtocol(
7417 HostPortPair("host.with.alternate", 80), 443,
7418 AlternateProtocolFromNextProto(next_proto));
7420 return session;
7423 int GroupNameTransactionHelper(
7424 const std::string& url,
7425 const scoped_refptr<HttpNetworkSession>& session) {
7426 HttpRequestInfo request;
7427 request.method = "GET";
7428 request.url = GURL(url);
7429 request.load_flags = 0;
7431 scoped_ptr<HttpTransaction> trans(
7432 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7434 TestCompletionCallback callback;
7436 // We do not complete this request, the dtor will clean the transaction up.
7437 return trans->Start(&request, callback.callback(), BoundNetLog());
7440 } // namespace
7442 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7443 const GroupNameTest tests[] = {
7445 "", // unused
7446 "http://www.google.com/direct",
7447 "www.google.com:80",
7448 false,
7451 "", // unused
7452 "http://[2001:1418:13:1::25]/direct",
7453 "[2001:1418:13:1::25]:80",
7454 false,
7457 // SSL Tests
7459 "", // unused
7460 "https://www.google.com/direct_ssl",
7461 "ssl/www.google.com:443",
7462 true,
7465 "", // unused
7466 "https://[2001:1418:13:1::25]/direct",
7467 "ssl/[2001:1418:13:1::25]:443",
7468 true,
7471 "", // unused
7472 "http://host.with.alternate/direct",
7473 "ssl/host.with.alternate:443",
7474 true,
7478 session_deps_.use_alternate_protocols = true;
7480 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7481 session_deps_.proxy_service.reset(
7482 ProxyService::CreateFixed(tests[i].proxy_server));
7483 scoped_refptr<HttpNetworkSession> session(
7484 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7486 HttpNetworkSessionPeer peer(session);
7487 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7488 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7489 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7490 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7491 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7492 new MockClientSocketPoolManager);
7493 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7494 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7495 peer.SetClientSocketPoolManager(
7496 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7498 EXPECT_EQ(ERR_IO_PENDING,
7499 GroupNameTransactionHelper(tests[i].url, session));
7500 if (tests[i].ssl)
7501 EXPECT_EQ(tests[i].expected_group_name,
7502 ssl_conn_pool->last_group_name_received());
7503 else
7504 EXPECT_EQ(tests[i].expected_group_name,
7505 transport_conn_pool->last_group_name_received());
7510 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7511 const GroupNameTest tests[] = {
7513 "http_proxy",
7514 "http://www.google.com/http_proxy_normal",
7515 "www.google.com:80",
7516 false,
7519 // SSL Tests
7521 "http_proxy",
7522 "https://www.google.com/http_connect_ssl",
7523 "ssl/www.google.com:443",
7524 true,
7528 "http_proxy",
7529 "http://host.with.alternate/direct",
7530 "ssl/host.with.alternate:443",
7531 true,
7535 "http_proxy",
7536 "ftp://ftp.google.com/http_proxy_normal",
7537 "ftp/ftp.google.com:21",
7538 false,
7542 session_deps_.use_alternate_protocols = true;
7544 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7545 session_deps_.proxy_service.reset(
7546 ProxyService::CreateFixed(tests[i].proxy_server));
7547 scoped_refptr<HttpNetworkSession> session(
7548 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7550 HttpNetworkSessionPeer peer(session);
7552 HostPortPair proxy_host("http_proxy", 80);
7553 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7554 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7555 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7556 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7558 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7559 new MockClientSocketPoolManager);
7560 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7561 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7562 peer.SetClientSocketPoolManager(
7563 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7565 EXPECT_EQ(ERR_IO_PENDING,
7566 GroupNameTransactionHelper(tests[i].url, session));
7567 if (tests[i].ssl)
7568 EXPECT_EQ(tests[i].expected_group_name,
7569 ssl_conn_pool->last_group_name_received());
7570 else
7571 EXPECT_EQ(tests[i].expected_group_name,
7572 http_proxy_pool->last_group_name_received());
7576 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7577 const GroupNameTest tests[] = {
7579 "socks4://socks_proxy:1080",
7580 "http://www.google.com/socks4_direct",
7581 "socks4/www.google.com:80",
7582 false,
7585 "socks5://socks_proxy:1080",
7586 "http://www.google.com/socks5_direct",
7587 "socks5/www.google.com:80",
7588 false,
7591 // SSL Tests
7593 "socks4://socks_proxy:1080",
7594 "https://www.google.com/socks4_ssl",
7595 "socks4/ssl/www.google.com:443",
7596 true,
7599 "socks5://socks_proxy:1080",
7600 "https://www.google.com/socks5_ssl",
7601 "socks5/ssl/www.google.com:443",
7602 true,
7606 "socks4://socks_proxy:1080",
7607 "http://host.with.alternate/direct",
7608 "socks4/ssl/host.with.alternate:443",
7609 true,
7613 session_deps_.use_alternate_protocols = true;
7615 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7616 session_deps_.proxy_service.reset(
7617 ProxyService::CreateFixed(tests[i].proxy_server));
7618 scoped_refptr<HttpNetworkSession> session(
7619 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7621 HttpNetworkSessionPeer peer(session);
7623 HostPortPair proxy_host("socks_proxy", 1080);
7624 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7625 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7626 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7627 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7629 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7630 new MockClientSocketPoolManager);
7631 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7632 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7633 peer.SetClientSocketPoolManager(
7634 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7636 scoped_ptr<HttpTransaction> trans(
7637 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7639 EXPECT_EQ(ERR_IO_PENDING,
7640 GroupNameTransactionHelper(tests[i].url, session));
7641 if (tests[i].ssl)
7642 EXPECT_EQ(tests[i].expected_group_name,
7643 ssl_conn_pool->last_group_name_received());
7644 else
7645 EXPECT_EQ(tests[i].expected_group_name,
7646 socks_conn_pool->last_group_name_received());
7650 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7651 HttpRequestInfo request;
7652 request.method = "GET";
7653 request.url = GURL("http://www.google.com/");
7655 session_deps_.proxy_service.reset(
7656 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7658 // This simulates failure resolving all hostnames; that means we will fail
7659 // connecting to both proxies (myproxy:70 and foobar:80).
7660 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7662 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7663 scoped_ptr<HttpTransaction> trans(
7664 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7666 TestCompletionCallback callback;
7668 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7669 EXPECT_EQ(ERR_IO_PENDING, rv);
7671 rv = callback.WaitForResult();
7672 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7675 // Base test to make sure that when the load flags for a request specify to
7676 // bypass the cache, the DNS cache is not used.
7677 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7678 int load_flags) {
7679 // Issue a request, asking to bypass the cache(s).
7680 HttpRequestInfo request;
7681 request.method = "GET";
7682 request.load_flags = load_flags;
7683 request.url = GURL("http://www.google.com/");
7685 // Select a host resolver that does caching.
7686 session_deps_.host_resolver.reset(new MockCachingHostResolver);
7688 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7689 scoped_ptr<HttpTransaction> trans(
7690 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7692 // Warm up the host cache so it has an entry for "www.google.com".
7693 AddressList addrlist;
7694 TestCompletionCallback callback;
7695 int rv = session_deps_.host_resolver->Resolve(
7696 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7697 DEFAULT_PRIORITY,
7698 &addrlist,
7699 callback.callback(),
7700 NULL,
7701 BoundNetLog());
7702 EXPECT_EQ(ERR_IO_PENDING, rv);
7703 rv = callback.WaitForResult();
7704 EXPECT_EQ(OK, rv);
7706 // Verify that it was added to host cache, by doing a subsequent async lookup
7707 // and confirming it completes synchronously.
7708 rv = session_deps_.host_resolver->Resolve(
7709 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7710 DEFAULT_PRIORITY,
7711 &addrlist,
7712 callback.callback(),
7713 NULL,
7714 BoundNetLog());
7715 ASSERT_EQ(OK, rv);
7717 // Inject a failure the next time that "www.google.com" is resolved. This way
7718 // we can tell if the next lookup hit the cache, or the "network".
7719 // (cache --> success, "network" --> failure).
7720 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7722 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7723 // first read -- this won't be reached as the host resolution will fail first.
7724 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7725 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7726 session_deps_.socket_factory->AddSocketDataProvider(&data);
7728 // Run the request.
7729 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7730 ASSERT_EQ(ERR_IO_PENDING, rv);
7731 rv = callback.WaitForResult();
7733 // If we bypassed the cache, we would have gotten a failure while resolving
7734 // "www.google.com".
7735 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7738 // There are multiple load flags that should trigger the host cache bypass.
7739 // Test each in isolation:
7740 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7741 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7744 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7745 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7748 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7749 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7752 // Make sure we can handle an error when writing the request.
7753 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7754 HttpRequestInfo request;
7755 request.method = "GET";
7756 request.url = GURL("http://www.foo.com/");
7757 request.load_flags = 0;
7759 MockWrite write_failure[] = {
7760 MockWrite(ASYNC, ERR_CONNECTION_RESET),
7762 StaticSocketDataProvider data(NULL, 0,
7763 write_failure, arraysize(write_failure));
7764 session_deps_.socket_factory->AddSocketDataProvider(&data);
7765 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7767 TestCompletionCallback callback;
7769 scoped_ptr<HttpTransaction> trans(
7770 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7772 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7773 EXPECT_EQ(ERR_IO_PENDING, rv);
7775 rv = callback.WaitForResult();
7776 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7779 // Check that a connection closed after the start of the headers finishes ok.
7780 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7781 HttpRequestInfo request;
7782 request.method = "GET";
7783 request.url = GURL("http://www.foo.com/");
7784 request.load_flags = 0;
7786 MockRead data_reads[] = {
7787 MockRead("HTTP/1."),
7788 MockRead(SYNCHRONOUS, OK),
7791 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7792 session_deps_.socket_factory->AddSocketDataProvider(&data);
7793 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7795 TestCompletionCallback callback;
7797 scoped_ptr<HttpTransaction> trans(
7798 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7800 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7801 EXPECT_EQ(ERR_IO_PENDING, rv);
7803 rv = callback.WaitForResult();
7804 EXPECT_EQ(OK, rv);
7806 const HttpResponseInfo* response = trans->GetResponseInfo();
7807 ASSERT_TRUE(response != NULL);
7809 EXPECT_TRUE(response->headers.get() != NULL);
7810 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7812 std::string response_data;
7813 rv = ReadTransaction(trans.get(), &response_data);
7814 EXPECT_EQ(OK, rv);
7815 EXPECT_EQ("", response_data);
7818 // Make sure that a dropped connection while draining the body for auth
7819 // restart does the right thing.
7820 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7821 HttpRequestInfo request;
7822 request.method = "GET";
7823 request.url = GURL("http://www.google.com/");
7824 request.load_flags = 0;
7826 MockWrite data_writes1[] = {
7827 MockWrite("GET / HTTP/1.1\r\n"
7828 "Host: www.google.com\r\n"
7829 "Connection: keep-alive\r\n\r\n"),
7832 MockRead data_reads1[] = {
7833 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7834 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7835 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7836 MockRead("Content-Length: 14\r\n\r\n"),
7837 MockRead("Unauth"),
7838 MockRead(ASYNC, ERR_CONNECTION_RESET),
7841 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7842 data_writes1, arraysize(data_writes1));
7843 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7845 // After calling trans->RestartWithAuth(), this is the request we should
7846 // be issuing -- the final header line contains the credentials.
7847 MockWrite data_writes2[] = {
7848 MockWrite("GET / HTTP/1.1\r\n"
7849 "Host: www.google.com\r\n"
7850 "Connection: keep-alive\r\n"
7851 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7854 // Lastly, the server responds with the actual content.
7855 MockRead data_reads2[] = {
7856 MockRead("HTTP/1.1 200 OK\r\n"),
7857 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7858 MockRead("Content-Length: 100\r\n\r\n"),
7859 MockRead(SYNCHRONOUS, OK),
7862 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7863 data_writes2, arraysize(data_writes2));
7864 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7867 TestCompletionCallback callback1;
7869 scoped_ptr<HttpTransaction> trans(
7870 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7872 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7873 EXPECT_EQ(ERR_IO_PENDING, rv);
7875 rv = callback1.WaitForResult();
7876 EXPECT_EQ(OK, rv);
7878 const HttpResponseInfo* response = trans->GetResponseInfo();
7879 ASSERT_TRUE(response != NULL);
7880 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7882 TestCompletionCallback callback2;
7884 rv = trans->RestartWithAuth(
7885 AuthCredentials(kFoo, kBar), callback2.callback());
7886 EXPECT_EQ(ERR_IO_PENDING, rv);
7888 rv = callback2.WaitForResult();
7889 EXPECT_EQ(OK, rv);
7891 response = trans->GetResponseInfo();
7892 ASSERT_TRUE(response != NULL);
7893 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7894 EXPECT_EQ(100, response->headers->GetContentLength());
7897 // Test HTTPS connections going through a proxy that sends extra data.
7898 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
7899 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7901 HttpRequestInfo request;
7902 request.method = "GET";
7903 request.url = GURL("https://www.google.com/");
7904 request.load_flags = 0;
7906 MockRead proxy_reads[] = {
7907 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7908 MockRead(SYNCHRONOUS, OK)
7911 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
7912 SSLSocketDataProvider ssl(ASYNC, OK);
7914 session_deps_.socket_factory->AddSocketDataProvider(&data);
7915 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7917 TestCompletionCallback callback;
7919 session_deps_.socket_factory->ResetNextMockIndexes();
7921 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7922 scoped_ptr<HttpTransaction> trans(
7923 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7925 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7926 EXPECT_EQ(ERR_IO_PENDING, rv);
7928 rv = callback.WaitForResult();
7929 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
7932 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
7933 HttpRequestInfo request;
7934 request.method = "GET";
7935 request.url = GURL("http://www.google.com/");
7936 request.load_flags = 0;
7938 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7939 scoped_ptr<HttpTransaction> trans(
7940 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7942 MockRead data_reads[] = {
7943 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7944 MockRead(SYNCHRONOUS, OK),
7947 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7948 session_deps_.socket_factory->AddSocketDataProvider(&data);
7950 TestCompletionCallback callback;
7952 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7953 EXPECT_EQ(ERR_IO_PENDING, rv);
7955 EXPECT_EQ(OK, callback.WaitForResult());
7957 const HttpResponseInfo* response = trans->GetResponseInfo();
7958 ASSERT_TRUE(response != NULL);
7960 EXPECT_TRUE(response->headers.get() != NULL);
7961 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7963 std::string response_data;
7964 rv = ReadTransaction(trans.get(), &response_data);
7965 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
7968 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
7969 base::FilePath temp_file_path;
7970 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
7971 const uint64 kFakeSize = 100000; // file is actually blank
7972 UploadFileElementReader::ScopedOverridingContentLengthForTests
7973 overriding_content_length(kFakeSize);
7975 ScopedVector<UploadElementReader> element_readers;
7976 element_readers.push_back(
7977 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7978 temp_file_path,
7980 kuint64max,
7981 base::Time()));
7982 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7984 HttpRequestInfo request;
7985 request.method = "POST";
7986 request.url = GURL("http://www.google.com/upload");
7987 request.upload_data_stream = &upload_data_stream;
7988 request.load_flags = 0;
7990 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7991 scoped_ptr<HttpTransaction> trans(
7992 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7994 MockRead data_reads[] = {
7995 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7996 MockRead("hello world"),
7997 MockRead(SYNCHRONOUS, OK),
7999 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8000 session_deps_.socket_factory->AddSocketDataProvider(&data);
8002 TestCompletionCallback callback;
8004 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8005 EXPECT_EQ(ERR_IO_PENDING, rv);
8007 rv = callback.WaitForResult();
8008 EXPECT_EQ(OK, rv);
8010 const HttpResponseInfo* response = trans->GetResponseInfo();
8011 ASSERT_TRUE(response != NULL);
8013 EXPECT_TRUE(response->headers.get() != NULL);
8014 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8016 std::string response_data;
8017 rv = ReadTransaction(trans.get(), &response_data);
8018 EXPECT_EQ(OK, rv);
8019 EXPECT_EQ("hello world", response_data);
8021 base::DeleteFile(temp_file_path, false);
8024 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8025 base::FilePath temp_file;
8026 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8027 std::string temp_file_content("Unreadable file.");
8028 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8029 temp_file_content.length()));
8030 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
8032 ScopedVector<UploadElementReader> element_readers;
8033 element_readers.push_back(
8034 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8035 temp_file,
8037 kuint64max,
8038 base::Time()));
8039 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8041 HttpRequestInfo request;
8042 request.method = "POST";
8043 request.url = GURL("http://www.google.com/upload");
8044 request.upload_data_stream = &upload_data_stream;
8045 request.load_flags = 0;
8047 // If we try to upload an unreadable file, the transaction should fail.
8048 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8049 scoped_ptr<HttpTransaction> trans(
8050 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8052 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8053 session_deps_.socket_factory->AddSocketDataProvider(&data);
8055 TestCompletionCallback callback;
8057 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8058 EXPECT_EQ(ERR_IO_PENDING, rv);
8060 rv = callback.WaitForResult();
8061 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8063 const HttpResponseInfo* response = trans->GetResponseInfo();
8064 EXPECT_FALSE(response);
8066 base::DeleteFile(temp_file, false);
8069 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8070 class FakeUploadElementReader : public UploadElementReader {
8071 public:
8072 FakeUploadElementReader() {}
8073 virtual ~FakeUploadElementReader() {}
8075 const CompletionCallback& callback() const { return callback_; }
8077 // UploadElementReader overrides:
8078 virtual int Init(const CompletionCallback& callback) OVERRIDE {
8079 callback_ = callback;
8080 return ERR_IO_PENDING;
8082 virtual uint64 GetContentLength() const OVERRIDE { return 0; }
8083 virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
8084 virtual int Read(IOBuffer* buf,
8085 int buf_length,
8086 const CompletionCallback& callback) OVERRIDE {
8087 return ERR_FAILED;
8090 private:
8091 CompletionCallback callback_;
8094 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8095 ScopedVector<UploadElementReader> element_readers;
8096 element_readers.push_back(fake_reader);
8097 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8099 HttpRequestInfo request;
8100 request.method = "POST";
8101 request.url = GURL("http://www.google.com/upload");
8102 request.upload_data_stream = &upload_data_stream;
8103 request.load_flags = 0;
8105 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8106 scoped_ptr<HttpTransaction> trans(
8107 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8109 StaticSocketDataProvider data;
8110 session_deps_.socket_factory->AddSocketDataProvider(&data);
8112 TestCompletionCallback callback;
8113 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8114 EXPECT_EQ(ERR_IO_PENDING, rv);
8115 base::MessageLoop::current()->RunUntilIdle();
8117 // Transaction is pending on request body initialization.
8118 ASSERT_FALSE(fake_reader->callback().is_null());
8120 // Return Init()'s result after the transaction gets destroyed.
8121 trans.reset();
8122 fake_reader->callback().Run(OK); // Should not crash.
8125 // Tests that changes to Auth realms are treated like auth rejections.
8126 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8128 HttpRequestInfo request;
8129 request.method = "GET";
8130 request.url = GURL("http://www.google.com/");
8131 request.load_flags = 0;
8133 // First transaction will request a resource and receive a Basic challenge
8134 // with realm="first_realm".
8135 MockWrite data_writes1[] = {
8136 MockWrite("GET / HTTP/1.1\r\n"
8137 "Host: www.google.com\r\n"
8138 "Connection: keep-alive\r\n"
8139 "\r\n"),
8141 MockRead data_reads1[] = {
8142 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8143 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8144 "\r\n"),
8147 // After calling trans->RestartWithAuth(), provide an Authentication header
8148 // for first_realm. The server will reject and provide a challenge with
8149 // second_realm.
8150 MockWrite data_writes2[] = {
8151 MockWrite("GET / HTTP/1.1\r\n"
8152 "Host: www.google.com\r\n"
8153 "Connection: keep-alive\r\n"
8154 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8155 "\r\n"),
8157 MockRead data_reads2[] = {
8158 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8159 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8160 "\r\n"),
8163 // This again fails, and goes back to first_realm. Make sure that the
8164 // entry is removed from cache.
8165 MockWrite data_writes3[] = {
8166 MockWrite("GET / HTTP/1.1\r\n"
8167 "Host: www.google.com\r\n"
8168 "Connection: keep-alive\r\n"
8169 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8170 "\r\n"),
8172 MockRead data_reads3[] = {
8173 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8174 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8175 "\r\n"),
8178 // Try one last time (with the correct password) and get the resource.
8179 MockWrite data_writes4[] = {
8180 MockWrite("GET / HTTP/1.1\r\n"
8181 "Host: www.google.com\r\n"
8182 "Connection: keep-alive\r\n"
8183 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8184 "\r\n"),
8186 MockRead data_reads4[] = {
8187 MockRead("HTTP/1.1 200 OK\r\n"
8188 "Content-Type: text/html; charset=iso-8859-1\r\n"
8189 "Content-Length: 5\r\n"
8190 "\r\n"
8191 "hello"),
8194 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8195 data_writes1, arraysize(data_writes1));
8196 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8197 data_writes2, arraysize(data_writes2));
8198 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8199 data_writes3, arraysize(data_writes3));
8200 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8201 data_writes4, arraysize(data_writes4));
8202 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8203 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8204 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8205 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8207 TestCompletionCallback callback1;
8209 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8210 scoped_ptr<HttpTransaction> trans(
8211 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8213 // Issue the first request with Authorize headers. There should be a
8214 // password prompt for first_realm waiting to be filled in after the
8215 // transaction completes.
8216 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8217 EXPECT_EQ(ERR_IO_PENDING, rv);
8218 rv = callback1.WaitForResult();
8219 EXPECT_EQ(OK, rv);
8220 const HttpResponseInfo* response = trans->GetResponseInfo();
8221 ASSERT_TRUE(response != NULL);
8222 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8223 ASSERT_FALSE(challenge == NULL);
8224 EXPECT_FALSE(challenge->is_proxy);
8225 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8226 EXPECT_EQ("first_realm", challenge->realm);
8227 EXPECT_EQ("basic", challenge->scheme);
8229 // Issue the second request with an incorrect password. There should be a
8230 // password prompt for second_realm waiting to be filled in after the
8231 // transaction completes.
8232 TestCompletionCallback callback2;
8233 rv = trans->RestartWithAuth(
8234 AuthCredentials(kFirst, kBaz), callback2.callback());
8235 EXPECT_EQ(ERR_IO_PENDING, rv);
8236 rv = callback2.WaitForResult();
8237 EXPECT_EQ(OK, rv);
8238 response = trans->GetResponseInfo();
8239 ASSERT_TRUE(response != NULL);
8240 challenge = response->auth_challenge.get();
8241 ASSERT_FALSE(challenge == NULL);
8242 EXPECT_FALSE(challenge->is_proxy);
8243 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8244 EXPECT_EQ("second_realm", challenge->realm);
8245 EXPECT_EQ("basic", challenge->scheme);
8247 // Issue the third request with another incorrect password. There should be
8248 // a password prompt for first_realm waiting to be filled in. If the password
8249 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8250 // first_realm was not correctly removed.
8251 TestCompletionCallback callback3;
8252 rv = trans->RestartWithAuth(
8253 AuthCredentials(kSecond, kFou), callback3.callback());
8254 EXPECT_EQ(ERR_IO_PENDING, rv);
8255 rv = callback3.WaitForResult();
8256 EXPECT_EQ(OK, rv);
8257 response = trans->GetResponseInfo();
8258 ASSERT_TRUE(response != NULL);
8259 challenge = response->auth_challenge.get();
8260 ASSERT_FALSE(challenge == NULL);
8261 EXPECT_FALSE(challenge->is_proxy);
8262 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8263 EXPECT_EQ("first_realm", challenge->realm);
8264 EXPECT_EQ("basic", challenge->scheme);
8266 // Issue the fourth request with the correct password and username.
8267 TestCompletionCallback callback4;
8268 rv = trans->RestartWithAuth(
8269 AuthCredentials(kFirst, kBar), callback4.callback());
8270 EXPECT_EQ(ERR_IO_PENDING, rv);
8271 rv = callback4.WaitForResult();
8272 EXPECT_EQ(OK, rv);
8273 response = trans->GetResponseInfo();
8274 ASSERT_TRUE(response != NULL);
8275 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8278 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8279 session_deps_.next_protos = SpdyNextProtos();
8280 session_deps_.use_alternate_protocols = true;
8282 std::string alternate_protocol_http_header =
8283 GetAlternateProtocolHttpHeader();
8285 MockRead data_reads[] = {
8286 MockRead("HTTP/1.1 200 OK\r\n"),
8287 MockRead(alternate_protocol_http_header.c_str()),
8288 MockRead("hello world"),
8289 MockRead(SYNCHRONOUS, OK),
8292 HttpRequestInfo request;
8293 request.method = "GET";
8294 request.url = GURL("http://www.google.com/");
8295 request.load_flags = 0;
8297 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8299 session_deps_.socket_factory->AddSocketDataProvider(&data);
8301 TestCompletionCallback callback;
8303 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8304 scoped_ptr<HttpTransaction> trans(
8305 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8307 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8308 EXPECT_EQ(ERR_IO_PENDING, rv);
8310 HostPortPair http_host_port_pair("www.google.com", 80);
8311 HttpServerProperties& http_server_properties =
8312 *session->http_server_properties();
8313 EXPECT_FALSE(
8314 http_server_properties.HasAlternateProtocol(http_host_port_pair));
8316 EXPECT_EQ(OK, callback.WaitForResult());
8318 const HttpResponseInfo* response = trans->GetResponseInfo();
8319 ASSERT_TRUE(response != NULL);
8320 ASSERT_TRUE(response->headers.get() != NULL);
8321 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8322 EXPECT_FALSE(response->was_fetched_via_spdy);
8323 EXPECT_FALSE(response->was_npn_negotiated);
8325 std::string response_data;
8326 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8327 EXPECT_EQ("hello world", response_data);
8329 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
8330 const PortAlternateProtocolPair alternate =
8331 http_server_properties.GetAlternateProtocol(http_host_port_pair);
8332 PortAlternateProtocolPair expected_alternate;
8333 expected_alternate.port = 443;
8334 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
8335 EXPECT_TRUE(expected_alternate.Equals(alternate));
8338 TEST_P(HttpNetworkTransactionTest,
8339 MarkBrokenAlternateProtocolAndFallback) {
8340 session_deps_.use_alternate_protocols = true;
8342 HttpRequestInfo request;
8343 request.method = "GET";
8344 request.url = GURL("http://www.google.com/");
8345 request.load_flags = 0;
8347 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8348 StaticSocketDataProvider first_data;
8349 first_data.set_connect_data(mock_connect);
8350 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8352 MockRead data_reads[] = {
8353 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8354 MockRead("hello world"),
8355 MockRead(ASYNC, OK),
8357 StaticSocketDataProvider second_data(
8358 data_reads, arraysize(data_reads), NULL, 0);
8359 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8361 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8363 base::WeakPtr<HttpServerProperties> http_server_properties =
8364 session->http_server_properties();
8365 // Port must be < 1024, or the header will be ignored (since initial port was
8366 // port 80 (another restricted port).
8367 http_server_properties->SetAlternateProtocol(
8368 HostPortPair::FromURL(request.url),
8369 666 /* port is ignored by MockConnect anyway */,
8370 AlternateProtocolFromNextProto(GetParam()));
8372 scoped_ptr<HttpTransaction> trans(
8373 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8374 TestCompletionCallback callback;
8376 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8377 EXPECT_EQ(ERR_IO_PENDING, rv);
8378 EXPECT_EQ(OK, callback.WaitForResult());
8380 const HttpResponseInfo* response = trans->GetResponseInfo();
8381 ASSERT_TRUE(response != NULL);
8382 ASSERT_TRUE(response->headers.get() != NULL);
8383 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8385 std::string response_data;
8386 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8387 EXPECT_EQ("hello world", response_data);
8389 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8390 HostPortPair::FromURL(request.url)));
8391 const PortAlternateProtocolPair alternate =
8392 http_server_properties->GetAlternateProtocol(
8393 HostPortPair::FromURL(request.url));
8394 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8397 TEST_P(HttpNetworkTransactionTest,
8398 AlternateProtocolPortRestrictedBlocked) {
8399 // Ensure that we're not allowed to redirect traffic via an alternate
8400 // protocol to an unrestricted (port >= 1024) when the original traffic was
8401 // on a restricted port (port < 1024). Ensure that we can redirect in all
8402 // other cases.
8403 session_deps_.use_alternate_protocols = true;
8405 HttpRequestInfo restricted_port_request;
8406 restricted_port_request.method = "GET";
8407 restricted_port_request.url = GURL("http://www.google.com:1023/");
8408 restricted_port_request.load_flags = 0;
8410 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8411 StaticSocketDataProvider first_data;
8412 first_data.set_connect_data(mock_connect);
8413 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8415 MockRead data_reads[] = {
8416 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8417 MockRead("hello world"),
8418 MockRead(ASYNC, OK),
8420 StaticSocketDataProvider second_data(
8421 data_reads, arraysize(data_reads), NULL, 0);
8422 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8424 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8426 base::WeakPtr<HttpServerProperties> http_server_properties =
8427 session->http_server_properties();
8428 const int kUnrestrictedAlternatePort = 1024;
8429 http_server_properties->SetAlternateProtocol(
8430 HostPortPair::FromURL(restricted_port_request.url),
8431 kUnrestrictedAlternatePort,
8432 AlternateProtocolFromNextProto(GetParam()));
8434 scoped_ptr<HttpTransaction> trans(
8435 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8436 TestCompletionCallback callback;
8438 int rv = trans->Start(
8439 &restricted_port_request,
8440 callback.callback(), BoundNetLog());
8441 EXPECT_EQ(ERR_IO_PENDING, rv);
8442 // Invalid change to unrestricted port should fail.
8443 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8446 TEST_P(HttpNetworkTransactionTest,
8447 AlternateProtocolPortRestrictedPermitted) {
8448 // Ensure that we're allowed to redirect traffic via an alternate
8449 // protocol to an unrestricted (port >= 1024) when the original traffic was
8450 // on a restricted port (port < 1024) if we set
8451 // enable_user_alternate_protocol_ports.
8453 session_deps_.use_alternate_protocols = true;
8454 session_deps_.enable_user_alternate_protocol_ports = true;
8456 HttpRequestInfo restricted_port_request;
8457 restricted_port_request.method = "GET";
8458 restricted_port_request.url = GURL("http://www.google.com:1023/");
8459 restricted_port_request.load_flags = 0;
8461 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8462 StaticSocketDataProvider first_data;
8463 first_data.set_connect_data(mock_connect);
8464 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8466 MockRead data_reads[] = {
8467 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8468 MockRead("hello world"),
8469 MockRead(ASYNC, OK),
8471 StaticSocketDataProvider second_data(
8472 data_reads, arraysize(data_reads), NULL, 0);
8473 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8475 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8477 base::WeakPtr<HttpServerProperties> http_server_properties =
8478 session->http_server_properties();
8479 const int kUnrestrictedAlternatePort = 1024;
8480 http_server_properties->SetAlternateProtocol(
8481 HostPortPair::FromURL(restricted_port_request.url),
8482 kUnrestrictedAlternatePort,
8483 AlternateProtocolFromNextProto(GetParam()));
8485 scoped_ptr<HttpTransaction> trans(
8486 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8487 TestCompletionCallback callback;
8489 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8490 &restricted_port_request,
8491 callback.callback(), BoundNetLog()));
8492 // Change to unrestricted port should succeed.
8493 EXPECT_EQ(OK, callback.WaitForResult());
8496 TEST_P(HttpNetworkTransactionTest,
8497 AlternateProtocolPortRestrictedAllowed) {
8498 // Ensure that we're not allowed to redirect traffic via an alternate
8499 // protocol to an unrestricted (port >= 1024) when the original traffic was
8500 // on a restricted port (port < 1024). Ensure that we can redirect in all
8501 // other cases.
8502 session_deps_.use_alternate_protocols = true;
8504 HttpRequestInfo restricted_port_request;
8505 restricted_port_request.method = "GET";
8506 restricted_port_request.url = GURL("http://www.google.com:1023/");
8507 restricted_port_request.load_flags = 0;
8509 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8510 StaticSocketDataProvider first_data;
8511 first_data.set_connect_data(mock_connect);
8512 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8514 MockRead data_reads[] = {
8515 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8516 MockRead("hello world"),
8517 MockRead(ASYNC, OK),
8519 StaticSocketDataProvider second_data(
8520 data_reads, arraysize(data_reads), NULL, 0);
8521 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8523 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8525 base::WeakPtr<HttpServerProperties> http_server_properties =
8526 session->http_server_properties();
8527 const int kRestrictedAlternatePort = 80;
8528 http_server_properties->SetAlternateProtocol(
8529 HostPortPair::FromURL(restricted_port_request.url),
8530 kRestrictedAlternatePort,
8531 AlternateProtocolFromNextProto(GetParam()));
8533 scoped_ptr<HttpTransaction> trans(
8534 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8535 TestCompletionCallback callback;
8537 int rv = trans->Start(
8538 &restricted_port_request,
8539 callback.callback(), BoundNetLog());
8540 EXPECT_EQ(ERR_IO_PENDING, rv);
8541 // Valid change to restricted port should pass.
8542 EXPECT_EQ(OK, callback.WaitForResult());
8545 TEST_P(HttpNetworkTransactionTest,
8546 AlternateProtocolPortUnrestrictedAllowed1) {
8547 // Ensure that we're not allowed to redirect traffic via an alternate
8548 // protocol to an unrestricted (port >= 1024) when the original traffic was
8549 // on a restricted port (port < 1024). Ensure that we can redirect in all
8550 // other cases.
8551 session_deps_.use_alternate_protocols = true;
8553 HttpRequestInfo unrestricted_port_request;
8554 unrestricted_port_request.method = "GET";
8555 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8556 unrestricted_port_request.load_flags = 0;
8558 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8559 StaticSocketDataProvider first_data;
8560 first_data.set_connect_data(mock_connect);
8561 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8563 MockRead data_reads[] = {
8564 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8565 MockRead("hello world"),
8566 MockRead(ASYNC, OK),
8568 StaticSocketDataProvider second_data(
8569 data_reads, arraysize(data_reads), NULL, 0);
8570 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8572 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8574 base::WeakPtr<HttpServerProperties> http_server_properties =
8575 session->http_server_properties();
8576 const int kRestrictedAlternatePort = 80;
8577 http_server_properties->SetAlternateProtocol(
8578 HostPortPair::FromURL(unrestricted_port_request.url),
8579 kRestrictedAlternatePort,
8580 AlternateProtocolFromNextProto(GetParam()));
8582 scoped_ptr<HttpTransaction> trans(
8583 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8584 TestCompletionCallback callback;
8586 int rv = trans->Start(
8587 &unrestricted_port_request, callback.callback(), BoundNetLog());
8588 EXPECT_EQ(ERR_IO_PENDING, rv);
8589 // Valid change to restricted port should pass.
8590 EXPECT_EQ(OK, callback.WaitForResult());
8593 TEST_P(HttpNetworkTransactionTest,
8594 AlternateProtocolPortUnrestrictedAllowed2) {
8595 // Ensure that we're not allowed to redirect traffic via an alternate
8596 // protocol to an unrestricted (port >= 1024) when the original traffic was
8597 // on a restricted port (port < 1024). Ensure that we can redirect in all
8598 // other cases.
8599 session_deps_.use_alternate_protocols = true;
8601 HttpRequestInfo unrestricted_port_request;
8602 unrestricted_port_request.method = "GET";
8603 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8604 unrestricted_port_request.load_flags = 0;
8606 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8607 StaticSocketDataProvider first_data;
8608 first_data.set_connect_data(mock_connect);
8609 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8611 MockRead data_reads[] = {
8612 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8613 MockRead("hello world"),
8614 MockRead(ASYNC, OK),
8616 StaticSocketDataProvider second_data(
8617 data_reads, arraysize(data_reads), NULL, 0);
8618 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8620 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8622 base::WeakPtr<HttpServerProperties> http_server_properties =
8623 session->http_server_properties();
8624 const int kUnrestrictedAlternatePort = 1024;
8625 http_server_properties->SetAlternateProtocol(
8626 HostPortPair::FromURL(unrestricted_port_request.url),
8627 kUnrestrictedAlternatePort,
8628 AlternateProtocolFromNextProto(GetParam()));
8630 scoped_ptr<HttpTransaction> trans(
8631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8632 TestCompletionCallback callback;
8634 int rv = trans->Start(
8635 &unrestricted_port_request, callback.callback(), BoundNetLog());
8636 EXPECT_EQ(ERR_IO_PENDING, rv);
8637 // Valid change to an unrestricted port should pass.
8638 EXPECT_EQ(OK, callback.WaitForResult());
8641 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
8642 // Ensure that we're not allowed to redirect traffic via an alternate
8643 // protocol to an unsafe port, and that we resume the second
8644 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8645 session_deps_.use_alternate_protocols = true;
8647 HttpRequestInfo request;
8648 request.method = "GET";
8649 request.url = GURL("http://www.google.com/");
8650 request.load_flags = 0;
8652 // The alternate protocol request will error out before we attempt to connect,
8653 // so only the standard HTTP request will try to connect.
8654 MockRead data_reads[] = {
8655 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8656 MockRead("hello world"),
8657 MockRead(ASYNC, OK),
8659 StaticSocketDataProvider data(
8660 data_reads, arraysize(data_reads), NULL, 0);
8661 session_deps_.socket_factory->AddSocketDataProvider(&data);
8663 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8665 base::WeakPtr<HttpServerProperties> http_server_properties =
8666 session->http_server_properties();
8667 const int kUnsafePort = 7;
8668 http_server_properties->SetAlternateProtocol(
8669 HostPortPair::FromURL(request.url),
8670 kUnsafePort,
8671 AlternateProtocolFromNextProto(GetParam()));
8673 scoped_ptr<HttpTransaction> trans(
8674 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8675 TestCompletionCallback callback;
8677 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8678 EXPECT_EQ(ERR_IO_PENDING, rv);
8679 // The HTTP request should succeed.
8680 EXPECT_EQ(OK, callback.WaitForResult());
8682 // Disable alternate protocol before the asserts.
8683 // HttpStreamFactory::set_use_alternate_protocols(false);
8685 const HttpResponseInfo* response = trans->GetResponseInfo();
8686 ASSERT_TRUE(response != NULL);
8687 ASSERT_TRUE(response->headers.get() != NULL);
8688 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8690 std::string response_data;
8691 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8692 EXPECT_EQ("hello world", response_data);
8695 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8696 session_deps_.use_alternate_protocols = true;
8697 session_deps_.next_protos = SpdyNextProtos();
8699 HttpRequestInfo request;
8700 request.method = "GET";
8701 request.url = GURL("http://www.google.com/");
8702 request.load_flags = 0;
8704 std::string alternate_protocol_http_header =
8705 GetAlternateProtocolHttpHeader();
8707 MockRead data_reads[] = {
8708 MockRead("HTTP/1.1 200 OK\r\n"),
8709 MockRead(alternate_protocol_http_header.c_str()),
8710 MockRead("hello world"),
8711 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8712 MockRead(ASYNC, OK)
8715 StaticSocketDataProvider first_transaction(
8716 data_reads, arraysize(data_reads), NULL, 0);
8717 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8719 SSLSocketDataProvider ssl(ASYNC, OK);
8720 ssl.SetNextProto(GetParam());
8721 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8723 scoped_ptr<SpdyFrame> req(
8724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8725 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8727 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8728 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8729 MockRead spdy_reads[] = {
8730 CreateMockRead(*resp),
8731 CreateMockRead(*data),
8732 MockRead(ASYNC, 0, 0),
8735 DelayedSocketData spdy_data(
8736 1, // wait for one write to finish before reading.
8737 spdy_reads, arraysize(spdy_reads),
8738 spdy_writes, arraysize(spdy_writes));
8739 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8741 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8742 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8743 NULL, 0, NULL, 0);
8744 hanging_non_alternate_protocol_socket.set_connect_data(
8745 never_finishing_connect);
8746 session_deps_.socket_factory->AddSocketDataProvider(
8747 &hanging_non_alternate_protocol_socket);
8749 TestCompletionCallback callback;
8751 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8752 scoped_ptr<HttpTransaction> trans(
8753 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8755 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8756 EXPECT_EQ(ERR_IO_PENDING, rv);
8757 EXPECT_EQ(OK, callback.WaitForResult());
8759 const HttpResponseInfo* response = trans->GetResponseInfo();
8760 ASSERT_TRUE(response != NULL);
8761 ASSERT_TRUE(response->headers.get() != NULL);
8762 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8764 std::string response_data;
8765 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8766 EXPECT_EQ("hello world", response_data);
8768 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8770 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8771 EXPECT_EQ(ERR_IO_PENDING, rv);
8772 EXPECT_EQ(OK, callback.WaitForResult());
8774 response = trans->GetResponseInfo();
8775 ASSERT_TRUE(response != NULL);
8776 ASSERT_TRUE(response->headers.get() != NULL);
8777 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8778 EXPECT_TRUE(response->was_fetched_via_spdy);
8779 EXPECT_TRUE(response->was_npn_negotiated);
8781 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8782 EXPECT_EQ("hello!", response_data);
8785 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8786 session_deps_.use_alternate_protocols = true;
8787 session_deps_.next_protos = SpdyNextProtos();
8789 HttpRequestInfo request;
8790 request.method = "GET";
8791 request.url = GURL("http://www.google.com/");
8792 request.load_flags = 0;
8794 std::string alternate_protocol_http_header =
8795 GetAlternateProtocolHttpHeader();
8797 MockRead data_reads[] = {
8798 MockRead("HTTP/1.1 200 OK\r\n"),
8799 MockRead(alternate_protocol_http_header.c_str()),
8800 MockRead("hello world"),
8801 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8802 MockRead(ASYNC, OK),
8805 StaticSocketDataProvider first_transaction(
8806 data_reads, arraysize(data_reads), NULL, 0);
8807 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8808 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8810 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8811 StaticSocketDataProvider hanging_socket(
8812 NULL, 0, NULL, 0);
8813 hanging_socket.set_connect_data(never_finishing_connect);
8814 // Socket 2 and 3 are the hanging Alternate-Protocol and
8815 // non-Alternate-Protocol jobs from the 2nd transaction.
8816 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8817 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8819 SSLSocketDataProvider ssl(ASYNC, OK);
8820 ssl.SetNextProto(GetParam());
8821 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8823 scoped_ptr<SpdyFrame> req1(
8824 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8825 scoped_ptr<SpdyFrame> req2(
8826 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8827 MockWrite spdy_writes[] = {
8828 CreateMockWrite(*req1),
8829 CreateMockWrite(*req2),
8831 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8832 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8833 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8834 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8835 MockRead spdy_reads[] = {
8836 CreateMockRead(*resp1),
8837 CreateMockRead(*data1),
8838 CreateMockRead(*resp2),
8839 CreateMockRead(*data2),
8840 MockRead(ASYNC, 0, 0),
8843 DelayedSocketData spdy_data(
8844 2, // wait for writes to finish before reading.
8845 spdy_reads, arraysize(spdy_reads),
8846 spdy_writes, arraysize(spdy_writes));
8847 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8848 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8850 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8851 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8853 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8854 TestCompletionCallback callback1;
8855 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8857 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8858 EXPECT_EQ(ERR_IO_PENDING, rv);
8859 EXPECT_EQ(OK, callback1.WaitForResult());
8861 const HttpResponseInfo* response = trans1.GetResponseInfo();
8862 ASSERT_TRUE(response != NULL);
8863 ASSERT_TRUE(response->headers.get() != NULL);
8864 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8866 std::string response_data;
8867 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8868 EXPECT_EQ("hello world", response_data);
8870 TestCompletionCallback callback2;
8871 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8872 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8873 EXPECT_EQ(ERR_IO_PENDING, rv);
8875 TestCompletionCallback callback3;
8876 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8877 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8878 EXPECT_EQ(ERR_IO_PENDING, rv);
8880 EXPECT_EQ(OK, callback2.WaitForResult());
8881 EXPECT_EQ(OK, callback3.WaitForResult());
8883 response = trans2.GetResponseInfo();
8884 ASSERT_TRUE(response != NULL);
8885 ASSERT_TRUE(response->headers.get() != NULL);
8886 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8887 EXPECT_TRUE(response->was_fetched_via_spdy);
8888 EXPECT_TRUE(response->was_npn_negotiated);
8889 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8890 EXPECT_EQ("hello!", response_data);
8892 response = trans3.GetResponseInfo();
8893 ASSERT_TRUE(response != NULL);
8894 ASSERT_TRUE(response->headers.get() != NULL);
8895 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8896 EXPECT_TRUE(response->was_fetched_via_spdy);
8897 EXPECT_TRUE(response->was_npn_negotiated);
8898 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
8899 EXPECT_EQ("hello!", response_data);
8902 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
8903 session_deps_.use_alternate_protocols = true;
8904 session_deps_.next_protos = SpdyNextProtos();
8906 HttpRequestInfo request;
8907 request.method = "GET";
8908 request.url = GURL("http://www.google.com/");
8909 request.load_flags = 0;
8911 std::string alternate_protocol_http_header =
8912 GetAlternateProtocolHttpHeader();
8914 MockRead data_reads[] = {
8915 MockRead("HTTP/1.1 200 OK\r\n"),
8916 MockRead(alternate_protocol_http_header.c_str()),
8917 MockRead("hello world"),
8918 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8919 MockRead(ASYNC, OK),
8922 StaticSocketDataProvider first_transaction(
8923 data_reads, arraysize(data_reads), NULL, 0);
8924 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8926 SSLSocketDataProvider ssl(ASYNC, OK);
8927 ssl.SetNextProto(GetParam());
8928 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8930 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8931 StaticSocketDataProvider hanging_alternate_protocol_socket(
8932 NULL, 0, NULL, 0);
8933 hanging_alternate_protocol_socket.set_connect_data(
8934 never_finishing_connect);
8935 session_deps_.socket_factory->AddSocketDataProvider(
8936 &hanging_alternate_protocol_socket);
8938 // 2nd request is just a copy of the first one, over HTTP again.
8939 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8941 TestCompletionCallback callback;
8943 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8944 scoped_ptr<HttpTransaction> trans(
8945 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8947 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8948 EXPECT_EQ(ERR_IO_PENDING, rv);
8949 EXPECT_EQ(OK, callback.WaitForResult());
8951 const HttpResponseInfo* response = trans->GetResponseInfo();
8952 ASSERT_TRUE(response != NULL);
8953 ASSERT_TRUE(response->headers.get() != NULL);
8954 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8956 std::string response_data;
8957 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8958 EXPECT_EQ("hello world", response_data);
8960 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8962 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8963 EXPECT_EQ(ERR_IO_PENDING, rv);
8964 EXPECT_EQ(OK, callback.WaitForResult());
8966 response = trans->GetResponseInfo();
8967 ASSERT_TRUE(response != NULL);
8968 ASSERT_TRUE(response->headers.get() != NULL);
8969 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8970 EXPECT_FALSE(response->was_fetched_via_spdy);
8971 EXPECT_FALSE(response->was_npn_negotiated);
8973 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8974 EXPECT_EQ("hello world", response_data);
8977 class CapturingProxyResolver : public ProxyResolver {
8978 public:
8979 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8980 virtual ~CapturingProxyResolver() {}
8982 virtual int GetProxyForURL(const GURL& url,
8983 ProxyInfo* results,
8984 const CompletionCallback& callback,
8985 RequestHandle* request,
8986 const BoundNetLog& net_log) OVERRIDE {
8987 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
8988 HostPortPair("myproxy", 80));
8989 results->UseProxyServer(proxy_server);
8990 resolved_.push_back(url);
8991 return OK;
8994 virtual void CancelRequest(RequestHandle request) OVERRIDE {
8995 NOTREACHED();
8998 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
8999 NOTREACHED();
9000 return LOAD_STATE_IDLE;
9003 virtual void CancelSetPacScript() OVERRIDE {
9004 NOTREACHED();
9007 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9008 const CompletionCallback& /*callback*/) OVERRIDE {
9009 return OK;
9012 const std::vector<GURL>& resolved() const { return resolved_; }
9014 private:
9015 std::vector<GURL> resolved_;
9017 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9020 TEST_P(HttpNetworkTransactionTest,
9021 UseAlternateProtocolForTunneledNpnSpdy) {
9022 session_deps_.use_alternate_protocols = true;
9023 session_deps_.next_protos = SpdyNextProtos();
9025 ProxyConfig proxy_config;
9026 proxy_config.set_auto_detect(true);
9027 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9029 CapturingProxyResolver* capturing_proxy_resolver =
9030 new CapturingProxyResolver();
9031 session_deps_.proxy_service.reset(new ProxyService(
9032 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
9033 NULL));
9034 CapturingNetLog net_log;
9035 session_deps_.net_log = &net_log;
9037 HttpRequestInfo request;
9038 request.method = "GET";
9039 request.url = GURL("http://www.google.com/");
9040 request.load_flags = 0;
9042 std::string alternate_protocol_http_header =
9043 GetAlternateProtocolHttpHeader();
9045 MockRead data_reads[] = {
9046 MockRead("HTTP/1.1 200 OK\r\n"),
9047 MockRead(alternate_protocol_http_header.c_str()),
9048 MockRead("hello world"),
9049 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9050 MockRead(ASYNC, OK),
9053 StaticSocketDataProvider first_transaction(
9054 data_reads, arraysize(data_reads), NULL, 0);
9055 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9057 SSLSocketDataProvider ssl(ASYNC, OK);
9058 ssl.SetNextProto(GetParam());
9059 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9061 scoped_ptr<SpdyFrame> req(
9062 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9063 MockWrite spdy_writes[] = {
9064 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9065 "Host: www.google.com\r\n"
9066 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9067 CreateMockWrite(*req), // 3
9070 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9072 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9073 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9074 MockRead spdy_reads[] = {
9075 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
9076 CreateMockRead(*resp.get(), 4), // 2, 4
9077 CreateMockRead(*data.get(), 4), // 5
9078 MockRead(ASYNC, 0, 0, 4), // 6
9081 OrderedSocketData spdy_data(
9082 spdy_reads, arraysize(spdy_reads),
9083 spdy_writes, arraysize(spdy_writes));
9084 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9086 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9087 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9088 NULL, 0, NULL, 0);
9089 hanging_non_alternate_protocol_socket.set_connect_data(
9090 never_finishing_connect);
9091 session_deps_.socket_factory->AddSocketDataProvider(
9092 &hanging_non_alternate_protocol_socket);
9094 TestCompletionCallback callback;
9096 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9097 scoped_ptr<HttpTransaction> trans(
9098 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9100 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9101 EXPECT_EQ(ERR_IO_PENDING, rv);
9102 EXPECT_EQ(OK, callback.WaitForResult());
9104 const HttpResponseInfo* response = trans->GetResponseInfo();
9105 ASSERT_TRUE(response != NULL);
9106 ASSERT_TRUE(response->headers.get() != NULL);
9107 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9108 EXPECT_FALSE(response->was_fetched_via_spdy);
9109 EXPECT_FALSE(response->was_npn_negotiated);
9111 std::string response_data;
9112 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9113 EXPECT_EQ("hello world", response_data);
9115 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9117 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9118 EXPECT_EQ(ERR_IO_PENDING, rv);
9119 EXPECT_EQ(OK, callback.WaitForResult());
9121 response = trans->GetResponseInfo();
9122 ASSERT_TRUE(response != NULL);
9123 ASSERT_TRUE(response->headers.get() != NULL);
9124 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9125 EXPECT_TRUE(response->was_fetched_via_spdy);
9126 EXPECT_TRUE(response->was_npn_negotiated);
9128 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9129 EXPECT_EQ("hello!", response_data);
9130 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
9131 EXPECT_EQ("http://www.google.com/",
9132 capturing_proxy_resolver->resolved()[0].spec());
9133 EXPECT_EQ("https://www.google.com/",
9134 capturing_proxy_resolver->resolved()[1].spec());
9136 LoadTimingInfo load_timing_info;
9137 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9138 TestLoadTimingNotReusedWithPac(load_timing_info,
9139 CONNECT_TIMING_HAS_SSL_TIMES);
9142 TEST_P(HttpNetworkTransactionTest,
9143 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9144 session_deps_.use_alternate_protocols = true;
9145 session_deps_.next_protos = SpdyNextProtos();
9147 HttpRequestInfo request;
9148 request.method = "GET";
9149 request.url = GURL("http://www.google.com/");
9150 request.load_flags = 0;
9152 std::string alternate_protocol_http_header =
9153 GetAlternateProtocolHttpHeader();
9155 MockRead data_reads[] = {
9156 MockRead("HTTP/1.1 200 OK\r\n"),
9157 MockRead(alternate_protocol_http_header.c_str()),
9158 MockRead("hello world"),
9159 MockRead(ASYNC, OK),
9162 StaticSocketDataProvider first_transaction(
9163 data_reads, arraysize(data_reads), NULL, 0);
9164 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9166 SSLSocketDataProvider ssl(ASYNC, OK);
9167 ssl.SetNextProto(GetParam());
9168 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9170 scoped_ptr<SpdyFrame> req(
9171 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9172 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9174 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9175 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9176 MockRead spdy_reads[] = {
9177 CreateMockRead(*resp),
9178 CreateMockRead(*data),
9179 MockRead(ASYNC, 0, 0),
9182 DelayedSocketData spdy_data(
9183 1, // wait for one write to finish before reading.
9184 spdy_reads, arraysize(spdy_reads),
9185 spdy_writes, arraysize(spdy_writes));
9186 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9188 TestCompletionCallback callback;
9190 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9192 scoped_ptr<HttpTransaction> trans(
9193 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9195 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9196 EXPECT_EQ(ERR_IO_PENDING, rv);
9197 EXPECT_EQ(OK, callback.WaitForResult());
9199 const HttpResponseInfo* response = trans->GetResponseInfo();
9200 ASSERT_TRUE(response != NULL);
9201 ASSERT_TRUE(response->headers.get() != NULL);
9202 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9204 std::string response_data;
9205 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9206 EXPECT_EQ("hello world", response_data);
9208 // Set up an initial SpdySession in the pool to reuse.
9209 HostPortPair host_port_pair("www.google.com", 443);
9210 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9211 PRIVACY_MODE_DISABLED);
9212 base::WeakPtr<SpdySession> spdy_session =
9213 CreateSecureSpdySession(session, key, BoundNetLog());
9215 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9217 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9218 EXPECT_EQ(ERR_IO_PENDING, rv);
9219 EXPECT_EQ(OK, callback.WaitForResult());
9221 response = trans->GetResponseInfo();
9222 ASSERT_TRUE(response != NULL);
9223 ASSERT_TRUE(response->headers.get() != NULL);
9224 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9225 EXPECT_TRUE(response->was_fetched_via_spdy);
9226 EXPECT_TRUE(response->was_npn_negotiated);
9228 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9229 EXPECT_EQ("hello!", response_data);
9232 // GenerateAuthToken is a mighty big test.
9233 // It tests all permutation of GenerateAuthToken behavior:
9234 // - Synchronous and Asynchronous completion.
9235 // - OK or error on completion.
9236 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9237 // - HTTP or HTTPS backend (to include proxy tunneling).
9238 // - Non-authenticating and authenticating backend.
9240 // In all, there are 44 reasonable permuations (for example, if there are
9241 // problems generating an auth token for an authenticating proxy, we don't
9242 // need to test all permutations of the backend server).
9244 // The test proceeds by going over each of the configuration cases, and
9245 // potentially running up to three rounds in each of the tests. The TestConfig
9246 // specifies both the configuration for the test as well as the expectations
9247 // for the results.
9248 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9249 static const char kServer[] = "http://www.example.com";
9250 static const char kSecureServer[] = "https://www.example.com";
9251 static const char kProxy[] = "myproxy:70";
9252 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9254 enum AuthTiming {
9255 AUTH_NONE,
9256 AUTH_SYNC,
9257 AUTH_ASYNC,
9260 const MockWrite kGet(
9261 "GET / HTTP/1.1\r\n"
9262 "Host: www.example.com\r\n"
9263 "Connection: keep-alive\r\n\r\n");
9264 const MockWrite kGetProxy(
9265 "GET http://www.example.com/ HTTP/1.1\r\n"
9266 "Host: www.example.com\r\n"
9267 "Proxy-Connection: keep-alive\r\n\r\n");
9268 const MockWrite kGetAuth(
9269 "GET / HTTP/1.1\r\n"
9270 "Host: www.example.com\r\n"
9271 "Connection: keep-alive\r\n"
9272 "Authorization: auth_token\r\n\r\n");
9273 const MockWrite kGetProxyAuth(
9274 "GET http://www.example.com/ HTTP/1.1\r\n"
9275 "Host: www.example.com\r\n"
9276 "Proxy-Connection: keep-alive\r\n"
9277 "Proxy-Authorization: auth_token\r\n\r\n");
9278 const MockWrite kGetAuthThroughProxy(
9279 "GET http://www.example.com/ HTTP/1.1\r\n"
9280 "Host: www.example.com\r\n"
9281 "Proxy-Connection: keep-alive\r\n"
9282 "Authorization: auth_token\r\n\r\n");
9283 const MockWrite kGetAuthWithProxyAuth(
9284 "GET http://www.example.com/ HTTP/1.1\r\n"
9285 "Host: www.example.com\r\n"
9286 "Proxy-Connection: keep-alive\r\n"
9287 "Proxy-Authorization: auth_token\r\n"
9288 "Authorization: auth_token\r\n\r\n");
9289 const MockWrite kConnect(
9290 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9291 "Host: www.example.com\r\n"
9292 "Proxy-Connection: keep-alive\r\n\r\n");
9293 const MockWrite kConnectProxyAuth(
9294 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9295 "Host: www.example.com\r\n"
9296 "Proxy-Connection: keep-alive\r\n"
9297 "Proxy-Authorization: auth_token\r\n\r\n");
9299 const MockRead kSuccess(
9300 "HTTP/1.1 200 OK\r\n"
9301 "Content-Type: text/html; charset=iso-8859-1\r\n"
9302 "Content-Length: 3\r\n\r\n"
9303 "Yes");
9304 const MockRead kFailure(
9305 "Should not be called.");
9306 const MockRead kServerChallenge(
9307 "HTTP/1.1 401 Unauthorized\r\n"
9308 "WWW-Authenticate: Mock realm=server\r\n"
9309 "Content-Type: text/html; charset=iso-8859-1\r\n"
9310 "Content-Length: 14\r\n\r\n"
9311 "Unauthorized\r\n");
9312 const MockRead kProxyChallenge(
9313 "HTTP/1.1 407 Unauthorized\r\n"
9314 "Proxy-Authenticate: Mock realm=proxy\r\n"
9315 "Proxy-Connection: close\r\n"
9316 "Content-Type: text/html; charset=iso-8859-1\r\n"
9317 "Content-Length: 14\r\n\r\n"
9318 "Unauthorized\r\n");
9319 const MockRead kProxyConnected(
9320 "HTTP/1.1 200 Connection Established\r\n\r\n");
9322 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9323 // no constructors, but the C++ compiler on Windows warns about
9324 // unspecified data in compound literals. So, moved to using constructors,
9325 // and TestRound's created with the default constructor should not be used.
9326 struct TestRound {
9327 TestRound()
9328 : expected_rv(ERR_UNEXPECTED),
9329 extra_write(NULL),
9330 extra_read(NULL) {
9332 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9333 int expected_rv_arg)
9334 : write(write_arg),
9335 read(read_arg),
9336 expected_rv(expected_rv_arg),
9337 extra_write(NULL),
9338 extra_read(NULL) {
9340 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9341 int expected_rv_arg, const MockWrite* extra_write_arg,
9342 const MockRead* extra_read_arg)
9343 : write(write_arg),
9344 read(read_arg),
9345 expected_rv(expected_rv_arg),
9346 extra_write(extra_write_arg),
9347 extra_read(extra_read_arg) {
9349 MockWrite write;
9350 MockRead read;
9351 int expected_rv;
9352 const MockWrite* extra_write;
9353 const MockRead* extra_read;
9356 static const int kNoSSL = 500;
9358 struct TestConfig {
9359 const char* proxy_url;
9360 AuthTiming proxy_auth_timing;
9361 int proxy_auth_rv;
9362 const char* server_url;
9363 AuthTiming server_auth_timing;
9364 int server_auth_rv;
9365 int num_auth_rounds;
9366 int first_ssl_round;
9367 TestRound rounds[3];
9368 } test_configs[] = {
9369 // Non-authenticating HTTP server with a direct connection.
9370 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9371 { TestRound(kGet, kSuccess, OK)}},
9372 // Authenticating HTTP server with a direct connection.
9373 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9374 { TestRound(kGet, kServerChallenge, OK),
9375 TestRound(kGetAuth, kSuccess, OK)}},
9376 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9377 { TestRound(kGet, kServerChallenge, OK),
9378 TestRound(kGetAuth, kFailure, kAuthErr)}},
9379 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9380 { TestRound(kGet, kServerChallenge, OK),
9381 TestRound(kGetAuth, kSuccess, OK)}},
9382 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9383 { TestRound(kGet, kServerChallenge, OK),
9384 TestRound(kGetAuth, kFailure, kAuthErr)}},
9385 // Non-authenticating HTTP server through a non-authenticating proxy.
9386 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9387 { TestRound(kGetProxy, kSuccess, OK)}},
9388 // Authenticating HTTP server through a non-authenticating proxy.
9389 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9390 { TestRound(kGetProxy, kServerChallenge, OK),
9391 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9392 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9393 { TestRound(kGetProxy, kServerChallenge, OK),
9394 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9395 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9396 { TestRound(kGetProxy, kServerChallenge, OK),
9397 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9398 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9399 { TestRound(kGetProxy, kServerChallenge, OK),
9400 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9401 // Non-authenticating HTTP server through an authenticating proxy.
9402 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9403 { TestRound(kGetProxy, kProxyChallenge, OK),
9404 TestRound(kGetProxyAuth, kSuccess, OK)}},
9405 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9406 { TestRound(kGetProxy, kProxyChallenge, OK),
9407 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9408 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9409 { TestRound(kGetProxy, kProxyChallenge, OK),
9410 TestRound(kGetProxyAuth, kSuccess, OK)}},
9411 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9412 { TestRound(kGetProxy, kProxyChallenge, OK),
9413 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9414 // Authenticating HTTP server through an authenticating proxy.
9415 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9416 { TestRound(kGetProxy, kProxyChallenge, OK),
9417 TestRound(kGetProxyAuth, kServerChallenge, OK),
9418 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9419 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9420 { TestRound(kGetProxy, kProxyChallenge, OK),
9421 TestRound(kGetProxyAuth, kServerChallenge, OK),
9422 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9423 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9424 { TestRound(kGetProxy, kProxyChallenge, OK),
9425 TestRound(kGetProxyAuth, kServerChallenge, OK),
9426 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9427 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9428 { TestRound(kGetProxy, kProxyChallenge, OK),
9429 TestRound(kGetProxyAuth, kServerChallenge, OK),
9430 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9431 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9432 { TestRound(kGetProxy, kProxyChallenge, OK),
9433 TestRound(kGetProxyAuth, kServerChallenge, OK),
9434 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9435 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9436 { TestRound(kGetProxy, kProxyChallenge, OK),
9437 TestRound(kGetProxyAuth, kServerChallenge, OK),
9438 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9439 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9440 { TestRound(kGetProxy, kProxyChallenge, OK),
9441 TestRound(kGetProxyAuth, kServerChallenge, OK),
9442 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9443 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9444 { TestRound(kGetProxy, kProxyChallenge, OK),
9445 TestRound(kGetProxyAuth, kServerChallenge, OK),
9446 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9447 // Non-authenticating HTTPS server with a direct connection.
9448 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9449 { TestRound(kGet, kSuccess, OK)}},
9450 // Authenticating HTTPS server with a direct connection.
9451 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9452 { TestRound(kGet, kServerChallenge, OK),
9453 TestRound(kGetAuth, kSuccess, OK)}},
9454 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9455 { TestRound(kGet, kServerChallenge, OK),
9456 TestRound(kGetAuth, kFailure, kAuthErr)}},
9457 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9458 { TestRound(kGet, kServerChallenge, OK),
9459 TestRound(kGetAuth, kSuccess, OK)}},
9460 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9461 { TestRound(kGet, kServerChallenge, OK),
9462 TestRound(kGetAuth, kFailure, kAuthErr)}},
9463 // Non-authenticating HTTPS server with a non-authenticating proxy.
9464 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9465 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9466 // Authenticating HTTPS server through a non-authenticating proxy.
9467 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9468 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9469 TestRound(kGetAuth, kSuccess, OK)}},
9470 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9471 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9472 TestRound(kGetAuth, kFailure, kAuthErr)}},
9473 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9474 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9475 TestRound(kGetAuth, kSuccess, OK)}},
9476 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9477 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9478 TestRound(kGetAuth, kFailure, kAuthErr)}},
9479 // Non-Authenticating HTTPS server through an authenticating proxy.
9480 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9481 { TestRound(kConnect, kProxyChallenge, OK),
9482 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9483 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9484 { TestRound(kConnect, kProxyChallenge, OK),
9485 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9486 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9487 { TestRound(kConnect, kProxyChallenge, OK),
9488 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9489 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9490 { TestRound(kConnect, kProxyChallenge, OK),
9491 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9492 // Authenticating HTTPS server through an authenticating proxy.
9493 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9494 { TestRound(kConnect, kProxyChallenge, OK),
9495 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9496 &kGet, &kServerChallenge),
9497 TestRound(kGetAuth, kSuccess, OK)}},
9498 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9499 { TestRound(kConnect, kProxyChallenge, OK),
9500 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9501 &kGet, &kServerChallenge),
9502 TestRound(kGetAuth, kFailure, kAuthErr)}},
9503 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9504 { TestRound(kConnect, kProxyChallenge, OK),
9505 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9506 &kGet, &kServerChallenge),
9507 TestRound(kGetAuth, kSuccess, OK)}},
9508 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9509 { TestRound(kConnect, kProxyChallenge, OK),
9510 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9511 &kGet, &kServerChallenge),
9512 TestRound(kGetAuth, kFailure, kAuthErr)}},
9513 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9514 { TestRound(kConnect, kProxyChallenge, OK),
9515 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9516 &kGet, &kServerChallenge),
9517 TestRound(kGetAuth, kSuccess, OK)}},
9518 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9519 { TestRound(kConnect, kProxyChallenge, OK),
9520 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9521 &kGet, &kServerChallenge),
9522 TestRound(kGetAuth, kFailure, kAuthErr)}},
9523 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9524 { TestRound(kConnect, kProxyChallenge, OK),
9525 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9526 &kGet, &kServerChallenge),
9527 TestRound(kGetAuth, kSuccess, OK)}},
9528 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9529 { TestRound(kConnect, kProxyChallenge, OK),
9530 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9531 &kGet, &kServerChallenge),
9532 TestRound(kGetAuth, kFailure, kAuthErr)}},
9535 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9536 HttpAuthHandlerMock::Factory* auth_factory(
9537 new HttpAuthHandlerMock::Factory());
9538 session_deps_.http_auth_handler_factory.reset(auth_factory);
9539 const TestConfig& test_config = test_configs[i];
9541 // Set up authentication handlers as necessary.
9542 if (test_config.proxy_auth_timing != AUTH_NONE) {
9543 for (int n = 0; n < 2; n++) {
9544 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9545 std::string auth_challenge = "Mock realm=proxy";
9546 GURL origin(test_config.proxy_url);
9547 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9548 auth_challenge.end());
9549 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9550 origin, BoundNetLog());
9551 auth_handler->SetGenerateExpectation(
9552 test_config.proxy_auth_timing == AUTH_ASYNC,
9553 test_config.proxy_auth_rv);
9554 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9557 if (test_config.server_auth_timing != AUTH_NONE) {
9558 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9559 std::string auth_challenge = "Mock realm=server";
9560 GURL origin(test_config.server_url);
9561 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9562 auth_challenge.end());
9563 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9564 origin, BoundNetLog());
9565 auth_handler->SetGenerateExpectation(
9566 test_config.server_auth_timing == AUTH_ASYNC,
9567 test_config.server_auth_rv);
9568 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9570 if (test_config.proxy_url) {
9571 session_deps_.proxy_service.reset(
9572 ProxyService::CreateFixed(test_config.proxy_url));
9573 } else {
9574 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9577 HttpRequestInfo request;
9578 request.method = "GET";
9579 request.url = GURL(test_config.server_url);
9580 request.load_flags = 0;
9582 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9583 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
9585 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9586 const TestRound& read_write_round = test_config.rounds[round];
9588 // Set up expected reads and writes.
9589 MockRead reads[2];
9590 reads[0] = read_write_round.read;
9591 size_t length_reads = 1;
9592 if (read_write_round.extra_read) {
9593 reads[1] = *read_write_round.extra_read;
9594 length_reads = 2;
9597 MockWrite writes[2];
9598 writes[0] = read_write_round.write;
9599 size_t length_writes = 1;
9600 if (read_write_round.extra_write) {
9601 writes[1] = *read_write_round.extra_write;
9602 length_writes = 2;
9604 StaticSocketDataProvider data_provider(
9605 reads, length_reads, writes, length_writes);
9606 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9608 // Add an SSL sequence if necessary.
9609 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9610 if (round >= test_config.first_ssl_round)
9611 session_deps_.socket_factory->AddSSLSocketDataProvider(
9612 &ssl_socket_data_provider);
9614 // Start or restart the transaction.
9615 TestCompletionCallback callback;
9616 int rv;
9617 if (round == 0) {
9618 rv = trans.Start(&request, callback.callback(), BoundNetLog());
9619 } else {
9620 rv = trans.RestartWithAuth(
9621 AuthCredentials(kFoo, kBar), callback.callback());
9623 if (rv == ERR_IO_PENDING)
9624 rv = callback.WaitForResult();
9626 // Compare results with expected data.
9627 EXPECT_EQ(read_write_round.expected_rv, rv);
9628 const HttpResponseInfo* response = trans.GetResponseInfo();
9629 if (read_write_round.expected_rv == OK) {
9630 ASSERT_TRUE(response != NULL);
9631 } else {
9632 EXPECT_TRUE(response == NULL);
9633 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9634 continue;
9636 if (round + 1 < test_config.num_auth_rounds) {
9637 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9638 } else {
9639 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9645 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9646 // Do multi-round authentication and make sure it works correctly.
9647 HttpAuthHandlerMock::Factory* auth_factory(
9648 new HttpAuthHandlerMock::Factory());
9649 session_deps_.http_auth_handler_factory.reset(auth_factory);
9650 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9651 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9652 session_deps_.host_resolver->set_synchronous_mode(true);
9654 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9655 auth_handler->set_connection_based(true);
9656 std::string auth_challenge = "Mock realm=server";
9657 GURL origin("http://www.example.com");
9658 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9659 auth_challenge.end());
9660 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9661 origin, BoundNetLog());
9662 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9664 int rv = OK;
9665 const HttpResponseInfo* response = NULL;
9666 HttpRequestInfo request;
9667 request.method = "GET";
9668 request.url = origin;
9669 request.load_flags = 0;
9671 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9673 // Use a TCP Socket Pool with only one connection per group. This is used
9674 // to validate that the TCP socket is not released to the pool between
9675 // each round of multi-round authentication.
9676 HttpNetworkSessionPeer session_peer(session);
9677 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9678 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9679 50, // Max sockets for pool
9680 1, // Max sockets per group
9681 &transport_pool_histograms,
9682 session_deps_.host_resolver.get(),
9683 session_deps_.socket_factory.get(),
9684 session_deps_.net_log);
9685 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
9686 new MockClientSocketPoolManager);
9687 mock_pool_manager->SetTransportSocketPool(transport_pool);
9688 session_peer.SetClientSocketPoolManager(
9689 mock_pool_manager.PassAs<ClientSocketPoolManager>());
9691 scoped_ptr<HttpTransaction> trans(
9692 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9693 TestCompletionCallback callback;
9695 const MockWrite kGet(
9696 "GET / HTTP/1.1\r\n"
9697 "Host: www.example.com\r\n"
9698 "Connection: keep-alive\r\n\r\n");
9699 const MockWrite kGetAuth(
9700 "GET / HTTP/1.1\r\n"
9701 "Host: www.example.com\r\n"
9702 "Connection: keep-alive\r\n"
9703 "Authorization: auth_token\r\n\r\n");
9705 const MockRead kServerChallenge(
9706 "HTTP/1.1 401 Unauthorized\r\n"
9707 "WWW-Authenticate: Mock realm=server\r\n"
9708 "Content-Type: text/html; charset=iso-8859-1\r\n"
9709 "Content-Length: 14\r\n\r\n"
9710 "Unauthorized\r\n");
9711 const MockRead kSuccess(
9712 "HTTP/1.1 200 OK\r\n"
9713 "Content-Type: text/html; charset=iso-8859-1\r\n"
9714 "Content-Length: 3\r\n\r\n"
9715 "Yes");
9717 MockWrite writes[] = {
9718 // First round
9719 kGet,
9720 // Second round
9721 kGetAuth,
9722 // Third round
9723 kGetAuth,
9724 // Fourth round
9725 kGetAuth,
9726 // Competing request
9727 kGet,
9729 MockRead reads[] = {
9730 // First round
9731 kServerChallenge,
9732 // Second round
9733 kServerChallenge,
9734 // Third round
9735 kServerChallenge,
9736 // Fourth round
9737 kSuccess,
9738 // Competing response
9739 kSuccess,
9741 StaticSocketDataProvider data_provider(reads, arraysize(reads),
9742 writes, arraysize(writes));
9743 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9745 const char* const kSocketGroup = "www.example.com:80";
9747 // First round of authentication.
9748 auth_handler->SetGenerateExpectation(false, OK);
9749 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9750 if (rv == ERR_IO_PENDING)
9751 rv = callback.WaitForResult();
9752 EXPECT_EQ(OK, rv);
9753 response = trans->GetResponseInfo();
9754 ASSERT_TRUE(response != NULL);
9755 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9756 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9758 // In between rounds, another request comes in for the same domain.
9759 // It should not be able to grab the TCP socket that trans has already
9760 // claimed.
9761 scoped_ptr<HttpTransaction> trans_compete(
9762 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9763 TestCompletionCallback callback_compete;
9764 rv = trans_compete->Start(
9765 &request, callback_compete.callback(), BoundNetLog());
9766 EXPECT_EQ(ERR_IO_PENDING, rv);
9767 // callback_compete.WaitForResult at this point would stall forever,
9768 // since the HttpNetworkTransaction does not release the request back to
9769 // the pool until after authentication completes.
9771 // Second round of authentication.
9772 auth_handler->SetGenerateExpectation(false, OK);
9773 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9774 if (rv == ERR_IO_PENDING)
9775 rv = callback.WaitForResult();
9776 EXPECT_EQ(OK, rv);
9777 response = trans->GetResponseInfo();
9778 ASSERT_TRUE(response != NULL);
9779 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9780 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9782 // Third round of authentication.
9783 auth_handler->SetGenerateExpectation(false, OK);
9784 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9785 if (rv == ERR_IO_PENDING)
9786 rv = callback.WaitForResult();
9787 EXPECT_EQ(OK, rv);
9788 response = trans->GetResponseInfo();
9789 ASSERT_TRUE(response != NULL);
9790 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9791 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9793 // Fourth round of authentication, which completes successfully.
9794 auth_handler->SetGenerateExpectation(false, OK);
9795 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9796 if (rv == ERR_IO_PENDING)
9797 rv = callback.WaitForResult();
9798 EXPECT_EQ(OK, rv);
9799 response = trans->GetResponseInfo();
9800 ASSERT_TRUE(response != NULL);
9801 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9802 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9804 // Read the body since the fourth round was successful. This will also
9805 // release the socket back to the pool.
9806 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9807 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9808 if (rv == ERR_IO_PENDING)
9809 rv = callback.WaitForResult();
9810 EXPECT_EQ(3, rv);
9811 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9812 EXPECT_EQ(0, rv);
9813 // There are still 0 idle sockets, since the trans_compete transaction
9814 // will be handed it immediately after trans releases it to the group.
9815 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9817 // The competing request can now finish. Wait for the headers and then
9818 // read the body.
9819 rv = callback_compete.WaitForResult();
9820 EXPECT_EQ(OK, rv);
9821 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9822 if (rv == ERR_IO_PENDING)
9823 rv = callback.WaitForResult();
9824 EXPECT_EQ(3, rv);
9825 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9826 EXPECT_EQ(0, rv);
9828 // Finally, the socket is released to the group.
9829 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9832 // This tests the case that a request is issued via http instead of spdy after
9833 // npn is negotiated.
9834 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9835 session_deps_.use_alternate_protocols = true;
9836 NextProtoVector next_protos;
9837 next_protos.push_back(kProtoHTTP11);
9838 session_deps_.next_protos = next_protos;
9840 HttpRequestInfo request;
9841 request.method = "GET";
9842 request.url = GURL("https://www.google.com/");
9843 request.load_flags = 0;
9845 MockWrite data_writes[] = {
9846 MockWrite("GET / HTTP/1.1\r\n"
9847 "Host: www.google.com\r\n"
9848 "Connection: keep-alive\r\n\r\n"),
9851 std::string alternate_protocol_http_header =
9852 GetAlternateProtocolHttpHeader();
9854 MockRead data_reads[] = {
9855 MockRead("HTTP/1.1 200 OK\r\n"),
9856 MockRead(alternate_protocol_http_header.c_str()),
9857 MockRead("hello world"),
9858 MockRead(SYNCHRONOUS, OK),
9861 SSLSocketDataProvider ssl(ASYNC, OK);
9862 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9863 ssl.next_proto = "http/1.1";
9864 ssl.protocol_negotiated = kProtoHTTP11;
9866 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9868 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9869 data_writes, arraysize(data_writes));
9870 session_deps_.socket_factory->AddSocketDataProvider(&data);
9872 TestCompletionCallback callback;
9874 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9875 scoped_ptr<HttpTransaction> trans(
9876 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9878 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9880 EXPECT_EQ(ERR_IO_PENDING, rv);
9881 EXPECT_EQ(OK, callback.WaitForResult());
9883 const HttpResponseInfo* response = trans->GetResponseInfo();
9884 ASSERT_TRUE(response != NULL);
9885 ASSERT_TRUE(response->headers.get() != NULL);
9886 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9888 std::string response_data;
9889 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9890 EXPECT_EQ("hello world", response_data);
9892 EXPECT_FALSE(response->was_fetched_via_spdy);
9893 EXPECT_TRUE(response->was_npn_negotiated);
9896 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
9897 // Simulate the SSL handshake completing with an NPN negotiation
9898 // followed by an immediate server closing of the socket.
9899 // Fix crash: http://crbug.com/46369
9900 session_deps_.use_alternate_protocols = true;
9901 session_deps_.next_protos = SpdyNextProtos();
9903 HttpRequestInfo request;
9904 request.method = "GET";
9905 request.url = GURL("https://www.google.com/");
9906 request.load_flags = 0;
9908 SSLSocketDataProvider ssl(ASYNC, OK);
9909 ssl.SetNextProto(GetParam());
9910 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9912 scoped_ptr<SpdyFrame> req(
9913 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9914 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9916 MockRead spdy_reads[] = {
9917 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
9920 DelayedSocketData spdy_data(
9921 0, // don't wait in this case, immediate hangup.
9922 spdy_reads, arraysize(spdy_reads),
9923 spdy_writes, arraysize(spdy_writes));
9924 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9926 TestCompletionCallback callback;
9928 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9929 scoped_ptr<HttpTransaction> trans(
9930 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9932 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9933 EXPECT_EQ(ERR_IO_PENDING, rv);
9934 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
9937 // A subclass of HttpAuthHandlerMock that records the request URL when
9938 // it gets it. This is needed since the auth handler may get destroyed
9939 // before we get a chance to query it.
9940 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
9941 public:
9942 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
9944 virtual ~UrlRecordingHttpAuthHandlerMock() {}
9946 protected:
9947 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
9948 const HttpRequestInfo* request,
9949 const CompletionCallback& callback,
9950 std::string* auth_token) OVERRIDE {
9951 *url_ = request->url;
9952 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9953 credentials, request, callback, auth_token);
9956 private:
9957 GURL* url_;
9960 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
9961 // This test ensures that the URL passed into the proxy is upgraded
9962 // to https when doing an Alternate Protocol upgrade.
9963 session_deps_.use_alternate_protocols = true;
9964 session_deps_.next_protos = SpdyNextProtos();
9966 session_deps_.proxy_service.reset(
9967 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9968 CapturingNetLog net_log;
9969 session_deps_.net_log = &net_log;
9970 GURL request_url;
9972 HttpAuthHandlerMock::Factory* auth_factory =
9973 new HttpAuthHandlerMock::Factory();
9974 UrlRecordingHttpAuthHandlerMock* auth_handler =
9975 new UrlRecordingHttpAuthHandlerMock(&request_url);
9976 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9977 auth_factory->set_do_init_from_challenge(true);
9978 session_deps_.http_auth_handler_factory.reset(auth_factory);
9981 HttpRequestInfo request;
9982 request.method = "GET";
9983 request.url = GURL("http://www.google.com");
9984 request.load_flags = 0;
9986 // First round goes unauthenticated through the proxy.
9987 MockWrite data_writes_1[] = {
9988 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9989 "Host: www.google.com\r\n"
9990 "Proxy-Connection: keep-alive\r\n"
9991 "\r\n"),
9993 MockRead data_reads_1[] = {
9994 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9995 MockRead("HTTP/1.1 200 OK\r\n"
9996 "Alternate-Protocol: 443:npn-spdy/2\r\n"
9997 "Proxy-Connection: close\r\n"
9998 "\r\n"),
10000 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10001 data_writes_1, arraysize(data_writes_1));
10003 // Second round tries to tunnel to www.google.com due to the
10004 // Alternate-Protocol announcement in the first round. It fails due
10005 // to a proxy authentication challenge.
10006 // After the failure, a tunnel is established to www.google.com using
10007 // Proxy-Authorization headers. There is then a SPDY request round.
10009 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10010 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10011 // does a Disconnect and Connect on the same socket, rather than trying
10012 // to obtain a new one.
10014 // NOTE: Originally, the proxy response to the second CONNECT request
10015 // simply returned another 407 so the unit test could skip the SSL connection
10016 // establishment and SPDY framing issues. Alas, the
10017 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10018 // complicated to set up expectations for than the SPDY session.
10020 scoped_ptr<SpdyFrame> req(
10021 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10022 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10023 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10025 MockWrite data_writes_2[] = {
10026 // First connection attempt without Proxy-Authorization.
10027 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10028 "Host: www.google.com\r\n"
10029 "Proxy-Connection: keep-alive\r\n"
10030 "\r\n"),
10032 // Second connection attempt with Proxy-Authorization.
10033 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10034 "Host: www.google.com\r\n"
10035 "Proxy-Connection: keep-alive\r\n"
10036 "Proxy-Authorization: auth_token\r\n"
10037 "\r\n"),
10039 // SPDY request
10040 CreateMockWrite(*req),
10042 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10043 "Proxy-Authenticate: Mock\r\n"
10044 "Proxy-Connection: close\r\n"
10045 "\r\n");
10046 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10047 MockRead data_reads_2[] = {
10048 // First connection attempt fails
10049 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
10050 MockRead(ASYNC, kRejectConnectResponse,
10051 arraysize(kRejectConnectResponse) - 1, 1),
10053 // Second connection attempt passes
10054 MockRead(ASYNC, kAcceptConnectResponse,
10055 arraysize(kAcceptConnectResponse) -1, 4),
10057 // SPDY response
10058 CreateMockRead(*resp.get(), 6),
10059 CreateMockRead(*data.get(), 6),
10060 MockRead(ASYNC, 0, 0, 6),
10062 OrderedSocketData data_2(
10063 data_reads_2, arraysize(data_reads_2),
10064 data_writes_2, arraysize(data_writes_2));
10066 SSLSocketDataProvider ssl(ASYNC, OK);
10067 ssl.SetNextProto(GetParam());
10069 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10070 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10071 NULL, 0, NULL, 0);
10072 hanging_non_alternate_protocol_socket.set_connect_data(
10073 never_finishing_connect);
10075 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10076 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10077 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10078 session_deps_.socket_factory->AddSocketDataProvider(
10079 &hanging_non_alternate_protocol_socket);
10080 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10082 // First round should work and provide the Alternate-Protocol state.
10083 TestCompletionCallback callback_1;
10084 scoped_ptr<HttpTransaction> trans_1(
10085 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10086 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10087 EXPECT_EQ(ERR_IO_PENDING, rv);
10088 EXPECT_EQ(OK, callback_1.WaitForResult());
10090 // Second round should attempt a tunnel connect and get an auth challenge.
10091 TestCompletionCallback callback_2;
10092 scoped_ptr<HttpTransaction> trans_2(
10093 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10094 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10095 EXPECT_EQ(ERR_IO_PENDING, rv);
10096 EXPECT_EQ(OK, callback_2.WaitForResult());
10097 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10098 ASSERT_TRUE(response != NULL);
10099 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10101 // Restart with auth. Tunnel should work and response received.
10102 TestCompletionCallback callback_3;
10103 rv = trans_2->RestartWithAuth(
10104 AuthCredentials(kFoo, kBar), callback_3.callback());
10105 EXPECT_EQ(ERR_IO_PENDING, rv);
10106 EXPECT_EQ(OK, callback_3.WaitForResult());
10108 // After all that work, these two lines (or actually, just the scheme) are
10109 // what this test is all about. Make sure it happens correctly.
10110 EXPECT_EQ("https", request_url.scheme());
10111 EXPECT_EQ("www.google.com", request_url.host());
10113 LoadTimingInfo load_timing_info;
10114 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10115 TestLoadTimingNotReusedWithPac(load_timing_info,
10116 CONNECT_TIMING_HAS_SSL_TIMES);
10119 // Test that if we cancel the transaction as the connection is completing, that
10120 // everything tears down correctly.
10121 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10122 // Setup everything about the connection to complete synchronously, so that
10123 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10124 // for is the callback from the HttpStreamRequest.
10125 // Then cancel the transaction.
10126 // Verify that we don't crash.
10127 MockConnect mock_connect(SYNCHRONOUS, OK);
10128 MockRead data_reads[] = {
10129 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10130 MockRead(SYNCHRONOUS, "hello world"),
10131 MockRead(SYNCHRONOUS, OK),
10134 HttpRequestInfo request;
10135 request.method = "GET";
10136 request.url = GURL("http://www.google.com/");
10137 request.load_flags = 0;
10139 session_deps_.host_resolver->set_synchronous_mode(true);
10140 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10141 scoped_ptr<HttpTransaction> trans(
10142 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
10144 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10145 data.set_connect_data(mock_connect);
10146 session_deps_.socket_factory->AddSocketDataProvider(&data);
10148 TestCompletionCallback callback;
10150 CapturingBoundNetLog log;
10151 int rv = trans->Start(&request, callback.callback(), log.bound());
10152 EXPECT_EQ(ERR_IO_PENDING, rv);
10153 trans.reset(); // Cancel the transaction here.
10155 base::MessageLoop::current()->RunUntilIdle();
10158 // Test that if a transaction is cancelled after receiving the headers, the
10159 // stream is drained properly and added back to the socket pool. The main
10160 // purpose of this test is to make sure that an HttpStreamParser can be read
10161 // from after the HttpNetworkTransaction and the objects it owns have been
10162 // deleted.
10163 // See http://crbug.com/368418
10164 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10165 MockRead data_reads[] = {
10166 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10167 MockRead(ASYNC, "Content-Length: 2\r\n"),
10168 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10169 MockRead(ASYNC, "1"),
10170 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10171 // HttpNetworkTransaction has been deleted.
10172 MockRead(ASYNC, "2"),
10173 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10175 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10176 session_deps_.socket_factory->AddSocketDataProvider(&data);
10178 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10181 HttpRequestInfo request;
10182 request.method = "GET";
10183 request.url = GURL("http://www.google.com/");
10184 request.load_flags = 0;
10186 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
10187 TestCompletionCallback callback;
10189 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10190 EXPECT_EQ(ERR_IO_PENDING, rv);
10191 callback.WaitForResult();
10193 const HttpResponseInfo* response = trans.GetResponseInfo();
10194 ASSERT_TRUE(response != NULL);
10195 EXPECT_TRUE(response->headers.get() != NULL);
10196 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10198 // The transaction and HttpRequestInfo are deleted.
10201 // Let the HttpResponseBodyDrainer drain the socket.
10202 base::MessageLoop::current()->RunUntilIdle();
10204 // Socket should now be idle, waiting to be reused.
10205 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
10208 // Test a basic GET request through a proxy.
10209 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10210 session_deps_.proxy_service.reset(
10211 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10212 CapturingBoundNetLog log;
10213 session_deps_.net_log = log.bound().net_log();
10214 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10216 HttpRequestInfo request;
10217 request.method = "GET";
10218 request.url = GURL("http://www.google.com/");
10220 MockWrite data_writes1[] = {
10221 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10222 "Host: www.google.com\r\n"
10223 "Proxy-Connection: keep-alive\r\n\r\n"),
10226 MockRead data_reads1[] = {
10227 MockRead("HTTP/1.1 200 OK\r\n"),
10228 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10229 MockRead("Content-Length: 100\r\n\r\n"),
10230 MockRead(SYNCHRONOUS, OK),
10233 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10234 data_writes1, arraysize(data_writes1));
10235 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10237 TestCompletionCallback callback1;
10239 scoped_ptr<HttpTransaction> trans(
10240 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10242 int rv = trans->Start(&request, callback1.callback(), log.bound());
10243 EXPECT_EQ(ERR_IO_PENDING, rv);
10245 rv = callback1.WaitForResult();
10246 EXPECT_EQ(OK, rv);
10248 const HttpResponseInfo* response = trans->GetResponseInfo();
10249 ASSERT_TRUE(response != NULL);
10251 EXPECT_TRUE(response->headers->IsKeepAlive());
10252 EXPECT_EQ(200, response->headers->response_code());
10253 EXPECT_EQ(100, response->headers->GetContentLength());
10254 EXPECT_TRUE(response->was_fetched_via_proxy);
10255 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10257 LoadTimingInfo load_timing_info;
10258 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10259 TestLoadTimingNotReusedWithPac(load_timing_info,
10260 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10263 // Test a basic HTTPS GET request through a proxy.
10264 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10265 session_deps_.proxy_service.reset(
10266 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10267 CapturingBoundNetLog log;
10268 session_deps_.net_log = log.bound().net_log();
10269 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10271 HttpRequestInfo request;
10272 request.method = "GET";
10273 request.url = GURL("https://www.google.com/");
10275 // Since we have proxy, should try to establish tunnel.
10276 MockWrite data_writes1[] = {
10277 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10278 "Host: www.google.com\r\n"
10279 "Proxy-Connection: keep-alive\r\n\r\n"),
10281 MockWrite("GET / HTTP/1.1\r\n"
10282 "Host: www.google.com\r\n"
10283 "Connection: keep-alive\r\n\r\n"),
10286 MockRead data_reads1[] = {
10287 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10289 MockRead("HTTP/1.1 200 OK\r\n"),
10290 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10291 MockRead("Content-Length: 100\r\n\r\n"),
10292 MockRead(SYNCHRONOUS, OK),
10295 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10296 data_writes1, arraysize(data_writes1));
10297 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10298 SSLSocketDataProvider ssl(ASYNC, OK);
10299 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10301 TestCompletionCallback callback1;
10303 scoped_ptr<HttpTransaction> trans(
10304 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10306 int rv = trans->Start(&request, callback1.callback(), log.bound());
10307 EXPECT_EQ(ERR_IO_PENDING, rv);
10309 rv = callback1.WaitForResult();
10310 EXPECT_EQ(OK, rv);
10311 net::CapturingNetLog::CapturedEntryList entries;
10312 log.GetEntries(&entries);
10313 size_t pos = ExpectLogContainsSomewhere(
10314 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10315 NetLog::PHASE_NONE);
10316 ExpectLogContainsSomewhere(
10317 entries, pos,
10318 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10319 NetLog::PHASE_NONE);
10321 const HttpResponseInfo* response = trans->GetResponseInfo();
10322 ASSERT_TRUE(response != NULL);
10324 EXPECT_TRUE(response->headers->IsKeepAlive());
10325 EXPECT_EQ(200, response->headers->response_code());
10326 EXPECT_EQ(100, response->headers->GetContentLength());
10327 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10328 EXPECT_TRUE(response->was_fetched_via_proxy);
10330 LoadTimingInfo load_timing_info;
10331 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10332 TestLoadTimingNotReusedWithPac(load_timing_info,
10333 CONNECT_TIMING_HAS_SSL_TIMES);
10336 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10337 // while establishing the tunnel.
10338 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10339 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10340 CapturingBoundNetLog log;
10341 session_deps_.net_log = log.bound().net_log();
10342 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10344 HttpRequestInfo request;
10345 request.method = "GET";
10346 request.url = GURL("https://www.google.com/");
10348 // Since we have proxy, should try to establish tunnel.
10349 MockWrite data_writes1[] = {
10350 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10351 "Host: www.google.com\r\n"
10352 "Proxy-Connection: keep-alive\r\n\r\n"),
10354 MockWrite("GET / HTTP/1.1\r\n"
10355 "Host: www.google.com\r\n"
10356 "Connection: keep-alive\r\n\r\n"),
10359 MockRead data_reads1[] = {
10360 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10361 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10362 MockRead(ASYNC, 0, 0), // EOF
10365 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10366 data_writes1, arraysize(data_writes1));
10367 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10368 SSLSocketDataProvider ssl(ASYNC, OK);
10369 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10371 TestCompletionCallback callback1;
10373 scoped_ptr<HttpTransaction> trans(
10374 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10376 int rv = trans->Start(&request, callback1.callback(), log.bound());
10377 EXPECT_EQ(ERR_IO_PENDING, rv);
10379 rv = callback1.WaitForResult();
10380 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10381 net::CapturingNetLog::CapturedEntryList entries;
10382 log.GetEntries(&entries);
10383 size_t pos = ExpectLogContainsSomewhere(
10384 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10385 NetLog::PHASE_NONE);
10386 ExpectLogContainsSomewhere(
10387 entries, pos,
10388 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10389 NetLog::PHASE_NONE);
10392 // Test for crbug.com/55424.
10393 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10394 scoped_ptr<SpdyFrame> req(
10395 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10396 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10398 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10399 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10400 MockRead spdy_reads[] = {
10401 CreateMockRead(*resp),
10402 CreateMockRead(*data),
10403 MockRead(ASYNC, 0, 0),
10406 DelayedSocketData spdy_data(
10407 1, // wait for one write to finish before reading.
10408 spdy_reads, arraysize(spdy_reads),
10409 spdy_writes, arraysize(spdy_writes));
10410 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10412 SSLSocketDataProvider ssl(ASYNC, OK);
10413 ssl.SetNextProto(GetParam());
10414 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10416 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10418 // Set up an initial SpdySession in the pool to reuse.
10419 HostPortPair host_port_pair("www.google.com", 443);
10420 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10421 PRIVACY_MODE_DISABLED);
10422 base::WeakPtr<SpdySession> spdy_session =
10423 CreateInsecureSpdySession(session, key, BoundNetLog());
10425 HttpRequestInfo request;
10426 request.method = "GET";
10427 request.url = GURL("https://www.google.com/");
10428 request.load_flags = 0;
10430 // This is the important line that marks this as a preconnect.
10431 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10433 scoped_ptr<HttpTransaction> trans(
10434 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10436 TestCompletionCallback callback;
10437 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10438 EXPECT_EQ(ERR_IO_PENDING, rv);
10439 EXPECT_EQ(OK, callback.WaitForResult());
10442 // Given a net error, cause that error to be returned from the first Write()
10443 // call and verify that the HttpTransaction fails with that error.
10444 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10445 int error, IoMode mode) {
10446 net::HttpRequestInfo request_info;
10447 request_info.url = GURL("https://www.example.com/");
10448 request_info.method = "GET";
10449 request_info.load_flags = net::LOAD_NORMAL;
10451 SSLSocketDataProvider ssl_data(mode, OK);
10452 net::MockWrite data_writes[] = {
10453 net::MockWrite(mode, error),
10455 net::StaticSocketDataProvider data(NULL, 0,
10456 data_writes, arraysize(data_writes));
10457 session_deps_.socket_factory->AddSocketDataProvider(&data);
10458 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10460 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10461 scoped_ptr<HttpTransaction> trans(
10462 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10464 TestCompletionCallback callback;
10465 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10466 if (rv == net::ERR_IO_PENDING)
10467 rv = callback.WaitForResult();
10468 ASSERT_EQ(error, rv);
10471 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10472 // Just check a grab bag of cert errors.
10473 static const int kErrors[] = {
10474 ERR_CERT_COMMON_NAME_INVALID,
10475 ERR_CERT_AUTHORITY_INVALID,
10476 ERR_CERT_DATE_INVALID,
10478 for (size_t i = 0; i < arraysize(kErrors); i++) {
10479 CheckErrorIsPassedBack(kErrors[i], ASYNC);
10480 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10484 // Ensure that a client certificate is removed from the SSL client auth
10485 // cache when:
10486 // 1) No proxy is involved.
10487 // 2) TLS False Start is disabled.
10488 // 3) The initial TLS handshake requests a client certificate.
10489 // 4) The client supplies an invalid/unacceptable certificate.
10490 TEST_P(HttpNetworkTransactionTest,
10491 ClientAuthCertCache_Direct_NoFalseStart) {
10492 net::HttpRequestInfo request_info;
10493 request_info.url = GURL("https://www.example.com/");
10494 request_info.method = "GET";
10495 request_info.load_flags = net::LOAD_NORMAL;
10497 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10498 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10500 // [ssl_]data1 contains the data for the first SSL handshake. When a
10501 // CertificateRequest is received for the first time, the handshake will
10502 // be aborted to allow the caller to provide a certificate.
10503 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10504 ssl_data1.cert_request_info = cert_request.get();
10505 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10506 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10507 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10509 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10510 // False Start is not being used, the result of the SSL handshake will be
10511 // returned as part of the SSLClientSocket::Connect() call. This test
10512 // matches the result of a server sending a handshake_failure alert,
10513 // rather than a Finished message, because it requires a client
10514 // certificate and none was supplied.
10515 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10516 ssl_data2.cert_request_info = cert_request.get();
10517 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10518 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10519 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10521 // [ssl_]data3 contains the data for the third SSL handshake. When a
10522 // connection to a server fails during an SSL handshake,
10523 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10524 // connection was attempted with TLSv1.1. This is transparent to the caller
10525 // of the HttpNetworkTransaction. Because this test failure is due to
10526 // requiring a client certificate, this fallback handshake should also
10527 // fail.
10528 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10529 ssl_data3.cert_request_info = cert_request.get();
10530 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10531 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10532 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10534 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10535 // connection to a server fails during an SSL handshake,
10536 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10537 // connection was attempted with TLSv1. This is transparent to the caller
10538 // of the HttpNetworkTransaction. Because this test failure is due to
10539 // requiring a client certificate, this fallback handshake should also
10540 // fail.
10541 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10542 ssl_data4.cert_request_info = cert_request.get();
10543 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10544 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10545 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10547 // Need one more if TLSv1.2 is enabled.
10548 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10549 ssl_data5.cert_request_info = cert_request.get();
10550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10551 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10552 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10554 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10555 scoped_ptr<HttpTransaction> trans(
10556 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10558 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10559 TestCompletionCallback callback;
10560 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10561 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10563 // Complete the SSL handshake, which should abort due to requiring a
10564 // client certificate.
10565 rv = callback.WaitForResult();
10566 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10568 // Indicate that no certificate should be supplied. From the perspective
10569 // of SSLClientCertCache, NULL is just as meaningful as a real
10570 // certificate, so this is the same as supply a
10571 // legitimate-but-unacceptable certificate.
10572 rv = trans->RestartWithCertificate(NULL, callback.callback());
10573 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10575 // Ensure the certificate was added to the client auth cache before
10576 // allowing the connection to continue restarting.
10577 scoped_refptr<X509Certificate> client_cert;
10578 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10579 HostPortPair("www.example.com", 443), &client_cert));
10580 ASSERT_EQ(NULL, client_cert.get());
10582 // Restart the handshake. This will consume ssl_data2, which fails, and
10583 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10584 // The result code is checked against what ssl_data4 should return.
10585 rv = callback.WaitForResult();
10586 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10588 // Ensure that the client certificate is removed from the cache on a
10589 // handshake failure.
10590 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10591 HostPortPair("www.example.com", 443), &client_cert));
10594 // Ensure that a client certificate is removed from the SSL client auth
10595 // cache when:
10596 // 1) No proxy is involved.
10597 // 2) TLS False Start is enabled.
10598 // 3) The initial TLS handshake requests a client certificate.
10599 // 4) The client supplies an invalid/unacceptable certificate.
10600 TEST_P(HttpNetworkTransactionTest,
10601 ClientAuthCertCache_Direct_FalseStart) {
10602 net::HttpRequestInfo request_info;
10603 request_info.url = GURL("https://www.example.com/");
10604 request_info.method = "GET";
10605 request_info.load_flags = net::LOAD_NORMAL;
10607 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10608 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10610 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10611 // return successfully after reading up to the peer's Certificate message.
10612 // This is to allow the caller to call SSLClientSocket::Write(), which can
10613 // enqueue application data to be sent in the same packet as the
10614 // ChangeCipherSpec and Finished messages.
10615 // The actual handshake will be finished when SSLClientSocket::Read() is
10616 // called, which expects to process the peer's ChangeCipherSpec and
10617 // Finished messages. If there was an error negotiating with the peer,
10618 // such as due to the peer requiring a client certificate when none was
10619 // supplied, the alert sent by the peer won't be processed until Read() is
10620 // called.
10622 // Like the non-False Start case, when a client certificate is requested by
10623 // the peer, the handshake is aborted during the Connect() call.
10624 // [ssl_]data1 represents the initial SSL handshake with the peer.
10625 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10626 ssl_data1.cert_request_info = cert_request.get();
10627 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10628 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10629 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10631 // When a client certificate is supplied, Connect() will not be aborted
10632 // when the peer requests the certificate. Instead, the handshake will
10633 // artificially succeed, allowing the caller to write the HTTP request to
10634 // the socket. The handshake messages are not processed until Read() is
10635 // called, which then detects that the handshake was aborted, due to the
10636 // peer sending a handshake_failure because it requires a client
10637 // certificate.
10638 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10639 ssl_data2.cert_request_info = cert_request.get();
10640 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10641 net::MockRead data2_reads[] = {
10642 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10644 net::StaticSocketDataProvider data2(
10645 data2_reads, arraysize(data2_reads), NULL, 0);
10646 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10648 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10649 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10650 // TLSv1. It has the same behaviour as [ssl_]data2.
10651 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10652 ssl_data3.cert_request_info = cert_request.get();
10653 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10654 net::StaticSocketDataProvider data3(
10655 data2_reads, arraysize(data2_reads), NULL, 0);
10656 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10658 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10659 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10660 SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10661 ssl_data4.cert_request_info = cert_request.get();
10662 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10663 net::StaticSocketDataProvider data4(
10664 data2_reads, arraysize(data2_reads), NULL, 0);
10665 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10667 // Need one more if TLSv1.2 is enabled.
10668 SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10669 ssl_data5.cert_request_info = cert_request.get();
10670 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10671 net::StaticSocketDataProvider data5(
10672 data2_reads, arraysize(data2_reads), NULL, 0);
10673 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10675 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10676 scoped_ptr<HttpTransaction> trans(
10677 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10679 // Begin the initial SSL handshake.
10680 TestCompletionCallback callback;
10681 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10682 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10684 // Complete the SSL handshake, which should abort due to requiring a
10685 // client certificate.
10686 rv = callback.WaitForResult();
10687 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10689 // Indicate that no certificate should be supplied. From the perspective
10690 // of SSLClientCertCache, NULL is just as meaningful as a real
10691 // certificate, so this is the same as supply a
10692 // legitimate-but-unacceptable certificate.
10693 rv = trans->RestartWithCertificate(NULL, callback.callback());
10694 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10696 // Ensure the certificate was added to the client auth cache before
10697 // allowing the connection to continue restarting.
10698 scoped_refptr<X509Certificate> client_cert;
10699 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10700 HostPortPair("www.example.com", 443), &client_cert));
10701 ASSERT_EQ(NULL, client_cert.get());
10703 // Restart the handshake. This will consume ssl_data2, which fails, and
10704 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10705 // The result code is checked against what ssl_data4 should return.
10706 rv = callback.WaitForResult();
10707 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10709 // Ensure that the client certificate is removed from the cache on a
10710 // handshake failure.
10711 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10712 HostPortPair("www.example.com", 443), &client_cert));
10715 // Ensure that a client certificate is removed from the SSL client auth
10716 // cache when:
10717 // 1) An HTTPS proxy is involved.
10718 // 3) The HTTPS proxy requests a client certificate.
10719 // 4) The client supplies an invalid/unacceptable certificate for the
10720 // proxy.
10721 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10722 // then for connecting to an HTTP endpoint.
10723 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10724 session_deps_.proxy_service.reset(
10725 ProxyService::CreateFixed("https://proxy:70"));
10726 CapturingBoundNetLog log;
10727 session_deps_.net_log = log.bound().net_log();
10729 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10730 cert_request->host_and_port = HostPortPair("proxy", 70);
10732 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10733 // [ssl_]data[1-3]. Rather than represending the endpoint
10734 // (www.example.com:443), they represent failures with the HTTPS proxy
10735 // (proxy:70).
10736 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10737 ssl_data1.cert_request_info = cert_request.get();
10738 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10739 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10740 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10742 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10743 ssl_data2.cert_request_info = cert_request.get();
10744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10745 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10746 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10748 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10749 #if 0
10750 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10751 ssl_data3.cert_request_info = cert_request.get();
10752 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10753 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10754 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10755 #endif
10757 net::HttpRequestInfo requests[2];
10758 requests[0].url = GURL("https://www.example.com/");
10759 requests[0].method = "GET";
10760 requests[0].load_flags = net::LOAD_NORMAL;
10762 requests[1].url = GURL("http://www.example.com/");
10763 requests[1].method = "GET";
10764 requests[1].load_flags = net::LOAD_NORMAL;
10766 for (size_t i = 0; i < arraysize(requests); ++i) {
10767 session_deps_.socket_factory->ResetNextMockIndexes();
10768 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10769 scoped_ptr<HttpNetworkTransaction> trans(
10770 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10772 // Begin the SSL handshake with the proxy.
10773 TestCompletionCallback callback;
10774 int rv = trans->Start(
10775 &requests[i], callback.callback(), net::BoundNetLog());
10776 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10778 // Complete the SSL handshake, which should abort due to requiring a
10779 // client certificate.
10780 rv = callback.WaitForResult();
10781 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10783 // Indicate that no certificate should be supplied. From the perspective
10784 // of SSLClientCertCache, NULL is just as meaningful as a real
10785 // certificate, so this is the same as supply a
10786 // legitimate-but-unacceptable certificate.
10787 rv = trans->RestartWithCertificate(NULL, callback.callback());
10788 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10790 // Ensure the certificate was added to the client auth cache before
10791 // allowing the connection to continue restarting.
10792 scoped_refptr<X509Certificate> client_cert;
10793 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10794 HostPortPair("proxy", 70), &client_cert));
10795 ASSERT_EQ(NULL, client_cert.get());
10796 // Ensure the certificate was NOT cached for the endpoint. This only
10797 // applies to HTTPS requests, but is fine to check for HTTP requests.
10798 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10799 HostPortPair("www.example.com", 443), &client_cert));
10801 // Restart the handshake. This will consume ssl_data2, which fails, and
10802 // then consume ssl_data3, which should also fail. The result code is
10803 // checked against what ssl_data3 should return.
10804 rv = callback.WaitForResult();
10805 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10807 // Now that the new handshake has failed, ensure that the client
10808 // certificate was removed from the client auth cache.
10809 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10810 HostPortPair("proxy", 70), &client_cert));
10811 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10812 HostPortPair("www.example.com", 443), &client_cert));
10816 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10817 // TEST_P is a macro that expands directly to code that stringizes the
10818 // arguments. As a result, macros passed as parameters (such as prefix
10819 // or test_case_name) will not be expanded by the preprocessor. To
10820 // work around this, indirect the macro for TEST_P, so that the
10821 // pre-processor will expand macros such as MAYBE_test_name before
10822 // instantiating the test.
10823 #define WRAPPED_TEST_P(test_case_name, test_name) \
10824 TEST_P(test_case_name, test_name)
10826 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10827 #if defined(OS_WIN)
10828 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10829 #else
10830 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10831 #endif
10832 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10833 session_deps_.use_alternate_protocols = true;
10834 session_deps_.next_protos = SpdyNextProtos();
10836 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10837 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10838 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10839 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10840 pool_peer.DisableDomainAuthenticationVerification();
10842 SSLSocketDataProvider ssl(ASYNC, OK);
10843 ssl.SetNextProto(GetParam());
10844 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10846 scoped_ptr<SpdyFrame> host1_req(
10847 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10848 scoped_ptr<SpdyFrame> host2_req(
10849 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10850 MockWrite spdy_writes[] = {
10851 CreateMockWrite(*host1_req, 1),
10852 CreateMockWrite(*host2_req, 4),
10854 scoped_ptr<SpdyFrame> host1_resp(
10855 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10856 scoped_ptr<SpdyFrame> host1_resp_body(
10857 spdy_util_.ConstructSpdyBodyFrame(1, true));
10858 scoped_ptr<SpdyFrame> host2_resp(
10859 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10860 scoped_ptr<SpdyFrame> host2_resp_body(
10861 spdy_util_.ConstructSpdyBodyFrame(3, true));
10862 MockRead spdy_reads[] = {
10863 CreateMockRead(*host1_resp, 2),
10864 CreateMockRead(*host1_resp_body, 3),
10865 CreateMockRead(*host2_resp, 5),
10866 CreateMockRead(*host2_resp_body, 6),
10867 MockRead(ASYNC, 0, 7),
10870 IPAddressNumber ip;
10871 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10872 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10873 MockConnect connect(ASYNC, OK, peer_addr);
10874 OrderedSocketData spdy_data(
10875 connect,
10876 spdy_reads, arraysize(spdy_reads),
10877 spdy_writes, arraysize(spdy_writes));
10878 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10880 TestCompletionCallback callback;
10881 HttpRequestInfo request1;
10882 request1.method = "GET";
10883 request1.url = GURL("https://www.google.com/");
10884 request1.load_flags = 0;
10885 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10887 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10888 EXPECT_EQ(ERR_IO_PENDING, rv);
10889 EXPECT_EQ(OK, callback.WaitForResult());
10891 const HttpResponseInfo* response = trans1.GetResponseInfo();
10892 ASSERT_TRUE(response != NULL);
10893 ASSERT_TRUE(response->headers.get() != NULL);
10894 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10896 std::string response_data;
10897 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10898 EXPECT_EQ("hello!", response_data);
10900 // Preload www.gmail.com into HostCache.
10901 HostPortPair host_port("www.gmail.com", 443);
10902 HostResolver::RequestInfo resolve_info(host_port);
10903 AddressList ignored;
10904 rv = session_deps_.host_resolver->Resolve(resolve_info,
10905 DEFAULT_PRIORITY,
10906 &ignored,
10907 callback.callback(),
10908 NULL,
10909 BoundNetLog());
10910 EXPECT_EQ(ERR_IO_PENDING, rv);
10911 rv = callback.WaitForResult();
10912 EXPECT_EQ(OK, rv);
10914 HttpRequestInfo request2;
10915 request2.method = "GET";
10916 request2.url = GURL("https://www.gmail.com/");
10917 request2.load_flags = 0;
10918 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10920 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10921 EXPECT_EQ(ERR_IO_PENDING, rv);
10922 EXPECT_EQ(OK, callback.WaitForResult());
10924 response = trans2.GetResponseInfo();
10925 ASSERT_TRUE(response != NULL);
10926 ASSERT_TRUE(response->headers.get() != NULL);
10927 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10928 EXPECT_TRUE(response->was_fetched_via_spdy);
10929 EXPECT_TRUE(response->was_npn_negotiated);
10930 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10931 EXPECT_EQ("hello!", response_data);
10933 #undef MAYBE_UseIPConnectionPooling
10935 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
10936 session_deps_.use_alternate_protocols = true;
10937 session_deps_.next_protos = SpdyNextProtos();
10939 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10940 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10941 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10942 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10943 pool_peer.DisableDomainAuthenticationVerification();
10945 SSLSocketDataProvider ssl(ASYNC, OK);
10946 ssl.SetNextProto(GetParam());
10947 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10949 scoped_ptr<SpdyFrame> host1_req(
10950 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10951 scoped_ptr<SpdyFrame> host2_req(
10952 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10953 MockWrite spdy_writes[] = {
10954 CreateMockWrite(*host1_req, 1),
10955 CreateMockWrite(*host2_req, 4),
10957 scoped_ptr<SpdyFrame> host1_resp(
10958 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10959 scoped_ptr<SpdyFrame> host1_resp_body(
10960 spdy_util_.ConstructSpdyBodyFrame(1, true));
10961 scoped_ptr<SpdyFrame> host2_resp(
10962 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10963 scoped_ptr<SpdyFrame> host2_resp_body(
10964 spdy_util_.ConstructSpdyBodyFrame(3, true));
10965 MockRead spdy_reads[] = {
10966 CreateMockRead(*host1_resp, 2),
10967 CreateMockRead(*host1_resp_body, 3),
10968 CreateMockRead(*host2_resp, 5),
10969 CreateMockRead(*host2_resp_body, 6),
10970 MockRead(ASYNC, 0, 7),
10973 IPAddressNumber ip;
10974 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10975 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10976 MockConnect connect(ASYNC, OK, peer_addr);
10977 OrderedSocketData spdy_data(
10978 connect,
10979 spdy_reads, arraysize(spdy_reads),
10980 spdy_writes, arraysize(spdy_writes));
10981 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10983 TestCompletionCallback callback;
10984 HttpRequestInfo request1;
10985 request1.method = "GET";
10986 request1.url = GURL("https://www.google.com/");
10987 request1.load_flags = 0;
10988 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10990 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10991 EXPECT_EQ(ERR_IO_PENDING, rv);
10992 EXPECT_EQ(OK, callback.WaitForResult());
10994 const HttpResponseInfo* response = trans1.GetResponseInfo();
10995 ASSERT_TRUE(response != NULL);
10996 ASSERT_TRUE(response->headers.get() != NULL);
10997 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10999 std::string response_data;
11000 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11001 EXPECT_EQ("hello!", response_data);
11003 HttpRequestInfo request2;
11004 request2.method = "GET";
11005 request2.url = GURL("https://www.gmail.com/");
11006 request2.load_flags = 0;
11007 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11009 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11010 EXPECT_EQ(ERR_IO_PENDING, rv);
11011 EXPECT_EQ(OK, callback.WaitForResult());
11013 response = trans2.GetResponseInfo();
11014 ASSERT_TRUE(response != NULL);
11015 ASSERT_TRUE(response->headers.get() != NULL);
11016 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11017 EXPECT_TRUE(response->was_fetched_via_spdy);
11018 EXPECT_TRUE(response->was_npn_negotiated);
11019 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11020 EXPECT_EQ("hello!", response_data);
11023 class OneTimeCachingHostResolver : public net::HostResolver {
11024 public:
11025 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11026 : host_port_(host_port) {}
11027 virtual ~OneTimeCachingHostResolver() {}
11029 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11031 // HostResolver methods:
11032 virtual int Resolve(const RequestInfo& info,
11033 RequestPriority priority,
11034 AddressList* addresses,
11035 const CompletionCallback& callback,
11036 RequestHandle* out_req,
11037 const BoundNetLog& net_log) OVERRIDE {
11038 return host_resolver_.Resolve(
11039 info, priority, addresses, callback, out_req, net_log);
11042 virtual int ResolveFromCache(const RequestInfo& info,
11043 AddressList* addresses,
11044 const BoundNetLog& net_log) OVERRIDE {
11045 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11046 if (rv == OK && info.host_port_pair().Equals(host_port_))
11047 host_resolver_.GetHostCache()->clear();
11048 return rv;
11051 virtual void CancelRequest(RequestHandle req) OVERRIDE {
11052 host_resolver_.CancelRequest(req);
11055 MockCachingHostResolver* GetMockHostResolver() {
11056 return &host_resolver_;
11059 private:
11060 MockCachingHostResolver host_resolver_;
11061 const HostPortPair host_port_;
11064 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11065 #if defined(OS_WIN)
11066 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11067 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11068 #else
11069 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11070 UseIPConnectionPoolingWithHostCacheExpiration
11071 #endif
11072 WRAPPED_TEST_P(HttpNetworkTransactionTest,
11073 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
11074 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11075 // prefix doesn't work with parametrized tests).
11076 #if defined(OS_WIN)
11077 return;
11078 #else
11079 session_deps_.use_alternate_protocols = true;
11080 session_deps_.next_protos = SpdyNextProtos();
11082 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11083 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11084 HttpNetworkSession::Params params =
11085 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11086 params.host_resolver = &host_resolver;
11087 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11088 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11089 pool_peer.DisableDomainAuthenticationVerification();
11091 SSLSocketDataProvider ssl(ASYNC, OK);
11092 ssl.SetNextProto(GetParam());
11093 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11095 scoped_ptr<SpdyFrame> host1_req(
11096 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
11097 scoped_ptr<SpdyFrame> host2_req(
11098 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11099 MockWrite spdy_writes[] = {
11100 CreateMockWrite(*host1_req, 1),
11101 CreateMockWrite(*host2_req, 4),
11103 scoped_ptr<SpdyFrame> host1_resp(
11104 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11105 scoped_ptr<SpdyFrame> host1_resp_body(
11106 spdy_util_.ConstructSpdyBodyFrame(1, true));
11107 scoped_ptr<SpdyFrame> host2_resp(
11108 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11109 scoped_ptr<SpdyFrame> host2_resp_body(
11110 spdy_util_.ConstructSpdyBodyFrame(3, true));
11111 MockRead spdy_reads[] = {
11112 CreateMockRead(*host1_resp, 2),
11113 CreateMockRead(*host1_resp_body, 3),
11114 CreateMockRead(*host2_resp, 5),
11115 CreateMockRead(*host2_resp_body, 6),
11116 MockRead(ASYNC, 0, 7),
11119 IPAddressNumber ip;
11120 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11121 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11122 MockConnect connect(ASYNC, OK, peer_addr);
11123 OrderedSocketData spdy_data(
11124 connect,
11125 spdy_reads, arraysize(spdy_reads),
11126 spdy_writes, arraysize(spdy_writes));
11127 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11129 TestCompletionCallback callback;
11130 HttpRequestInfo request1;
11131 request1.method = "GET";
11132 request1.url = GURL("https://www.google.com/");
11133 request1.load_flags = 0;
11134 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11136 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11137 EXPECT_EQ(ERR_IO_PENDING, rv);
11138 EXPECT_EQ(OK, callback.WaitForResult());
11140 const HttpResponseInfo* response = trans1.GetResponseInfo();
11141 ASSERT_TRUE(response != NULL);
11142 ASSERT_TRUE(response->headers.get() != NULL);
11143 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11145 std::string response_data;
11146 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11147 EXPECT_EQ("hello!", response_data);
11149 // Preload cache entries into HostCache.
11150 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11151 AddressList ignored;
11152 rv = host_resolver.Resolve(resolve_info,
11153 DEFAULT_PRIORITY,
11154 &ignored,
11155 callback.callback(),
11156 NULL,
11157 BoundNetLog());
11158 EXPECT_EQ(ERR_IO_PENDING, rv);
11159 rv = callback.WaitForResult();
11160 EXPECT_EQ(OK, rv);
11162 HttpRequestInfo request2;
11163 request2.method = "GET";
11164 request2.url = GURL("https://www.gmail.com/");
11165 request2.load_flags = 0;
11166 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11168 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11169 EXPECT_EQ(ERR_IO_PENDING, rv);
11170 EXPECT_EQ(OK, callback.WaitForResult());
11172 response = trans2.GetResponseInfo();
11173 ASSERT_TRUE(response != NULL);
11174 ASSERT_TRUE(response->headers.get() != NULL);
11175 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11176 EXPECT_TRUE(response->was_fetched_via_spdy);
11177 EXPECT_TRUE(response->was_npn_negotiated);
11178 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11179 EXPECT_EQ("hello!", response_data);
11180 #endif
11182 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11184 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11185 const std::string https_url = "https://www.google.com/";
11186 const std::string http_url = "http://www.google.com:443/";
11188 // SPDY GET for HTTPS URL
11189 scoped_ptr<SpdyFrame> req1(
11190 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11192 MockWrite writes1[] = {
11193 CreateMockWrite(*req1, 0),
11196 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11197 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11198 MockRead reads1[] = {
11199 CreateMockRead(*resp1, 1),
11200 CreateMockRead(*body1, 2),
11201 MockRead(ASYNC, ERR_IO_PENDING, 3)
11204 DelayedSocketData data1(
11205 1, reads1, arraysize(reads1),
11206 writes1, arraysize(writes1));
11207 MockConnect connect_data1(ASYNC, OK);
11208 data1.set_connect_data(connect_data1);
11210 // HTTP GET for the HTTP URL
11211 MockWrite writes2[] = {
11212 MockWrite(ASYNC, 4,
11213 "GET / HTTP/1.1\r\n"
11214 "Host: www.google.com:443\r\n"
11215 "Connection: keep-alive\r\n\r\n"),
11218 MockRead reads2[] = {
11219 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11220 MockRead(ASYNC, 6, "hello"),
11221 MockRead(ASYNC, 7, OK),
11224 DelayedSocketData data2(
11225 1, reads2, arraysize(reads2),
11226 writes2, arraysize(writes2));
11228 SSLSocketDataProvider ssl(ASYNC, OK);
11229 ssl.SetNextProto(GetParam());
11230 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11231 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11232 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11234 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11236 // Start the first transaction to set up the SpdySession
11237 HttpRequestInfo request1;
11238 request1.method = "GET";
11239 request1.url = GURL(https_url);
11240 request1.load_flags = 0;
11241 HttpNetworkTransaction trans1(LOWEST, session.get());
11242 TestCompletionCallback callback1;
11243 EXPECT_EQ(ERR_IO_PENDING,
11244 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11245 base::MessageLoop::current()->RunUntilIdle();
11247 EXPECT_EQ(OK, callback1.WaitForResult());
11248 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11250 // Now, start the HTTP request
11251 HttpRequestInfo request2;
11252 request2.method = "GET";
11253 request2.url = GURL(http_url);
11254 request2.load_flags = 0;
11255 HttpNetworkTransaction trans2(MEDIUM, session.get());
11256 TestCompletionCallback callback2;
11257 EXPECT_EQ(ERR_IO_PENDING,
11258 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11259 base::MessageLoop::current()->RunUntilIdle();
11261 EXPECT_EQ(OK, callback2.WaitForResult());
11262 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11265 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
11266 const std::string https_url = "https://www.google.com/";
11267 const std::string http_url = "http://www.google.com:443/";
11269 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11270 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
11271 LOWEST));
11272 scoped_ptr<SpdyFrame> req1(
11273 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11274 scoped_ptr<SpdyFrame> wrapped_req1(
11275 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
11277 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11278 SpdySynStreamIR req2_ir(3);
11279 spdy_util_.SetPriority(MEDIUM, &req2_ir);
11280 req2_ir.set_fin(true);
11281 req2_ir.SetHeader(spdy_util_.GetMethodKey(), "GET");
11282 req2_ir.SetHeader(spdy_util_.GetPathKey(),
11283 spdy_util_.is_spdy2() ? http_url.c_str() : "/");
11284 req2_ir.SetHeader(spdy_util_.GetHostKey(), "www.google.com:443");
11285 req2_ir.SetHeader(spdy_util_.GetSchemeKey(), "http");
11286 spdy_util_.MaybeAddVersionHeader(&req2_ir);
11287 scoped_ptr<SpdyFrame> req2(
11288 spdy_util_.CreateFramer(false)->SerializeFrame(req2_ir));
11290 MockWrite writes1[] = {
11291 CreateMockWrite(*connect, 0),
11292 CreateMockWrite(*wrapped_req1, 2),
11293 CreateMockWrite(*req2, 5),
11296 scoped_ptr<SpdyFrame> conn_resp(
11297 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11298 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11299 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11300 scoped_ptr<SpdyFrame> wrapped_resp1(
11301 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
11302 scoped_ptr<SpdyFrame> wrapped_body1(
11303 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
11304 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11305 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11306 MockRead reads1[] = {
11307 CreateMockRead(*conn_resp, 1),
11308 CreateMockRead(*wrapped_resp1, 3),
11309 CreateMockRead(*wrapped_body1, 4),
11310 CreateMockRead(*resp2, 6),
11311 CreateMockRead(*body2, 7),
11312 MockRead(ASYNC, ERR_IO_PENDING, 8)
11315 DeterministicSocketData data1(reads1, arraysize(reads1),
11316 writes1, arraysize(writes1));
11317 MockConnect connect_data1(ASYNC, OK);
11318 data1.set_connect_data(connect_data1);
11320 session_deps_.proxy_service.reset(
11321 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11322 CapturingNetLog log;
11323 session_deps_.net_log = &log;
11324 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11325 ssl1.SetNextProto(GetParam());
11326 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11327 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11328 ssl2.SetNextProto(GetParam());
11329 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11330 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
11332 scoped_refptr<HttpNetworkSession> session(
11333 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11335 // Start the first transaction to set up the SpdySession
11336 HttpRequestInfo request1;
11337 request1.method = "GET";
11338 request1.url = GURL(https_url);
11339 request1.load_flags = 0;
11340 HttpNetworkTransaction trans1(LOWEST, session.get());
11341 TestCompletionCallback callback1;
11342 EXPECT_EQ(ERR_IO_PENDING,
11343 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11344 base::MessageLoop::current()->RunUntilIdle();
11345 data1.RunFor(4);
11347 EXPECT_EQ(OK, callback1.WaitForResult());
11348 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11350 LoadTimingInfo load_timing_info1;
11351 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
11352 TestLoadTimingNotReusedWithPac(load_timing_info1,
11353 CONNECT_TIMING_HAS_SSL_TIMES);
11355 // Now, start the HTTP request
11356 HttpRequestInfo request2;
11357 request2.method = "GET";
11358 request2.url = GURL(http_url);
11359 request2.load_flags = 0;
11360 HttpNetworkTransaction trans2(MEDIUM, session.get());
11361 TestCompletionCallback callback2;
11362 EXPECT_EQ(ERR_IO_PENDING,
11363 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11364 base::MessageLoop::current()->RunUntilIdle();
11365 data1.RunFor(3);
11367 EXPECT_EQ(OK, callback2.WaitForResult());
11368 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11370 LoadTimingInfo load_timing_info2;
11371 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
11372 // The established SPDY sessions is considered reused by the HTTP request.
11373 TestLoadTimingReusedWithPac(load_timing_info2);
11374 // HTTP requests over a SPDY session should have a different connection
11375 // socket_log_id than requests over a tunnel.
11376 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
11379 TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
11380 session_deps_.force_spdy_always = true;
11381 const std::string https_url = "https://www.google.com/";
11382 const std::string http_url = "http://www.google.com:443/";
11384 // SPDY GET for HTTPS URL
11385 scoped_ptr<SpdyFrame> req1(
11386 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11387 // SPDY GET for the HTTP URL
11388 scoped_ptr<SpdyFrame> req2(
11389 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11391 MockWrite writes[] = {
11392 CreateMockWrite(*req1, 1),
11393 CreateMockWrite(*req2, 4),
11396 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11397 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11398 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11399 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11400 MockRead reads[] = {
11401 CreateMockRead(*resp1, 2),
11402 CreateMockRead(*body1, 3),
11403 CreateMockRead(*resp2, 5),
11404 CreateMockRead(*body2, 6),
11405 MockRead(ASYNC, ERR_IO_PENDING, 7)
11408 OrderedSocketData data(reads, arraysize(reads),
11409 writes, arraysize(writes));
11411 SSLSocketDataProvider ssl(ASYNC, OK);
11412 ssl.SetNextProto(GetParam());
11413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11414 session_deps_.socket_factory->AddSocketDataProvider(&data);
11416 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11418 // Start the first transaction to set up the SpdySession
11419 HttpRequestInfo request1;
11420 request1.method = "GET";
11421 request1.url = GURL(https_url);
11422 request1.load_flags = 0;
11423 HttpNetworkTransaction trans1(LOWEST, session.get());
11424 TestCompletionCallback callback1;
11425 EXPECT_EQ(ERR_IO_PENDING,
11426 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11427 base::MessageLoop::current()->RunUntilIdle();
11429 EXPECT_EQ(OK, callback1.WaitForResult());
11430 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11432 // Now, start the HTTP request
11433 HttpRequestInfo request2;
11434 request2.method = "GET";
11435 request2.url = GURL(http_url);
11436 request2.load_flags = 0;
11437 HttpNetworkTransaction trans2(MEDIUM, session.get());
11438 TestCompletionCallback callback2;
11439 EXPECT_EQ(ERR_IO_PENDING,
11440 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11441 base::MessageLoop::current()->RunUntilIdle();
11443 EXPECT_EQ(OK, callback2.WaitForResult());
11444 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11447 // Test that in the case where we have a SPDY session to a SPDY proxy
11448 // that we do not pool other origins that resolve to the same IP when
11449 // the certificate does not match the new origin.
11450 // http://crbug.com/134690
11451 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11452 const std::string url1 = "http://www.google.com/";
11453 const std::string url2 = "https://mail.google.com/";
11454 const std::string ip_addr = "1.2.3.4";
11456 // SPDY GET for HTTP URL (through SPDY proxy)
11457 scoped_ptr<SpdyHeaderBlock> headers(
11458 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11459 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
11460 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
11462 MockWrite writes1[] = {
11463 CreateMockWrite(*req1, 0),
11466 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11467 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11468 MockRead reads1[] = {
11469 CreateMockRead(*resp1, 1),
11470 CreateMockRead(*body1, 2),
11471 MockRead(ASYNC, OK, 3) // EOF
11474 scoped_ptr<DeterministicSocketData> data1(
11475 new DeterministicSocketData(reads1, arraysize(reads1),
11476 writes1, arraysize(writes1)));
11477 IPAddressNumber ip;
11478 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11479 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11480 MockConnect connect_data1(ASYNC, OK, peer_addr);
11481 data1->set_connect_data(connect_data1);
11483 // SPDY GET for HTTPS URL (direct)
11484 scoped_ptr<SpdyFrame> req2(
11485 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11487 MockWrite writes2[] = {
11488 CreateMockWrite(*req2, 0),
11491 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11492 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11493 MockRead reads2[] = {
11494 CreateMockRead(*resp2, 1),
11495 CreateMockRead(*body2, 2),
11496 MockRead(ASYNC, OK, 3) // EOF
11499 scoped_ptr<DeterministicSocketData> data2(
11500 new DeterministicSocketData(reads2, arraysize(reads2),
11501 writes2, arraysize(writes2)));
11502 MockConnect connect_data2(ASYNC, OK);
11503 data2->set_connect_data(connect_data2);
11505 // Set up a proxy config that sends HTTP requests to a proxy, and
11506 // all others direct.
11507 ProxyConfig proxy_config;
11508 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11509 CapturingProxyResolver* capturing_proxy_resolver =
11510 new CapturingProxyResolver();
11511 session_deps_.proxy_service.reset(new ProxyService(
11512 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11513 NULL));
11515 // Load a valid cert. Note, that this does not need to
11516 // be valid for proxy because the MockSSLClientSocket does
11517 // not actually verify it. But SpdySession will use this
11518 // to see if it is valid for the new origin
11519 base::FilePath certs_dir = GetTestCertsDirectory();
11520 scoped_refptr<X509Certificate> server_cert(
11521 ImportCertFromFile(certs_dir, "ok_cert.pem"));
11522 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11524 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11525 ssl1.SetNextProto(GetParam());
11526 ssl1.cert = server_cert;
11527 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11528 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11529 data1.get());
11531 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11532 ssl2.SetNextProto(GetParam());
11533 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11534 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11535 data2.get());
11537 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11538 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11539 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11541 scoped_refptr<HttpNetworkSession> session(
11542 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11544 // Start the first transaction to set up the SpdySession
11545 HttpRequestInfo request1;
11546 request1.method = "GET";
11547 request1.url = GURL(url1);
11548 request1.load_flags = 0;
11549 HttpNetworkTransaction trans1(LOWEST, session.get());
11550 TestCompletionCallback callback1;
11551 ASSERT_EQ(ERR_IO_PENDING,
11552 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11553 data1->RunFor(3);
11555 ASSERT_TRUE(callback1.have_result());
11556 EXPECT_EQ(OK, callback1.WaitForResult());
11557 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11559 // Now, start the HTTP request
11560 HttpRequestInfo request2;
11561 request2.method = "GET";
11562 request2.url = GURL(url2);
11563 request2.load_flags = 0;
11564 HttpNetworkTransaction trans2(MEDIUM, session.get());
11565 TestCompletionCallback callback2;
11566 EXPECT_EQ(ERR_IO_PENDING,
11567 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11568 base::MessageLoop::current()->RunUntilIdle();
11569 data2->RunFor(3);
11571 ASSERT_TRUE(callback2.have_result());
11572 EXPECT_EQ(OK, callback2.WaitForResult());
11573 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11576 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11577 // error) in SPDY session, removes the socket from pool and closes the SPDY
11578 // session. Verify that new url's from the same HttpNetworkSession (and a new
11579 // SpdySession) do work. http://crbug.com/224701
11580 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11581 const std::string https_url = "https://www.google.com/";
11583 MockRead reads1[] = {
11584 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11587 scoped_ptr<DeterministicSocketData> data1(
11588 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11589 data1->SetStop(1);
11591 scoped_ptr<SpdyFrame> req2(
11592 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11593 MockWrite writes2[] = {
11594 CreateMockWrite(*req2, 0),
11597 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11598 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11599 MockRead reads2[] = {
11600 CreateMockRead(*resp2, 1),
11601 CreateMockRead(*body2, 2),
11602 MockRead(ASYNC, OK, 3) // EOF
11605 scoped_ptr<DeterministicSocketData> data2(
11606 new DeterministicSocketData(reads2, arraysize(reads2),
11607 writes2, arraysize(writes2)));
11609 SSLSocketDataProvider ssl1(ASYNC, OK);
11610 ssl1.SetNextProto(GetParam());
11611 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11612 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11613 data1.get());
11615 SSLSocketDataProvider ssl2(ASYNC, OK);
11616 ssl2.SetNextProto(GetParam());
11617 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11618 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11619 data2.get());
11621 scoped_refptr<HttpNetworkSession> session(
11622 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11624 // Start the first transaction to set up the SpdySession and verify that
11625 // connection was closed.
11626 HttpRequestInfo request1;
11627 request1.method = "GET";
11628 request1.url = GURL(https_url);
11629 request1.load_flags = 0;
11630 HttpNetworkTransaction trans1(MEDIUM, session.get());
11631 TestCompletionCallback callback1;
11632 EXPECT_EQ(ERR_IO_PENDING,
11633 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11634 base::MessageLoop::current()->RunUntilIdle();
11635 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11637 // Now, start the second request and make sure it succeeds.
11638 HttpRequestInfo request2;
11639 request2.method = "GET";
11640 request2.url = GURL(https_url);
11641 request2.load_flags = 0;
11642 HttpNetworkTransaction trans2(MEDIUM, session.get());
11643 TestCompletionCallback callback2;
11644 EXPECT_EQ(ERR_IO_PENDING,
11645 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11646 base::MessageLoop::current()->RunUntilIdle();
11647 data2->RunFor(3);
11649 ASSERT_TRUE(callback2.have_result());
11650 EXPECT_EQ(OK, callback2.WaitForResult());
11651 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11654 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11655 session_deps_.next_protos = SpdyNextProtos();
11656 ClientSocketPoolManager::set_max_sockets_per_group(
11657 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11658 ClientSocketPoolManager::set_max_sockets_per_pool(
11659 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11661 // Use two different hosts with different IPs so they don't get pooled.
11662 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11663 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11664 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11666 SSLSocketDataProvider ssl1(ASYNC, OK);
11667 ssl1.SetNextProto(GetParam());
11668 SSLSocketDataProvider ssl2(ASYNC, OK);
11669 ssl2.SetNextProto(GetParam());
11670 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11671 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11673 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11674 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11675 MockWrite spdy1_writes[] = {
11676 CreateMockWrite(*host1_req, 1),
11678 scoped_ptr<SpdyFrame> host1_resp(
11679 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11680 scoped_ptr<SpdyFrame> host1_resp_body(
11681 spdy_util_.ConstructSpdyBodyFrame(1, true));
11682 MockRead spdy1_reads[] = {
11683 CreateMockRead(*host1_resp, 2),
11684 CreateMockRead(*host1_resp_body, 3),
11685 MockRead(ASYNC, ERR_IO_PENDING, 4),
11688 scoped_ptr<OrderedSocketData> spdy1_data(
11689 new OrderedSocketData(
11690 spdy1_reads, arraysize(spdy1_reads),
11691 spdy1_writes, arraysize(spdy1_writes)));
11692 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11694 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11695 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11696 MockWrite spdy2_writes[] = {
11697 CreateMockWrite(*host2_req, 1),
11699 scoped_ptr<SpdyFrame> host2_resp(
11700 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11701 scoped_ptr<SpdyFrame> host2_resp_body(
11702 spdy_util_.ConstructSpdyBodyFrame(1, true));
11703 MockRead spdy2_reads[] = {
11704 CreateMockRead(*host2_resp, 2),
11705 CreateMockRead(*host2_resp_body, 3),
11706 MockRead(ASYNC, ERR_IO_PENDING, 4),
11709 scoped_ptr<OrderedSocketData> spdy2_data(
11710 new OrderedSocketData(
11711 spdy2_reads, arraysize(spdy2_reads),
11712 spdy2_writes, arraysize(spdy2_writes)));
11713 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11715 MockWrite http_write[] = {
11716 MockWrite("GET / HTTP/1.1\r\n"
11717 "Host: www.a.com\r\n"
11718 "Connection: keep-alive\r\n\r\n"),
11721 MockRead http_read[] = {
11722 MockRead("HTTP/1.1 200 OK\r\n"),
11723 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11724 MockRead("Content-Length: 6\r\n\r\n"),
11725 MockRead("hello!"),
11727 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11728 http_write, arraysize(http_write));
11729 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11731 HostPortPair host_port_pair_a("www.a.com", 443);
11732 SpdySessionKey spdy_session_key_a(
11733 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11734 EXPECT_FALSE(
11735 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11737 TestCompletionCallback callback;
11738 HttpRequestInfo request1;
11739 request1.method = "GET";
11740 request1.url = GURL("https://www.a.com/");
11741 request1.load_flags = 0;
11742 scoped_ptr<HttpNetworkTransaction> trans(
11743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11745 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11746 EXPECT_EQ(ERR_IO_PENDING, rv);
11747 EXPECT_EQ(OK, callback.WaitForResult());
11749 const HttpResponseInfo* response = trans->GetResponseInfo();
11750 ASSERT_TRUE(response != NULL);
11751 ASSERT_TRUE(response->headers.get() != NULL);
11752 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11753 EXPECT_TRUE(response->was_fetched_via_spdy);
11754 EXPECT_TRUE(response->was_npn_negotiated);
11756 std::string response_data;
11757 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11758 EXPECT_EQ("hello!", response_data);
11759 trans.reset();
11760 EXPECT_TRUE(
11761 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11763 HostPortPair host_port_pair_b("www.b.com", 443);
11764 SpdySessionKey spdy_session_key_b(
11765 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11766 EXPECT_FALSE(
11767 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11768 HttpRequestInfo request2;
11769 request2.method = "GET";
11770 request2.url = GURL("https://www.b.com/");
11771 request2.load_flags = 0;
11772 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11774 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11775 EXPECT_EQ(ERR_IO_PENDING, rv);
11776 EXPECT_EQ(OK, callback.WaitForResult());
11778 response = trans->GetResponseInfo();
11779 ASSERT_TRUE(response != NULL);
11780 ASSERT_TRUE(response->headers.get() != NULL);
11781 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11782 EXPECT_TRUE(response->was_fetched_via_spdy);
11783 EXPECT_TRUE(response->was_npn_negotiated);
11784 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11785 EXPECT_EQ("hello!", response_data);
11786 EXPECT_FALSE(
11787 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11788 EXPECT_TRUE(
11789 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11791 HostPortPair host_port_pair_a1("www.a.com", 80);
11792 SpdySessionKey spdy_session_key_a1(
11793 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11794 EXPECT_FALSE(
11795 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11796 HttpRequestInfo request3;
11797 request3.method = "GET";
11798 request3.url = GURL("http://www.a.com/");
11799 request3.load_flags = 0;
11800 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11802 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11803 EXPECT_EQ(ERR_IO_PENDING, rv);
11804 EXPECT_EQ(OK, callback.WaitForResult());
11806 response = trans->GetResponseInfo();
11807 ASSERT_TRUE(response != NULL);
11808 ASSERT_TRUE(response->headers.get() != NULL);
11809 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11810 EXPECT_FALSE(response->was_fetched_via_spdy);
11811 EXPECT_FALSE(response->was_npn_negotiated);
11812 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11813 EXPECT_EQ("hello!", response_data);
11814 EXPECT_FALSE(
11815 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11816 EXPECT_FALSE(
11817 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11820 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11821 HttpRequestInfo request;
11822 request.method = "GET";
11823 request.url = GURL("http://www.google.com/");
11824 request.load_flags = 0;
11826 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11827 scoped_ptr<HttpTransaction> trans(
11828 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11830 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11831 StaticSocketDataProvider data;
11832 data.set_connect_data(mock_connect);
11833 session_deps_.socket_factory->AddSocketDataProvider(&data);
11835 TestCompletionCallback callback;
11837 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11838 EXPECT_EQ(ERR_IO_PENDING, rv);
11840 rv = callback.WaitForResult();
11841 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11843 EXPECT_EQ(NULL, trans->GetResponseInfo());
11845 // We don't care whether this succeeds or fails, but it shouldn't crash.
11846 HttpRequestHeaders request_headers;
11847 trans->GetFullRequestHeaders(&request_headers);
11850 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11851 HttpRequestInfo request;
11852 request.method = "GET";
11853 request.url = GURL("http://www.google.com/");
11854 request.load_flags = 0;
11856 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11857 scoped_ptr<HttpTransaction> trans(
11858 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11860 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11861 StaticSocketDataProvider data;
11862 data.set_connect_data(mock_connect);
11863 session_deps_.socket_factory->AddSocketDataProvider(&data);
11865 TestCompletionCallback callback;
11867 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11868 EXPECT_EQ(ERR_IO_PENDING, rv);
11870 rv = callback.WaitForResult();
11871 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11873 EXPECT_EQ(NULL, trans->GetResponseInfo());
11875 // We don't care whether this succeeds or fails, but it shouldn't crash.
11876 HttpRequestHeaders request_headers;
11877 trans->GetFullRequestHeaders(&request_headers);
11880 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
11881 HttpRequestInfo request;
11882 request.method = "GET";
11883 request.url = GURL("http://www.google.com/");
11884 request.load_flags = 0;
11886 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11887 scoped_ptr<HttpTransaction> trans(
11888 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11890 MockWrite data_writes[] = {
11891 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
11893 MockRead data_reads[] = {
11894 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11897 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11898 data_writes, arraysize(data_writes));
11899 session_deps_.socket_factory->AddSocketDataProvider(&data);
11901 TestCompletionCallback callback;
11903 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11904 EXPECT_EQ(ERR_IO_PENDING, rv);
11906 rv = callback.WaitForResult();
11907 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11909 EXPECT_EQ(NULL, trans->GetResponseInfo());
11911 HttpRequestHeaders request_headers;
11912 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11913 EXPECT_TRUE(request_headers.HasHeader("Host"));
11916 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
11917 HttpRequestInfo request;
11918 request.method = "GET";
11919 request.url = GURL("http://www.google.com/");
11920 request.load_flags = 0;
11922 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11923 scoped_ptr<HttpTransaction> trans(
11924 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11926 MockWrite data_writes[] = {
11927 MockWrite(ASYNC, ERR_CONNECTION_RESET),
11929 MockRead data_reads[] = {
11930 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11933 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11934 data_writes, arraysize(data_writes));
11935 session_deps_.socket_factory->AddSocketDataProvider(&data);
11937 TestCompletionCallback callback;
11939 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11940 EXPECT_EQ(ERR_IO_PENDING, rv);
11942 rv = callback.WaitForResult();
11943 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11945 EXPECT_EQ(NULL, trans->GetResponseInfo());
11947 HttpRequestHeaders request_headers;
11948 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11949 EXPECT_TRUE(request_headers.HasHeader("Host"));
11952 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
11953 HttpRequestInfo request;
11954 request.method = "GET";
11955 request.url = GURL("http://www.google.com/");
11956 request.load_flags = 0;
11958 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11959 scoped_ptr<HttpTransaction> trans(
11960 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11962 MockWrite data_writes[] = {
11963 MockWrite("GET / HTTP/1.1\r\n"
11964 "Host: www.google.com\r\n"
11965 "Connection: keep-alive\r\n\r\n"),
11967 MockRead data_reads[] = {
11968 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
11971 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11972 data_writes, arraysize(data_writes));
11973 session_deps_.socket_factory->AddSocketDataProvider(&data);
11975 TestCompletionCallback callback;
11977 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11978 EXPECT_EQ(ERR_IO_PENDING, rv);
11980 rv = callback.WaitForResult();
11981 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11983 EXPECT_EQ(NULL, trans->GetResponseInfo());
11985 HttpRequestHeaders request_headers;
11986 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11987 EXPECT_TRUE(request_headers.HasHeader("Host"));
11990 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
11991 HttpRequestInfo request;
11992 request.method = "GET";
11993 request.url = GURL("http://www.google.com/");
11994 request.load_flags = 0;
11996 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11997 scoped_ptr<HttpTransaction> trans(
11998 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12000 MockWrite data_writes[] = {
12001 MockWrite("GET / HTTP/1.1\r\n"
12002 "Host: www.google.com\r\n"
12003 "Connection: keep-alive\r\n\r\n"),
12005 MockRead data_reads[] = {
12006 MockRead(ASYNC, ERR_CONNECTION_RESET),
12009 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12010 data_writes, arraysize(data_writes));
12011 session_deps_.socket_factory->AddSocketDataProvider(&data);
12013 TestCompletionCallback callback;
12015 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12016 EXPECT_EQ(ERR_IO_PENDING, rv);
12018 rv = callback.WaitForResult();
12019 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12021 EXPECT_EQ(NULL, trans->GetResponseInfo());
12023 HttpRequestHeaders request_headers;
12024 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12025 EXPECT_TRUE(request_headers.HasHeader("Host"));
12028 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12029 HttpRequestInfo request;
12030 request.method = "GET";
12031 request.url = GURL("http://www.google.com/");
12032 request.load_flags = 0;
12033 request.extra_headers.SetHeader("X-Foo", "bar");
12035 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12036 scoped_ptr<HttpTransaction> trans(
12037 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12039 MockWrite data_writes[] = {
12040 MockWrite("GET / HTTP/1.1\r\n"
12041 "Host: www.google.com\r\n"
12042 "Connection: keep-alive\r\n"
12043 "X-Foo: bar\r\n\r\n"),
12045 MockRead data_reads[] = {
12046 MockRead("HTTP/1.1 200 OK\r\n"
12047 "Content-Length: 5\r\n\r\n"
12048 "hello"),
12049 MockRead(ASYNC, ERR_UNEXPECTED),
12052 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12053 data_writes, arraysize(data_writes));
12054 session_deps_.socket_factory->AddSocketDataProvider(&data);
12056 TestCompletionCallback callback;
12058 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12059 EXPECT_EQ(ERR_IO_PENDING, rv);
12061 rv = callback.WaitForResult();
12062 EXPECT_EQ(OK, rv);
12064 HttpRequestHeaders request_headers;
12065 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12066 std::string foo;
12067 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12068 EXPECT_EQ("bar", foo);
12071 namespace {
12073 // Fake HttpStreamBase that simply records calls to SetPriority().
12074 class FakeStream : public HttpStreamBase,
12075 public base::SupportsWeakPtr<FakeStream> {
12076 public:
12077 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12078 virtual ~FakeStream() {}
12080 RequestPriority priority() const { return priority_; }
12082 virtual int InitializeStream(const HttpRequestInfo* request_info,
12083 RequestPriority priority,
12084 const BoundNetLog& net_log,
12085 const CompletionCallback& callback) OVERRIDE {
12086 return ERR_IO_PENDING;
12089 virtual int SendRequest(const HttpRequestHeaders& request_headers,
12090 HttpResponseInfo* response,
12091 const CompletionCallback& callback) OVERRIDE {
12092 ADD_FAILURE();
12093 return ERR_UNEXPECTED;
12096 virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
12097 ADD_FAILURE();
12098 return ERR_UNEXPECTED;
12101 virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
12102 const CompletionCallback& callback) OVERRIDE {
12103 ADD_FAILURE();
12104 return ERR_UNEXPECTED;
12107 virtual void Close(bool not_reusable) OVERRIDE {}
12109 virtual bool IsResponseBodyComplete() const OVERRIDE {
12110 ADD_FAILURE();
12111 return false;
12114 virtual bool CanFindEndOfResponse() const OVERRIDE {
12115 return false;
12118 virtual bool IsConnectionReused() const OVERRIDE {
12119 ADD_FAILURE();
12120 return false;
12123 virtual void SetConnectionReused() OVERRIDE {
12124 ADD_FAILURE();
12127 virtual bool IsConnectionReusable() const OVERRIDE {
12128 ADD_FAILURE();
12129 return false;
12132 virtual int64 GetTotalReceivedBytes() const OVERRIDE {
12133 ADD_FAILURE();
12134 return 0;
12137 virtual bool GetLoadTimingInfo(
12138 LoadTimingInfo* load_timing_info) const OVERRIDE {
12139 ADD_FAILURE();
12140 return false;
12143 virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
12144 ADD_FAILURE();
12147 virtual void GetSSLCertRequestInfo(
12148 SSLCertRequestInfo* cert_request_info) OVERRIDE {
12149 ADD_FAILURE();
12152 virtual bool IsSpdyHttpStream() const OVERRIDE {
12153 ADD_FAILURE();
12154 return false;
12157 virtual void Drain(HttpNetworkSession* session) OVERRIDE {
12158 ADD_FAILURE();
12161 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12162 priority_ = priority;
12165 private:
12166 RequestPriority priority_;
12168 DISALLOW_COPY_AND_ASSIGN(FakeStream);
12171 // Fake HttpStreamRequest that simply records calls to SetPriority()
12172 // and vends FakeStreams with its current priority.
12173 class FakeStreamRequest : public HttpStreamRequest,
12174 public base::SupportsWeakPtr<FakeStreamRequest> {
12175 public:
12176 FakeStreamRequest(RequestPriority priority,
12177 HttpStreamRequest::Delegate* delegate)
12178 : priority_(priority),
12179 delegate_(delegate),
12180 websocket_stream_create_helper_(NULL) {}
12182 FakeStreamRequest(RequestPriority priority,
12183 HttpStreamRequest::Delegate* delegate,
12184 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
12185 : priority_(priority),
12186 delegate_(delegate),
12187 websocket_stream_create_helper_(create_helper) {}
12189 virtual ~FakeStreamRequest() {}
12191 RequestPriority priority() const { return priority_; }
12193 const WebSocketHandshakeStreamBase::CreateHelper*
12194 websocket_stream_create_helper() const {
12195 return websocket_stream_create_helper_;
12198 // Create a new FakeStream and pass it to the request's
12199 // delegate. Returns a weak pointer to the FakeStream.
12200 base::WeakPtr<FakeStream> FinishStreamRequest() {
12201 FakeStream* fake_stream = new FakeStream(priority_);
12202 // Do this before calling OnStreamReady() as OnStreamReady() may
12203 // immediately delete |fake_stream|.
12204 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
12205 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
12206 return weak_stream;
12209 virtual int RestartTunnelWithProxyAuth(
12210 const AuthCredentials& credentials) OVERRIDE {
12211 ADD_FAILURE();
12212 return ERR_UNEXPECTED;
12215 virtual LoadState GetLoadState() const OVERRIDE {
12216 ADD_FAILURE();
12217 return LoadState();
12220 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12221 priority_ = priority;
12224 virtual bool was_npn_negotiated() const OVERRIDE {
12225 return false;
12228 virtual NextProto protocol_negotiated() const OVERRIDE {
12229 return kProtoUnknown;
12232 virtual bool using_spdy() const OVERRIDE {
12233 return false;
12236 private:
12237 RequestPriority priority_;
12238 HttpStreamRequest::Delegate* const delegate_;
12239 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
12241 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12244 // Fake HttpStreamFactory that vends FakeStreamRequests.
12245 class FakeStreamFactory : public HttpStreamFactory {
12246 public:
12247 FakeStreamFactory() {}
12248 virtual ~FakeStreamFactory() {}
12250 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12251 // RequestStream() (which may be NULL if it was destroyed already).
12252 base::WeakPtr<FakeStreamRequest> last_stream_request() {
12253 return last_stream_request_;
12256 virtual HttpStreamRequest* RequestStream(
12257 const HttpRequestInfo& info,
12258 RequestPriority priority,
12259 const SSLConfig& server_ssl_config,
12260 const SSLConfig& proxy_ssl_config,
12261 HttpStreamRequest::Delegate* delegate,
12262 const BoundNetLog& net_log) OVERRIDE {
12263 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12264 last_stream_request_ = fake_request->AsWeakPtr();
12265 return fake_request;
12268 virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
12269 const HttpRequestInfo& info,
12270 RequestPriority priority,
12271 const SSLConfig& server_ssl_config,
12272 const SSLConfig& proxy_ssl_config,
12273 HttpStreamRequest::Delegate* delegate,
12274 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
12275 const BoundNetLog& net_log) OVERRIDE {
12276 FakeStreamRequest* fake_request =
12277 new FakeStreamRequest(priority, delegate, create_helper);
12278 last_stream_request_ = fake_request->AsWeakPtr();
12279 return fake_request;
12282 virtual void PreconnectStreams(int num_streams,
12283 const HttpRequestInfo& info,
12284 RequestPriority priority,
12285 const SSLConfig& server_ssl_config,
12286 const SSLConfig& proxy_ssl_config) OVERRIDE {
12287 ADD_FAILURE();
12290 virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
12291 ADD_FAILURE();
12292 return NULL;
12295 private:
12296 base::WeakPtr<FakeStreamRequest> last_stream_request_;
12298 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12301 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12302 // worth doing.
12303 class FakeWebSocketStreamCreateHelper :
12304 public WebSocketHandshakeStreamBase::CreateHelper {
12305 public:
12306 virtual WebSocketHandshakeStreamBase* CreateBasicStream(
12307 scoped_ptr<ClientSocketHandle> connection,
12308 bool using_proxy) OVERRIDE {
12309 NOTREACHED();
12310 return NULL;
12313 virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
12314 const base::WeakPtr<SpdySession>& session,
12315 bool use_relative_url) OVERRIDE {
12316 NOTREACHED();
12317 return NULL;
12320 virtual ~FakeWebSocketStreamCreateHelper() {}
12322 virtual scoped_ptr<WebSocketStream> Upgrade() {
12323 NOTREACHED();
12324 return scoped_ptr<WebSocketStream>();
12328 } // namespace
12330 // Make sure that HttpNetworkTransaction passes on its priority to its
12331 // stream request on start.
12332 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
12333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12334 HttpNetworkSessionPeer peer(session);
12335 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12336 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12338 HttpNetworkTransaction trans(LOW, session);
12340 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
12342 HttpRequestInfo request;
12343 TestCompletionCallback callback;
12344 EXPECT_EQ(ERR_IO_PENDING,
12345 trans.Start(&request, callback.callback(), BoundNetLog()));
12347 base::WeakPtr<FakeStreamRequest> fake_request =
12348 fake_factory->last_stream_request();
12349 ASSERT_TRUE(fake_request != NULL);
12350 EXPECT_EQ(LOW, fake_request->priority());
12353 // Make sure that HttpNetworkTransaction passes on its priority
12354 // updates to its stream request.
12355 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
12356 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12357 HttpNetworkSessionPeer peer(session);
12358 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12359 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12361 HttpNetworkTransaction trans(LOW, session);
12363 HttpRequestInfo request;
12364 TestCompletionCallback callback;
12365 EXPECT_EQ(ERR_IO_PENDING,
12366 trans.Start(&request, callback.callback(), BoundNetLog()));
12368 base::WeakPtr<FakeStreamRequest> fake_request =
12369 fake_factory->last_stream_request();
12370 ASSERT_TRUE(fake_request != NULL);
12371 EXPECT_EQ(LOW, fake_request->priority());
12373 trans.SetPriority(LOWEST);
12374 ASSERT_TRUE(fake_request != NULL);
12375 EXPECT_EQ(LOWEST, fake_request->priority());
12378 // Make sure that HttpNetworkTransaction passes on its priority
12379 // updates to its stream.
12380 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
12381 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12382 HttpNetworkSessionPeer peer(session);
12383 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12384 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12386 HttpNetworkTransaction trans(LOW, session);
12388 HttpRequestInfo request;
12389 TestCompletionCallback callback;
12390 EXPECT_EQ(ERR_IO_PENDING,
12391 trans.Start(&request, callback.callback(), BoundNetLog()));
12393 base::WeakPtr<FakeStreamRequest> fake_request =
12394 fake_factory->last_stream_request();
12395 ASSERT_TRUE(fake_request != NULL);
12396 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
12397 ASSERT_TRUE(fake_stream != NULL);
12398 EXPECT_EQ(LOW, fake_stream->priority());
12400 trans.SetPriority(LOWEST);
12401 EXPECT_EQ(LOWEST, fake_stream->priority());
12404 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
12405 // The same logic needs to be tested for both ws: and wss: schemes, but this
12406 // test is already parameterised on NextProto, so it uses a loop to verify
12407 // that the different schemes work.
12408 std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"};
12409 for (size_t i = 0; i < arraysize(test_cases); ++i) {
12410 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12411 HttpNetworkSessionPeer peer(session);
12412 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12413 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
12414 peer.SetHttpStreamFactoryForWebSocket(
12415 scoped_ptr<HttpStreamFactory>(fake_factory));
12417 HttpNetworkTransaction trans(LOW, session);
12418 trans.SetWebSocketHandshakeStreamCreateHelper(
12419 &websocket_stream_create_helper);
12421 HttpRequestInfo request;
12422 TestCompletionCallback callback;
12423 request.method = "GET";
12424 request.url = GURL(test_cases[i]);
12426 EXPECT_EQ(ERR_IO_PENDING,
12427 trans.Start(&request, callback.callback(), BoundNetLog()));
12429 base::WeakPtr<FakeStreamRequest> fake_request =
12430 fake_factory->last_stream_request();
12431 ASSERT_TRUE(fake_request != NULL);
12432 EXPECT_EQ(&websocket_stream_create_helper,
12433 fake_request->websocket_stream_create_helper());
12437 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12438 // if the transport socket pool is stalled on the global socket limit.
12439 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
12440 ClientSocketPoolManager::set_max_sockets_per_group(
12441 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12442 ClientSocketPoolManager::set_max_sockets_per_pool(
12443 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12445 // Set up SSL request.
12447 HttpRequestInfo ssl_request;
12448 ssl_request.method = "GET";
12449 ssl_request.url = GURL("https://www.google.com/");
12451 MockWrite ssl_writes[] = {
12452 MockWrite("GET / HTTP/1.1\r\n"
12453 "Host: www.google.com\r\n"
12454 "Connection: keep-alive\r\n\r\n"),
12456 MockRead ssl_reads[] = {
12457 MockRead("HTTP/1.1 200 OK\r\n"),
12458 MockRead("Content-Length: 11\r\n\r\n"),
12459 MockRead("hello world"),
12460 MockRead(SYNCHRONOUS, OK),
12462 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
12463 ssl_writes, arraysize(ssl_writes));
12464 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12466 SSLSocketDataProvider ssl(ASYNC, OK);
12467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12469 // Set up HTTP request.
12471 HttpRequestInfo http_request;
12472 http_request.method = "GET";
12473 http_request.url = GURL("http://www.google.com/");
12475 MockWrite http_writes[] = {
12476 MockWrite("GET / HTTP/1.1\r\n"
12477 "Host: www.google.com\r\n"
12478 "Connection: keep-alive\r\n\r\n"),
12480 MockRead http_reads[] = {
12481 MockRead("HTTP/1.1 200 OK\r\n"),
12482 MockRead("Content-Length: 7\r\n\r\n"),
12483 MockRead("falafel"),
12484 MockRead(SYNCHRONOUS, OK),
12486 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12487 http_writes, arraysize(http_writes));
12488 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12492 // Start the SSL request.
12493 TestCompletionCallback ssl_callback;
12494 scoped_ptr<HttpTransaction> ssl_trans(
12495 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12496 ASSERT_EQ(ERR_IO_PENDING,
12497 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
12498 BoundNetLog()));
12500 // Start the HTTP request. Pool should stall.
12501 TestCompletionCallback http_callback;
12502 scoped_ptr<HttpTransaction> http_trans(
12503 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12504 ASSERT_EQ(ERR_IO_PENDING,
12505 http_trans->Start(&http_request, http_callback.callback(),
12506 BoundNetLog()));
12507 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12509 // Wait for response from SSL request.
12510 ASSERT_EQ(OK, ssl_callback.WaitForResult());
12511 std::string response_data;
12512 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
12513 EXPECT_EQ("hello world", response_data);
12515 // The SSL socket should automatically be closed, so the HTTP request can
12516 // start.
12517 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12518 ASSERT_FALSE(IsTransportSocketPoolStalled(session));
12520 // The HTTP request can now complete.
12521 ASSERT_EQ(OK, http_callback.WaitForResult());
12522 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12523 EXPECT_EQ("falafel", response_data);
12525 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12528 // Tests that when a SSL connection is established but there's no corresponding
12529 // request that needs it, the new socket is closed if the transport socket pool
12530 // is stalled on the global socket limit.
12531 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
12532 ClientSocketPoolManager::set_max_sockets_per_group(
12533 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12534 ClientSocketPoolManager::set_max_sockets_per_pool(
12535 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12537 // Set up an ssl request.
12539 HttpRequestInfo ssl_request;
12540 ssl_request.method = "GET";
12541 ssl_request.url = GURL("https://www.foopy.com/");
12543 // No data will be sent on the SSL socket.
12544 StaticSocketDataProvider ssl_data;
12545 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12547 SSLSocketDataProvider ssl(ASYNC, OK);
12548 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12550 // Set up HTTP request.
12552 HttpRequestInfo http_request;
12553 http_request.method = "GET";
12554 http_request.url = GURL("http://www.google.com/");
12556 MockWrite http_writes[] = {
12557 MockWrite("GET / HTTP/1.1\r\n"
12558 "Host: www.google.com\r\n"
12559 "Connection: keep-alive\r\n\r\n"),
12561 MockRead http_reads[] = {
12562 MockRead("HTTP/1.1 200 OK\r\n"),
12563 MockRead("Content-Length: 7\r\n\r\n"),
12564 MockRead("falafel"),
12565 MockRead(SYNCHRONOUS, OK),
12567 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12568 http_writes, arraysize(http_writes));
12569 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12571 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12573 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12574 // cancelled when a normal transaction is cancelled.
12575 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
12576 net::SSLConfig ssl_config;
12577 session->ssl_config_service()->GetSSLConfig(&ssl_config);
12578 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
12579 ssl_config, ssl_config);
12580 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12582 // Start the HTTP request. Pool should stall.
12583 TestCompletionCallback http_callback;
12584 scoped_ptr<HttpTransaction> http_trans(
12585 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12586 ASSERT_EQ(ERR_IO_PENDING,
12587 http_trans->Start(&http_request, http_callback.callback(),
12588 BoundNetLog()));
12589 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12591 // The SSL connection will automatically be closed once the connection is
12592 // established, to let the HTTP request start.
12593 ASSERT_EQ(OK, http_callback.WaitForResult());
12594 std::string response_data;
12595 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12596 EXPECT_EQ("falafel", response_data);
12598 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12601 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
12602 ScopedVector<UploadElementReader> element_readers;
12603 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12604 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12606 HttpRequestInfo request;
12607 request.method = "POST";
12608 request.url = GURL("http://www.foo.com/");
12609 request.upload_data_stream = &upload_data_stream;
12610 request.load_flags = 0;
12612 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12613 scoped_ptr<HttpTransaction> trans(
12614 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12615 // Send headers successfully, but get an error while sending the body.
12616 MockWrite data_writes[] = {
12617 MockWrite("POST / HTTP/1.1\r\n"
12618 "Host: www.foo.com\r\n"
12619 "Connection: keep-alive\r\n"
12620 "Content-Length: 3\r\n\r\n"),
12621 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12624 MockRead data_reads[] = {
12625 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12626 MockRead("hello world"),
12627 MockRead(SYNCHRONOUS, OK),
12629 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12630 arraysize(data_writes));
12631 session_deps_.socket_factory->AddSocketDataProvider(&data);
12633 TestCompletionCallback callback;
12635 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12636 EXPECT_EQ(ERR_IO_PENDING, rv);
12638 rv = callback.WaitForResult();
12639 EXPECT_EQ(OK, rv);
12641 const HttpResponseInfo* response = trans->GetResponseInfo();
12642 ASSERT_TRUE(response != NULL);
12644 EXPECT_TRUE(response->headers.get() != NULL);
12645 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12647 std::string response_data;
12648 rv = ReadTransaction(trans.get(), &response_data);
12649 EXPECT_EQ(OK, rv);
12650 EXPECT_EQ("hello world", response_data);
12653 // This test makes sure the retry logic doesn't trigger when reading an error
12654 // response from a server that rejected a POST with a CONNECTION_RESET.
12655 TEST_P(HttpNetworkTransactionTest,
12656 PostReadsErrorResponseAfterResetOnReusedSocket) {
12657 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12658 MockWrite data_writes[] = {
12659 MockWrite("GET / HTTP/1.1\r\n"
12660 "Host: www.foo.com\r\n"
12661 "Connection: keep-alive\r\n\r\n"),
12662 MockWrite("POST / HTTP/1.1\r\n"
12663 "Host: www.foo.com\r\n"
12664 "Connection: keep-alive\r\n"
12665 "Content-Length: 3\r\n\r\n"),
12666 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12669 MockRead data_reads[] = {
12670 MockRead("HTTP/1.1 200 Peachy\r\n"
12671 "Content-Length: 14\r\n\r\n"),
12672 MockRead("first response"),
12673 MockRead("HTTP/1.1 400 Not OK\r\n"
12674 "Content-Length: 15\r\n\r\n"),
12675 MockRead("second response"),
12676 MockRead(SYNCHRONOUS, OK),
12678 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12679 arraysize(data_writes));
12680 session_deps_.socket_factory->AddSocketDataProvider(&data);
12682 TestCompletionCallback callback;
12683 HttpRequestInfo request1;
12684 request1.method = "GET";
12685 request1.url = GURL("http://www.foo.com/");
12686 request1.load_flags = 0;
12688 scoped_ptr<HttpTransaction> trans1(
12689 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12690 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
12691 EXPECT_EQ(ERR_IO_PENDING, rv);
12693 rv = callback.WaitForResult();
12694 EXPECT_EQ(OK, rv);
12696 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12697 ASSERT_TRUE(response1 != NULL);
12699 EXPECT_TRUE(response1->headers.get() != NULL);
12700 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
12702 std::string response_data1;
12703 rv = ReadTransaction(trans1.get(), &response_data1);
12704 EXPECT_EQ(OK, rv);
12705 EXPECT_EQ("first response", response_data1);
12706 // Delete the transaction to release the socket back into the socket pool.
12707 trans1.reset();
12709 ScopedVector<UploadElementReader> element_readers;
12710 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12711 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12713 HttpRequestInfo request2;
12714 request2.method = "POST";
12715 request2.url = GURL("http://www.foo.com/");
12716 request2.upload_data_stream = &upload_data_stream;
12717 request2.load_flags = 0;
12719 scoped_ptr<HttpTransaction> trans2(
12720 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12721 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
12722 EXPECT_EQ(ERR_IO_PENDING, rv);
12724 rv = callback.WaitForResult();
12725 EXPECT_EQ(OK, rv);
12727 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
12728 ASSERT_TRUE(response2 != NULL);
12730 EXPECT_TRUE(response2->headers.get() != NULL);
12731 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
12733 std::string response_data2;
12734 rv = ReadTransaction(trans2.get(), &response_data2);
12735 EXPECT_EQ(OK, rv);
12736 EXPECT_EQ("second response", response_data2);
12739 TEST_P(HttpNetworkTransactionTest,
12740 PostReadsErrorResponseAfterResetPartialBodySent) {
12741 ScopedVector<UploadElementReader> element_readers;
12742 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12743 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12745 HttpRequestInfo request;
12746 request.method = "POST";
12747 request.url = GURL("http://www.foo.com/");
12748 request.upload_data_stream = &upload_data_stream;
12749 request.load_flags = 0;
12751 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12752 scoped_ptr<HttpTransaction> trans(
12753 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12754 // Send headers successfully, but get an error while sending the body.
12755 MockWrite data_writes[] = {
12756 MockWrite("POST / HTTP/1.1\r\n"
12757 "Host: www.foo.com\r\n"
12758 "Connection: keep-alive\r\n"
12759 "Content-Length: 3\r\n\r\n"
12760 "fo"),
12761 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12764 MockRead data_reads[] = {
12765 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12766 MockRead("hello world"),
12767 MockRead(SYNCHRONOUS, OK),
12769 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12770 arraysize(data_writes));
12771 session_deps_.socket_factory->AddSocketDataProvider(&data);
12773 TestCompletionCallback callback;
12775 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12776 EXPECT_EQ(ERR_IO_PENDING, rv);
12778 rv = callback.WaitForResult();
12779 EXPECT_EQ(OK, rv);
12781 const HttpResponseInfo* response = trans->GetResponseInfo();
12782 ASSERT_TRUE(response != NULL);
12784 EXPECT_TRUE(response->headers.get() != NULL);
12785 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12787 std::string response_data;
12788 rv = ReadTransaction(trans.get(), &response_data);
12789 EXPECT_EQ(OK, rv);
12790 EXPECT_EQ("hello world", response_data);
12793 // This tests the more common case than the previous test, where headers and
12794 // body are not merged into a single request.
12795 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
12796 ScopedVector<UploadElementReader> element_readers;
12797 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12798 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
12800 HttpRequestInfo request;
12801 request.method = "POST";
12802 request.url = GURL("http://www.foo.com/");
12803 request.upload_data_stream = &upload_data_stream;
12804 request.load_flags = 0;
12806 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12807 scoped_ptr<HttpTransaction> trans(
12808 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12809 // Send headers successfully, but get an error while sending the body.
12810 MockWrite data_writes[] = {
12811 MockWrite("POST / HTTP/1.1\r\n"
12812 "Host: www.foo.com\r\n"
12813 "Connection: keep-alive\r\n"
12814 "Transfer-Encoding: chunked\r\n\r\n"),
12815 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12818 MockRead data_reads[] = {
12819 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12820 MockRead("hello world"),
12821 MockRead(SYNCHRONOUS, OK),
12823 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12824 arraysize(data_writes));
12825 session_deps_.socket_factory->AddSocketDataProvider(&data);
12827 TestCompletionCallback callback;
12829 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12830 EXPECT_EQ(ERR_IO_PENDING, rv);
12831 // Make sure the headers are sent before adding a chunk. This ensures that
12832 // they can't be merged with the body in a single send. Not currently
12833 // necessary since a chunked body is never merged with headers, but this makes
12834 // the test more future proof.
12835 base::RunLoop().RunUntilIdle();
12837 upload_data_stream.AppendChunk("last chunk", 10, true);
12839 rv = callback.WaitForResult();
12840 EXPECT_EQ(OK, rv);
12842 const HttpResponseInfo* response = trans->GetResponseInfo();
12843 ASSERT_TRUE(response != NULL);
12845 EXPECT_TRUE(response->headers.get() != NULL);
12846 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12848 std::string response_data;
12849 rv = ReadTransaction(trans.get(), &response_data);
12850 EXPECT_EQ(OK, rv);
12851 EXPECT_EQ("hello world", response_data);
12854 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
12855 ScopedVector<UploadElementReader> element_readers;
12856 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12857 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12859 HttpRequestInfo request;
12860 request.method = "POST";
12861 request.url = GURL("http://www.foo.com/");
12862 request.upload_data_stream = &upload_data_stream;
12863 request.load_flags = 0;
12865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12866 scoped_ptr<HttpTransaction> trans(
12867 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12869 MockWrite data_writes[] = {
12870 MockWrite("POST / HTTP/1.1\r\n"
12871 "Host: www.foo.com\r\n"
12872 "Connection: keep-alive\r\n"
12873 "Content-Length: 3\r\n\r\n"),
12874 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12877 MockRead data_reads[] = {
12878 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12879 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12880 MockRead("hello world"),
12881 MockRead(SYNCHRONOUS, OK),
12883 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12884 arraysize(data_writes));
12885 session_deps_.socket_factory->AddSocketDataProvider(&data);
12887 TestCompletionCallback callback;
12889 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12890 EXPECT_EQ(ERR_IO_PENDING, rv);
12892 rv = callback.WaitForResult();
12893 EXPECT_EQ(OK, rv);
12895 const HttpResponseInfo* response = trans->GetResponseInfo();
12896 ASSERT_TRUE(response != NULL);
12898 EXPECT_TRUE(response->headers.get() != NULL);
12899 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12901 std::string response_data;
12902 rv = ReadTransaction(trans.get(), &response_data);
12903 EXPECT_EQ(OK, rv);
12904 EXPECT_EQ("hello world", response_data);
12907 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
12908 ScopedVector<UploadElementReader> element_readers;
12909 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12910 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12912 HttpRequestInfo request;
12913 request.method = "POST";
12914 request.url = GURL("http://www.foo.com/");
12915 request.upload_data_stream = &upload_data_stream;
12916 request.load_flags = 0;
12918 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12919 scoped_ptr<HttpTransaction> trans(
12920 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12921 // Send headers successfully, but get an error while sending the body.
12922 MockWrite data_writes[] = {
12923 MockWrite("POST / HTTP/1.1\r\n"
12924 "Host: www.foo.com\r\n"
12925 "Connection: keep-alive\r\n"
12926 "Content-Length: 3\r\n\r\n"),
12927 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12930 MockRead data_reads[] = {
12931 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
12932 MockRead("hello world"),
12933 MockRead(SYNCHRONOUS, OK),
12935 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12936 arraysize(data_writes));
12937 session_deps_.socket_factory->AddSocketDataProvider(&data);
12939 TestCompletionCallback callback;
12941 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12942 EXPECT_EQ(ERR_IO_PENDING, rv);
12944 rv = callback.WaitForResult();
12945 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12947 const HttpResponseInfo* response = trans->GetResponseInfo();
12948 EXPECT_TRUE(response == NULL);
12951 TEST_P(HttpNetworkTransactionTest,
12952 PostIgnoresNonErrorResponseAfterResetAnd100) {
12953 ScopedVector<UploadElementReader> element_readers;
12954 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12955 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12957 HttpRequestInfo request;
12958 request.method = "POST";
12959 request.url = GURL("http://www.foo.com/");
12960 request.upload_data_stream = &upload_data_stream;
12961 request.load_flags = 0;
12963 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12964 scoped_ptr<HttpTransaction> trans(
12965 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12966 // Send headers successfully, but get an error while sending the body.
12967 MockWrite data_writes[] = {
12968 MockWrite("POST / HTTP/1.1\r\n"
12969 "Host: www.foo.com\r\n"
12970 "Connection: keep-alive\r\n"
12971 "Content-Length: 3\r\n\r\n"),
12972 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12975 MockRead data_reads[] = {
12976 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12977 MockRead("HTTP/1.0 302 Redirect\r\n"),
12978 MockRead("Location: http://somewhere-else.com/\r\n"),
12979 MockRead("Content-Length: 0\r\n\r\n"),
12980 MockRead(SYNCHRONOUS, OK),
12982 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12983 arraysize(data_writes));
12984 session_deps_.socket_factory->AddSocketDataProvider(&data);
12986 TestCompletionCallback callback;
12988 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12989 EXPECT_EQ(ERR_IO_PENDING, rv);
12991 rv = callback.WaitForResult();
12992 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12994 const HttpResponseInfo* response = trans->GetResponseInfo();
12995 EXPECT_TRUE(response == NULL);
12998 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
12999 ScopedVector<UploadElementReader> element_readers;
13000 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13001 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13003 HttpRequestInfo request;
13004 request.method = "POST";
13005 request.url = GURL("http://www.foo.com/");
13006 request.upload_data_stream = &upload_data_stream;
13007 request.load_flags = 0;
13009 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13010 scoped_ptr<HttpTransaction> trans(
13011 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13012 // Send headers successfully, but get an error while sending the body.
13013 MockWrite data_writes[] = {
13014 MockWrite("POST / HTTP/1.1\r\n"
13015 "Host: www.foo.com\r\n"
13016 "Connection: keep-alive\r\n"
13017 "Content-Length: 3\r\n\r\n"),
13018 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13021 MockRead data_reads[] = {
13022 MockRead("HTTP 0.9 rocks!"),
13023 MockRead(SYNCHRONOUS, OK),
13025 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13026 arraysize(data_writes));
13027 session_deps_.socket_factory->AddSocketDataProvider(&data);
13029 TestCompletionCallback callback;
13031 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13032 EXPECT_EQ(ERR_IO_PENDING, rv);
13034 rv = callback.WaitForResult();
13035 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13037 const HttpResponseInfo* response = trans->GetResponseInfo();
13038 EXPECT_TRUE(response == NULL);
13041 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
13042 ScopedVector<UploadElementReader> element_readers;
13043 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13044 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13046 HttpRequestInfo request;
13047 request.method = "POST";
13048 request.url = GURL("http://www.foo.com/");
13049 request.upload_data_stream = &upload_data_stream;
13050 request.load_flags = 0;
13052 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13053 scoped_ptr<HttpTransaction> trans(
13054 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13055 // Send headers successfully, but get an error while sending the body.
13056 MockWrite data_writes[] = {
13057 MockWrite("POST / HTTP/1.1\r\n"
13058 "Host: www.foo.com\r\n"
13059 "Connection: keep-alive\r\n"
13060 "Content-Length: 3\r\n\r\n"),
13061 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13064 MockRead data_reads[] = {
13065 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13066 MockRead(SYNCHRONOUS, OK),
13068 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13069 arraysize(data_writes));
13070 session_deps_.socket_factory->AddSocketDataProvider(&data);
13072 TestCompletionCallback callback;
13074 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13075 EXPECT_EQ(ERR_IO_PENDING, rv);
13077 rv = callback.WaitForResult();
13078 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13080 const HttpResponseInfo* response = trans->GetResponseInfo();
13081 EXPECT_TRUE(response == NULL);
13084 } // namespace net