Add a function to create a bookmark app from a WebApplicationInfo.
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blob02a77e4cc6b52031e5ef7b466946a1b01a335211
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_unittest.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();
268 HttpStreamFactory::set_use_alternate_protocols(false);
269 HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
272 // This is the expected return from a current server advertising SPDY.
273 std::string GetAlternateProtocolHttpHeader() {
274 return
275 std::string("Alternate-Protocol: 443:") +
276 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
277 "\r\n\r\n";
280 // Either |write_failure| specifies a write failure or |read_failure|
281 // specifies a read failure when using a reused socket. In either case, the
282 // failure should cause the network transaction to resend the request, and the
283 // other argument should be NULL.
284 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
285 const MockRead* read_failure);
287 // Either |write_failure| specifies a write failure or |read_failure|
288 // specifies a read failure when using a reused socket. In either case, the
289 // failure should cause the network transaction to resend the request, and the
290 // other argument should be NULL.
291 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
292 const MockRead* read_failure,
293 bool use_spdy);
295 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
296 size_t data_count) {
297 SimpleGetHelperResult out;
299 HttpRequestInfo request;
300 request.method = "GET";
301 request.url = GURL("http://www.google.com/");
302 request.load_flags = 0;
304 CapturingBoundNetLog log;
305 session_deps_.net_log = log.bound().net_log();
306 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
307 scoped_ptr<HttpTransaction> trans(
308 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
310 for (size_t i = 0; i < data_count; ++i) {
311 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
314 TestCompletionCallback callback;
316 EXPECT_TRUE(log.bound().IsLogging());
317 int rv = trans->Start(&request, callback.callback(), log.bound());
318 EXPECT_EQ(ERR_IO_PENDING, rv);
320 out.rv = callback.WaitForResult();
322 // Even in the failure cases that use this function, connections are always
323 // successfully established before the error.
324 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
325 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
327 if (out.rv != OK)
328 return out;
330 const HttpResponseInfo* response = trans->GetResponseInfo();
331 // Can't use ASSERT_* inside helper functions like this, so
332 // return an error.
333 if (response == NULL || response->headers.get() == NULL) {
334 out.rv = ERR_UNEXPECTED;
335 return out;
337 out.status_line = response->headers->GetStatusLine();
339 EXPECT_EQ("127.0.0.1", response->socket_address.host());
340 EXPECT_EQ(80, response->socket_address.port());
342 rv = ReadTransaction(trans.get(), &out.response_data);
343 EXPECT_EQ(OK, rv);
345 net::CapturingNetLog::CapturedEntryList entries;
346 log.GetEntries(&entries);
347 size_t pos = ExpectLogContainsSomewhere(
348 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
349 NetLog::PHASE_NONE);
350 ExpectLogContainsSomewhere(
351 entries, pos,
352 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
353 NetLog::PHASE_NONE);
355 std::string line;
356 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
357 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
359 HttpRequestHeaders request_headers;
360 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
361 std::string value;
362 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
363 EXPECT_EQ("www.google.com", value);
364 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
365 EXPECT_EQ("keep-alive", value);
367 std::string response_headers;
368 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
369 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
370 response_headers);
372 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
373 return out;
376 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
377 size_t reads_count) {
378 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
379 StaticSocketDataProvider* data[] = { &reads };
380 return SimpleGetHelperForData(data, 1);
383 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
384 int64 size = 0;
385 for (size_t i = 0; i < reads_count; ++i)
386 size += data_reads[i].data_len;
387 return size;
390 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
391 int expected_status);
393 void ConnectStatusHelper(const MockRead& status);
395 void BypassHostCacheOnRefreshHelper(int load_flags);
397 void CheckErrorIsPassedBack(int error, IoMode mode);
399 SpdyTestUtil spdy_util_;
400 SpdySessionDependencies session_deps_;
402 // Original socket limits. Some tests set these. Safest to always restore
403 // them once each test has been run.
404 int old_max_group_sockets_;
405 int old_max_pool_sockets_;
408 INSTANTIATE_TEST_CASE_P(
409 NextProto,
410 HttpNetworkTransactionTest,
411 testing::Values(kProtoDeprecatedSPDY2,
412 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
413 kProtoHTTP2Draft04));
415 namespace {
417 class BeforeNetworkStartHandler {
418 public:
419 explicit BeforeNetworkStartHandler(bool defer)
420 : defer_on_before_network_start_(defer),
421 observed_before_network_start_(false) {}
423 void OnBeforeNetworkStart(bool* defer) {
424 *defer = defer_on_before_network_start_;
425 observed_before_network_start_ = true;
428 bool observed_before_network_start() const {
429 return observed_before_network_start_;
432 private:
433 const bool defer_on_before_network_start_;
434 bool observed_before_network_start_;
436 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
439 // Fill |str| with a long header list that consumes >= |size| bytes.
440 void FillLargeHeadersString(std::string* str, int size) {
441 const char* row =
442 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
443 const int sizeof_row = strlen(row);
444 const int num_rows = static_cast<int>(
445 ceil(static_cast<float>(size) / sizeof_row));
446 const int sizeof_data = num_rows * sizeof_row;
447 DCHECK(sizeof_data >= size);
448 str->reserve(sizeof_data);
450 for (int i = 0; i < num_rows; ++i)
451 str->append(row, sizeof_row);
454 // Alternative functions that eliminate randomness and dependency on the local
455 // host name so that the generated NTLM messages are reproducible.
456 void MockGenerateRandom1(uint8* output, size_t n) {
457 static const uint8 bytes[] = {
458 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
460 static size_t current_byte = 0;
461 for (size_t i = 0; i < n; ++i) {
462 output[i] = bytes[current_byte++];
463 current_byte %= arraysize(bytes);
467 void MockGenerateRandom2(uint8* output, size_t n) {
468 static const uint8 bytes[] = {
469 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
470 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
472 static size_t current_byte = 0;
473 for (size_t i = 0; i < n; ++i) {
474 output[i] = bytes[current_byte++];
475 current_byte %= arraysize(bytes);
479 std::string MockGetHostName() {
480 return "WTC-WIN7";
483 template<typename ParentPool>
484 class CaptureGroupNameSocketPool : public ParentPool {
485 public:
486 CaptureGroupNameSocketPool(HostResolver* host_resolver,
487 CertVerifier* cert_verifier);
489 const std::string last_group_name_received() const {
490 return last_group_name_;
493 virtual int RequestSocket(const std::string& group_name,
494 const void* socket_params,
495 RequestPriority priority,
496 ClientSocketHandle* handle,
497 const CompletionCallback& callback,
498 const BoundNetLog& net_log) {
499 last_group_name_ = group_name;
500 return ERR_IO_PENDING;
502 virtual void CancelRequest(const std::string& group_name,
503 ClientSocketHandle* handle) {}
504 virtual void ReleaseSocket(const std::string& group_name,
505 scoped_ptr<StreamSocket> socket,
506 int id) {}
507 virtual void CloseIdleSockets() {}
508 virtual int IdleSocketCount() const {
509 return 0;
511 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
512 return 0;
514 virtual LoadState GetLoadState(const std::string& group_name,
515 const ClientSocketHandle* handle) const {
516 return LOAD_STATE_IDLE;
518 virtual base::TimeDelta ConnectionTimeout() const {
519 return base::TimeDelta();
522 private:
523 std::string last_group_name_;
526 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
527 CaptureGroupNameTransportSocketPool;
528 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
529 CaptureGroupNameHttpProxySocketPool;
530 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
531 CaptureGroupNameSOCKSSocketPool;
532 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
533 CaptureGroupNameSSLSocketPool;
535 template<typename ParentPool>
536 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
537 HostResolver* host_resolver,
538 CertVerifier* /* cert_verifier */)
539 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
541 template<>
542 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
543 HostResolver* host_resolver,
544 CertVerifier* /* cert_verifier */)
545 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
547 template <>
548 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
549 HostResolver* host_resolver,
550 CertVerifier* cert_verifier)
551 : SSLClientSocketPool(0,
553 NULL,
554 host_resolver,
555 cert_verifier,
556 NULL,
557 NULL,
558 NULL,
559 std::string(),
560 NULL,
561 NULL,
562 NULL,
563 NULL,
564 NULL,
565 NULL) {}
567 //-----------------------------------------------------------------------------
569 // Helper functions for validating that AuthChallengeInfo's are correctly
570 // configured for common cases.
571 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
572 if (!auth_challenge)
573 return false;
574 EXPECT_FALSE(auth_challenge->is_proxy);
575 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
576 EXPECT_EQ("MyRealm1", auth_challenge->realm);
577 EXPECT_EQ("basic", auth_challenge->scheme);
578 return true;
581 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
582 if (!auth_challenge)
583 return false;
584 EXPECT_TRUE(auth_challenge->is_proxy);
585 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
586 EXPECT_EQ("MyRealm1", auth_challenge->realm);
587 EXPECT_EQ("basic", auth_challenge->scheme);
588 return true;
591 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
592 if (!auth_challenge)
593 return false;
594 EXPECT_FALSE(auth_challenge->is_proxy);
595 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
596 EXPECT_EQ("digestive", auth_challenge->realm);
597 EXPECT_EQ("digest", auth_challenge->scheme);
598 return true;
601 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
602 if (!auth_challenge)
603 return false;
604 EXPECT_FALSE(auth_challenge->is_proxy);
605 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
606 EXPECT_EQ(std::string(), auth_challenge->realm);
607 EXPECT_EQ("ntlm", auth_challenge->scheme);
608 return true;
611 } // namespace
613 TEST_P(HttpNetworkTransactionTest, Basic) {
614 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
615 scoped_ptr<HttpTransaction> trans(
616 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
619 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
620 MockRead data_reads[] = {
621 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
622 MockRead("hello world"),
623 MockRead(SYNCHRONOUS, OK),
625 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
626 arraysize(data_reads));
627 EXPECT_EQ(OK, out.rv);
628 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
629 EXPECT_EQ("hello world", out.response_data);
630 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
631 EXPECT_EQ(reads_size, out.totalReceivedBytes);
634 // Response with no status line.
635 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
636 MockRead data_reads[] = {
637 MockRead("hello world"),
638 MockRead(SYNCHRONOUS, OK),
640 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
641 arraysize(data_reads));
642 EXPECT_EQ(OK, out.rv);
643 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
644 EXPECT_EQ("hello world", out.response_data);
645 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
646 EXPECT_EQ(reads_size, out.totalReceivedBytes);
649 // Allow up to 4 bytes of junk to precede status line.
650 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
651 MockRead data_reads[] = {
652 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
653 MockRead(SYNCHRONOUS, OK),
655 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
656 arraysize(data_reads));
657 EXPECT_EQ(OK, out.rv);
658 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
659 EXPECT_EQ("DATA", out.response_data);
660 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
661 EXPECT_EQ(reads_size, out.totalReceivedBytes);
664 // Allow up to 4 bytes of junk to precede status line.
665 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
666 MockRead data_reads[] = {
667 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
668 MockRead(SYNCHRONOUS, OK),
670 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
671 arraysize(data_reads));
672 EXPECT_EQ(OK, out.rv);
673 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
674 EXPECT_EQ("DATA", out.response_data);
675 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
676 EXPECT_EQ(reads_size, out.totalReceivedBytes);
679 // Beyond 4 bytes of slop and it should fail to find a status line.
680 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
681 MockRead data_reads[] = {
682 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
683 MockRead(SYNCHRONOUS, OK),
685 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
686 arraysize(data_reads));
687 EXPECT_EQ(OK, out.rv);
688 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
689 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
690 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
691 EXPECT_EQ(reads_size, out.totalReceivedBytes);
694 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
695 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
696 MockRead data_reads[] = {
697 MockRead("\n"),
698 MockRead("\n"),
699 MockRead("Q"),
700 MockRead("J"),
701 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
702 MockRead(SYNCHRONOUS, OK),
704 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
705 arraysize(data_reads));
706 EXPECT_EQ(OK, out.rv);
707 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
708 EXPECT_EQ("DATA", out.response_data);
709 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
710 EXPECT_EQ(reads_size, out.totalReceivedBytes);
713 // Close the connection before enough bytes to have a status line.
714 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
715 MockRead data_reads[] = {
716 MockRead("HTT"),
717 MockRead(SYNCHRONOUS, OK),
719 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
720 arraysize(data_reads));
721 EXPECT_EQ(OK, out.rv);
722 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
723 EXPECT_EQ("HTT", out.response_data);
724 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
725 EXPECT_EQ(reads_size, out.totalReceivedBytes);
728 // Simulate a 204 response, lacking a Content-Length header, sent over a
729 // persistent connection. The response should still terminate since a 204
730 // cannot have a response body.
731 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
732 char junk[] = "junk";
733 MockRead data_reads[] = {
734 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
735 MockRead(junk), // Should not be read!!
736 MockRead(SYNCHRONOUS, OK),
738 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
739 arraysize(data_reads));
740 EXPECT_EQ(OK, out.rv);
741 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
742 EXPECT_EQ("", out.response_data);
743 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
744 int64 response_size = reads_size - strlen(junk);
745 EXPECT_EQ(response_size, out.totalReceivedBytes);
748 // A simple request using chunked encoding with some extra data after.
749 // (Like might be seen in a pipelined response.)
750 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
751 std::string final_chunk = "0\r\n\r\n";
752 std::string extra_data = "HTTP/1.1 200 OK\r\n";
753 std::string last_read = final_chunk + extra_data;
754 MockRead data_reads[] = {
755 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
756 MockRead("5\r\nHello\r\n"),
757 MockRead("1\r\n"),
758 MockRead(" \r\n"),
759 MockRead("5\r\nworld\r\n"),
760 MockRead(last_read.data()),
761 MockRead(SYNCHRONOUS, OK),
763 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
764 arraysize(data_reads));
765 EXPECT_EQ(OK, out.rv);
766 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
767 EXPECT_EQ("Hello world", out.response_data);
768 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
769 int64 response_size = reads_size - extra_data.size();
770 EXPECT_EQ(response_size, out.totalReceivedBytes);
773 // Next tests deal with http://crbug.com/56344.
775 TEST_P(HttpNetworkTransactionTest,
776 MultipleContentLengthHeadersNoTransferEncoding) {
777 MockRead data_reads[] = {
778 MockRead("HTTP/1.1 200 OK\r\n"),
779 MockRead("Content-Length: 10\r\n"),
780 MockRead("Content-Length: 5\r\n\r\n"),
782 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
783 arraysize(data_reads));
784 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
787 TEST_P(HttpNetworkTransactionTest,
788 DuplicateContentLengthHeadersNoTransferEncoding) {
789 MockRead data_reads[] = {
790 MockRead("HTTP/1.1 200 OK\r\n"),
791 MockRead("Content-Length: 5\r\n"),
792 MockRead("Content-Length: 5\r\n\r\n"),
793 MockRead("Hello"),
795 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
796 arraysize(data_reads));
797 EXPECT_EQ(OK, out.rv);
798 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
799 EXPECT_EQ("Hello", out.response_data);
802 TEST_P(HttpNetworkTransactionTest,
803 ComplexContentLengthHeadersNoTransferEncoding) {
804 // More than 2 dupes.
806 MockRead data_reads[] = {
807 MockRead("HTTP/1.1 200 OK\r\n"),
808 MockRead("Content-Length: 5\r\n"),
809 MockRead("Content-Length: 5\r\n"),
810 MockRead("Content-Length: 5\r\n\r\n"),
811 MockRead("Hello"),
813 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
814 arraysize(data_reads));
815 EXPECT_EQ(OK, out.rv);
816 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
817 EXPECT_EQ("Hello", out.response_data);
819 // HTTP/1.0
821 MockRead data_reads[] = {
822 MockRead("HTTP/1.0 200 OK\r\n"),
823 MockRead("Content-Length: 5\r\n"),
824 MockRead("Content-Length: 5\r\n"),
825 MockRead("Content-Length: 5\r\n\r\n"),
826 MockRead("Hello"),
828 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
829 arraysize(data_reads));
830 EXPECT_EQ(OK, out.rv);
831 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
832 EXPECT_EQ("Hello", out.response_data);
834 // 2 dupes and one mismatched.
836 MockRead data_reads[] = {
837 MockRead("HTTP/1.1 200 OK\r\n"),
838 MockRead("Content-Length: 10\r\n"),
839 MockRead("Content-Length: 10\r\n"),
840 MockRead("Content-Length: 5\r\n\r\n"),
842 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
843 arraysize(data_reads));
844 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
848 TEST_P(HttpNetworkTransactionTest,
849 MultipleContentLengthHeadersTransferEncoding) {
850 MockRead data_reads[] = {
851 MockRead("HTTP/1.1 200 OK\r\n"),
852 MockRead("Content-Length: 666\r\n"),
853 MockRead("Content-Length: 1337\r\n"),
854 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
855 MockRead("5\r\nHello\r\n"),
856 MockRead("1\r\n"),
857 MockRead(" \r\n"),
858 MockRead("5\r\nworld\r\n"),
859 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
860 MockRead(SYNCHRONOUS, OK),
862 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
863 arraysize(data_reads));
864 EXPECT_EQ(OK, out.rv);
865 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
866 EXPECT_EQ("Hello world", out.response_data);
869 // Next tests deal with http://crbug.com/98895.
871 // Checks that a single Content-Disposition header results in no error.
872 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
873 MockRead data_reads[] = {
874 MockRead("HTTP/1.1 200 OK\r\n"),
875 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
876 MockRead("Content-Length: 5\r\n\r\n"),
877 MockRead("Hello"),
879 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
880 arraysize(data_reads));
881 EXPECT_EQ(OK, out.rv);
882 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
883 EXPECT_EQ("Hello", out.response_data);
886 // Checks that two identical Content-Disposition headers result in no error.
887 TEST_P(HttpNetworkTransactionTest,
888 TwoIdenticalContentDispositionHeaders) {
889 MockRead data_reads[] = {
890 MockRead("HTTP/1.1 200 OK\r\n"),
891 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
892 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
893 MockRead("Content-Length: 5\r\n\r\n"),
894 MockRead("Hello"),
896 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
897 arraysize(data_reads));
898 EXPECT_EQ(OK, out.rv);
899 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
900 EXPECT_EQ("Hello", out.response_data);
903 // Checks that two distinct Content-Disposition headers result in an error.
904 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
905 MockRead data_reads[] = {
906 MockRead("HTTP/1.1 200 OK\r\n"),
907 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
908 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
909 MockRead("Content-Length: 5\r\n\r\n"),
910 MockRead("Hello"),
912 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
913 arraysize(data_reads));
914 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
917 // Checks that two identical Location headers result in no error.
918 // Also tests Location header behavior.
919 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
920 MockRead data_reads[] = {
921 MockRead("HTTP/1.1 302 Redirect\r\n"),
922 MockRead("Location: http://good.com/\r\n"),
923 MockRead("Location: http://good.com/\r\n"),
924 MockRead("Content-Length: 0\r\n\r\n"),
925 MockRead(SYNCHRONOUS, OK),
928 HttpRequestInfo request;
929 request.method = "GET";
930 request.url = GURL("http://redirect.com/");
931 request.load_flags = 0;
933 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
934 scoped_ptr<HttpTransaction> trans(
935 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
937 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
938 session_deps_.socket_factory->AddSocketDataProvider(&data);
940 TestCompletionCallback callback;
942 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
943 EXPECT_EQ(ERR_IO_PENDING, rv);
945 EXPECT_EQ(OK, callback.WaitForResult());
947 const HttpResponseInfo* response = trans->GetResponseInfo();
948 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
949 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
950 std::string url;
951 EXPECT_TRUE(response->headers->IsRedirect(&url));
952 EXPECT_EQ("http://good.com/", url);
955 // Checks that two distinct Location headers result in an error.
956 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
957 MockRead data_reads[] = {
958 MockRead("HTTP/1.1 302 Redirect\r\n"),
959 MockRead("Location: http://good.com/\r\n"),
960 MockRead("Location: http://evil.com/\r\n"),
961 MockRead("Content-Length: 0\r\n\r\n"),
962 MockRead(SYNCHRONOUS, OK),
964 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
965 arraysize(data_reads));
966 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
969 // Do a request using the HEAD method. Verify that we don't try to read the
970 // message body (since HEAD has none).
971 TEST_P(HttpNetworkTransactionTest, Head) {
972 HttpRequestInfo request;
973 request.method = "HEAD";
974 request.url = GURL("http://www.google.com/");
975 request.load_flags = 0;
977 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
978 scoped_ptr<HttpTransaction> trans(
979 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
981 MockWrite data_writes1[] = {
982 MockWrite("HEAD / HTTP/1.1\r\n"
983 "Host: www.google.com\r\n"
984 "Connection: keep-alive\r\n"
985 "Content-Length: 0\r\n\r\n"),
987 MockRead data_reads1[] = {
988 MockRead("HTTP/1.1 404 Not Found\r\n"),
989 MockRead("Server: Blah\r\n"),
990 MockRead("Content-Length: 1234\r\n\r\n"),
992 // No response body because the test stops reading here.
993 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
996 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
997 data_writes1, arraysize(data_writes1));
998 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1000 TestCompletionCallback callback1;
1002 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1003 EXPECT_EQ(ERR_IO_PENDING, rv);
1005 rv = callback1.WaitForResult();
1006 EXPECT_EQ(OK, rv);
1008 const HttpResponseInfo* response = trans->GetResponseInfo();
1009 ASSERT_TRUE(response != NULL);
1011 // Check that the headers got parsed.
1012 EXPECT_TRUE(response->headers.get() != NULL);
1013 EXPECT_EQ(1234, response->headers->GetContentLength());
1014 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1016 std::string server_header;
1017 void* iter = NULL;
1018 bool has_server_header = response->headers->EnumerateHeader(
1019 &iter, "Server", &server_header);
1020 EXPECT_TRUE(has_server_header);
1021 EXPECT_EQ("Blah", server_header);
1023 // Reading should give EOF right away, since there is no message body
1024 // (despite non-zero content-length).
1025 std::string response_data;
1026 rv = ReadTransaction(trans.get(), &response_data);
1027 EXPECT_EQ(OK, rv);
1028 EXPECT_EQ("", response_data);
1031 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1032 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1034 MockRead data_reads[] = {
1035 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1036 MockRead("hello"),
1037 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1038 MockRead("world"),
1039 MockRead(SYNCHRONOUS, OK),
1041 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1042 session_deps_.socket_factory->AddSocketDataProvider(&data);
1044 const char* const kExpectedResponseData[] = {
1045 "hello", "world"
1048 for (int i = 0; i < 2; ++i) {
1049 HttpRequestInfo request;
1050 request.method = "GET";
1051 request.url = GURL("http://www.google.com/");
1052 request.load_flags = 0;
1054 scoped_ptr<HttpTransaction> trans(
1055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1057 TestCompletionCallback callback;
1059 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1060 EXPECT_EQ(ERR_IO_PENDING, rv);
1062 rv = callback.WaitForResult();
1063 EXPECT_EQ(OK, rv);
1065 const HttpResponseInfo* response = trans->GetResponseInfo();
1066 ASSERT_TRUE(response != NULL);
1068 EXPECT_TRUE(response->headers.get() != NULL);
1069 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1071 std::string response_data;
1072 rv = ReadTransaction(trans.get(), &response_data);
1073 EXPECT_EQ(OK, rv);
1074 EXPECT_EQ(kExpectedResponseData[i], response_data);
1078 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1079 ScopedVector<UploadElementReader> element_readers;
1080 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1081 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1083 HttpRequestInfo request;
1084 request.method = "POST";
1085 request.url = GURL("http://www.foo.com/");
1086 request.upload_data_stream = &upload_data_stream;
1087 request.load_flags = 0;
1089 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1090 scoped_ptr<HttpTransaction> trans(
1091 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1093 MockRead data_reads[] = {
1094 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1095 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1096 MockRead("hello world"),
1097 MockRead(SYNCHRONOUS, OK),
1099 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1100 session_deps_.socket_factory->AddSocketDataProvider(&data);
1102 TestCompletionCallback callback;
1104 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1105 EXPECT_EQ(ERR_IO_PENDING, rv);
1107 rv = callback.WaitForResult();
1108 EXPECT_EQ(OK, rv);
1110 const HttpResponseInfo* response = trans->GetResponseInfo();
1111 ASSERT_TRUE(response != NULL);
1113 EXPECT_TRUE(response->headers.get() != NULL);
1114 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1116 std::string response_data;
1117 rv = ReadTransaction(trans.get(), &response_data);
1118 EXPECT_EQ(OK, rv);
1119 EXPECT_EQ("hello world", response_data);
1122 // This test is almost the same as Ignores100 above, but the response contains
1123 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1124 // HTTP/1.1 and the two status headers are read in one read.
1125 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1126 HttpRequestInfo request;
1127 request.method = "GET";
1128 request.url = GURL("http://www.foo.com/");
1129 request.load_flags = 0;
1131 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1132 scoped_ptr<HttpTransaction> trans(
1133 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1135 MockRead data_reads[] = {
1136 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1137 "HTTP/1.1 200 OK\r\n\r\n"),
1138 MockRead("hello world"),
1139 MockRead(SYNCHRONOUS, OK),
1141 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1142 session_deps_.socket_factory->AddSocketDataProvider(&data);
1144 TestCompletionCallback callback;
1146 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1147 EXPECT_EQ(ERR_IO_PENDING, rv);
1149 rv = callback.WaitForResult();
1150 EXPECT_EQ(OK, rv);
1152 const HttpResponseInfo* response = trans->GetResponseInfo();
1153 ASSERT_TRUE(response != NULL);
1155 EXPECT_TRUE(response->headers.get() != NULL);
1156 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1158 std::string response_data;
1159 rv = ReadTransaction(trans.get(), &response_data);
1160 EXPECT_EQ(OK, rv);
1161 EXPECT_EQ("hello world", response_data);
1164 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1165 HttpRequestInfo request;
1166 request.method = "POST";
1167 request.url = GURL("http://www.foo.com/");
1168 request.load_flags = 0;
1170 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1171 scoped_ptr<HttpTransaction> trans(
1172 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1174 MockRead data_reads[] = {
1175 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1176 MockRead(ASYNC, 0),
1178 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1179 session_deps_.socket_factory->AddSocketDataProvider(&data);
1181 TestCompletionCallback callback;
1183 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1184 EXPECT_EQ(ERR_IO_PENDING, rv);
1186 rv = callback.WaitForResult();
1187 EXPECT_EQ(OK, rv);
1189 std::string response_data;
1190 rv = ReadTransaction(trans.get(), &response_data);
1191 EXPECT_EQ(OK, rv);
1192 EXPECT_EQ("", response_data);
1195 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1196 HttpRequestInfo request;
1197 request.method = "POST";
1198 request.url = GURL("http://www.foo.com/");
1199 request.load_flags = 0;
1201 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1202 scoped_ptr<HttpTransaction> trans(
1203 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1206 MockRead data_reads[] = {
1207 MockRead(ASYNC, 0),
1209 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1210 session_deps_.socket_factory->AddSocketDataProvider(&data);
1212 TestCompletionCallback callback;
1214 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1215 EXPECT_EQ(ERR_IO_PENDING, rv);
1217 rv = callback.WaitForResult();
1218 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1221 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1222 const MockWrite* write_failure,
1223 const MockRead* read_failure) {
1224 HttpRequestInfo request;
1225 request.method = "GET";
1226 request.url = GURL("http://www.foo.com/");
1227 request.load_flags = 0;
1229 CapturingNetLog net_log;
1230 session_deps_.net_log = &net_log;
1231 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1233 // Written data for successfully sending both requests.
1234 MockWrite data1_writes[] = {
1235 MockWrite("GET / HTTP/1.1\r\n"
1236 "Host: www.foo.com\r\n"
1237 "Connection: keep-alive\r\n\r\n"),
1238 MockWrite("GET / HTTP/1.1\r\n"
1239 "Host: www.foo.com\r\n"
1240 "Connection: keep-alive\r\n\r\n")
1243 // Read results for the first request.
1244 MockRead data1_reads[] = {
1245 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1246 MockRead("hello"),
1247 MockRead(ASYNC, OK),
1250 if (write_failure) {
1251 ASSERT_FALSE(read_failure);
1252 data1_writes[1] = *write_failure;
1253 } else {
1254 ASSERT_TRUE(read_failure);
1255 data1_reads[2] = *read_failure;
1258 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1259 data1_writes, arraysize(data1_writes));
1260 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1262 MockRead data2_reads[] = {
1263 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1264 MockRead("world"),
1265 MockRead(ASYNC, OK),
1267 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1268 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1270 const char* kExpectedResponseData[] = {
1271 "hello", "world"
1274 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1275 for (int i = 0; i < 2; ++i) {
1276 TestCompletionCallback callback;
1278 scoped_ptr<HttpTransaction> trans(
1279 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1281 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1282 EXPECT_EQ(ERR_IO_PENDING, rv);
1284 rv = callback.WaitForResult();
1285 EXPECT_EQ(OK, rv);
1287 LoadTimingInfo load_timing_info;
1288 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1289 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1290 if (i == 0) {
1291 first_socket_log_id = load_timing_info.socket_log_id;
1292 } else {
1293 // The second request should be using a new socket.
1294 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1297 const HttpResponseInfo* response = trans->GetResponseInfo();
1298 ASSERT_TRUE(response != NULL);
1300 EXPECT_TRUE(response->headers.get() != NULL);
1301 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1303 std::string response_data;
1304 rv = ReadTransaction(trans.get(), &response_data);
1305 EXPECT_EQ(OK, rv);
1306 EXPECT_EQ(kExpectedResponseData[i], response_data);
1310 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1311 const MockWrite* write_failure,
1312 const MockRead* read_failure,
1313 bool use_spdy) {
1314 HttpRequestInfo request;
1315 request.method = "GET";
1316 request.url = GURL("https://www.foo.com/");
1317 request.load_flags = 0;
1319 CapturingNetLog net_log;
1320 session_deps_.net_log = &net_log;
1321 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1323 SSLSocketDataProvider ssl1(ASYNC, OK);
1324 SSLSocketDataProvider ssl2(ASYNC, OK);
1325 if (use_spdy) {
1326 ssl1.SetNextProto(GetParam());
1327 ssl2.SetNextProto(GetParam());
1329 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1332 // SPDY versions of the request and response.
1333 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1334 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1335 scoped_ptr<SpdyFrame> spdy_response(
1336 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1337 scoped_ptr<SpdyFrame> spdy_data(
1338 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1340 // HTTP/1.1 versions of the request and response.
1341 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1342 "Host: www.foo.com\r\n"
1343 "Connection: keep-alive\r\n\r\n";
1344 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1345 const char kHttpData[] = "hello";
1347 std::vector<MockRead> data1_reads;
1348 std::vector<MockWrite> data1_writes;
1349 if (write_failure) {
1350 ASSERT_FALSE(read_failure);
1351 data1_writes.push_back(*write_failure);
1352 data1_reads.push_back(MockRead(ASYNC, OK));
1353 } else {
1354 ASSERT_TRUE(read_failure);
1355 if (use_spdy) {
1356 data1_writes.push_back(CreateMockWrite(*spdy_request));
1357 } else {
1358 data1_writes.push_back(MockWrite(kHttpRequest));
1360 data1_reads.push_back(*read_failure);
1363 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1364 &data1_writes[0], data1_writes.size());
1365 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1367 std::vector<MockRead> data2_reads;
1368 std::vector<MockWrite> data2_writes;
1370 if (use_spdy) {
1371 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1373 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1374 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1375 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1376 } else {
1377 data2_writes.push_back(
1378 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1380 data2_reads.push_back(
1381 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1382 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1383 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1385 OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
1386 &data2_writes[0], data2_writes.size());
1387 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1389 // Preconnect a socket.
1390 net::SSLConfig ssl_config;
1391 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1392 if (session->http_stream_factory()->has_next_protos())
1393 ssl_config.next_protos = session->http_stream_factory()->next_protos();
1394 session->http_stream_factory()->PreconnectStreams(
1395 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1396 // Wait for the preconnect to complete.
1397 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1398 base::RunLoop().RunUntilIdle();
1399 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1401 // Make the request.
1402 TestCompletionCallback callback;
1404 scoped_ptr<HttpTransaction> trans(
1405 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1407 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1408 EXPECT_EQ(ERR_IO_PENDING, rv);
1410 rv = callback.WaitForResult();
1411 EXPECT_EQ(OK, rv);
1413 LoadTimingInfo load_timing_info;
1414 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1415 TestLoadTimingNotReused(
1416 load_timing_info,
1417 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1419 const HttpResponseInfo* response = trans->GetResponseInfo();
1420 ASSERT_TRUE(response != NULL);
1422 EXPECT_TRUE(response->headers.get() != NULL);
1423 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1425 std::string response_data;
1426 rv = ReadTransaction(trans.get(), &response_data);
1427 EXPECT_EQ(OK, rv);
1428 EXPECT_EQ(kHttpData, response_data);
1431 TEST_P(HttpNetworkTransactionTest,
1432 KeepAliveConnectionNotConnectedOnWrite) {
1433 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1434 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1437 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1438 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1439 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1442 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1443 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1444 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1447 TEST_P(HttpNetworkTransactionTest,
1448 PreconnectErrorNotConnectedOnWrite) {
1449 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1450 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1453 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1454 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1455 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1458 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1459 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1460 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1463 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1464 MockRead read_failure(ASYNC, OK); // EOF
1465 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1468 TEST_P(HttpNetworkTransactionTest,
1469 SpdyPreconnectErrorNotConnectedOnWrite) {
1470 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1471 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1474 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1475 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1476 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1479 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1480 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1481 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1484 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1485 MockRead read_failure(ASYNC, OK); // EOF
1486 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1489 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1490 HttpRequestInfo request;
1491 request.method = "GET";
1492 request.url = GURL("http://www.google.com/");
1493 request.load_flags = 0;
1495 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1496 scoped_ptr<HttpTransaction> trans(
1497 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1499 MockRead data_reads[] = {
1500 MockRead(ASYNC, ERR_CONNECTION_RESET),
1501 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1502 MockRead("hello world"),
1503 MockRead(SYNCHRONOUS, OK),
1505 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1506 session_deps_.socket_factory->AddSocketDataProvider(&data);
1508 TestCompletionCallback callback;
1510 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1511 EXPECT_EQ(ERR_IO_PENDING, rv);
1513 rv = callback.WaitForResult();
1514 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1516 const HttpResponseInfo* response = trans->GetResponseInfo();
1517 EXPECT_TRUE(response == NULL);
1520 // What do various browsers do when the server closes a non-keepalive
1521 // connection without sending any response header or body?
1523 // IE7: error page
1524 // Safari 3.1.2 (Windows): error page
1525 // Firefox 3.0.1: blank page
1526 // Opera 9.52: after five attempts, blank page
1527 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1528 // Us: error page (EMPTY_RESPONSE)
1529 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1530 MockRead data_reads[] = {
1531 MockRead(SYNCHRONOUS, OK), // EOF
1532 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1533 MockRead("hello world"),
1534 MockRead(SYNCHRONOUS, OK),
1536 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1537 arraysize(data_reads));
1538 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1541 // Test that network access can be deferred and resumed.
1542 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1543 HttpRequestInfo request;
1544 request.method = "GET";
1545 request.url = GURL("http://www.google.com/");
1546 request.load_flags = 0;
1548 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1549 scoped_ptr<HttpTransaction> trans(
1550 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1552 // Defer on OnBeforeNetworkStart.
1553 BeforeNetworkStartHandler net_start_handler(true); // defer
1554 trans->SetBeforeNetworkStartCallback(
1555 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1556 base::Unretained(&net_start_handler)));
1558 MockRead data_reads[] = {
1559 MockRead("HTTP/1.0 200 OK\r\n"),
1560 MockRead("Content-Length: 5\r\n\r\n"),
1561 MockRead("hello"),
1562 MockRead(SYNCHRONOUS, 0),
1564 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1565 session_deps_.socket_factory->AddSocketDataProvider(&data);
1567 TestCompletionCallback callback;
1569 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1570 EXPECT_EQ(ERR_IO_PENDING, rv);
1571 base::MessageLoop::current()->RunUntilIdle();
1573 // Should have deferred for network start.
1574 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1575 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1576 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1578 trans->ResumeNetworkStart();
1579 rv = callback.WaitForResult();
1580 EXPECT_EQ(OK, rv);
1581 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1583 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1584 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1585 if (rv == ERR_IO_PENDING)
1586 rv = callback.WaitForResult();
1587 EXPECT_EQ(5, rv);
1588 trans.reset();
1591 // Test that network use can be deferred and canceled.
1592 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1593 HttpRequestInfo request;
1594 request.method = "GET";
1595 request.url = GURL("http://www.google.com/");
1596 request.load_flags = 0;
1598 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1599 scoped_ptr<HttpTransaction> trans(
1600 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1602 // Defer on OnBeforeNetworkStart.
1603 BeforeNetworkStartHandler net_start_handler(true); // defer
1604 trans->SetBeforeNetworkStartCallback(
1605 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1606 base::Unretained(&net_start_handler)));
1608 TestCompletionCallback callback;
1610 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1611 EXPECT_EQ(ERR_IO_PENDING, rv);
1612 base::MessageLoop::current()->RunUntilIdle();
1614 // Should have deferred for network start.
1615 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1616 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1617 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1620 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1621 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1622 // destructor in such situations.
1623 // See http://crbug.com/154712 and http://crbug.com/156609.
1624 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1625 HttpRequestInfo request;
1626 request.method = "GET";
1627 request.url = GURL("http://www.google.com/");
1628 request.load_flags = 0;
1630 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1631 scoped_ptr<HttpTransaction> trans(
1632 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1634 MockRead data_reads[] = {
1635 MockRead("HTTP/1.0 200 OK\r\n"),
1636 MockRead("Connection: keep-alive\r\n"),
1637 MockRead("Content-Length: 100\r\n\r\n"),
1638 MockRead("hello"),
1639 MockRead(SYNCHRONOUS, 0),
1641 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1642 session_deps_.socket_factory->AddSocketDataProvider(&data);
1644 TestCompletionCallback callback;
1646 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1647 EXPECT_EQ(ERR_IO_PENDING, rv);
1649 rv = callback.WaitForResult();
1650 EXPECT_EQ(OK, rv);
1652 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1653 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1654 if (rv == ERR_IO_PENDING)
1655 rv = callback.WaitForResult();
1656 EXPECT_EQ(5, rv);
1657 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1658 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1660 trans.reset();
1661 base::MessageLoop::current()->RunUntilIdle();
1662 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1665 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1666 HttpRequestInfo request;
1667 request.method = "GET";
1668 request.url = GURL("http://www.google.com/");
1669 request.load_flags = 0;
1671 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1672 scoped_ptr<HttpTransaction> trans(
1673 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1675 MockRead data_reads[] = {
1676 MockRead("HTTP/1.0 200 OK\r\n"),
1677 MockRead("Connection: keep-alive\r\n"),
1678 MockRead("Content-Length: 100\r\n\r\n"),
1679 MockRead(SYNCHRONOUS, 0),
1681 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1682 session_deps_.socket_factory->AddSocketDataProvider(&data);
1684 TestCompletionCallback callback;
1686 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1687 EXPECT_EQ(ERR_IO_PENDING, rv);
1689 rv = callback.WaitForResult();
1690 EXPECT_EQ(OK, rv);
1692 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1693 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1694 if (rv == ERR_IO_PENDING)
1695 rv = callback.WaitForResult();
1696 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1698 trans.reset();
1699 base::MessageLoop::current()->RunUntilIdle();
1700 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1703 // Test that we correctly reuse a keep-alive connection after not explicitly
1704 // reading the body.
1705 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1706 HttpRequestInfo request;
1707 request.method = "GET";
1708 request.url = GURL("http://www.foo.com/");
1709 request.load_flags = 0;
1711 CapturingNetLog net_log;
1712 session_deps_.net_log = &net_log;
1713 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1715 // Note that because all these reads happen in the same
1716 // StaticSocketDataProvider, it shows that the same socket is being reused for
1717 // all transactions.
1718 MockRead data1_reads[] = {
1719 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1720 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1721 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1722 MockRead("HTTP/1.1 302 Found\r\n"
1723 "Content-Length: 0\r\n\r\n"),
1724 MockRead("HTTP/1.1 302 Found\r\n"
1725 "Content-Length: 5\r\n\r\n"
1726 "hello"),
1727 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1728 "Content-Length: 0\r\n\r\n"),
1729 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1730 "Content-Length: 5\r\n\r\n"
1731 "hello"),
1732 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1733 MockRead("hello"),
1735 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1736 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1738 MockRead data2_reads[] = {
1739 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1741 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1742 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1744 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1745 std::string response_lines[kNumUnreadBodies];
1747 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1748 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1749 TestCompletionCallback callback;
1751 scoped_ptr<HttpTransaction> trans(
1752 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1754 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1755 EXPECT_EQ(ERR_IO_PENDING, rv);
1757 rv = callback.WaitForResult();
1758 EXPECT_EQ(OK, rv);
1760 LoadTimingInfo load_timing_info;
1761 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1762 if (i == 0) {
1763 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1764 first_socket_log_id = load_timing_info.socket_log_id;
1765 } else {
1766 TestLoadTimingReused(load_timing_info);
1767 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1770 const HttpResponseInfo* response = trans->GetResponseInfo();
1771 ASSERT_TRUE(response != NULL);
1773 ASSERT_TRUE(response->headers.get() != NULL);
1774 response_lines[i] = response->headers->GetStatusLine();
1776 // We intentionally don't read the response bodies.
1779 const char* const kStatusLines[] = {
1780 "HTTP/1.1 204 No Content",
1781 "HTTP/1.1 205 Reset Content",
1782 "HTTP/1.1 304 Not Modified",
1783 "HTTP/1.1 302 Found",
1784 "HTTP/1.1 302 Found",
1785 "HTTP/1.1 301 Moved Permanently",
1786 "HTTP/1.1 301 Moved Permanently",
1789 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1790 forgot_to_update_kStatusLines);
1792 for (int i = 0; i < kNumUnreadBodies; ++i)
1793 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1795 TestCompletionCallback callback;
1796 scoped_ptr<HttpTransaction> trans(
1797 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1798 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1799 EXPECT_EQ(ERR_IO_PENDING, rv);
1800 rv = callback.WaitForResult();
1801 EXPECT_EQ(OK, rv);
1802 const HttpResponseInfo* response = trans->GetResponseInfo();
1803 ASSERT_TRUE(response != NULL);
1804 ASSERT_TRUE(response->headers.get() != NULL);
1805 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1806 std::string response_data;
1807 rv = ReadTransaction(trans.get(), &response_data);
1808 EXPECT_EQ(OK, rv);
1809 EXPECT_EQ("hello", response_data);
1812 // Test the request-challenge-retry sequence for basic auth.
1813 // (basic auth is the easiest to mock, because it has no randomness).
1814 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1815 HttpRequestInfo request;
1816 request.method = "GET";
1817 request.url = GURL("http://www.google.com/");
1818 request.load_flags = 0;
1820 CapturingNetLog log;
1821 session_deps_.net_log = &log;
1822 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1823 scoped_ptr<HttpTransaction> trans(
1824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1826 MockWrite data_writes1[] = {
1827 MockWrite("GET / HTTP/1.1\r\n"
1828 "Host: www.google.com\r\n"
1829 "Connection: keep-alive\r\n\r\n"),
1832 MockRead data_reads1[] = {
1833 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1834 // Give a couple authenticate options (only the middle one is actually
1835 // supported).
1836 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1837 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1838 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1839 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1840 // Large content-length -- won't matter, as connection will be reset.
1841 MockRead("Content-Length: 10000\r\n\r\n"),
1842 MockRead(SYNCHRONOUS, ERR_FAILED),
1845 // After calling trans->RestartWithAuth(), this is the request we should
1846 // be issuing -- the final header line contains the credentials.
1847 MockWrite data_writes2[] = {
1848 MockWrite("GET / HTTP/1.1\r\n"
1849 "Host: www.google.com\r\n"
1850 "Connection: keep-alive\r\n"
1851 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1854 // Lastly, the server responds with the actual content.
1855 MockRead data_reads2[] = {
1856 MockRead("HTTP/1.0 200 OK\r\n"),
1857 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1858 MockRead("Content-Length: 100\r\n\r\n"),
1859 MockRead(SYNCHRONOUS, OK),
1862 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1863 data_writes1, arraysize(data_writes1));
1864 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1865 data_writes2, arraysize(data_writes2));
1866 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1867 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1869 TestCompletionCallback callback1;
1871 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1872 EXPECT_EQ(ERR_IO_PENDING, rv);
1874 rv = callback1.WaitForResult();
1875 EXPECT_EQ(OK, rv);
1877 LoadTimingInfo load_timing_info1;
1878 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1879 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1881 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1882 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1884 const HttpResponseInfo* response = trans->GetResponseInfo();
1885 ASSERT_TRUE(response != NULL);
1886 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1888 TestCompletionCallback callback2;
1890 rv = trans->RestartWithAuth(
1891 AuthCredentials(kFoo, kBar), callback2.callback());
1892 EXPECT_EQ(ERR_IO_PENDING, rv);
1894 rv = callback2.WaitForResult();
1895 EXPECT_EQ(OK, rv);
1897 LoadTimingInfo load_timing_info2;
1898 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1899 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1900 // The load timing after restart should have a new socket ID, and times after
1901 // those of the first load timing.
1902 EXPECT_LE(load_timing_info1.receive_headers_end,
1903 load_timing_info2.connect_timing.connect_start);
1904 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1906 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1907 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1909 response = trans->GetResponseInfo();
1910 ASSERT_TRUE(response != NULL);
1911 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1912 EXPECT_EQ(100, response->headers->GetContentLength());
1915 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1916 HttpRequestInfo request;
1917 request.method = "GET";
1918 request.url = GURL("http://www.google.com/");
1919 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1921 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1922 scoped_ptr<HttpTransaction> trans(
1923 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1925 MockWrite data_writes[] = {
1926 MockWrite("GET / HTTP/1.1\r\n"
1927 "Host: www.google.com\r\n"
1928 "Connection: keep-alive\r\n\r\n"),
1931 MockRead data_reads[] = {
1932 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1933 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1934 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1935 // Large content-length -- won't matter, as connection will be reset.
1936 MockRead("Content-Length: 10000\r\n\r\n"),
1937 MockRead(SYNCHRONOUS, ERR_FAILED),
1940 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1941 data_writes, arraysize(data_writes));
1942 session_deps_.socket_factory->AddSocketDataProvider(&data);
1943 TestCompletionCallback callback;
1945 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1946 EXPECT_EQ(ERR_IO_PENDING, rv);
1948 rv = callback.WaitForResult();
1949 EXPECT_EQ(0, rv);
1951 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
1952 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
1954 const HttpResponseInfo* response = trans->GetResponseInfo();
1955 ASSERT_TRUE(response != NULL);
1956 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1959 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1960 // connection.
1961 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1962 HttpRequestInfo request;
1963 request.method = "GET";
1964 request.url = GURL("http://www.google.com/");
1965 request.load_flags = 0;
1967 CapturingNetLog log;
1968 session_deps_.net_log = &log;
1969 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1971 MockWrite data_writes1[] = {
1972 MockWrite("GET / HTTP/1.1\r\n"
1973 "Host: www.google.com\r\n"
1974 "Connection: keep-alive\r\n\r\n"),
1976 // After calling trans->RestartWithAuth(), this is the request we should
1977 // be issuing -- the final header line contains the credentials.
1978 MockWrite("GET / HTTP/1.1\r\n"
1979 "Host: www.google.com\r\n"
1980 "Connection: keep-alive\r\n"
1981 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1984 MockRead data_reads1[] = {
1985 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1986 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1987 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1988 MockRead("Content-Length: 14\r\n\r\n"),
1989 MockRead("Unauthorized\r\n"),
1991 // Lastly, the server responds with the actual content.
1992 MockRead("HTTP/1.1 200 OK\r\n"),
1993 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1994 MockRead("Content-Length: 5\r\n\r\n"),
1995 MockRead("Hello"),
1998 // If there is a regression where we disconnect a Keep-Alive
1999 // connection during an auth roundtrip, we'll end up reading this.
2000 MockRead data_reads2[] = {
2001 MockRead(SYNCHRONOUS, ERR_FAILED),
2004 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2005 data_writes1, arraysize(data_writes1));
2006 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2007 NULL, 0);
2008 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2009 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2011 TestCompletionCallback callback1;
2013 scoped_ptr<HttpTransaction> trans(
2014 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2015 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2016 EXPECT_EQ(ERR_IO_PENDING, rv);
2018 rv = callback1.WaitForResult();
2019 EXPECT_EQ(OK, rv);
2021 LoadTimingInfo load_timing_info1;
2022 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2023 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2025 const HttpResponseInfo* response = trans->GetResponseInfo();
2026 ASSERT_TRUE(response != NULL);
2027 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2029 TestCompletionCallback callback2;
2031 rv = trans->RestartWithAuth(
2032 AuthCredentials(kFoo, kBar), callback2.callback());
2033 EXPECT_EQ(ERR_IO_PENDING, rv);
2035 rv = callback2.WaitForResult();
2036 EXPECT_EQ(OK, rv);
2038 LoadTimingInfo load_timing_info2;
2039 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2040 TestLoadTimingReused(load_timing_info2);
2041 // The load timing after restart should have the same socket ID, and times
2042 // those of the first load timing.
2043 EXPECT_LE(load_timing_info1.receive_headers_end,
2044 load_timing_info2.send_start);
2045 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2047 response = trans->GetResponseInfo();
2048 ASSERT_TRUE(response != NULL);
2049 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2050 EXPECT_EQ(5, response->headers->GetContentLength());
2052 std::string response_data;
2053 rv = ReadTransaction(trans.get(), &response_data);
2054 EXPECT_EQ(OK, rv);
2055 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2056 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2059 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2060 // connection and with no response body to drain.
2061 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2062 HttpRequestInfo request;
2063 request.method = "GET";
2064 request.url = GURL("http://www.google.com/");
2065 request.load_flags = 0;
2067 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2069 MockWrite data_writes1[] = {
2070 MockWrite("GET / HTTP/1.1\r\n"
2071 "Host: www.google.com\r\n"
2072 "Connection: keep-alive\r\n\r\n"),
2074 // After calling trans->RestartWithAuth(), this is the request we should
2075 // be issuing -- the final header line contains the credentials.
2076 MockWrite("GET / HTTP/1.1\r\n"
2077 "Host: www.google.com\r\n"
2078 "Connection: keep-alive\r\n"
2079 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2082 MockRead data_reads1[] = {
2083 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2084 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2085 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2087 // Lastly, the server responds with the actual content.
2088 MockRead("HTTP/1.1 200 OK\r\n"),
2089 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2090 MockRead("Content-Length: 5\r\n\r\n"),
2091 MockRead("hello"),
2094 // An incorrect reconnect would cause this to be read.
2095 MockRead data_reads2[] = {
2096 MockRead(SYNCHRONOUS, ERR_FAILED),
2099 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2100 data_writes1, arraysize(data_writes1));
2101 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2102 NULL, 0);
2103 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2104 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2106 TestCompletionCallback callback1;
2108 scoped_ptr<HttpTransaction> trans(
2109 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2110 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2111 EXPECT_EQ(ERR_IO_PENDING, rv);
2113 rv = callback1.WaitForResult();
2114 EXPECT_EQ(OK, rv);
2116 const HttpResponseInfo* response = trans->GetResponseInfo();
2117 ASSERT_TRUE(response != NULL);
2118 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2120 TestCompletionCallback callback2;
2122 rv = trans->RestartWithAuth(
2123 AuthCredentials(kFoo, kBar), callback2.callback());
2124 EXPECT_EQ(ERR_IO_PENDING, rv);
2126 rv = callback2.WaitForResult();
2127 EXPECT_EQ(OK, rv);
2129 response = trans->GetResponseInfo();
2130 ASSERT_TRUE(response != NULL);
2131 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2132 EXPECT_EQ(5, response->headers->GetContentLength());
2135 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2136 // connection and with a large response body to drain.
2137 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2138 HttpRequestInfo request;
2139 request.method = "GET";
2140 request.url = GURL("http://www.google.com/");
2141 request.load_flags = 0;
2143 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2145 MockWrite data_writes1[] = {
2146 MockWrite("GET / HTTP/1.1\r\n"
2147 "Host: www.google.com\r\n"
2148 "Connection: keep-alive\r\n\r\n"),
2150 // After calling trans->RestartWithAuth(), this is the request we should
2151 // be issuing -- the final header line contains the credentials.
2152 MockWrite("GET / HTTP/1.1\r\n"
2153 "Host: www.google.com\r\n"
2154 "Connection: keep-alive\r\n"
2155 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2158 // Respond with 5 kb of response body.
2159 std::string large_body_string("Unauthorized");
2160 large_body_string.append(5 * 1024, ' ');
2161 large_body_string.append("\r\n");
2163 MockRead data_reads1[] = {
2164 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2165 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2166 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2167 // 5134 = 12 + 5 * 1024 + 2
2168 MockRead("Content-Length: 5134\r\n\r\n"),
2169 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2171 // Lastly, the server responds with the actual content.
2172 MockRead("HTTP/1.1 200 OK\r\n"),
2173 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2174 MockRead("Content-Length: 5\r\n\r\n"),
2175 MockRead("hello"),
2178 // An incorrect reconnect would cause this to be read.
2179 MockRead data_reads2[] = {
2180 MockRead(SYNCHRONOUS, ERR_FAILED),
2183 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2184 data_writes1, arraysize(data_writes1));
2185 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2186 NULL, 0);
2187 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2188 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2190 TestCompletionCallback callback1;
2192 scoped_ptr<HttpTransaction> trans(
2193 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2194 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2195 EXPECT_EQ(ERR_IO_PENDING, rv);
2197 rv = callback1.WaitForResult();
2198 EXPECT_EQ(OK, rv);
2200 const HttpResponseInfo* response = trans->GetResponseInfo();
2201 ASSERT_TRUE(response != NULL);
2202 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2204 TestCompletionCallback callback2;
2206 rv = trans->RestartWithAuth(
2207 AuthCredentials(kFoo, kBar), callback2.callback());
2208 EXPECT_EQ(ERR_IO_PENDING, rv);
2210 rv = callback2.WaitForResult();
2211 EXPECT_EQ(OK, rv);
2213 response = trans->GetResponseInfo();
2214 ASSERT_TRUE(response != NULL);
2215 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2216 EXPECT_EQ(5, response->headers->GetContentLength());
2219 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2220 // connection, but the server gets impatient and closes the connection.
2221 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2222 HttpRequestInfo request;
2223 request.method = "GET";
2224 request.url = GURL("http://www.google.com/");
2225 request.load_flags = 0;
2227 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2229 MockWrite data_writes1[] = {
2230 MockWrite("GET / HTTP/1.1\r\n"
2231 "Host: www.google.com\r\n"
2232 "Connection: keep-alive\r\n\r\n"),
2233 // This simulates the seemingly successful write to a closed connection
2234 // if the bug is not fixed.
2235 MockWrite("GET / HTTP/1.1\r\n"
2236 "Host: www.google.com\r\n"
2237 "Connection: keep-alive\r\n"
2238 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2241 MockRead data_reads1[] = {
2242 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2243 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2244 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2245 MockRead("Content-Length: 14\r\n\r\n"),
2246 // Tell MockTCPClientSocket to simulate the server closing the connection.
2247 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2248 MockRead("Unauthorized\r\n"),
2249 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2252 // After calling trans->RestartWithAuth(), this is the request we should
2253 // be issuing -- the final header line contains the credentials.
2254 MockWrite data_writes2[] = {
2255 MockWrite("GET / HTTP/1.1\r\n"
2256 "Host: www.google.com\r\n"
2257 "Connection: keep-alive\r\n"
2258 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2261 // Lastly, the server responds with the actual content.
2262 MockRead data_reads2[] = {
2263 MockRead("HTTP/1.1 200 OK\r\n"),
2264 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2265 MockRead("Content-Length: 5\r\n\r\n"),
2266 MockRead("hello"),
2269 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2270 data_writes1, arraysize(data_writes1));
2271 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2272 data_writes2, arraysize(data_writes2));
2273 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2274 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2276 TestCompletionCallback callback1;
2278 scoped_ptr<HttpTransaction> trans(
2279 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2280 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2281 EXPECT_EQ(ERR_IO_PENDING, rv);
2283 rv = callback1.WaitForResult();
2284 EXPECT_EQ(OK, rv);
2286 const HttpResponseInfo* response = trans->GetResponseInfo();
2287 ASSERT_TRUE(response != NULL);
2288 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2290 TestCompletionCallback callback2;
2292 rv = trans->RestartWithAuth(
2293 AuthCredentials(kFoo, kBar), callback2.callback());
2294 EXPECT_EQ(ERR_IO_PENDING, rv);
2296 rv = callback2.WaitForResult();
2297 EXPECT_EQ(OK, rv);
2299 response = trans->GetResponseInfo();
2300 ASSERT_TRUE(response != NULL);
2301 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2302 EXPECT_EQ(5, response->headers->GetContentLength());
2305 // Test the request-challenge-retry sequence for basic auth, over a connection
2306 // that requires a restart when setting up an SSL tunnel.
2307 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
2308 HttpRequestInfo request;
2309 request.method = "GET";
2310 request.url = GURL("https://www.google.com/");
2311 // when the no authentication data flag is set.
2312 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2314 // Configure against proxy server "myproxy:70".
2315 session_deps_.proxy_service.reset(
2316 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2317 CapturingBoundNetLog log;
2318 session_deps_.net_log = log.bound().net_log();
2319 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2321 // Since we have proxy, should try to establish tunnel.
2322 MockWrite data_writes1[] = {
2323 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2324 "Host: www.google.com\r\n"
2325 "Proxy-Connection: keep-alive\r\n\r\n"),
2327 // After calling trans->RestartWithAuth(), this is the request we should
2328 // be issuing -- the final header line contains the credentials.
2329 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2330 "Host: www.google.com\r\n"
2331 "Proxy-Connection: keep-alive\r\n"
2332 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2334 MockWrite("GET / HTTP/1.1\r\n"
2335 "Host: www.google.com\r\n"
2336 "Connection: keep-alive\r\n\r\n"),
2339 // The proxy responds to the connect with a 407, using a persistent
2340 // connection.
2341 MockRead data_reads1[] = {
2342 // No credentials.
2343 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2344 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2345 MockRead("Proxy-Connection: close\r\n\r\n"),
2347 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2349 MockRead("HTTP/1.1 200 OK\r\n"),
2350 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2351 MockRead("Content-Length: 5\r\n\r\n"),
2352 MockRead(SYNCHRONOUS, "hello"),
2355 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2356 data_writes1, arraysize(data_writes1));
2357 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2358 SSLSocketDataProvider ssl(ASYNC, OK);
2359 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2361 TestCompletionCallback callback1;
2363 scoped_ptr<HttpTransaction> trans(
2364 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2366 int rv = trans->Start(&request, callback1.callback(), log.bound());
2367 EXPECT_EQ(ERR_IO_PENDING, rv);
2369 rv = callback1.WaitForResult();
2370 EXPECT_EQ(OK, rv);
2371 net::CapturingNetLog::CapturedEntryList entries;
2372 log.GetEntries(&entries);
2373 size_t pos = ExpectLogContainsSomewhere(
2374 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2375 NetLog::PHASE_NONE);
2376 ExpectLogContainsSomewhere(
2377 entries, pos,
2378 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2379 NetLog::PHASE_NONE);
2381 const HttpResponseInfo* response = trans->GetResponseInfo();
2382 ASSERT_TRUE(response != NULL);
2383 ASSERT_FALSE(response->headers.get() == NULL);
2384 EXPECT_EQ(407, response->headers->response_code());
2385 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2386 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2388 LoadTimingInfo load_timing_info;
2389 // CONNECT requests and responses are handled at the connect job level, so
2390 // the transaction does not yet have a connection.
2391 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2393 TestCompletionCallback callback2;
2395 rv = trans->RestartWithAuth(
2396 AuthCredentials(kFoo, kBar), callback2.callback());
2397 EXPECT_EQ(ERR_IO_PENDING, rv);
2399 rv = callback2.WaitForResult();
2400 EXPECT_EQ(OK, rv);
2402 response = trans->GetResponseInfo();
2403 ASSERT_TRUE(response != NULL);
2405 EXPECT_TRUE(response->headers->IsKeepAlive());
2406 EXPECT_EQ(200, response->headers->response_code());
2407 EXPECT_EQ(5, response->headers->GetContentLength());
2408 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2410 // The password prompt info should not be set.
2411 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2413 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2414 TestLoadTimingNotReusedWithPac(load_timing_info,
2415 CONNECT_TIMING_HAS_SSL_TIMES);
2417 trans.reset();
2418 session->CloseAllConnections();
2421 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2422 // proxy connection, when setting up an SSL tunnel.
2423 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2424 HttpRequestInfo request;
2425 request.method = "GET";
2426 request.url = GURL("https://www.google.com/");
2427 // Ensure that proxy authentication is attempted even
2428 // when the no authentication data flag is set.
2429 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2431 // Configure against proxy server "myproxy:70".
2432 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2433 CapturingBoundNetLog log;
2434 session_deps_.net_log = log.bound().net_log();
2435 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2437 scoped_ptr<HttpTransaction> trans(
2438 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2440 // Since we have proxy, should try to establish tunnel.
2441 MockWrite data_writes1[] = {
2442 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2443 "Host: www.google.com\r\n"
2444 "Proxy-Connection: keep-alive\r\n\r\n"),
2446 // After calling trans->RestartWithAuth(), this is the request we should
2447 // be issuing -- the final header line contains the credentials.
2448 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2449 "Host: www.google.com\r\n"
2450 "Proxy-Connection: keep-alive\r\n"
2451 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2454 // The proxy responds to the connect with a 407, using a persistent
2455 // connection.
2456 MockRead data_reads1[] = {
2457 // No credentials.
2458 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2459 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2460 MockRead("Content-Length: 10\r\n\r\n"),
2461 MockRead("0123456789"),
2463 // Wrong credentials (wrong password).
2464 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2465 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2466 MockRead("Content-Length: 10\r\n\r\n"),
2467 // No response body because the test stops reading here.
2468 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2471 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2472 data_writes1, arraysize(data_writes1));
2473 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2475 TestCompletionCallback callback1;
2477 int rv = trans->Start(&request, callback1.callback(), log.bound());
2478 EXPECT_EQ(ERR_IO_PENDING, rv);
2480 rv = callback1.WaitForResult();
2481 EXPECT_EQ(OK, rv);
2482 net::CapturingNetLog::CapturedEntryList entries;
2483 log.GetEntries(&entries);
2484 size_t pos = ExpectLogContainsSomewhere(
2485 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2486 NetLog::PHASE_NONE);
2487 ExpectLogContainsSomewhere(
2488 entries, pos,
2489 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2490 NetLog::PHASE_NONE);
2492 const HttpResponseInfo* response = trans->GetResponseInfo();
2493 ASSERT_TRUE(response != NULL);
2494 ASSERT_FALSE(response->headers.get() == NULL);
2495 EXPECT_TRUE(response->headers->IsKeepAlive());
2496 EXPECT_EQ(407, response->headers->response_code());
2497 EXPECT_EQ(10, response->headers->GetContentLength());
2498 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2499 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2501 TestCompletionCallback callback2;
2503 // Wrong password (should be "bar").
2504 rv = trans->RestartWithAuth(
2505 AuthCredentials(kFoo, kBaz), callback2.callback());
2506 EXPECT_EQ(ERR_IO_PENDING, rv);
2508 rv = callback2.WaitForResult();
2509 EXPECT_EQ(OK, rv);
2511 response = trans->GetResponseInfo();
2512 ASSERT_TRUE(response != NULL);
2513 ASSERT_FALSE(response->headers.get() == NULL);
2514 EXPECT_TRUE(response->headers->IsKeepAlive());
2515 EXPECT_EQ(407, response->headers->response_code());
2516 EXPECT_EQ(10, response->headers->GetContentLength());
2517 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2518 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2520 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2521 // out of scope.
2522 session->CloseAllConnections();
2525 // Test that we don't read the response body when we fail to establish a tunnel,
2526 // even if the user cancels the proxy's auth attempt.
2527 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2528 HttpRequestInfo request;
2529 request.method = "GET";
2530 request.url = GURL("https://www.google.com/");
2531 request.load_flags = 0;
2533 // Configure against proxy server "myproxy:70".
2534 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2536 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2538 scoped_ptr<HttpTransaction> trans(
2539 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2541 // Since we have proxy, should try to establish tunnel.
2542 MockWrite data_writes[] = {
2543 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2544 "Host: www.google.com\r\n"
2545 "Proxy-Connection: keep-alive\r\n\r\n"),
2548 // The proxy responds to the connect with a 407.
2549 MockRead data_reads[] = {
2550 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2551 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2552 MockRead("Content-Length: 10\r\n\r\n"),
2553 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2556 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2557 data_writes, arraysize(data_writes));
2558 session_deps_.socket_factory->AddSocketDataProvider(&data);
2560 TestCompletionCallback callback;
2562 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2563 EXPECT_EQ(ERR_IO_PENDING, rv);
2565 rv = callback.WaitForResult();
2566 EXPECT_EQ(OK, rv);
2568 const HttpResponseInfo* response = trans->GetResponseInfo();
2569 ASSERT_TRUE(response != NULL);
2571 EXPECT_TRUE(response->headers->IsKeepAlive());
2572 EXPECT_EQ(407, response->headers->response_code());
2573 EXPECT_EQ(10, response->headers->GetContentLength());
2574 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2576 std::string response_data;
2577 rv = ReadTransaction(trans.get(), &response_data);
2578 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2580 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2581 session->CloseAllConnections();
2584 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2585 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2586 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2587 HttpRequestInfo request;
2588 request.method = "GET";
2589 request.url = GURL("http://www.google.com/");
2590 request.load_flags = 0;
2592 // We are using a DIRECT connection (i.e. no proxy) for this session.
2593 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2594 scoped_ptr<HttpTransaction> trans(
2595 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
2597 MockWrite data_writes1[] = {
2598 MockWrite("GET / HTTP/1.1\r\n"
2599 "Host: www.google.com\r\n"
2600 "Connection: keep-alive\r\n\r\n"),
2603 MockRead data_reads1[] = {
2604 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2605 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2606 // Large content-length -- won't matter, as connection will be reset.
2607 MockRead("Content-Length: 10000\r\n\r\n"),
2608 MockRead(SYNCHRONOUS, ERR_FAILED),
2611 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2612 data_writes1, arraysize(data_writes1));
2613 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2615 TestCompletionCallback callback;
2617 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2618 EXPECT_EQ(ERR_IO_PENDING, rv);
2620 rv = callback.WaitForResult();
2621 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2624 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2625 // through a non-authenticating proxy. The request should fail with
2626 // ERR_UNEXPECTED_PROXY_AUTH.
2627 // Note that it is impossible to detect if an HTTP server returns a 407 through
2628 // a non-authenticating proxy - there is nothing to indicate whether the
2629 // response came from the proxy or the server, so it is treated as if the proxy
2630 // issued the challenge.
2631 TEST_P(HttpNetworkTransactionTest,
2632 HttpsServerRequestsProxyAuthThroughProxy) {
2633 HttpRequestInfo request;
2634 request.method = "GET";
2635 request.url = GURL("https://www.google.com/");
2637 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2638 CapturingBoundNetLog log;
2639 session_deps_.net_log = log.bound().net_log();
2640 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2642 // Since we have proxy, should try to establish tunnel.
2643 MockWrite data_writes1[] = {
2644 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2645 "Host: www.google.com\r\n"
2646 "Proxy-Connection: keep-alive\r\n\r\n"),
2648 MockWrite("GET / HTTP/1.1\r\n"
2649 "Host: www.google.com\r\n"
2650 "Connection: keep-alive\r\n\r\n"),
2653 MockRead data_reads1[] = {
2654 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2656 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2657 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2658 MockRead("\r\n"),
2659 MockRead(SYNCHRONOUS, OK),
2662 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2663 data_writes1, arraysize(data_writes1));
2664 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2665 SSLSocketDataProvider ssl(ASYNC, OK);
2666 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2668 TestCompletionCallback callback1;
2670 scoped_ptr<HttpTransaction> trans(
2671 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2673 int rv = trans->Start(&request, callback1.callback(), log.bound());
2674 EXPECT_EQ(ERR_IO_PENDING, rv);
2676 rv = callback1.WaitForResult();
2677 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2678 net::CapturingNetLog::CapturedEntryList entries;
2679 log.GetEntries(&entries);
2680 size_t pos = ExpectLogContainsSomewhere(
2681 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2682 NetLog::PHASE_NONE);
2683 ExpectLogContainsSomewhere(
2684 entries, pos,
2685 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2686 NetLog::PHASE_NONE);
2689 // Test the load timing for HTTPS requests with an HTTP proxy.
2690 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2691 HttpRequestInfo request1;
2692 request1.method = "GET";
2693 request1.url = GURL("https://www.google.com/1");
2695 HttpRequestInfo request2;
2696 request2.method = "GET";
2697 request2.url = GURL("https://www.google.com/2");
2699 // Configure against proxy server "myproxy:70".
2700 session_deps_.proxy_service.reset(
2701 ProxyService::CreateFixed("PROXY myproxy:70"));
2702 CapturingBoundNetLog log;
2703 session_deps_.net_log = log.bound().net_log();
2704 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2706 // Since we have proxy, should try to establish tunnel.
2707 MockWrite data_writes1[] = {
2708 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2709 "Host: www.google.com\r\n"
2710 "Proxy-Connection: keep-alive\r\n\r\n"),
2712 MockWrite("GET /1 HTTP/1.1\r\n"
2713 "Host: www.google.com\r\n"
2714 "Connection: keep-alive\r\n\r\n"),
2716 MockWrite("GET /2 HTTP/1.1\r\n"
2717 "Host: www.google.com\r\n"
2718 "Connection: keep-alive\r\n\r\n"),
2721 // The proxy responds to the connect with a 407, using a persistent
2722 // connection.
2723 MockRead data_reads1[] = {
2724 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2726 MockRead("HTTP/1.1 200 OK\r\n"),
2727 MockRead("Content-Length: 1\r\n\r\n"),
2728 MockRead(SYNCHRONOUS, "1"),
2730 MockRead("HTTP/1.1 200 OK\r\n"),
2731 MockRead("Content-Length: 2\r\n\r\n"),
2732 MockRead(SYNCHRONOUS, "22"),
2735 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2736 data_writes1, arraysize(data_writes1));
2737 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2738 SSLSocketDataProvider ssl(ASYNC, OK);
2739 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2741 TestCompletionCallback callback1;
2742 scoped_ptr<HttpTransaction> trans1(
2743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2745 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2746 EXPECT_EQ(ERR_IO_PENDING, rv);
2748 rv = callback1.WaitForResult();
2749 EXPECT_EQ(OK, rv);
2751 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2752 ASSERT_TRUE(response1 != NULL);
2753 ASSERT_TRUE(response1->headers.get() != NULL);
2754 EXPECT_EQ(1, response1->headers->GetContentLength());
2756 LoadTimingInfo load_timing_info1;
2757 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2758 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2760 trans1.reset();
2762 TestCompletionCallback callback2;
2763 scoped_ptr<HttpTransaction> trans2(
2764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2766 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2767 EXPECT_EQ(ERR_IO_PENDING, rv);
2769 rv = callback2.WaitForResult();
2770 EXPECT_EQ(OK, rv);
2772 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2773 ASSERT_TRUE(response2 != NULL);
2774 ASSERT_TRUE(response2->headers.get() != NULL);
2775 EXPECT_EQ(2, response2->headers->GetContentLength());
2777 LoadTimingInfo load_timing_info2;
2778 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2779 TestLoadTimingReused(load_timing_info2);
2781 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2783 trans2.reset();
2784 session->CloseAllConnections();
2787 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2788 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2789 HttpRequestInfo request1;
2790 request1.method = "GET";
2791 request1.url = GURL("https://www.google.com/1");
2793 HttpRequestInfo request2;
2794 request2.method = "GET";
2795 request2.url = GURL("https://www.google.com/2");
2797 // Configure against proxy server "myproxy:70".
2798 session_deps_.proxy_service.reset(
2799 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2800 CapturingBoundNetLog log;
2801 session_deps_.net_log = log.bound().net_log();
2802 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2804 // Since we have proxy, should try to establish tunnel.
2805 MockWrite data_writes1[] = {
2806 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2807 "Host: www.google.com\r\n"
2808 "Proxy-Connection: keep-alive\r\n\r\n"),
2810 MockWrite("GET /1 HTTP/1.1\r\n"
2811 "Host: www.google.com\r\n"
2812 "Connection: keep-alive\r\n\r\n"),
2814 MockWrite("GET /2 HTTP/1.1\r\n"
2815 "Host: www.google.com\r\n"
2816 "Connection: keep-alive\r\n\r\n"),
2819 // The proxy responds to the connect with a 407, using a persistent
2820 // connection.
2821 MockRead data_reads1[] = {
2822 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2824 MockRead("HTTP/1.1 200 OK\r\n"),
2825 MockRead("Content-Length: 1\r\n\r\n"),
2826 MockRead(SYNCHRONOUS, "1"),
2828 MockRead("HTTP/1.1 200 OK\r\n"),
2829 MockRead("Content-Length: 2\r\n\r\n"),
2830 MockRead(SYNCHRONOUS, "22"),
2833 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2834 data_writes1, arraysize(data_writes1));
2835 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2836 SSLSocketDataProvider ssl(ASYNC, OK);
2837 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2839 TestCompletionCallback callback1;
2840 scoped_ptr<HttpTransaction> trans1(
2841 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2843 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2844 EXPECT_EQ(ERR_IO_PENDING, rv);
2846 rv = callback1.WaitForResult();
2847 EXPECT_EQ(OK, rv);
2849 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2850 ASSERT_TRUE(response1 != NULL);
2851 ASSERT_TRUE(response1->headers.get() != NULL);
2852 EXPECT_EQ(1, response1->headers->GetContentLength());
2854 LoadTimingInfo load_timing_info1;
2855 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2856 TestLoadTimingNotReusedWithPac(load_timing_info1,
2857 CONNECT_TIMING_HAS_SSL_TIMES);
2859 trans1.reset();
2861 TestCompletionCallback callback2;
2862 scoped_ptr<HttpTransaction> trans2(
2863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2865 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2866 EXPECT_EQ(ERR_IO_PENDING, rv);
2868 rv = callback2.WaitForResult();
2869 EXPECT_EQ(OK, rv);
2871 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2872 ASSERT_TRUE(response2 != NULL);
2873 ASSERT_TRUE(response2->headers.get() != NULL);
2874 EXPECT_EQ(2, response2->headers->GetContentLength());
2876 LoadTimingInfo load_timing_info2;
2877 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2878 TestLoadTimingReusedWithPac(load_timing_info2);
2880 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2882 trans2.reset();
2883 session->CloseAllConnections();
2886 // Test a simple get through an HTTPS Proxy.
2887 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2888 HttpRequestInfo request;
2889 request.method = "GET";
2890 request.url = GURL("http://www.google.com/");
2892 // Configure against https proxy server "proxy:70".
2893 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2894 "https://proxy:70"));
2895 CapturingBoundNetLog log;
2896 session_deps_.net_log = log.bound().net_log();
2897 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2899 // Since we have proxy, should use full url
2900 MockWrite data_writes1[] = {
2901 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2902 "Host: www.google.com\r\n"
2903 "Proxy-Connection: keep-alive\r\n\r\n"),
2906 MockRead data_reads1[] = {
2907 MockRead("HTTP/1.1 200 OK\r\n"),
2908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2909 MockRead("Content-Length: 100\r\n\r\n"),
2910 MockRead(SYNCHRONOUS, OK),
2913 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2914 data_writes1, arraysize(data_writes1));
2915 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2916 SSLSocketDataProvider ssl(ASYNC, OK);
2917 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2919 TestCompletionCallback callback1;
2921 scoped_ptr<HttpTransaction> trans(
2922 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2924 int rv = trans->Start(&request, callback1.callback(), log.bound());
2925 EXPECT_EQ(ERR_IO_PENDING, rv);
2927 rv = callback1.WaitForResult();
2928 EXPECT_EQ(OK, rv);
2930 LoadTimingInfo load_timing_info;
2931 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2932 TestLoadTimingNotReused(load_timing_info,
2933 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2935 const HttpResponseInfo* response = trans->GetResponseInfo();
2936 ASSERT_TRUE(response != NULL);
2938 EXPECT_TRUE(response->headers->IsKeepAlive());
2939 EXPECT_EQ(200, response->headers->response_code());
2940 EXPECT_EQ(100, response->headers->GetContentLength());
2941 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2943 // The password prompt info should not be set.
2944 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2947 // Test a SPDY get through an HTTPS Proxy.
2948 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2949 HttpRequestInfo request;
2950 request.method = "GET";
2951 request.url = GURL("http://www.google.com/");
2952 request.load_flags = 0;
2954 // Configure against https proxy server "proxy:70".
2955 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2956 "https://proxy:70"));
2957 CapturingBoundNetLog log;
2958 session_deps_.net_log = log.bound().net_log();
2959 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2961 // fetch http://www.google.com/ via SPDY
2962 scoped_ptr<SpdyFrame> req(
2963 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2964 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2966 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2967 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2968 MockRead spdy_reads[] = {
2969 CreateMockRead(*resp),
2970 CreateMockRead(*data),
2971 MockRead(ASYNC, 0, 0),
2974 DelayedSocketData spdy_data(
2975 1, // wait for one write to finish before reading.
2976 spdy_reads, arraysize(spdy_reads),
2977 spdy_writes, arraysize(spdy_writes));
2978 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2980 SSLSocketDataProvider ssl(ASYNC, OK);
2981 ssl.SetNextProto(GetParam());
2982 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2984 TestCompletionCallback callback1;
2986 scoped_ptr<HttpTransaction> trans(
2987 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2989 int rv = trans->Start(&request, callback1.callback(), log.bound());
2990 EXPECT_EQ(ERR_IO_PENDING, rv);
2992 rv = callback1.WaitForResult();
2993 EXPECT_EQ(OK, rv);
2995 LoadTimingInfo load_timing_info;
2996 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2997 TestLoadTimingNotReused(load_timing_info,
2998 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3000 const HttpResponseInfo* response = trans->GetResponseInfo();
3001 ASSERT_TRUE(response != NULL);
3002 ASSERT_TRUE(response->headers.get() != NULL);
3003 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3005 std::string response_data;
3006 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3007 EXPECT_EQ(kUploadData, response_data);
3010 // Test a SPDY get through an HTTPS Proxy.
3011 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3012 HttpRequestInfo request;
3013 request.method = "GET";
3014 request.url = GURL("http://www.google.com/");
3015 request.load_flags = 0;
3017 // Configure against https proxy server "myproxy:70".
3018 session_deps_.proxy_service.reset(
3019 ProxyService::CreateFixed("https://myproxy:70"));
3020 CapturingBoundNetLog log;
3021 session_deps_.net_log = log.bound().net_log();
3022 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3024 // The first request will be a bare GET, the second request will be a
3025 // GET with a Proxy-Authorization header.
3026 scoped_ptr<SpdyFrame> req_get(
3027 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3028 const char* const kExtraAuthorizationHeaders[] = {
3029 "proxy-authorization", "Basic Zm9vOmJhcg=="
3031 scoped_ptr<SpdyFrame> req_get_authorization(
3032 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3033 arraysize(kExtraAuthorizationHeaders) / 2,
3034 false,
3036 LOWEST,
3037 false));
3038 MockWrite spdy_writes[] = {
3039 CreateMockWrite(*req_get, 1),
3040 CreateMockWrite(*req_get_authorization, 4),
3043 // The first response is a 407 proxy authentication challenge, and the second
3044 // response will be a 200 response since the second request includes a valid
3045 // Authorization header.
3046 const char* const kExtraAuthenticationHeaders[] = {
3047 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3049 scoped_ptr<SpdyFrame> resp_authentication(
3050 spdy_util_.ConstructSpdySynReplyError(
3051 "407 Proxy Authentication Required",
3052 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3053 1));
3054 scoped_ptr<SpdyFrame> body_authentication(
3055 spdy_util_.ConstructSpdyBodyFrame(1, true));
3056 scoped_ptr<SpdyFrame> resp_data(
3057 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3058 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3059 MockRead spdy_reads[] = {
3060 CreateMockRead(*resp_authentication, 2),
3061 CreateMockRead(*body_authentication, 3),
3062 CreateMockRead(*resp_data, 5),
3063 CreateMockRead(*body_data, 6),
3064 MockRead(ASYNC, 0, 7),
3067 OrderedSocketData data(
3068 spdy_reads, arraysize(spdy_reads),
3069 spdy_writes, arraysize(spdy_writes));
3070 session_deps_.socket_factory->AddSocketDataProvider(&data);
3072 SSLSocketDataProvider ssl(ASYNC, OK);
3073 ssl.SetNextProto(GetParam());
3074 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3076 TestCompletionCallback callback1;
3078 scoped_ptr<HttpTransaction> trans(
3079 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3081 int rv = trans->Start(&request, callback1.callback(), log.bound());
3082 EXPECT_EQ(ERR_IO_PENDING, rv);
3084 rv = callback1.WaitForResult();
3085 EXPECT_EQ(OK, rv);
3087 const HttpResponseInfo* const response = trans->GetResponseInfo();
3089 ASSERT_TRUE(response != NULL);
3090 ASSERT_TRUE(response->headers.get() != NULL);
3091 EXPECT_EQ(407, response->headers->response_code());
3092 EXPECT_TRUE(response->was_fetched_via_spdy);
3093 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3095 TestCompletionCallback callback2;
3097 rv = trans->RestartWithAuth(
3098 AuthCredentials(kFoo, kBar), callback2.callback());
3099 EXPECT_EQ(ERR_IO_PENDING, rv);
3101 rv = callback2.WaitForResult();
3102 EXPECT_EQ(OK, rv);
3104 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3106 ASSERT_TRUE(response_restart != NULL);
3107 ASSERT_TRUE(response_restart->headers.get() != NULL);
3108 EXPECT_EQ(200, response_restart->headers->response_code());
3109 // The password prompt info should not be set.
3110 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3113 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3114 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3115 HttpRequestInfo request;
3116 request.method = "GET";
3117 request.url = GURL("https://www.google.com/");
3118 request.load_flags = 0;
3120 // Configure against https proxy server "proxy:70".
3121 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3122 "https://proxy:70"));
3123 CapturingBoundNetLog log;
3124 session_deps_.net_log = log.bound().net_log();
3125 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3127 scoped_ptr<HttpTransaction> trans(
3128 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3130 // CONNECT to www.google.com:443 via SPDY
3131 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3132 LOWEST));
3133 // fetch https://www.google.com/ via HTTP
3135 const char get[] = "GET / HTTP/1.1\r\n"
3136 "Host: www.google.com\r\n"
3137 "Connection: keep-alive\r\n\r\n";
3138 scoped_ptr<SpdyFrame> wrapped_get(
3139 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3140 scoped_ptr<SpdyFrame> conn_resp(
3141 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3142 const char resp[] = "HTTP/1.1 200 OK\r\n"
3143 "Content-Length: 10\r\n\r\n";
3144 scoped_ptr<SpdyFrame> wrapped_get_resp(
3145 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3146 scoped_ptr<SpdyFrame> wrapped_body(
3147 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3148 scoped_ptr<SpdyFrame> window_update(
3149 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3151 MockWrite spdy_writes[] = {
3152 CreateMockWrite(*connect, 1),
3153 CreateMockWrite(*wrapped_get, 3),
3154 CreateMockWrite(*window_update, 5),
3157 MockRead spdy_reads[] = {
3158 CreateMockRead(*conn_resp, 2, ASYNC),
3159 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3160 CreateMockRead(*wrapped_body, 6, ASYNC),
3161 CreateMockRead(*wrapped_body, 7, ASYNC),
3162 MockRead(ASYNC, 0, 8),
3165 OrderedSocketData spdy_data(
3166 spdy_reads, arraysize(spdy_reads),
3167 spdy_writes, arraysize(spdy_writes));
3168 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3170 SSLSocketDataProvider ssl(ASYNC, OK);
3171 ssl.SetNextProto(GetParam());
3172 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3173 SSLSocketDataProvider ssl2(ASYNC, OK);
3174 ssl2.was_npn_negotiated = false;
3175 ssl2.protocol_negotiated = kProtoUnknown;
3176 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3178 TestCompletionCallback callback1;
3180 int rv = trans->Start(&request, callback1.callback(), log.bound());
3181 EXPECT_EQ(ERR_IO_PENDING, rv);
3183 rv = callback1.WaitForResult();
3184 EXPECT_EQ(OK, rv);
3186 LoadTimingInfo load_timing_info;
3187 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3188 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3190 const HttpResponseInfo* response = trans->GetResponseInfo();
3191 ASSERT_TRUE(response != NULL);
3192 ASSERT_TRUE(response->headers.get() != NULL);
3193 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3195 std::string response_data;
3196 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3197 EXPECT_EQ("1234567890", response_data);
3200 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3201 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3202 HttpRequestInfo request;
3203 request.method = "GET";
3204 request.url = GURL("https://www.google.com/");
3205 request.load_flags = 0;
3207 // Configure against https proxy server "proxy:70".
3208 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3209 "https://proxy:70"));
3210 CapturingBoundNetLog log;
3211 session_deps_.net_log = log.bound().net_log();
3212 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3214 scoped_ptr<HttpTransaction> trans(
3215 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3217 // CONNECT to www.google.com:443 via SPDY
3218 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3219 LOWEST));
3220 // fetch https://www.google.com/ via SPDY
3221 const char* const kMyUrl = "https://www.google.com/";
3222 scoped_ptr<SpdyFrame> get(
3223 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3224 scoped_ptr<SpdyFrame> wrapped_get(
3225 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3226 scoped_ptr<SpdyFrame> conn_resp(
3227 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3228 scoped_ptr<SpdyFrame> get_resp(
3229 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3230 scoped_ptr<SpdyFrame> wrapped_get_resp(
3231 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3232 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3233 scoped_ptr<SpdyFrame> wrapped_body(
3234 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3235 scoped_ptr<SpdyFrame> window_update_get_resp(
3236 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3237 scoped_ptr<SpdyFrame> window_update_body(
3238 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3240 MockWrite spdy_writes[] = {
3241 CreateMockWrite(*connect, 1),
3242 CreateMockWrite(*wrapped_get, 3),
3243 CreateMockWrite(*window_update_get_resp, 5),
3244 CreateMockWrite(*window_update_body, 7),
3247 MockRead spdy_reads[] = {
3248 CreateMockRead(*conn_resp, 2, ASYNC),
3249 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3250 CreateMockRead(*wrapped_body, 6, ASYNC),
3251 MockRead(ASYNC, 0, 8),
3254 OrderedSocketData spdy_data(
3255 spdy_reads, arraysize(spdy_reads),
3256 spdy_writes, arraysize(spdy_writes));
3257 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3259 SSLSocketDataProvider ssl(ASYNC, OK);
3260 ssl.SetNextProto(GetParam());
3261 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3262 SSLSocketDataProvider ssl2(ASYNC, OK);
3263 ssl2.SetNextProto(GetParam());
3264 ssl2.protocol_negotiated = GetParam();
3265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3267 TestCompletionCallback callback1;
3269 int rv = trans->Start(&request, callback1.callback(), log.bound());
3270 EXPECT_EQ(ERR_IO_PENDING, rv);
3272 rv = callback1.WaitForResult();
3273 EXPECT_EQ(OK, rv);
3275 LoadTimingInfo load_timing_info;
3276 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3277 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3279 const HttpResponseInfo* response = trans->GetResponseInfo();
3280 ASSERT_TRUE(response != NULL);
3281 ASSERT_TRUE(response->headers.get() != NULL);
3282 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3284 std::string response_data;
3285 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3286 EXPECT_EQ(kUploadData, response_data);
3289 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3290 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3291 HttpRequestInfo request;
3292 request.method = "GET";
3293 request.url = GURL("https://www.google.com/");
3294 request.load_flags = 0;
3296 // Configure against https proxy server "proxy:70".
3297 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3298 "https://proxy:70"));
3299 CapturingBoundNetLog log;
3300 session_deps_.net_log = log.bound().net_log();
3301 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3303 scoped_ptr<HttpTransaction> trans(
3304 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3306 // CONNECT to www.google.com:443 via SPDY
3307 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3308 LOWEST));
3309 scoped_ptr<SpdyFrame> get(
3310 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3312 MockWrite spdy_writes[] = {
3313 CreateMockWrite(*connect, 1),
3314 CreateMockWrite(*get, 3),
3317 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3318 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3319 MockRead spdy_reads[] = {
3320 CreateMockRead(*resp, 2, ASYNC),
3321 MockRead(ASYNC, 0, 4),
3324 OrderedSocketData spdy_data(
3325 spdy_reads, arraysize(spdy_reads),
3326 spdy_writes, arraysize(spdy_writes));
3327 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3329 SSLSocketDataProvider ssl(ASYNC, OK);
3330 ssl.SetNextProto(GetParam());
3331 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3332 SSLSocketDataProvider ssl2(ASYNC, OK);
3333 ssl2.SetNextProto(GetParam());
3334 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3336 TestCompletionCallback callback1;
3338 int rv = trans->Start(&request, callback1.callback(), log.bound());
3339 EXPECT_EQ(ERR_IO_PENDING, rv);
3341 rv = callback1.WaitForResult();
3342 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3344 // TODO(ttuttle): Anything else to check here?
3347 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3348 // HTTPS Proxy to different servers.
3349 TEST_P(HttpNetworkTransactionTest,
3350 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3351 // Configure against https proxy server "proxy:70".
3352 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3353 "https://proxy:70"));
3354 CapturingBoundNetLog log;
3355 session_deps_.net_log = log.bound().net_log();
3356 scoped_refptr<HttpNetworkSession> session(
3357 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3359 HttpRequestInfo request1;
3360 request1.method = "GET";
3361 request1.url = GURL("https://www.google.com/");
3362 request1.load_flags = 0;
3364 HttpRequestInfo request2;
3365 request2.method = "GET";
3366 request2.url = GURL("https://news.google.com/");
3367 request2.load_flags = 0;
3369 // CONNECT to www.google.com:443 via SPDY.
3370 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3371 LOWEST));
3372 scoped_ptr<SpdyFrame> conn_resp1(
3373 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3375 // Fetch https://www.google.com/ via HTTP.
3376 const char get1[] = "GET / HTTP/1.1\r\n"
3377 "Host: www.google.com\r\n"
3378 "Connection: keep-alive\r\n\r\n";
3379 scoped_ptr<SpdyFrame> wrapped_get1(
3380 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3381 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3382 "Content-Length: 1\r\n\r\n";
3383 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3384 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3385 scoped_ptr<SpdyFrame> wrapped_body1(
3386 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3387 scoped_ptr<SpdyFrame> window_update(
3388 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3390 // CONNECT to news.google.com:443 via SPDY.
3391 const char* const kConnectHeaders2[] = {
3392 spdy_util_.GetMethodKey(), "CONNECT",
3393 spdy_util_.GetPathKey(), "news.google.com:443",
3394 spdy_util_.GetHostKey(), "news.google.com",
3395 spdy_util_.GetVersionKey(), "HTTP/1.1",
3397 scoped_ptr<SpdyFrame> connect2(
3398 spdy_util_.ConstructSpdyControlFrame(NULL,
3400 /*compressed*/ false,
3402 LOWEST,
3403 SYN_STREAM,
3404 CONTROL_FLAG_NONE,
3405 kConnectHeaders2,
3406 arraysize(kConnectHeaders2),
3407 0));
3408 scoped_ptr<SpdyFrame> conn_resp2(
3409 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3411 // Fetch https://news.google.com/ via HTTP.
3412 const char get2[] = "GET / HTTP/1.1\r\n"
3413 "Host: news.google.com\r\n"
3414 "Connection: keep-alive\r\n\r\n";
3415 scoped_ptr<SpdyFrame> wrapped_get2(
3416 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3417 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3418 "Content-Length: 2\r\n\r\n";
3419 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3420 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3421 scoped_ptr<SpdyFrame> wrapped_body2(
3422 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3424 MockWrite spdy_writes[] = {
3425 CreateMockWrite(*connect1, 0),
3426 CreateMockWrite(*wrapped_get1, 2),
3427 CreateMockWrite(*connect2, 5),
3428 CreateMockWrite(*wrapped_get2, 7),
3431 MockRead spdy_reads[] = {
3432 CreateMockRead(*conn_resp1, 1, ASYNC),
3433 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3434 CreateMockRead(*wrapped_body1, 4, ASYNC),
3435 CreateMockRead(*conn_resp2, 6, ASYNC),
3436 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3437 CreateMockRead(*wrapped_body2, 9, ASYNC),
3438 MockRead(ASYNC, 0, 10),
3441 DeterministicSocketData spdy_data(
3442 spdy_reads, arraysize(spdy_reads),
3443 spdy_writes, arraysize(spdy_writes));
3444 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3446 SSLSocketDataProvider ssl(ASYNC, OK);
3447 ssl.SetNextProto(GetParam());
3448 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3449 SSLSocketDataProvider ssl2(ASYNC, OK);
3450 ssl2.was_npn_negotiated = false;
3451 ssl2.protocol_negotiated = kProtoUnknown;
3452 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3453 SSLSocketDataProvider ssl3(ASYNC, OK);
3454 ssl3.was_npn_negotiated = false;
3455 ssl3.protocol_negotiated = kProtoUnknown;
3456 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3458 TestCompletionCallback callback;
3460 scoped_ptr<HttpTransaction> trans(
3461 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3462 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3463 EXPECT_EQ(ERR_IO_PENDING, rv);
3464 // The first connect and request, each of their responses, and the body.
3465 spdy_data.RunFor(5);
3467 rv = callback.WaitForResult();
3468 EXPECT_EQ(OK, rv);
3470 LoadTimingInfo load_timing_info;
3471 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3472 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3474 const HttpResponseInfo* response = trans->GetResponseInfo();
3475 ASSERT_TRUE(response != NULL);
3476 ASSERT_TRUE(response->headers.get() != NULL);
3477 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3479 std::string response_data;
3480 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3481 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3483 scoped_ptr<HttpTransaction> trans2(
3484 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3485 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3486 EXPECT_EQ(ERR_IO_PENDING, rv);
3488 // The second connect and request, each of their responses, and the body.
3489 spdy_data.RunFor(5);
3490 rv = callback.WaitForResult();
3491 EXPECT_EQ(OK, rv);
3493 LoadTimingInfo load_timing_info2;
3494 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3495 // Even though the SPDY connection is reused, a new tunnelled connection has
3496 // to be created, so the socket's load timing looks like a fresh connection.
3497 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3499 // The requests should have different IDs, since they each are using their own
3500 // separate stream.
3501 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3503 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3506 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3507 // HTTPS Proxy to the same server.
3508 TEST_P(HttpNetworkTransactionTest,
3509 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3510 // Configure against https proxy server "proxy:70".
3511 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3512 "https://proxy:70"));
3513 CapturingBoundNetLog log;
3514 session_deps_.net_log = log.bound().net_log();
3515 scoped_refptr<HttpNetworkSession> session(
3516 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3518 HttpRequestInfo request1;
3519 request1.method = "GET";
3520 request1.url = GURL("https://www.google.com/");
3521 request1.load_flags = 0;
3523 HttpRequestInfo request2;
3524 request2.method = "GET";
3525 request2.url = GURL("https://www.google.com/2");
3526 request2.load_flags = 0;
3528 // CONNECT to www.google.com:443 via SPDY.
3529 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3530 LOWEST));
3531 scoped_ptr<SpdyFrame> conn_resp1(
3532 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3534 // Fetch https://www.google.com/ via HTTP.
3535 const char get1[] = "GET / HTTP/1.1\r\n"
3536 "Host: www.google.com\r\n"
3537 "Connection: keep-alive\r\n\r\n";
3538 scoped_ptr<SpdyFrame> wrapped_get1(
3539 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3540 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3541 "Content-Length: 1\r\n\r\n";
3542 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3543 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3544 scoped_ptr<SpdyFrame> wrapped_body1(
3545 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3546 scoped_ptr<SpdyFrame> window_update(
3547 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3549 // Fetch https://www.google.com/2 via HTTP.
3550 const char get2[] = "GET /2 HTTP/1.1\r\n"
3551 "Host: www.google.com\r\n"
3552 "Connection: keep-alive\r\n\r\n";
3553 scoped_ptr<SpdyFrame> wrapped_get2(
3554 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3555 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3556 "Content-Length: 2\r\n\r\n";
3557 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3558 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3559 scoped_ptr<SpdyFrame> wrapped_body2(
3560 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3562 MockWrite spdy_writes[] = {
3563 CreateMockWrite(*connect1, 0),
3564 CreateMockWrite(*wrapped_get1, 2),
3565 CreateMockWrite(*wrapped_get2, 5),
3568 MockRead spdy_reads[] = {
3569 CreateMockRead(*conn_resp1, 1, ASYNC),
3570 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3571 CreateMockRead(*wrapped_body1, 4, ASYNC),
3572 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3573 CreateMockRead(*wrapped_body2, 7, ASYNC),
3574 MockRead(ASYNC, 0, 8),
3577 DeterministicSocketData spdy_data(
3578 spdy_reads, arraysize(spdy_reads),
3579 spdy_writes, arraysize(spdy_writes));
3580 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3582 SSLSocketDataProvider ssl(ASYNC, OK);
3583 ssl.SetNextProto(GetParam());
3584 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3585 SSLSocketDataProvider ssl2(ASYNC, OK);
3586 ssl2.was_npn_negotiated = false;
3587 ssl2.protocol_negotiated = kProtoUnknown;
3588 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3590 TestCompletionCallback callback;
3592 scoped_ptr<HttpTransaction> trans(
3593 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3594 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3595 EXPECT_EQ(ERR_IO_PENDING, rv);
3596 // The first connect and request, each of their responses, and the body.
3597 spdy_data.RunFor(5);
3599 rv = callback.WaitForResult();
3600 EXPECT_EQ(OK, rv);
3602 LoadTimingInfo load_timing_info;
3603 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3604 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3606 const HttpResponseInfo* response = trans->GetResponseInfo();
3607 ASSERT_TRUE(response != NULL);
3608 ASSERT_TRUE(response->headers.get() != NULL);
3609 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3611 std::string response_data;
3612 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3613 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3614 trans.reset();
3616 scoped_ptr<HttpTransaction> trans2(
3617 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3618 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3619 EXPECT_EQ(ERR_IO_PENDING, rv);
3621 // The second request, response, and body. There should not be a second
3622 // connect.
3623 spdy_data.RunFor(3);
3624 rv = callback.WaitForResult();
3625 EXPECT_EQ(OK, rv);
3627 LoadTimingInfo load_timing_info2;
3628 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3629 TestLoadTimingReused(load_timing_info2);
3631 // The requests should have the same ID.
3632 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3634 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3637 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3638 // Proxy to different servers.
3639 TEST_P(HttpNetworkTransactionTest,
3640 HttpsProxySpdyLoadTimingTwoHttpRequests) {
3641 // Configure against https proxy server "proxy:70".
3642 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3643 "https://proxy:70"));
3644 CapturingBoundNetLog log;
3645 session_deps_.net_log = log.bound().net_log();
3646 scoped_refptr<HttpNetworkSession> session(
3647 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3649 HttpRequestInfo request1;
3650 request1.method = "GET";
3651 request1.url = GURL("http://www.google.com/");
3652 request1.load_flags = 0;
3654 HttpRequestInfo request2;
3655 request2.method = "GET";
3656 request2.url = GURL("http://news.google.com/");
3657 request2.load_flags = 0;
3659 // http://www.google.com/
3660 scoped_ptr<SpdyHeaderBlock> headers(
3661 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3662 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
3663 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3664 scoped_ptr<SpdyFrame> get_resp1(
3665 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3666 scoped_ptr<SpdyFrame> body1(
3667 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3669 // http://news.google.com/
3670 scoped_ptr<SpdyHeaderBlock> headers2(
3671 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3672 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
3673 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3674 scoped_ptr<SpdyFrame> get_resp2(
3675 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3676 scoped_ptr<SpdyFrame> body2(
3677 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3679 MockWrite spdy_writes[] = {
3680 CreateMockWrite(*get1, 0),
3681 CreateMockWrite(*get2, 3),
3684 MockRead spdy_reads[] = {
3685 CreateMockRead(*get_resp1, 1, ASYNC),
3686 CreateMockRead(*body1, 2, ASYNC),
3687 CreateMockRead(*get_resp2, 4, ASYNC),
3688 CreateMockRead(*body2, 5, ASYNC),
3689 MockRead(ASYNC, 0, 6),
3692 DeterministicSocketData spdy_data(
3693 spdy_reads, arraysize(spdy_reads),
3694 spdy_writes, arraysize(spdy_writes));
3695 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3697 SSLSocketDataProvider ssl(ASYNC, OK);
3698 ssl.SetNextProto(GetParam());
3699 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3701 TestCompletionCallback callback;
3703 scoped_ptr<HttpTransaction> trans(
3704 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3705 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3706 EXPECT_EQ(ERR_IO_PENDING, rv);
3707 spdy_data.RunFor(2);
3709 rv = callback.WaitForResult();
3710 EXPECT_EQ(OK, rv);
3712 LoadTimingInfo load_timing_info;
3713 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3714 TestLoadTimingNotReused(load_timing_info,
3715 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3717 const HttpResponseInfo* response = trans->GetResponseInfo();
3718 ASSERT_TRUE(response != NULL);
3719 ASSERT_TRUE(response->headers.get() != NULL);
3720 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3722 std::string response_data;
3723 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3724 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3725 spdy_data.RunFor(1);
3726 EXPECT_EQ(1, callback.WaitForResult());
3727 // Delete the first request, so the second one can reuse the socket.
3728 trans.reset();
3730 scoped_ptr<HttpTransaction> trans2(
3731 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3732 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3733 EXPECT_EQ(ERR_IO_PENDING, rv);
3735 spdy_data.RunFor(2);
3736 rv = callback.WaitForResult();
3737 EXPECT_EQ(OK, rv);
3739 LoadTimingInfo load_timing_info2;
3740 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3741 TestLoadTimingReused(load_timing_info2);
3743 // The requests should have the same ID.
3744 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3746 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3747 spdy_data.RunFor(1);
3748 EXPECT_EQ(2, callback.WaitForResult());
3751 // Test the challenge-response-retry sequence through an HTTPS Proxy
3752 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3753 HttpRequestInfo request;
3754 request.method = "GET";
3755 request.url = GURL("http://www.google.com/");
3756 // when the no authentication data flag is set.
3757 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3759 // Configure against https proxy server "myproxy:70".
3760 session_deps_.proxy_service.reset(
3761 ProxyService::CreateFixed("https://myproxy:70"));
3762 CapturingBoundNetLog log;
3763 session_deps_.net_log = log.bound().net_log();
3764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3766 // Since we have proxy, should use full url
3767 MockWrite data_writes1[] = {
3768 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3769 "Host: www.google.com\r\n"
3770 "Proxy-Connection: keep-alive\r\n\r\n"),
3772 // After calling trans->RestartWithAuth(), this is the request we should
3773 // be issuing -- the final header line contains the credentials.
3774 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3775 "Host: www.google.com\r\n"
3776 "Proxy-Connection: keep-alive\r\n"
3777 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3780 // The proxy responds to the GET with a 407, using a persistent
3781 // connection.
3782 MockRead data_reads1[] = {
3783 // No credentials.
3784 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3785 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3786 MockRead("Proxy-Connection: keep-alive\r\n"),
3787 MockRead("Content-Length: 0\r\n\r\n"),
3789 MockRead("HTTP/1.1 200 OK\r\n"),
3790 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3791 MockRead("Content-Length: 100\r\n\r\n"),
3792 MockRead(SYNCHRONOUS, OK),
3795 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3796 data_writes1, arraysize(data_writes1));
3797 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3798 SSLSocketDataProvider ssl(ASYNC, OK);
3799 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3801 TestCompletionCallback callback1;
3803 scoped_ptr<HttpTransaction> trans(
3804 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3806 int rv = trans->Start(&request, callback1.callback(), log.bound());
3807 EXPECT_EQ(ERR_IO_PENDING, rv);
3809 rv = callback1.WaitForResult();
3810 EXPECT_EQ(OK, rv);
3812 LoadTimingInfo load_timing_info;
3813 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3814 TestLoadTimingNotReused(load_timing_info,
3815 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3817 const HttpResponseInfo* response = trans->GetResponseInfo();
3818 ASSERT_TRUE(response != NULL);
3819 ASSERT_FALSE(response->headers.get() == NULL);
3820 EXPECT_EQ(407, response->headers->response_code());
3821 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3822 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3824 TestCompletionCallback callback2;
3826 rv = trans->RestartWithAuth(
3827 AuthCredentials(kFoo, kBar), callback2.callback());
3828 EXPECT_EQ(ERR_IO_PENDING, rv);
3830 rv = callback2.WaitForResult();
3831 EXPECT_EQ(OK, rv);
3833 load_timing_info = LoadTimingInfo();
3834 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3835 // Retrying with HTTP AUTH is considered to be reusing a socket.
3836 TestLoadTimingReused(load_timing_info);
3838 response = trans->GetResponseInfo();
3839 ASSERT_TRUE(response != NULL);
3841 EXPECT_TRUE(response->headers->IsKeepAlive());
3842 EXPECT_EQ(200, response->headers->response_code());
3843 EXPECT_EQ(100, response->headers->GetContentLength());
3844 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3846 // The password prompt info should not be set.
3847 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3850 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3851 const MockRead& status, int expected_status) {
3852 HttpRequestInfo request;
3853 request.method = "GET";
3854 request.url = GURL("https://www.google.com/");
3855 request.load_flags = 0;
3857 // Configure against proxy server "myproxy:70".
3858 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3859 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3861 // Since we have proxy, should try to establish tunnel.
3862 MockWrite data_writes[] = {
3863 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3864 "Host: www.google.com\r\n"
3865 "Proxy-Connection: keep-alive\r\n\r\n"),
3868 MockRead data_reads[] = {
3869 status,
3870 MockRead("Content-Length: 10\r\n\r\n"),
3871 // No response body because the test stops reading here.
3872 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3875 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3876 data_writes, arraysize(data_writes));
3877 session_deps_.socket_factory->AddSocketDataProvider(&data);
3879 TestCompletionCallback callback;
3881 scoped_ptr<HttpTransaction> trans(
3882 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3884 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3885 EXPECT_EQ(ERR_IO_PENDING, rv);
3887 rv = callback.WaitForResult();
3888 EXPECT_EQ(expected_status, rv);
3891 void HttpNetworkTransactionTest::ConnectStatusHelper(
3892 const MockRead& status) {
3893 ConnectStatusHelperWithExpectedStatus(
3894 status, ERR_TUNNEL_CONNECTION_FAILED);
3897 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3898 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3901 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3902 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3905 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3906 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3909 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3910 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3913 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
3914 ConnectStatusHelper(
3915 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3918 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
3919 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3922 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
3923 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3926 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
3927 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3930 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
3931 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3934 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
3935 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3938 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
3939 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3942 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
3943 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3946 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
3947 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3950 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
3951 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3954 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
3955 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3958 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
3959 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3962 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
3963 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3966 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
3967 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3970 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
3971 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3974 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
3975 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3978 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
3979 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3982 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
3983 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3986 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
3987 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3990 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
3991 ConnectStatusHelperWithExpectedStatus(
3992 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3993 ERR_PROXY_AUTH_UNSUPPORTED);
3996 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
3997 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4000 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4001 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4004 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4005 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4008 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4009 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4012 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4013 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4016 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4017 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4020 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4021 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4024 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4025 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4028 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4029 ConnectStatusHelper(
4030 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4033 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4034 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4037 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4038 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4041 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4042 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4045 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4046 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4049 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4050 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4053 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4054 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4057 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4058 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4061 // Test the flow when both the proxy server AND origin server require
4062 // authentication. Again, this uses basic auth for both since that is
4063 // the simplest to mock.
4064 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4065 HttpRequestInfo request;
4066 request.method = "GET";
4067 request.url = GURL("http://www.google.com/");
4068 request.load_flags = 0;
4070 // Configure against proxy server "myproxy:70".
4071 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4072 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4074 scoped_ptr<HttpTransaction> trans(
4075 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4077 MockWrite data_writes1[] = {
4078 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4079 "Host: www.google.com\r\n"
4080 "Proxy-Connection: keep-alive\r\n\r\n"),
4083 MockRead data_reads1[] = {
4084 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4085 // Give a couple authenticate options (only the middle one is actually
4086 // supported).
4087 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4088 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4089 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4090 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4091 // Large content-length -- won't matter, as connection will be reset.
4092 MockRead("Content-Length: 10000\r\n\r\n"),
4093 MockRead(SYNCHRONOUS, ERR_FAILED),
4096 // After calling trans->RestartWithAuth() the first time, this is the
4097 // request we should be issuing -- the final header line contains the
4098 // proxy's credentials.
4099 MockWrite data_writes2[] = {
4100 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4101 "Host: www.google.com\r\n"
4102 "Proxy-Connection: keep-alive\r\n"
4103 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4106 // Now the proxy server lets the request pass through to origin server.
4107 // The origin server responds with a 401.
4108 MockRead data_reads2[] = {
4109 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4110 // Note: We are using the same realm-name as the proxy server. This is
4111 // completely valid, as realms are unique across hosts.
4112 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4113 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4114 MockRead("Content-Length: 2000\r\n\r\n"),
4115 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4118 // After calling trans->RestartWithAuth() the second time, we should send
4119 // the credentials for both the proxy and origin server.
4120 MockWrite data_writes3[] = {
4121 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4122 "Host: www.google.com\r\n"
4123 "Proxy-Connection: keep-alive\r\n"
4124 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4125 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4128 // Lastly we get the desired content.
4129 MockRead data_reads3[] = {
4130 MockRead("HTTP/1.0 200 OK\r\n"),
4131 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4132 MockRead("Content-Length: 100\r\n\r\n"),
4133 MockRead(SYNCHRONOUS, OK),
4136 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4137 data_writes1, arraysize(data_writes1));
4138 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4139 data_writes2, arraysize(data_writes2));
4140 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4141 data_writes3, arraysize(data_writes3));
4142 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4143 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4144 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4146 TestCompletionCallback callback1;
4148 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4149 EXPECT_EQ(ERR_IO_PENDING, rv);
4151 rv = callback1.WaitForResult();
4152 EXPECT_EQ(OK, rv);
4154 const HttpResponseInfo* response = trans->GetResponseInfo();
4155 ASSERT_TRUE(response != NULL);
4156 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4158 TestCompletionCallback callback2;
4160 rv = trans->RestartWithAuth(
4161 AuthCredentials(kFoo, kBar), callback2.callback());
4162 EXPECT_EQ(ERR_IO_PENDING, rv);
4164 rv = callback2.WaitForResult();
4165 EXPECT_EQ(OK, rv);
4167 response = trans->GetResponseInfo();
4168 ASSERT_TRUE(response != NULL);
4169 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4171 TestCompletionCallback callback3;
4173 rv = trans->RestartWithAuth(
4174 AuthCredentials(kFoo2, kBar2), callback3.callback());
4175 EXPECT_EQ(ERR_IO_PENDING, rv);
4177 rv = callback3.WaitForResult();
4178 EXPECT_EQ(OK, rv);
4180 response = trans->GetResponseInfo();
4181 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4182 EXPECT_EQ(100, response->headers->GetContentLength());
4185 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4186 // can't hook into its internals to cause it to generate predictable NTLM
4187 // authorization headers.
4188 #if defined(NTLM_PORTABLE)
4189 // The NTLM authentication unit tests were generated by capturing the HTTP
4190 // requests and responses using Fiddler 2 and inspecting the generated random
4191 // bytes in the debugger.
4193 // Enter the correct password and authenticate successfully.
4194 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4195 HttpRequestInfo request;
4196 request.method = "GET";
4197 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4199 // Ensure load is not disrupted by flags which suppress behaviour specific
4200 // to other auth schemes.
4201 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4203 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4204 MockGetHostName);
4205 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4207 MockWrite data_writes1[] = {
4208 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4209 "Host: 172.22.68.17\r\n"
4210 "Connection: keep-alive\r\n\r\n"),
4213 MockRead data_reads1[] = {
4214 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4215 // Negotiate and NTLM are often requested together. However, we only want
4216 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4217 // the header that requests Negotiate for this test.
4218 MockRead("WWW-Authenticate: NTLM\r\n"),
4219 MockRead("Connection: close\r\n"),
4220 MockRead("Content-Length: 42\r\n"),
4221 MockRead("Content-Type: text/html\r\n\r\n"),
4222 // Missing content -- won't matter, as connection will be reset.
4223 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4226 MockWrite data_writes2[] = {
4227 // After restarting with a null identity, this is the
4228 // request we should be issuing -- the final header line contains a Type
4229 // 1 message.
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 "
4234 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4236 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4237 // (the credentials for the origin server). The second request continues
4238 // on the same connection.
4239 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4240 "Host: 172.22.68.17\r\n"
4241 "Connection: keep-alive\r\n"
4242 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4243 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4244 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4245 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4246 "ahlhx5I=\r\n\r\n"),
4249 MockRead data_reads2[] = {
4250 // The origin server responds with a Type 2 message.
4251 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4252 MockRead("WWW-Authenticate: NTLM "
4253 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4254 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4255 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4256 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4257 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4258 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4259 "BtAAAAAAA=\r\n"),
4260 MockRead("Content-Length: 42\r\n"),
4261 MockRead("Content-Type: text/html\r\n\r\n"),
4262 MockRead("You are not authorized to view this page\r\n"),
4264 // Lastly we get the desired content.
4265 MockRead("HTTP/1.1 200 OK\r\n"),
4266 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4267 MockRead("Content-Length: 13\r\n\r\n"),
4268 MockRead("Please Login\r\n"),
4269 MockRead(SYNCHRONOUS, OK),
4272 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4273 data_writes1, arraysize(data_writes1));
4274 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4275 data_writes2, arraysize(data_writes2));
4276 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4277 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4279 TestCompletionCallback callback1;
4281 scoped_ptr<HttpTransaction> trans(
4282 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4284 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4285 EXPECT_EQ(ERR_IO_PENDING, rv);
4287 rv = callback1.WaitForResult();
4288 EXPECT_EQ(OK, rv);
4290 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4292 const HttpResponseInfo* response = trans->GetResponseInfo();
4293 ASSERT_FALSE(response == NULL);
4294 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4296 TestCompletionCallback callback2;
4298 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4299 callback2.callback());
4300 EXPECT_EQ(ERR_IO_PENDING, rv);
4302 rv = callback2.WaitForResult();
4303 EXPECT_EQ(OK, rv);
4305 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4307 response = trans->GetResponseInfo();
4308 ASSERT_TRUE(response != NULL);
4309 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4311 TestCompletionCallback callback3;
4313 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4314 EXPECT_EQ(ERR_IO_PENDING, rv);
4316 rv = callback3.WaitForResult();
4317 EXPECT_EQ(OK, rv);
4319 response = trans->GetResponseInfo();
4320 ASSERT_TRUE(response != NULL);
4321 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4322 EXPECT_EQ(13, response->headers->GetContentLength());
4325 // Enter a wrong password, and then the correct one.
4326 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4327 HttpRequestInfo request;
4328 request.method = "GET";
4329 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4330 request.load_flags = 0;
4332 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4333 MockGetHostName);
4334 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4336 MockWrite data_writes1[] = {
4337 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4338 "Host: 172.22.68.17\r\n"
4339 "Connection: keep-alive\r\n\r\n"),
4342 MockRead data_reads1[] = {
4343 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4344 // Negotiate and NTLM are often requested together. However, we only want
4345 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4346 // the header that requests Negotiate for this test.
4347 MockRead("WWW-Authenticate: NTLM\r\n"),
4348 MockRead("Connection: close\r\n"),
4349 MockRead("Content-Length: 42\r\n"),
4350 MockRead("Content-Type: text/html\r\n\r\n"),
4351 // Missing content -- won't matter, as connection will be reset.
4352 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4355 MockWrite data_writes2[] = {
4356 // After restarting with a null identity, this is the
4357 // request we should be issuing -- the final header line contains a Type
4358 // 1 message.
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 "
4363 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4365 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4366 // (the credentials for the origin server). The second request continues
4367 // on the same connection.
4368 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4369 "Host: 172.22.68.17\r\n"
4370 "Connection: keep-alive\r\n"
4371 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4372 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4373 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4374 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4375 "4Ww7b7E=\r\n\r\n"),
4378 MockRead data_reads2[] = {
4379 // The origin server responds with a Type 2 message.
4380 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4381 MockRead("WWW-Authenticate: NTLM "
4382 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4383 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4384 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4385 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4386 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4387 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4388 "BtAAAAAAA=\r\n"),
4389 MockRead("Content-Length: 42\r\n"),
4390 MockRead("Content-Type: text/html\r\n\r\n"),
4391 MockRead("You are not authorized to view this page\r\n"),
4393 // Wrong password.
4394 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4395 MockRead("WWW-Authenticate: NTLM\r\n"),
4396 MockRead("Connection: close\r\n"),
4397 MockRead("Content-Length: 42\r\n"),
4398 MockRead("Content-Type: text/html\r\n\r\n"),
4399 // Missing content -- won't matter, as connection will be reset.
4400 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4403 MockWrite data_writes3[] = {
4404 // After restarting with a null identity, this is the
4405 // request we should be issuing -- the final header line contains a Type
4406 // 1 message.
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 "
4411 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4413 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4414 // (the credentials for the origin server). The second request continues
4415 // on the same connection.
4416 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4417 "Host: 172.22.68.17\r\n"
4418 "Connection: keep-alive\r\n"
4419 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4420 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4421 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4422 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4423 "+4MUm7c=\r\n\r\n"),
4426 MockRead data_reads3[] = {
4427 // The origin server responds with a Type 2 message.
4428 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4429 MockRead("WWW-Authenticate: NTLM "
4430 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4431 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4432 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4433 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4434 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4435 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4436 "BtAAAAAAA=\r\n"),
4437 MockRead("Content-Length: 42\r\n"),
4438 MockRead("Content-Type: text/html\r\n\r\n"),
4439 MockRead("You are not authorized to view this page\r\n"),
4441 // Lastly we get the desired content.
4442 MockRead("HTTP/1.1 200 OK\r\n"),
4443 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4444 MockRead("Content-Length: 13\r\n\r\n"),
4445 MockRead("Please Login\r\n"),
4446 MockRead(SYNCHRONOUS, OK),
4449 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4450 data_writes1, arraysize(data_writes1));
4451 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4452 data_writes2, arraysize(data_writes2));
4453 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4454 data_writes3, arraysize(data_writes3));
4455 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4456 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4457 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4459 TestCompletionCallback callback1;
4461 scoped_ptr<HttpTransaction> trans(
4462 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4464 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4465 EXPECT_EQ(ERR_IO_PENDING, rv);
4467 rv = callback1.WaitForResult();
4468 EXPECT_EQ(OK, rv);
4470 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4472 const HttpResponseInfo* response = trans->GetResponseInfo();
4473 ASSERT_TRUE(response != NULL);
4474 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4476 TestCompletionCallback callback2;
4478 // Enter the wrong password.
4479 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4480 callback2.callback());
4481 EXPECT_EQ(ERR_IO_PENDING, rv);
4483 rv = callback2.WaitForResult();
4484 EXPECT_EQ(OK, rv);
4486 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4487 TestCompletionCallback callback3;
4488 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4489 EXPECT_EQ(ERR_IO_PENDING, rv);
4490 rv = callback3.WaitForResult();
4491 EXPECT_EQ(OK, rv);
4492 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4494 response = trans->GetResponseInfo();
4495 ASSERT_FALSE(response == NULL);
4496 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4498 TestCompletionCallback callback4;
4500 // Now enter the right password.
4501 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4502 callback4.callback());
4503 EXPECT_EQ(ERR_IO_PENDING, rv);
4505 rv = callback4.WaitForResult();
4506 EXPECT_EQ(OK, rv);
4508 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4510 TestCompletionCallback callback5;
4512 // One more roundtrip
4513 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4514 EXPECT_EQ(ERR_IO_PENDING, rv);
4516 rv = callback5.WaitForResult();
4517 EXPECT_EQ(OK, rv);
4519 response = trans->GetResponseInfo();
4520 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4521 EXPECT_EQ(13, response->headers->GetContentLength());
4523 #endif // NTLM_PORTABLE
4525 // Test reading a server response which has only headers, and no body.
4526 // After some maximum number of bytes is consumed, the transaction should
4527 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4528 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4529 HttpRequestInfo request;
4530 request.method = "GET";
4531 request.url = GURL("http://www.google.com/");
4532 request.load_flags = 0;
4534 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4535 scoped_ptr<HttpTransaction> trans(
4536 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4538 // Respond with 300 kb of headers (we should fail after 256 kb).
4539 std::string large_headers_string;
4540 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4542 MockRead data_reads[] = {
4543 MockRead("HTTP/1.0 200 OK\r\n"),
4544 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4545 MockRead("\r\nBODY"),
4546 MockRead(SYNCHRONOUS, OK),
4548 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4549 session_deps_.socket_factory->AddSocketDataProvider(&data);
4551 TestCompletionCallback callback;
4553 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4554 EXPECT_EQ(ERR_IO_PENDING, rv);
4556 rv = callback.WaitForResult();
4557 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4559 const HttpResponseInfo* response = trans->GetResponseInfo();
4560 EXPECT_TRUE(response == NULL);
4563 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4564 // establish tunnel.
4565 // http://code.google.com/p/chromium/issues/detail?id=3772
4566 TEST_P(HttpNetworkTransactionTest,
4567 DontRecycleTransportSocketForSSLTunnel) {
4568 HttpRequestInfo request;
4569 request.method = "GET";
4570 request.url = GURL("https://www.google.com/");
4571 request.load_flags = 0;
4573 // Configure against proxy server "myproxy:70".
4574 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4576 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4578 scoped_ptr<HttpTransaction> trans(
4579 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4581 // Since we have proxy, should try to establish tunnel.
4582 MockWrite data_writes1[] = {
4583 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4584 "Host: www.google.com\r\n"
4585 "Proxy-Connection: keep-alive\r\n\r\n"),
4588 // The proxy responds to the connect with a 404, using a persistent
4589 // connection. Usually a proxy would return 501 (not implemented),
4590 // or 200 (tunnel established).
4591 MockRead data_reads1[] = {
4592 MockRead("HTTP/1.1 404 Not Found\r\n"),
4593 MockRead("Content-Length: 10\r\n\r\n"),
4594 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4597 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4598 data_writes1, arraysize(data_writes1));
4599 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4601 TestCompletionCallback callback1;
4603 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4604 EXPECT_EQ(ERR_IO_PENDING, rv);
4606 rv = callback1.WaitForResult();
4607 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4609 const HttpResponseInfo* response = trans->GetResponseInfo();
4610 EXPECT_TRUE(response == NULL);
4612 // Empty the current queue. This is necessary because idle sockets are
4613 // added to the connection pool asynchronously with a PostTask.
4614 base::MessageLoop::current()->RunUntilIdle();
4616 // We now check to make sure the TCPClientSocket was not added back to
4617 // the pool.
4618 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4619 trans.reset();
4620 base::MessageLoop::current()->RunUntilIdle();
4621 // Make sure that the socket didn't get recycled after calling the destructor.
4622 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4625 // Make sure that we recycle a socket after reading all of the response body.
4626 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4627 HttpRequestInfo request;
4628 request.method = "GET";
4629 request.url = GURL("http://www.google.com/");
4630 request.load_flags = 0;
4632 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4634 scoped_ptr<HttpTransaction> trans(
4635 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4637 MockRead data_reads[] = {
4638 // A part of the response body is received with the response headers.
4639 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4640 // The rest of the response body is received in two parts.
4641 MockRead("lo"),
4642 MockRead(" world"),
4643 MockRead("junk"), // Should not be read!!
4644 MockRead(SYNCHRONOUS, OK),
4647 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4648 session_deps_.socket_factory->AddSocketDataProvider(&data);
4650 TestCompletionCallback callback;
4652 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4653 EXPECT_EQ(ERR_IO_PENDING, rv);
4655 rv = callback.WaitForResult();
4656 EXPECT_EQ(OK, rv);
4658 const HttpResponseInfo* response = trans->GetResponseInfo();
4659 ASSERT_TRUE(response != NULL);
4661 EXPECT_TRUE(response->headers.get() != NULL);
4662 std::string status_line = response->headers->GetStatusLine();
4663 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4665 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4667 std::string response_data;
4668 rv = ReadTransaction(trans.get(), &response_data);
4669 EXPECT_EQ(OK, rv);
4670 EXPECT_EQ("hello world", response_data);
4672 // Empty the current queue. This is necessary because idle sockets are
4673 // added to the connection pool asynchronously with a PostTask.
4674 base::MessageLoop::current()->RunUntilIdle();
4676 // We now check to make sure the socket was added back to the pool.
4677 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4680 // Make sure that we recycle a SSL socket after reading all of the response
4681 // body.
4682 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4683 HttpRequestInfo request;
4684 request.method = "GET";
4685 request.url = GURL("https://www.google.com/");
4686 request.load_flags = 0;
4688 MockWrite data_writes[] = {
4689 MockWrite("GET / HTTP/1.1\r\n"
4690 "Host: www.google.com\r\n"
4691 "Connection: keep-alive\r\n\r\n"),
4694 MockRead data_reads[] = {
4695 MockRead("HTTP/1.1 200 OK\r\n"),
4696 MockRead("Content-Length: 11\r\n\r\n"),
4697 MockRead("hello world"),
4698 MockRead(SYNCHRONOUS, OK),
4701 SSLSocketDataProvider ssl(ASYNC, OK);
4702 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4704 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4705 data_writes, arraysize(data_writes));
4706 session_deps_.socket_factory->AddSocketDataProvider(&data);
4708 TestCompletionCallback callback;
4710 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4711 scoped_ptr<HttpTransaction> trans(
4712 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4714 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4716 EXPECT_EQ(ERR_IO_PENDING, rv);
4717 EXPECT_EQ(OK, callback.WaitForResult());
4719 const HttpResponseInfo* response = trans->GetResponseInfo();
4720 ASSERT_TRUE(response != NULL);
4721 ASSERT_TRUE(response->headers.get() != NULL);
4722 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4724 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4726 std::string response_data;
4727 rv = ReadTransaction(trans.get(), &response_data);
4728 EXPECT_EQ(OK, rv);
4729 EXPECT_EQ("hello world", response_data);
4731 // Empty the current queue. This is necessary because idle sockets are
4732 // added to the connection pool asynchronously with a PostTask.
4733 base::MessageLoop::current()->RunUntilIdle();
4735 // We now check to make sure the socket was added back to the pool.
4736 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4739 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4740 // from the pool and make sure that we recover okay.
4741 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4742 HttpRequestInfo request;
4743 request.method = "GET";
4744 request.url = GURL("https://www.google.com/");
4745 request.load_flags = 0;
4747 MockWrite data_writes[] = {
4748 MockWrite("GET / HTTP/1.1\r\n"
4749 "Host: www.google.com\r\n"
4750 "Connection: keep-alive\r\n\r\n"),
4751 MockWrite("GET / HTTP/1.1\r\n"
4752 "Host: www.google.com\r\n"
4753 "Connection: keep-alive\r\n\r\n"),
4756 MockRead data_reads[] = {
4757 MockRead("HTTP/1.1 200 OK\r\n"),
4758 MockRead("Content-Length: 11\r\n\r\n"),
4759 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4760 MockRead("hello world"),
4761 MockRead(ASYNC, 0, 0) // EOF
4764 SSLSocketDataProvider ssl(ASYNC, OK);
4765 SSLSocketDataProvider ssl2(ASYNC, OK);
4766 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4767 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4769 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4770 data_writes, arraysize(data_writes));
4771 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4772 data_writes, arraysize(data_writes));
4773 session_deps_.socket_factory->AddSocketDataProvider(&data);
4774 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4776 TestCompletionCallback callback;
4778 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4779 scoped_ptr<HttpTransaction> trans(
4780 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4782 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4784 EXPECT_EQ(ERR_IO_PENDING, rv);
4785 EXPECT_EQ(OK, callback.WaitForResult());
4787 const HttpResponseInfo* response = trans->GetResponseInfo();
4788 ASSERT_TRUE(response != NULL);
4789 ASSERT_TRUE(response->headers.get() != NULL);
4790 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4792 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4794 std::string response_data;
4795 rv = ReadTransaction(trans.get(), &response_data);
4796 EXPECT_EQ(OK, rv);
4797 EXPECT_EQ("hello world", response_data);
4799 // Empty the current queue. This is necessary because idle sockets are
4800 // added to the connection pool asynchronously with a PostTask.
4801 base::MessageLoop::current()->RunUntilIdle();
4803 // We now check to make sure the socket was added back to the pool.
4804 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4806 // Now start the second transaction, which should reuse the previous socket.
4808 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4810 rv = trans->Start(&request, callback.callback(), BoundNetLog());
4812 EXPECT_EQ(ERR_IO_PENDING, rv);
4813 EXPECT_EQ(OK, callback.WaitForResult());
4815 response = trans->GetResponseInfo();
4816 ASSERT_TRUE(response != NULL);
4817 ASSERT_TRUE(response->headers.get() != NULL);
4818 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4820 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4822 rv = ReadTransaction(trans.get(), &response_data);
4823 EXPECT_EQ(OK, rv);
4824 EXPECT_EQ("hello world", response_data);
4826 // Empty the current queue. This is necessary because idle sockets are
4827 // added to the connection pool asynchronously with a PostTask.
4828 base::MessageLoop::current()->RunUntilIdle();
4830 // We now check to make sure the socket was added back to the pool.
4831 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4834 // Make sure that we recycle a socket after a zero-length response.
4835 // http://crbug.com/9880
4836 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4837 HttpRequestInfo request;
4838 request.method = "GET";
4839 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4840 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4841 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4842 "rt=prt.2642,ol.2649,xjs.2951");
4843 request.load_flags = 0;
4845 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4847 scoped_ptr<HttpTransaction> trans(
4848 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4850 MockRead data_reads[] = {
4851 MockRead("HTTP/1.1 204 No Content\r\n"
4852 "Content-Length: 0\r\n"
4853 "Content-Type: text/html\r\n\r\n"),
4854 MockRead("junk"), // Should not be read!!
4855 MockRead(SYNCHRONOUS, OK),
4858 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4859 session_deps_.socket_factory->AddSocketDataProvider(&data);
4861 TestCompletionCallback callback;
4863 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4864 EXPECT_EQ(ERR_IO_PENDING, rv);
4866 rv = callback.WaitForResult();
4867 EXPECT_EQ(OK, rv);
4869 const HttpResponseInfo* response = trans->GetResponseInfo();
4870 ASSERT_TRUE(response != NULL);
4872 EXPECT_TRUE(response->headers.get() != NULL);
4873 std::string status_line = response->headers->GetStatusLine();
4874 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4876 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4878 std::string response_data;
4879 rv = ReadTransaction(trans.get(), &response_data);
4880 EXPECT_EQ(OK, rv);
4881 EXPECT_EQ("", response_data);
4883 // Empty the current queue. This is necessary because idle sockets are
4884 // added to the connection pool asynchronously with a PostTask.
4885 base::MessageLoop::current()->RunUntilIdle();
4887 // We now check to make sure the socket was added back to the pool.
4888 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4891 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
4892 ScopedVector<UploadElementReader> element_readers;
4893 element_readers.push_back(new UploadBytesElementReader("foo", 3));
4894 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
4896 HttpRequestInfo request[2];
4897 // Transaction 1: a GET request that succeeds. The socket is recycled
4898 // after use.
4899 request[0].method = "GET";
4900 request[0].url = GURL("http://www.google.com/");
4901 request[0].load_flags = 0;
4902 // Transaction 2: a POST request. Reuses the socket kept alive from
4903 // transaction 1. The first attempts fails when writing the POST data.
4904 // This causes the transaction to retry with a new socket. The second
4905 // attempt succeeds.
4906 request[1].method = "POST";
4907 request[1].url = GURL("http://www.google.com/login.cgi");
4908 request[1].upload_data_stream = &upload_data_stream;
4909 request[1].load_flags = 0;
4911 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4913 // The first socket is used for transaction 1 and the first attempt of
4914 // transaction 2.
4916 // The response of transaction 1.
4917 MockRead data_reads1[] = {
4918 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4919 MockRead("hello world"),
4920 MockRead(SYNCHRONOUS, OK),
4922 // The mock write results of transaction 1 and the first attempt of
4923 // transaction 2.
4924 MockWrite data_writes1[] = {
4925 MockWrite(SYNCHRONOUS, 64), // GET
4926 MockWrite(SYNCHRONOUS, 93), // POST
4927 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
4929 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4930 data_writes1, arraysize(data_writes1));
4932 // The second socket is used for the second attempt of transaction 2.
4934 // The response of transaction 2.
4935 MockRead data_reads2[] = {
4936 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4937 MockRead("welcome"),
4938 MockRead(SYNCHRONOUS, OK),
4940 // The mock write results of the second attempt of transaction 2.
4941 MockWrite data_writes2[] = {
4942 MockWrite(SYNCHRONOUS, 93), // POST
4943 MockWrite(SYNCHRONOUS, 3), // POST data
4945 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4946 data_writes2, arraysize(data_writes2));
4948 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4949 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4951 const char* kExpectedResponseData[] = {
4952 "hello world", "welcome"
4955 for (int i = 0; i < 2; ++i) {
4956 scoped_ptr<HttpTransaction> trans(
4957 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4959 TestCompletionCallback callback;
4961 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
4962 EXPECT_EQ(ERR_IO_PENDING, rv);
4964 rv = callback.WaitForResult();
4965 EXPECT_EQ(OK, rv);
4967 const HttpResponseInfo* response = trans->GetResponseInfo();
4968 ASSERT_TRUE(response != NULL);
4970 EXPECT_TRUE(response->headers.get() != NULL);
4971 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4973 std::string response_data;
4974 rv = ReadTransaction(trans.get(), &response_data);
4975 EXPECT_EQ(OK, rv);
4976 EXPECT_EQ(kExpectedResponseData[i], response_data);
4980 // Test the request-challenge-retry sequence for basic auth when there is
4981 // an identity in the URL. The request should be sent as normal, but when
4982 // it fails the identity from the URL is used to answer the challenge.
4983 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
4984 HttpRequestInfo request;
4985 request.method = "GET";
4986 request.url = GURL("http://foo:b@r@www.google.com/");
4987 request.load_flags = LOAD_NORMAL;
4989 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4990 scoped_ptr<HttpTransaction> trans(
4991 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4993 // The password contains an escaped character -- for this test to pass it
4994 // will need to be unescaped by HttpNetworkTransaction.
4995 EXPECT_EQ("b%40r", request.url.password());
4997 MockWrite data_writes1[] = {
4998 MockWrite("GET / HTTP/1.1\r\n"
4999 "Host: www.google.com\r\n"
5000 "Connection: keep-alive\r\n\r\n"),
5003 MockRead data_reads1[] = {
5004 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5005 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5006 MockRead("Content-Length: 10\r\n\r\n"),
5007 MockRead(SYNCHRONOUS, ERR_FAILED),
5010 // After the challenge above, the transaction will be restarted using the
5011 // identity from the url (foo, b@r) to answer the challenge.
5012 MockWrite data_writes2[] = {
5013 MockWrite("GET / HTTP/1.1\r\n"
5014 "Host: www.google.com\r\n"
5015 "Connection: keep-alive\r\n"
5016 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5019 MockRead data_reads2[] = {
5020 MockRead("HTTP/1.0 200 OK\r\n"),
5021 MockRead("Content-Length: 100\r\n\r\n"),
5022 MockRead(SYNCHRONOUS, OK),
5025 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5026 data_writes1, arraysize(data_writes1));
5027 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5028 data_writes2, arraysize(data_writes2));
5029 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5030 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5032 TestCompletionCallback callback1;
5033 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5034 EXPECT_EQ(ERR_IO_PENDING, rv);
5035 rv = callback1.WaitForResult();
5036 EXPECT_EQ(OK, rv);
5037 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5039 TestCompletionCallback callback2;
5040 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5041 EXPECT_EQ(ERR_IO_PENDING, rv);
5042 rv = callback2.WaitForResult();
5043 EXPECT_EQ(OK, rv);
5044 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5046 const HttpResponseInfo* response = trans->GetResponseInfo();
5047 ASSERT_TRUE(response != NULL);
5049 // There is no challenge info, since the identity in URL worked.
5050 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5052 EXPECT_EQ(100, response->headers->GetContentLength());
5054 // Empty the current queue.
5055 base::MessageLoop::current()->RunUntilIdle();
5058 // Test the request-challenge-retry sequence for basic auth when there is an
5059 // incorrect identity in the URL. The identity from the URL should be used only
5060 // once.
5061 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5062 HttpRequestInfo request;
5063 request.method = "GET";
5064 // Note: the URL has a username:password in it. The password "baz" is
5065 // wrong (should be "bar").
5066 request.url = GURL("http://foo:baz@www.google.com/");
5068 request.load_flags = LOAD_NORMAL;
5070 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5071 scoped_ptr<HttpTransaction> trans(
5072 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5074 MockWrite data_writes1[] = {
5075 MockWrite("GET / HTTP/1.1\r\n"
5076 "Host: www.google.com\r\n"
5077 "Connection: keep-alive\r\n\r\n"),
5080 MockRead data_reads1[] = {
5081 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5082 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5083 MockRead("Content-Length: 10\r\n\r\n"),
5084 MockRead(SYNCHRONOUS, ERR_FAILED),
5087 // After the challenge above, the transaction will be restarted using the
5088 // identity from the url (foo, baz) to answer the challenge.
5089 MockWrite data_writes2[] = {
5090 MockWrite("GET / HTTP/1.1\r\n"
5091 "Host: www.google.com\r\n"
5092 "Connection: keep-alive\r\n"
5093 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5096 MockRead data_reads2[] = {
5097 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5098 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5099 MockRead("Content-Length: 10\r\n\r\n"),
5100 MockRead(SYNCHRONOUS, ERR_FAILED),
5103 // After the challenge above, the transaction will be restarted using the
5104 // identity supplied by the user (foo, bar) to answer the challenge.
5105 MockWrite data_writes3[] = {
5106 MockWrite("GET / HTTP/1.1\r\n"
5107 "Host: www.google.com\r\n"
5108 "Connection: keep-alive\r\n"
5109 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5112 MockRead data_reads3[] = {
5113 MockRead("HTTP/1.0 200 OK\r\n"),
5114 MockRead("Content-Length: 100\r\n\r\n"),
5115 MockRead(SYNCHRONOUS, OK),
5118 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5119 data_writes1, arraysize(data_writes1));
5120 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5121 data_writes2, arraysize(data_writes2));
5122 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5123 data_writes3, arraysize(data_writes3));
5124 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5125 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5126 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5128 TestCompletionCallback callback1;
5130 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5131 EXPECT_EQ(ERR_IO_PENDING, rv);
5133 rv = callback1.WaitForResult();
5134 EXPECT_EQ(OK, rv);
5136 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5137 TestCompletionCallback callback2;
5138 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5139 EXPECT_EQ(ERR_IO_PENDING, rv);
5140 rv = callback2.WaitForResult();
5141 EXPECT_EQ(OK, rv);
5142 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5144 const HttpResponseInfo* response = trans->GetResponseInfo();
5145 ASSERT_TRUE(response != NULL);
5146 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5148 TestCompletionCallback callback3;
5149 rv = trans->RestartWithAuth(
5150 AuthCredentials(kFoo, kBar), callback3.callback());
5151 EXPECT_EQ(ERR_IO_PENDING, rv);
5152 rv = callback3.WaitForResult();
5153 EXPECT_EQ(OK, rv);
5154 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5156 response = trans->GetResponseInfo();
5157 ASSERT_TRUE(response != NULL);
5159 // There is no challenge info, since the identity worked.
5160 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5162 EXPECT_EQ(100, response->headers->GetContentLength());
5164 // Empty the current queue.
5165 base::MessageLoop::current()->RunUntilIdle();
5169 // Test the request-challenge-retry sequence for basic auth when there is a
5170 // correct identity in the URL, but its use is being suppressed. The identity
5171 // from the URL should never be used.
5172 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5173 HttpRequestInfo request;
5174 request.method = "GET";
5175 request.url = GURL("http://foo:bar@www.google.com/");
5176 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5178 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5179 scoped_ptr<HttpTransaction> trans(
5180 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5182 MockWrite data_writes1[] = {
5183 MockWrite("GET / HTTP/1.1\r\n"
5184 "Host: www.google.com\r\n"
5185 "Connection: keep-alive\r\n\r\n"),
5188 MockRead data_reads1[] = {
5189 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5190 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5191 MockRead("Content-Length: 10\r\n\r\n"),
5192 MockRead(SYNCHRONOUS, ERR_FAILED),
5195 // After the challenge above, the transaction will be restarted using the
5196 // identity supplied by the user, not the one in the URL, to answer the
5197 // challenge.
5198 MockWrite data_writes3[] = {
5199 MockWrite("GET / HTTP/1.1\r\n"
5200 "Host: www.google.com\r\n"
5201 "Connection: keep-alive\r\n"
5202 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5205 MockRead data_reads3[] = {
5206 MockRead("HTTP/1.0 200 OK\r\n"),
5207 MockRead("Content-Length: 100\r\n\r\n"),
5208 MockRead(SYNCHRONOUS, OK),
5211 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5212 data_writes1, arraysize(data_writes1));
5213 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5214 data_writes3, arraysize(data_writes3));
5215 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5216 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5218 TestCompletionCallback callback1;
5219 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5220 EXPECT_EQ(ERR_IO_PENDING, rv);
5221 rv = callback1.WaitForResult();
5222 EXPECT_EQ(OK, rv);
5223 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5225 const HttpResponseInfo* response = trans->GetResponseInfo();
5226 ASSERT_TRUE(response != NULL);
5227 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5229 TestCompletionCallback callback3;
5230 rv = trans->RestartWithAuth(
5231 AuthCredentials(kFoo, kBar), callback3.callback());
5232 EXPECT_EQ(ERR_IO_PENDING, rv);
5233 rv = callback3.WaitForResult();
5234 EXPECT_EQ(OK, rv);
5235 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5237 response = trans->GetResponseInfo();
5238 ASSERT_TRUE(response != NULL);
5240 // There is no challenge info, since the identity worked.
5241 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5242 EXPECT_EQ(100, response->headers->GetContentLength());
5244 // Empty the current queue.
5245 base::MessageLoop::current()->RunUntilIdle();
5248 // Test that previously tried username/passwords for a realm get re-used.
5249 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5250 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5252 // Transaction 1: authenticate (foo, bar) on MyRealm1
5254 HttpRequestInfo request;
5255 request.method = "GET";
5256 request.url = GURL("http://www.google.com/x/y/z");
5257 request.load_flags = 0;
5259 scoped_ptr<HttpTransaction> trans(
5260 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5262 MockWrite data_writes1[] = {
5263 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5264 "Host: www.google.com\r\n"
5265 "Connection: keep-alive\r\n\r\n"),
5268 MockRead data_reads1[] = {
5269 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5270 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5271 MockRead("Content-Length: 10000\r\n\r\n"),
5272 MockRead(SYNCHRONOUS, ERR_FAILED),
5275 // Resend with authorization (username=foo, password=bar)
5276 MockWrite data_writes2[] = {
5277 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5278 "Host: www.google.com\r\n"
5279 "Connection: keep-alive\r\n"
5280 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5283 // Sever accepts the authorization.
5284 MockRead data_reads2[] = {
5285 MockRead("HTTP/1.0 200 OK\r\n"),
5286 MockRead("Content-Length: 100\r\n\r\n"),
5287 MockRead(SYNCHRONOUS, OK),
5290 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5291 data_writes1, arraysize(data_writes1));
5292 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5293 data_writes2, arraysize(data_writes2));
5294 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5295 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5297 TestCompletionCallback callback1;
5299 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5300 EXPECT_EQ(ERR_IO_PENDING, rv);
5302 rv = callback1.WaitForResult();
5303 EXPECT_EQ(OK, rv);
5305 const HttpResponseInfo* response = trans->GetResponseInfo();
5306 ASSERT_TRUE(response != NULL);
5307 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5309 TestCompletionCallback callback2;
5311 rv = trans->RestartWithAuth(
5312 AuthCredentials(kFoo, kBar), callback2.callback());
5313 EXPECT_EQ(ERR_IO_PENDING, rv);
5315 rv = callback2.WaitForResult();
5316 EXPECT_EQ(OK, rv);
5318 response = trans->GetResponseInfo();
5319 ASSERT_TRUE(response != NULL);
5320 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5321 EXPECT_EQ(100, response->headers->GetContentLength());
5324 // ------------------------------------------------------------------------
5326 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5328 HttpRequestInfo request;
5329 request.method = "GET";
5330 // Note that Transaction 1 was at /x/y/z, so this is in the same
5331 // protection space as MyRealm1.
5332 request.url = GURL("http://www.google.com/x/y/a/b");
5333 request.load_flags = 0;
5335 scoped_ptr<HttpTransaction> trans(
5336 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5338 MockWrite data_writes1[] = {
5339 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5340 "Host: www.google.com\r\n"
5341 "Connection: keep-alive\r\n"
5342 // Send preemptive authorization for MyRealm1
5343 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5346 // The server didn't like the preemptive authorization, and
5347 // challenges us for a different realm (MyRealm2).
5348 MockRead data_reads1[] = {
5349 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5350 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5351 MockRead("Content-Length: 10000\r\n\r\n"),
5352 MockRead(SYNCHRONOUS, ERR_FAILED),
5355 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5356 MockWrite data_writes2[] = {
5357 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5358 "Host: www.google.com\r\n"
5359 "Connection: keep-alive\r\n"
5360 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5363 // Sever accepts the authorization.
5364 MockRead data_reads2[] = {
5365 MockRead("HTTP/1.0 200 OK\r\n"),
5366 MockRead("Content-Length: 100\r\n\r\n"),
5367 MockRead(SYNCHRONOUS, OK),
5370 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5371 data_writes1, arraysize(data_writes1));
5372 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5373 data_writes2, arraysize(data_writes2));
5374 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5375 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5377 TestCompletionCallback callback1;
5379 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5380 EXPECT_EQ(ERR_IO_PENDING, rv);
5382 rv = callback1.WaitForResult();
5383 EXPECT_EQ(OK, rv);
5385 const HttpResponseInfo* response = trans->GetResponseInfo();
5386 ASSERT_TRUE(response != NULL);
5387 ASSERT_TRUE(response->auth_challenge.get());
5388 EXPECT_FALSE(response->auth_challenge->is_proxy);
5389 EXPECT_EQ("www.google.com:80",
5390 response->auth_challenge->challenger.ToString());
5391 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5392 EXPECT_EQ("basic", response->auth_challenge->scheme);
5394 TestCompletionCallback callback2;
5396 rv = trans->RestartWithAuth(
5397 AuthCredentials(kFoo2, kBar2), callback2.callback());
5398 EXPECT_EQ(ERR_IO_PENDING, rv);
5400 rv = callback2.WaitForResult();
5401 EXPECT_EQ(OK, rv);
5403 response = trans->GetResponseInfo();
5404 ASSERT_TRUE(response != NULL);
5405 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5406 EXPECT_EQ(100, response->headers->GetContentLength());
5409 // ------------------------------------------------------------------------
5411 // Transaction 3: Resend a request in MyRealm's protection space --
5412 // succeed with preemptive authorization.
5414 HttpRequestInfo request;
5415 request.method = "GET";
5416 request.url = GURL("http://www.google.com/x/y/z2");
5417 request.load_flags = 0;
5419 scoped_ptr<HttpTransaction> trans(
5420 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5422 MockWrite data_writes1[] = {
5423 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5424 "Host: www.google.com\r\n"
5425 "Connection: keep-alive\r\n"
5426 // The authorization for MyRealm1 gets sent preemptively
5427 // (since the url is in the same protection space)
5428 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5431 // Sever accepts the preemptive authorization
5432 MockRead data_reads1[] = {
5433 MockRead("HTTP/1.0 200 OK\r\n"),
5434 MockRead("Content-Length: 100\r\n\r\n"),
5435 MockRead(SYNCHRONOUS, OK),
5438 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5439 data_writes1, arraysize(data_writes1));
5440 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5442 TestCompletionCallback callback1;
5444 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5445 EXPECT_EQ(ERR_IO_PENDING, rv);
5447 rv = callback1.WaitForResult();
5448 EXPECT_EQ(OK, rv);
5450 const HttpResponseInfo* response = trans->GetResponseInfo();
5451 ASSERT_TRUE(response != NULL);
5453 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5454 EXPECT_EQ(100, response->headers->GetContentLength());
5457 // ------------------------------------------------------------------------
5459 // Transaction 4: request another URL in MyRealm (however the
5460 // url is not known to belong to the protection space, so no pre-auth).
5462 HttpRequestInfo request;
5463 request.method = "GET";
5464 request.url = GURL("http://www.google.com/x/1");
5465 request.load_flags = 0;
5467 scoped_ptr<HttpTransaction> trans(
5468 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5470 MockWrite data_writes1[] = {
5471 MockWrite("GET /x/1 HTTP/1.1\r\n"
5472 "Host: www.google.com\r\n"
5473 "Connection: keep-alive\r\n\r\n"),
5476 MockRead data_reads1[] = {
5477 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5478 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5479 MockRead("Content-Length: 10000\r\n\r\n"),
5480 MockRead(SYNCHRONOUS, ERR_FAILED),
5483 // Resend with authorization from MyRealm's cache.
5484 MockWrite data_writes2[] = {
5485 MockWrite("GET /x/1 HTTP/1.1\r\n"
5486 "Host: www.google.com\r\n"
5487 "Connection: keep-alive\r\n"
5488 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5491 // Sever accepts the authorization.
5492 MockRead data_reads2[] = {
5493 MockRead("HTTP/1.0 200 OK\r\n"),
5494 MockRead("Content-Length: 100\r\n\r\n"),
5495 MockRead(SYNCHRONOUS, OK),
5498 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5499 data_writes1, arraysize(data_writes1));
5500 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5501 data_writes2, arraysize(data_writes2));
5502 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5503 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5505 TestCompletionCallback callback1;
5507 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5508 EXPECT_EQ(ERR_IO_PENDING, rv);
5510 rv = callback1.WaitForResult();
5511 EXPECT_EQ(OK, rv);
5513 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5514 TestCompletionCallback callback2;
5515 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5516 EXPECT_EQ(ERR_IO_PENDING, rv);
5517 rv = callback2.WaitForResult();
5518 EXPECT_EQ(OK, rv);
5519 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5521 const HttpResponseInfo* response = trans->GetResponseInfo();
5522 ASSERT_TRUE(response != NULL);
5523 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5524 EXPECT_EQ(100, response->headers->GetContentLength());
5527 // ------------------------------------------------------------------------
5529 // Transaction 5: request a URL in MyRealm, but the server rejects the
5530 // cached identity. Should invalidate and re-prompt.
5532 HttpRequestInfo request;
5533 request.method = "GET";
5534 request.url = GURL("http://www.google.com/p/q/t");
5535 request.load_flags = 0;
5537 scoped_ptr<HttpTransaction> trans(
5538 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5540 MockWrite data_writes1[] = {
5541 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5542 "Host: www.google.com\r\n"
5543 "Connection: keep-alive\r\n\r\n"),
5546 MockRead data_reads1[] = {
5547 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5548 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5549 MockRead("Content-Length: 10000\r\n\r\n"),
5550 MockRead(SYNCHRONOUS, ERR_FAILED),
5553 // Resend with authorization from cache for MyRealm.
5554 MockWrite data_writes2[] = {
5555 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5556 "Host: www.google.com\r\n"
5557 "Connection: keep-alive\r\n"
5558 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5561 // Sever rejects the authorization.
5562 MockRead data_reads2[] = {
5563 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5564 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5565 MockRead("Content-Length: 10000\r\n\r\n"),
5566 MockRead(SYNCHRONOUS, ERR_FAILED),
5569 // At this point we should prompt for new credentials for MyRealm.
5570 // Restart with username=foo3, password=foo4.
5571 MockWrite data_writes3[] = {
5572 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5573 "Host: www.google.com\r\n"
5574 "Connection: keep-alive\r\n"
5575 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5578 // Sever accepts the authorization.
5579 MockRead data_reads3[] = {
5580 MockRead("HTTP/1.0 200 OK\r\n"),
5581 MockRead("Content-Length: 100\r\n\r\n"),
5582 MockRead(SYNCHRONOUS, OK),
5585 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5586 data_writes1, arraysize(data_writes1));
5587 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5588 data_writes2, arraysize(data_writes2));
5589 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5590 data_writes3, arraysize(data_writes3));
5591 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5592 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5593 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5595 TestCompletionCallback callback1;
5597 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5598 EXPECT_EQ(ERR_IO_PENDING, rv);
5600 rv = callback1.WaitForResult();
5601 EXPECT_EQ(OK, rv);
5603 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5604 TestCompletionCallback callback2;
5605 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5606 EXPECT_EQ(ERR_IO_PENDING, rv);
5607 rv = callback2.WaitForResult();
5608 EXPECT_EQ(OK, rv);
5609 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5611 const HttpResponseInfo* response = trans->GetResponseInfo();
5612 ASSERT_TRUE(response != NULL);
5613 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5615 TestCompletionCallback callback3;
5617 rv = trans->RestartWithAuth(
5618 AuthCredentials(kFoo3, kBar3), callback3.callback());
5619 EXPECT_EQ(ERR_IO_PENDING, rv);
5621 rv = callback3.WaitForResult();
5622 EXPECT_EQ(OK, rv);
5624 response = trans->GetResponseInfo();
5625 ASSERT_TRUE(response != NULL);
5626 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5627 EXPECT_EQ(100, response->headers->GetContentLength());
5631 // Tests that nonce count increments when multiple auth attempts
5632 // are started with the same nonce.
5633 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5634 HttpAuthHandlerDigest::Factory* digest_factory =
5635 new HttpAuthHandlerDigest::Factory();
5636 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5637 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5638 digest_factory->set_nonce_generator(nonce_generator);
5639 session_deps_.http_auth_handler_factory.reset(digest_factory);
5640 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5642 // Transaction 1: authenticate (foo, bar) on MyRealm1
5644 HttpRequestInfo request;
5645 request.method = "GET";
5646 request.url = GURL("http://www.google.com/x/y/z");
5647 request.load_flags = 0;
5649 scoped_ptr<HttpTransaction> trans(
5650 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5652 MockWrite data_writes1[] = {
5653 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5654 "Host: www.google.com\r\n"
5655 "Connection: keep-alive\r\n\r\n"),
5658 MockRead data_reads1[] = {
5659 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5660 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5661 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5662 MockRead(SYNCHRONOUS, OK),
5665 // Resend with authorization (username=foo, password=bar)
5666 MockWrite data_writes2[] = {
5667 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5668 "Host: www.google.com\r\n"
5669 "Connection: keep-alive\r\n"
5670 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5671 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5672 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5673 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5676 // Sever accepts the authorization.
5677 MockRead data_reads2[] = {
5678 MockRead("HTTP/1.0 200 OK\r\n"),
5679 MockRead(SYNCHRONOUS, OK),
5682 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5683 data_writes1, arraysize(data_writes1));
5684 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5685 data_writes2, arraysize(data_writes2));
5686 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5687 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5689 TestCompletionCallback callback1;
5691 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5692 EXPECT_EQ(ERR_IO_PENDING, rv);
5694 rv = callback1.WaitForResult();
5695 EXPECT_EQ(OK, rv);
5697 const HttpResponseInfo* response = trans->GetResponseInfo();
5698 ASSERT_TRUE(response != NULL);
5699 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5701 TestCompletionCallback callback2;
5703 rv = trans->RestartWithAuth(
5704 AuthCredentials(kFoo, kBar), callback2.callback());
5705 EXPECT_EQ(ERR_IO_PENDING, rv);
5707 rv = callback2.WaitForResult();
5708 EXPECT_EQ(OK, rv);
5710 response = trans->GetResponseInfo();
5711 ASSERT_TRUE(response != NULL);
5712 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5715 // ------------------------------------------------------------------------
5717 // Transaction 2: Request another resource in digestive's protection space.
5718 // This will preemptively add an Authorization header which should have an
5719 // "nc" value of 2 (as compared to 1 in the first use.
5721 HttpRequestInfo request;
5722 request.method = "GET";
5723 // Note that Transaction 1 was at /x/y/z, so this is in the same
5724 // protection space as digest.
5725 request.url = GURL("http://www.google.com/x/y/a/b");
5726 request.load_flags = 0;
5728 scoped_ptr<HttpTransaction> trans(
5729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5731 MockWrite data_writes1[] = {
5732 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5733 "Host: www.google.com\r\n"
5734 "Connection: keep-alive\r\n"
5735 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5736 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5737 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5738 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5741 // Sever accepts the authorization.
5742 MockRead data_reads1[] = {
5743 MockRead("HTTP/1.0 200 OK\r\n"),
5744 MockRead("Content-Length: 100\r\n\r\n"),
5745 MockRead(SYNCHRONOUS, OK),
5748 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5749 data_writes1, arraysize(data_writes1));
5750 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5752 TestCompletionCallback callback1;
5754 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5755 EXPECT_EQ(ERR_IO_PENDING, rv);
5757 rv = callback1.WaitForResult();
5758 EXPECT_EQ(OK, rv);
5760 const HttpResponseInfo* response = trans->GetResponseInfo();
5761 ASSERT_TRUE(response != NULL);
5762 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5766 // Test the ResetStateForRestart() private method.
5767 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5768 // Create a transaction (the dependencies aren't important).
5769 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5770 scoped_ptr<HttpNetworkTransaction> trans(
5771 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5773 // Setup some state (which we expect ResetStateForRestart() will clear).
5774 trans->read_buf_ = new IOBuffer(15);
5775 trans->read_buf_len_ = 15;
5776 trans->request_headers_.SetHeader("Authorization", "NTLM");
5778 // Setup state in response_
5779 HttpResponseInfo* response = &trans->response_;
5780 response->auth_challenge = new AuthChallengeInfo();
5781 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
5782 response->response_time = base::Time::Now();
5783 response->was_cached = true; // (Wouldn't ever actually be true...)
5785 { // Setup state for response_.vary_data
5786 HttpRequestInfo request;
5787 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5788 std::replace(temp.begin(), temp.end(), '\n', '\0');
5789 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5790 request.extra_headers.SetHeader("Foo", "1");
5791 request.extra_headers.SetHeader("bar", "23");
5792 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5795 // Cause the above state to be reset.
5796 trans->ResetStateForRestart();
5798 // Verify that the state that needed to be reset, has been reset.
5799 EXPECT_TRUE(trans->read_buf_.get() == NULL);
5800 EXPECT_EQ(0, trans->read_buf_len_);
5801 EXPECT_TRUE(trans->request_headers_.IsEmpty());
5802 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5803 EXPECT_TRUE(response->headers.get() == NULL);
5804 EXPECT_FALSE(response->was_cached);
5805 EXPECT_EQ(0U, response->ssl_info.cert_status);
5806 EXPECT_FALSE(response->vary_data.is_valid());
5809 // Test HTTPS connections to a site with a bad certificate
5810 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5811 HttpRequestInfo request;
5812 request.method = "GET";
5813 request.url = GURL("https://www.google.com/");
5814 request.load_flags = 0;
5816 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5817 scoped_ptr<HttpTransaction> trans(
5818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5820 MockWrite data_writes[] = {
5821 MockWrite("GET / HTTP/1.1\r\n"
5822 "Host: www.google.com\r\n"
5823 "Connection: keep-alive\r\n\r\n"),
5826 MockRead data_reads[] = {
5827 MockRead("HTTP/1.0 200 OK\r\n"),
5828 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5829 MockRead("Content-Length: 100\r\n\r\n"),
5830 MockRead(SYNCHRONOUS, OK),
5833 StaticSocketDataProvider ssl_bad_certificate;
5834 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5835 data_writes, arraysize(data_writes));
5836 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5837 SSLSocketDataProvider ssl(ASYNC, OK);
5839 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5840 session_deps_.socket_factory->AddSocketDataProvider(&data);
5841 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5842 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5844 TestCompletionCallback callback;
5846 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5847 EXPECT_EQ(ERR_IO_PENDING, rv);
5849 rv = callback.WaitForResult();
5850 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5852 rv = trans->RestartIgnoringLastError(callback.callback());
5853 EXPECT_EQ(ERR_IO_PENDING, rv);
5855 rv = callback.WaitForResult();
5856 EXPECT_EQ(OK, rv);
5858 const HttpResponseInfo* response = trans->GetResponseInfo();
5860 ASSERT_TRUE(response != NULL);
5861 EXPECT_EQ(100, response->headers->GetContentLength());
5864 // Test HTTPS connections to a site with a bad certificate, going through a
5865 // proxy
5866 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5867 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5869 HttpRequestInfo request;
5870 request.method = "GET";
5871 request.url = GURL("https://www.google.com/");
5872 request.load_flags = 0;
5874 MockWrite proxy_writes[] = {
5875 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5876 "Host: www.google.com\r\n"
5877 "Proxy-Connection: keep-alive\r\n\r\n"),
5880 MockRead proxy_reads[] = {
5881 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5882 MockRead(SYNCHRONOUS, OK)
5885 MockWrite data_writes[] = {
5886 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5887 "Host: www.google.com\r\n"
5888 "Proxy-Connection: keep-alive\r\n\r\n"),
5889 MockWrite("GET / HTTP/1.1\r\n"
5890 "Host: www.google.com\r\n"
5891 "Connection: keep-alive\r\n\r\n"),
5894 MockRead data_reads[] = {
5895 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5896 MockRead("HTTP/1.0 200 OK\r\n"),
5897 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5898 MockRead("Content-Length: 100\r\n\r\n"),
5899 MockRead(SYNCHRONOUS, OK),
5902 StaticSocketDataProvider ssl_bad_certificate(
5903 proxy_reads, arraysize(proxy_reads),
5904 proxy_writes, arraysize(proxy_writes));
5905 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5906 data_writes, arraysize(data_writes));
5907 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5908 SSLSocketDataProvider ssl(ASYNC, OK);
5910 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5911 session_deps_.socket_factory->AddSocketDataProvider(&data);
5912 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5913 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5915 TestCompletionCallback callback;
5917 for (int i = 0; i < 2; i++) {
5918 session_deps_.socket_factory->ResetNextMockIndexes();
5920 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5921 scoped_ptr<HttpTransaction> trans(
5922 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5924 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5925 EXPECT_EQ(ERR_IO_PENDING, rv);
5927 rv = callback.WaitForResult();
5928 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5930 rv = trans->RestartIgnoringLastError(callback.callback());
5931 EXPECT_EQ(ERR_IO_PENDING, rv);
5933 rv = callback.WaitForResult();
5934 EXPECT_EQ(OK, rv);
5936 const HttpResponseInfo* response = trans->GetResponseInfo();
5938 ASSERT_TRUE(response != NULL);
5939 EXPECT_EQ(100, response->headers->GetContentLength());
5944 // Test HTTPS connections to a site, going through an HTTPS proxy
5945 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
5946 session_deps_.proxy_service.reset(
5947 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5948 CapturingNetLog net_log;
5949 session_deps_.net_log = &net_log;
5951 HttpRequestInfo request;
5952 request.method = "GET";
5953 request.url = GURL("https://www.google.com/");
5954 request.load_flags = 0;
5956 MockWrite data_writes[] = {
5957 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5958 "Host: www.google.com\r\n"
5959 "Proxy-Connection: keep-alive\r\n\r\n"),
5960 MockWrite("GET / HTTP/1.1\r\n"
5961 "Host: www.google.com\r\n"
5962 "Connection: keep-alive\r\n\r\n"),
5965 MockRead data_reads[] = {
5966 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5967 MockRead("HTTP/1.1 200 OK\r\n"),
5968 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5969 MockRead("Content-Length: 100\r\n\r\n"),
5970 MockRead(SYNCHRONOUS, OK),
5973 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5974 data_writes, arraysize(data_writes));
5975 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5976 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
5978 session_deps_.socket_factory->AddSocketDataProvider(&data);
5979 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5980 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
5982 TestCompletionCallback callback;
5984 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5985 scoped_ptr<HttpTransaction> trans(
5986 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5988 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5989 EXPECT_EQ(ERR_IO_PENDING, rv);
5991 rv = callback.WaitForResult();
5992 EXPECT_EQ(OK, rv);
5993 const HttpResponseInfo* response = trans->GetResponseInfo();
5995 ASSERT_TRUE(response != NULL);
5997 EXPECT_TRUE(response->headers->IsKeepAlive());
5998 EXPECT_EQ(200, response->headers->response_code());
5999 EXPECT_EQ(100, response->headers->GetContentLength());
6000 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6002 LoadTimingInfo load_timing_info;
6003 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6004 TestLoadTimingNotReusedWithPac(load_timing_info,
6005 CONNECT_TIMING_HAS_SSL_TIMES);
6008 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6009 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6010 session_deps_.proxy_service.reset(
6011 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6012 CapturingNetLog net_log;
6013 session_deps_.net_log = &net_log;
6015 HttpRequestInfo request;
6016 request.method = "GET";
6017 request.url = GURL("https://www.google.com/");
6018 request.load_flags = 0;
6020 MockWrite data_writes[] = {
6021 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6022 "Host: www.google.com\r\n"
6023 "Proxy-Connection: keep-alive\r\n\r\n"),
6026 MockRead data_reads[] = {
6027 MockRead("HTTP/1.1 302 Redirect\r\n"),
6028 MockRead("Location: http://login.example.com/\r\n"),
6029 MockRead("Content-Length: 0\r\n\r\n"),
6030 MockRead(SYNCHRONOUS, OK),
6033 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6034 data_writes, arraysize(data_writes));
6035 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6037 session_deps_.socket_factory->AddSocketDataProvider(&data);
6038 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6040 TestCompletionCallback callback;
6042 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6043 scoped_ptr<HttpTransaction> trans(
6044 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6046 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6047 EXPECT_EQ(ERR_IO_PENDING, rv);
6049 rv = callback.WaitForResult();
6050 EXPECT_EQ(OK, rv);
6051 const HttpResponseInfo* response = trans->GetResponseInfo();
6053 ASSERT_TRUE(response != NULL);
6055 EXPECT_EQ(302, response->headers->response_code());
6056 std::string url;
6057 EXPECT_TRUE(response->headers->IsRedirect(&url));
6058 EXPECT_EQ("http://login.example.com/", url);
6060 // In the case of redirects from proxies, HttpNetworkTransaction returns
6061 // timing for the proxy connection instead of the connection to the host,
6062 // and no send / receive times.
6063 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6064 LoadTimingInfo load_timing_info;
6065 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6067 EXPECT_FALSE(load_timing_info.socket_reused);
6068 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6070 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6071 EXPECT_LE(load_timing_info.proxy_resolve_start,
6072 load_timing_info.proxy_resolve_end);
6073 EXPECT_LE(load_timing_info.proxy_resolve_end,
6074 load_timing_info.connect_timing.connect_start);
6075 ExpectConnectTimingHasTimes(
6076 load_timing_info.connect_timing,
6077 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6079 EXPECT_TRUE(load_timing_info.send_start.is_null());
6080 EXPECT_TRUE(load_timing_info.send_end.is_null());
6081 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6084 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6085 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6086 session_deps_.proxy_service.reset(
6087 ProxyService::CreateFixed("https://proxy:70"));
6089 HttpRequestInfo request;
6090 request.method = "GET";
6091 request.url = GURL("https://www.google.com/");
6092 request.load_flags = 0;
6094 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6095 LOWEST));
6096 scoped_ptr<SpdyFrame> goaway(
6097 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6098 MockWrite data_writes[] = {
6099 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6100 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
6103 static const char* const kExtraHeaders[] = {
6104 "location",
6105 "http://login.example.com/",
6107 scoped_ptr<SpdyFrame> resp(
6108 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6109 arraysize(kExtraHeaders)/2, 1));
6110 MockRead data_reads[] = {
6111 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6112 MockRead(ASYNC, 0, 2), // EOF
6115 DelayedSocketData data(
6116 1, // wait for one write to finish before reading.
6117 data_reads, arraysize(data_reads),
6118 data_writes, arraysize(data_writes));
6119 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6120 proxy_ssl.SetNextProto(GetParam());
6122 session_deps_.socket_factory->AddSocketDataProvider(&data);
6123 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6125 TestCompletionCallback callback;
6127 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6128 scoped_ptr<HttpTransaction> trans(
6129 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6131 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6132 EXPECT_EQ(ERR_IO_PENDING, rv);
6134 rv = callback.WaitForResult();
6135 EXPECT_EQ(OK, rv);
6136 const HttpResponseInfo* response = trans->GetResponseInfo();
6138 ASSERT_TRUE(response != NULL);
6140 EXPECT_EQ(302, response->headers->response_code());
6141 std::string url;
6142 EXPECT_TRUE(response->headers->IsRedirect(&url));
6143 EXPECT_EQ("http://login.example.com/", url);
6146 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6147 TEST_P(HttpNetworkTransactionTest,
6148 ErrorResponseToHttpsConnectViaHttpsProxy) {
6149 session_deps_.proxy_service.reset(
6150 ProxyService::CreateFixed("https://proxy:70"));
6152 HttpRequestInfo request;
6153 request.method = "GET";
6154 request.url = GURL("https://www.google.com/");
6155 request.load_flags = 0;
6157 MockWrite data_writes[] = {
6158 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6159 "Host: www.google.com\r\n"
6160 "Proxy-Connection: keep-alive\r\n\r\n"),
6163 MockRead data_reads[] = {
6164 MockRead("HTTP/1.1 404 Not Found\r\n"),
6165 MockRead("Content-Length: 23\r\n\r\n"),
6166 MockRead("The host does not exist"),
6167 MockRead(SYNCHRONOUS, OK),
6170 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6171 data_writes, arraysize(data_writes));
6172 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6174 session_deps_.socket_factory->AddSocketDataProvider(&data);
6175 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6177 TestCompletionCallback callback;
6179 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6180 scoped_ptr<HttpTransaction> trans(
6181 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6183 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6184 EXPECT_EQ(ERR_IO_PENDING, rv);
6186 rv = callback.WaitForResult();
6187 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6189 // TODO(ttuttle): Anything else to check here?
6192 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6193 TEST_P(HttpNetworkTransactionTest,
6194 ErrorResponseToHttpsConnectViaSpdyProxy) {
6195 session_deps_.proxy_service.reset(
6196 ProxyService::CreateFixed("https://proxy:70"));
6198 HttpRequestInfo request;
6199 request.method = "GET";
6200 request.url = GURL("https://www.google.com/");
6201 request.load_flags = 0;
6203 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6204 LOWEST));
6205 scoped_ptr<SpdyFrame> rst(
6206 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6207 MockWrite data_writes[] = {
6208 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6209 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6212 static const char* const kExtraHeaders[] = {
6213 "location",
6214 "http://login.example.com/",
6216 scoped_ptr<SpdyFrame> resp(
6217 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6218 arraysize(kExtraHeaders)/2, 1));
6219 scoped_ptr<SpdyFrame> body(
6220 spdy_util_.ConstructSpdyBodyFrame(
6221 1, "The host does not exist", 23, true));
6222 MockRead data_reads[] = {
6223 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6224 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6225 MockRead(ASYNC, 0, 4), // EOF
6228 DelayedSocketData data(
6229 1, // wait for one write to finish before reading.
6230 data_reads, arraysize(data_reads),
6231 data_writes, arraysize(data_writes));
6232 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6233 proxy_ssl.SetNextProto(GetParam());
6235 session_deps_.socket_factory->AddSocketDataProvider(&data);
6236 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6238 TestCompletionCallback callback;
6240 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6241 scoped_ptr<HttpTransaction> trans(
6242 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6244 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6245 EXPECT_EQ(ERR_IO_PENDING, rv);
6247 rv = callback.WaitForResult();
6248 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6250 // TODO(ttuttle): Anything else to check here?
6253 // Test the request-challenge-retry sequence for basic auth, through
6254 // a SPDY proxy over a single SPDY session.
6255 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6256 HttpRequestInfo request;
6257 request.method = "GET";
6258 request.url = GURL("https://www.google.com/");
6259 // when the no authentication data flag is set.
6260 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
6262 // Configure against https proxy server "myproxy:70".
6263 session_deps_.proxy_service.reset(
6264 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6265 CapturingBoundNetLog log;
6266 session_deps_.net_log = log.bound().net_log();
6267 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6269 // Since we have proxy, should try to establish tunnel.
6270 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6271 LOWEST));
6272 scoped_ptr<SpdyFrame> rst(
6273 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6275 // After calling trans->RestartWithAuth(), this is the request we should
6276 // be issuing -- the final header line contains the credentials.
6277 const char* const kAuthCredentials[] = {
6278 "proxy-authorization", "Basic Zm9vOmJhcg==",
6280 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6281 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
6282 // fetch https://www.google.com/ via HTTP
6283 const char get[] = "GET / HTTP/1.1\r\n"
6284 "Host: www.google.com\r\n"
6285 "Connection: keep-alive\r\n\r\n";
6286 scoped_ptr<SpdyFrame> wrapped_get(
6287 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6289 MockWrite spdy_writes[] = {
6290 CreateMockWrite(*req, 1, ASYNC),
6291 CreateMockWrite(*rst, 4, ASYNC),
6292 CreateMockWrite(*connect2, 5),
6293 CreateMockWrite(*wrapped_get, 8),
6296 // The proxy responds to the connect with a 407, using a persistent
6297 // connection.
6298 const char* const kAuthChallenge[] = {
6299 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
6300 spdy_util_.GetVersionKey(), "HTTP/1.1",
6301 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6304 scoped_ptr<SpdyFrame> conn_auth_resp(
6305 spdy_util_.ConstructSpdyControlFrame(NULL,
6307 false,
6309 LOWEST,
6310 SYN_REPLY,
6311 CONTROL_FLAG_NONE,
6312 kAuthChallenge,
6313 arraysize(kAuthChallenge),
6314 0));
6316 scoped_ptr<SpdyFrame> conn_resp(
6317 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6318 const char resp[] = "HTTP/1.1 200 OK\r\n"
6319 "Content-Length: 5\r\n\r\n";
6321 scoped_ptr<SpdyFrame> wrapped_get_resp(
6322 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6323 scoped_ptr<SpdyFrame> wrapped_body(
6324 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6325 MockRead spdy_reads[] = {
6326 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6327 CreateMockRead(*conn_resp, 6, ASYNC),
6328 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6329 CreateMockRead(*wrapped_body, 10, ASYNC),
6330 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6333 OrderedSocketData spdy_data(
6334 spdy_reads, arraysize(spdy_reads),
6335 spdy_writes, arraysize(spdy_writes));
6336 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6337 // Negotiate SPDY to the proxy
6338 SSLSocketDataProvider proxy(ASYNC, OK);
6339 proxy.SetNextProto(GetParam());
6340 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6341 // Vanilla SSL to the server
6342 SSLSocketDataProvider server(ASYNC, OK);
6343 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6345 TestCompletionCallback callback1;
6347 scoped_ptr<HttpTransaction> trans(
6348 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6350 int rv = trans->Start(&request, callback1.callback(), log.bound());
6351 EXPECT_EQ(ERR_IO_PENDING, rv);
6353 rv = callback1.WaitForResult();
6354 EXPECT_EQ(OK, rv);
6355 net::CapturingNetLog::CapturedEntryList entries;
6356 log.GetEntries(&entries);
6357 size_t pos = ExpectLogContainsSomewhere(
6358 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6359 NetLog::PHASE_NONE);
6360 ExpectLogContainsSomewhere(
6361 entries, pos,
6362 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6363 NetLog::PHASE_NONE);
6365 const HttpResponseInfo* response = trans->GetResponseInfo();
6366 ASSERT_TRUE(response != NULL);
6367 ASSERT_FALSE(response->headers.get() == NULL);
6368 EXPECT_EQ(407, response->headers->response_code());
6369 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6370 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6371 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6373 TestCompletionCallback callback2;
6375 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6376 callback2.callback());
6377 EXPECT_EQ(ERR_IO_PENDING, rv);
6379 rv = callback2.WaitForResult();
6380 EXPECT_EQ(OK, rv);
6382 response = trans->GetResponseInfo();
6383 ASSERT_TRUE(response != NULL);
6385 EXPECT_TRUE(response->headers->IsKeepAlive());
6386 EXPECT_EQ(200, response->headers->response_code());
6387 EXPECT_EQ(5, response->headers->GetContentLength());
6388 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6390 // The password prompt info should not be set.
6391 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6393 LoadTimingInfo load_timing_info;
6394 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6395 TestLoadTimingNotReusedWithPac(load_timing_info,
6396 CONNECT_TIMING_HAS_SSL_TIMES);
6398 trans.reset();
6399 session->CloseAllConnections();
6402 // Test that an explicitly trusted SPDY proxy can push a resource from an
6403 // origin that is different from that of its associated resource.
6404 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6405 HttpRequestInfo request;
6406 HttpRequestInfo push_request;
6408 request.method = "GET";
6409 request.url = GURL("http://www.google.com/");
6410 push_request.method = "GET";
6411 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6413 // Configure against https proxy server "myproxy:70".
6414 session_deps_.proxy_service.reset(
6415 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6416 CapturingBoundNetLog log;
6417 session_deps_.net_log = log.bound().net_log();
6419 // Enable cross-origin push.
6420 session_deps_.trusted_spdy_proxy = "myproxy:70";
6422 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6424 scoped_ptr<SpdyFrame> stream1_syn(
6425 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6427 MockWrite spdy_writes[] = {
6428 CreateMockWrite(*stream1_syn, 1, ASYNC),
6431 scoped_ptr<SpdyFrame>
6432 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6434 scoped_ptr<SpdyFrame>
6435 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6437 scoped_ptr<SpdyFrame>
6438 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6442 "http://www.another-origin.com/foo.dat"));
6443 const char kPushedData[] = "pushed";
6444 scoped_ptr<SpdyFrame> stream2_body(
6445 spdy_util_.ConstructSpdyBodyFrame(
6446 2, kPushedData, strlen(kPushedData), true));
6448 MockRead spdy_reads[] = {
6449 CreateMockRead(*stream1_reply, 2, ASYNC),
6450 CreateMockRead(*stream2_syn, 3, ASYNC),
6451 CreateMockRead(*stream1_body, 4, ASYNC),
6452 CreateMockRead(*stream2_body, 5, ASYNC),
6453 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6456 OrderedSocketData spdy_data(
6457 spdy_reads, arraysize(spdy_reads),
6458 spdy_writes, arraysize(spdy_writes));
6459 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6460 // Negotiate SPDY to the proxy
6461 SSLSocketDataProvider proxy(ASYNC, OK);
6462 proxy.SetNextProto(GetParam());
6463 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6465 scoped_ptr<HttpTransaction> trans(
6466 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6467 TestCompletionCallback callback;
6468 int rv = trans->Start(&request, callback.callback(), log.bound());
6469 EXPECT_EQ(ERR_IO_PENDING, rv);
6471 rv = callback.WaitForResult();
6472 EXPECT_EQ(OK, rv);
6473 const HttpResponseInfo* response = trans->GetResponseInfo();
6475 scoped_ptr<HttpTransaction> push_trans(
6476 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6477 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6478 EXPECT_EQ(ERR_IO_PENDING, rv);
6480 rv = callback.WaitForResult();
6481 EXPECT_EQ(OK, rv);
6482 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6484 ASSERT_TRUE(response != NULL);
6485 EXPECT_TRUE(response->headers->IsKeepAlive());
6487 EXPECT_EQ(200, response->headers->response_code());
6488 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6490 std::string response_data;
6491 rv = ReadTransaction(trans.get(), &response_data);
6492 EXPECT_EQ(OK, rv);
6493 EXPECT_EQ("hello!", response_data);
6495 LoadTimingInfo load_timing_info;
6496 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6497 TestLoadTimingNotReusedWithPac(load_timing_info,
6498 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6500 // Verify the pushed stream.
6501 EXPECT_TRUE(push_response->headers.get() != NULL);
6502 EXPECT_EQ(200, push_response->headers->response_code());
6504 rv = ReadTransaction(push_trans.get(), &response_data);
6505 EXPECT_EQ(OK, rv);
6506 EXPECT_EQ("pushed", response_data);
6508 LoadTimingInfo push_load_timing_info;
6509 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6510 TestLoadTimingReusedWithPac(push_load_timing_info);
6511 // The transactions should share a socket ID, despite being for different
6512 // origins.
6513 EXPECT_EQ(load_timing_info.socket_log_id,
6514 push_load_timing_info.socket_log_id);
6516 trans.reset();
6517 push_trans.reset();
6518 session->CloseAllConnections();
6521 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6522 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6523 HttpRequestInfo request;
6525 request.method = "GET";
6526 request.url = GURL("http://www.google.com/");
6528 // Configure against https proxy server "myproxy:70".
6529 session_deps_.proxy_service.reset(
6530 ProxyService::CreateFixed("https://myproxy:70"));
6531 CapturingBoundNetLog log;
6532 session_deps_.net_log = log.bound().net_log();
6534 // Enable cross-origin push.
6535 session_deps_.trusted_spdy_proxy = "myproxy:70";
6537 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6539 scoped_ptr<SpdyFrame> stream1_syn(
6540 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6542 scoped_ptr<SpdyFrame> push_rst(
6543 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6545 MockWrite spdy_writes[] = {
6546 CreateMockWrite(*stream1_syn, 1, ASYNC),
6547 CreateMockWrite(*push_rst, 4),
6550 scoped_ptr<SpdyFrame>
6551 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6553 scoped_ptr<SpdyFrame>
6554 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6556 scoped_ptr<SpdyFrame>
6557 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6561 "https://www.another-origin.com/foo.dat"));
6563 MockRead spdy_reads[] = {
6564 CreateMockRead(*stream1_reply, 2, ASYNC),
6565 CreateMockRead(*stream2_syn, 3, ASYNC),
6566 CreateMockRead(*stream1_body, 5, ASYNC),
6567 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6570 OrderedSocketData spdy_data(
6571 spdy_reads, arraysize(spdy_reads),
6572 spdy_writes, arraysize(spdy_writes));
6573 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6574 // Negotiate SPDY to the proxy
6575 SSLSocketDataProvider proxy(ASYNC, OK);
6576 proxy.SetNextProto(GetParam());
6577 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6579 scoped_ptr<HttpTransaction> trans(
6580 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6581 TestCompletionCallback callback;
6582 int rv = trans->Start(&request, callback.callback(), log.bound());
6583 EXPECT_EQ(ERR_IO_PENDING, rv);
6585 rv = callback.WaitForResult();
6586 EXPECT_EQ(OK, rv);
6587 const HttpResponseInfo* response = trans->GetResponseInfo();
6589 ASSERT_TRUE(response != NULL);
6590 EXPECT_TRUE(response->headers->IsKeepAlive());
6592 EXPECT_EQ(200, response->headers->response_code());
6593 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6595 std::string response_data;
6596 rv = ReadTransaction(trans.get(), &response_data);
6597 EXPECT_EQ(OK, rv);
6598 EXPECT_EQ("hello!", response_data);
6600 trans.reset();
6601 session->CloseAllConnections();
6604 // Test HTTPS connections to a site with a bad certificate, going through an
6605 // HTTPS proxy
6606 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6607 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6608 "https://proxy:70"));
6610 HttpRequestInfo request;
6611 request.method = "GET";
6612 request.url = GURL("https://www.google.com/");
6613 request.load_flags = 0;
6615 // Attempt to fetch the URL from a server with a bad cert
6616 MockWrite bad_cert_writes[] = {
6617 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6618 "Host: www.google.com\r\n"
6619 "Proxy-Connection: keep-alive\r\n\r\n"),
6622 MockRead bad_cert_reads[] = {
6623 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6624 MockRead(SYNCHRONOUS, OK)
6627 // Attempt to fetch the URL with a good cert
6628 MockWrite good_data_writes[] = {
6629 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6630 "Host: www.google.com\r\n"
6631 "Proxy-Connection: keep-alive\r\n\r\n"),
6632 MockWrite("GET / HTTP/1.1\r\n"
6633 "Host: www.google.com\r\n"
6634 "Connection: keep-alive\r\n\r\n"),
6637 MockRead good_cert_reads[] = {
6638 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6639 MockRead("HTTP/1.0 200 OK\r\n"),
6640 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6641 MockRead("Content-Length: 100\r\n\r\n"),
6642 MockRead(SYNCHRONOUS, OK),
6645 StaticSocketDataProvider ssl_bad_certificate(
6646 bad_cert_reads, arraysize(bad_cert_reads),
6647 bad_cert_writes, arraysize(bad_cert_writes));
6648 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6649 good_data_writes, arraysize(good_data_writes));
6650 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6651 SSLSocketDataProvider ssl(ASYNC, OK);
6653 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6654 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6655 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6656 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6658 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6659 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6660 session_deps_.socket_factory->AddSocketDataProvider(&data);
6661 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6663 TestCompletionCallback callback;
6665 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6666 scoped_ptr<HttpTransaction> trans(
6667 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6669 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6670 EXPECT_EQ(ERR_IO_PENDING, rv);
6672 rv = callback.WaitForResult();
6673 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6675 rv = trans->RestartIgnoringLastError(callback.callback());
6676 EXPECT_EQ(ERR_IO_PENDING, rv);
6678 rv = callback.WaitForResult();
6679 EXPECT_EQ(OK, rv);
6681 const HttpResponseInfo* response = trans->GetResponseInfo();
6683 ASSERT_TRUE(response != NULL);
6684 EXPECT_EQ(100, response->headers->GetContentLength());
6687 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6688 HttpRequestInfo request;
6689 request.method = "GET";
6690 request.url = GURL("http://www.google.com/");
6691 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6692 "Chromium Ultra Awesome X Edition");
6694 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6695 scoped_ptr<HttpTransaction> trans(
6696 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6698 MockWrite data_writes[] = {
6699 MockWrite("GET / HTTP/1.1\r\n"
6700 "Host: www.google.com\r\n"
6701 "Connection: keep-alive\r\n"
6702 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6705 // Lastly, the server responds with the actual content.
6706 MockRead data_reads[] = {
6707 MockRead("HTTP/1.0 200 OK\r\n"),
6708 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6709 MockRead("Content-Length: 100\r\n\r\n"),
6710 MockRead(SYNCHRONOUS, OK),
6713 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6714 data_writes, arraysize(data_writes));
6715 session_deps_.socket_factory->AddSocketDataProvider(&data);
6717 TestCompletionCallback callback;
6719 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6720 EXPECT_EQ(ERR_IO_PENDING, rv);
6722 rv = callback.WaitForResult();
6723 EXPECT_EQ(OK, rv);
6726 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6727 HttpRequestInfo request;
6728 request.method = "GET";
6729 request.url = GURL("https://www.google.com/");
6730 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6731 "Chromium Ultra Awesome X Edition");
6733 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6734 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6735 scoped_ptr<HttpTransaction> trans(
6736 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6738 MockWrite data_writes[] = {
6739 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6740 "Host: www.google.com\r\n"
6741 "Proxy-Connection: keep-alive\r\n"
6742 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6744 MockRead data_reads[] = {
6745 // Return an error, so the transaction stops here (this test isn't
6746 // interested in the rest).
6747 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6748 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6749 MockRead("Proxy-Connection: close\r\n\r\n"),
6752 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6753 data_writes, arraysize(data_writes));
6754 session_deps_.socket_factory->AddSocketDataProvider(&data);
6756 TestCompletionCallback callback;
6758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6759 EXPECT_EQ(ERR_IO_PENDING, rv);
6761 rv = callback.WaitForResult();
6762 EXPECT_EQ(OK, rv);
6765 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6766 HttpRequestInfo request;
6767 request.method = "GET";
6768 request.url = GURL("http://www.google.com/");
6769 request.load_flags = 0;
6770 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6771 "http://the.previous.site.com/");
6773 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6774 scoped_ptr<HttpTransaction> trans(
6775 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6777 MockWrite data_writes[] = {
6778 MockWrite("GET / HTTP/1.1\r\n"
6779 "Host: www.google.com\r\n"
6780 "Connection: keep-alive\r\n"
6781 "Referer: http://the.previous.site.com/\r\n\r\n"),
6784 // Lastly, the server responds with the actual content.
6785 MockRead data_reads[] = {
6786 MockRead("HTTP/1.0 200 OK\r\n"),
6787 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6788 MockRead("Content-Length: 100\r\n\r\n"),
6789 MockRead(SYNCHRONOUS, OK),
6792 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6793 data_writes, arraysize(data_writes));
6794 session_deps_.socket_factory->AddSocketDataProvider(&data);
6796 TestCompletionCallback callback;
6798 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6799 EXPECT_EQ(ERR_IO_PENDING, rv);
6801 rv = callback.WaitForResult();
6802 EXPECT_EQ(OK, rv);
6805 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6806 HttpRequestInfo request;
6807 request.method = "POST";
6808 request.url = GURL("http://www.google.com/");
6810 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6811 scoped_ptr<HttpTransaction> trans(
6812 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6814 MockWrite data_writes[] = {
6815 MockWrite("POST / HTTP/1.1\r\n"
6816 "Host: www.google.com\r\n"
6817 "Connection: keep-alive\r\n"
6818 "Content-Length: 0\r\n\r\n"),
6821 // Lastly, the server responds with the actual content.
6822 MockRead data_reads[] = {
6823 MockRead("HTTP/1.0 200 OK\r\n"),
6824 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6825 MockRead("Content-Length: 100\r\n\r\n"),
6826 MockRead(SYNCHRONOUS, OK),
6829 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6830 data_writes, arraysize(data_writes));
6831 session_deps_.socket_factory->AddSocketDataProvider(&data);
6833 TestCompletionCallback callback;
6835 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6836 EXPECT_EQ(ERR_IO_PENDING, rv);
6838 rv = callback.WaitForResult();
6839 EXPECT_EQ(OK, rv);
6842 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6843 HttpRequestInfo request;
6844 request.method = "PUT";
6845 request.url = GURL("http://www.google.com/");
6847 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6848 scoped_ptr<HttpTransaction> trans(
6849 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6851 MockWrite data_writes[] = {
6852 MockWrite("PUT / HTTP/1.1\r\n"
6853 "Host: www.google.com\r\n"
6854 "Connection: keep-alive\r\n"
6855 "Content-Length: 0\r\n\r\n"),
6858 // Lastly, the server responds with the actual content.
6859 MockRead data_reads[] = {
6860 MockRead("HTTP/1.0 200 OK\r\n"),
6861 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6862 MockRead("Content-Length: 100\r\n\r\n"),
6863 MockRead(SYNCHRONOUS, OK),
6866 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6867 data_writes, arraysize(data_writes));
6868 session_deps_.socket_factory->AddSocketDataProvider(&data);
6870 TestCompletionCallback callback;
6872 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6873 EXPECT_EQ(ERR_IO_PENDING, rv);
6875 rv = callback.WaitForResult();
6876 EXPECT_EQ(OK, rv);
6879 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6880 HttpRequestInfo request;
6881 request.method = "HEAD";
6882 request.url = GURL("http://www.google.com/");
6884 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6885 scoped_ptr<HttpTransaction> trans(
6886 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6888 MockWrite data_writes[] = {
6889 MockWrite("HEAD / HTTP/1.1\r\n"
6890 "Host: www.google.com\r\n"
6891 "Connection: keep-alive\r\n"
6892 "Content-Length: 0\r\n\r\n"),
6895 // Lastly, the server responds with the actual content.
6896 MockRead data_reads[] = {
6897 MockRead("HTTP/1.0 200 OK\r\n"),
6898 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6899 MockRead("Content-Length: 100\r\n\r\n"),
6900 MockRead(SYNCHRONOUS, OK),
6903 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6904 data_writes, arraysize(data_writes));
6905 session_deps_.socket_factory->AddSocketDataProvider(&data);
6907 TestCompletionCallback callback;
6909 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6910 EXPECT_EQ(ERR_IO_PENDING, rv);
6912 rv = callback.WaitForResult();
6913 EXPECT_EQ(OK, rv);
6916 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
6917 HttpRequestInfo request;
6918 request.method = "GET";
6919 request.url = GURL("http://www.google.com/");
6920 request.load_flags = LOAD_BYPASS_CACHE;
6922 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6923 scoped_ptr<HttpTransaction> trans(
6924 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6926 MockWrite data_writes[] = {
6927 MockWrite("GET / HTTP/1.1\r\n"
6928 "Host: www.google.com\r\n"
6929 "Connection: keep-alive\r\n"
6930 "Pragma: no-cache\r\n"
6931 "Cache-Control: no-cache\r\n\r\n"),
6934 // Lastly, the server responds with the actual content.
6935 MockRead data_reads[] = {
6936 MockRead("HTTP/1.0 200 OK\r\n"),
6937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6938 MockRead("Content-Length: 100\r\n\r\n"),
6939 MockRead(SYNCHRONOUS, OK),
6942 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6943 data_writes, arraysize(data_writes));
6944 session_deps_.socket_factory->AddSocketDataProvider(&data);
6946 TestCompletionCallback callback;
6948 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6949 EXPECT_EQ(ERR_IO_PENDING, rv);
6951 rv = callback.WaitForResult();
6952 EXPECT_EQ(OK, rv);
6955 TEST_P(HttpNetworkTransactionTest,
6956 BuildRequest_CacheControlValidateCache) {
6957 HttpRequestInfo request;
6958 request.method = "GET";
6959 request.url = GURL("http://www.google.com/");
6960 request.load_flags = LOAD_VALIDATE_CACHE;
6962 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6963 scoped_ptr<HttpTransaction> trans(
6964 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6966 MockWrite data_writes[] = {
6967 MockWrite("GET / HTTP/1.1\r\n"
6968 "Host: www.google.com\r\n"
6969 "Connection: keep-alive\r\n"
6970 "Cache-Control: max-age=0\r\n\r\n"),
6973 // Lastly, the server responds with the actual content.
6974 MockRead data_reads[] = {
6975 MockRead("HTTP/1.0 200 OK\r\n"),
6976 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6977 MockRead("Content-Length: 100\r\n\r\n"),
6978 MockRead(SYNCHRONOUS, OK),
6981 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6982 data_writes, arraysize(data_writes));
6983 session_deps_.socket_factory->AddSocketDataProvider(&data);
6985 TestCompletionCallback callback;
6987 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6988 EXPECT_EQ(ERR_IO_PENDING, rv);
6990 rv = callback.WaitForResult();
6991 EXPECT_EQ(OK, rv);
6994 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
6995 HttpRequestInfo request;
6996 request.method = "GET";
6997 request.url = GURL("http://www.google.com/");
6998 request.extra_headers.SetHeader("FooHeader", "Bar");
7000 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7001 scoped_ptr<HttpTransaction> trans(
7002 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7004 MockWrite data_writes[] = {
7005 MockWrite("GET / HTTP/1.1\r\n"
7006 "Host: www.google.com\r\n"
7007 "Connection: keep-alive\r\n"
7008 "FooHeader: Bar\r\n\r\n"),
7011 // Lastly, the server responds with the actual content.
7012 MockRead data_reads[] = {
7013 MockRead("HTTP/1.0 200 OK\r\n"),
7014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7015 MockRead("Content-Length: 100\r\n\r\n"),
7016 MockRead(SYNCHRONOUS, OK),
7019 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7020 data_writes, arraysize(data_writes));
7021 session_deps_.socket_factory->AddSocketDataProvider(&data);
7023 TestCompletionCallback callback;
7025 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7026 EXPECT_EQ(ERR_IO_PENDING, rv);
7028 rv = callback.WaitForResult();
7029 EXPECT_EQ(OK, rv);
7032 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7033 HttpRequestInfo request;
7034 request.method = "GET";
7035 request.url = GURL("http://www.google.com/");
7036 request.extra_headers.SetHeader("referer", "www.foo.com");
7037 request.extra_headers.SetHeader("hEllo", "Kitty");
7038 request.extra_headers.SetHeader("FoO", "bar");
7040 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7041 scoped_ptr<HttpTransaction> trans(
7042 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7044 MockWrite data_writes[] = {
7045 MockWrite("GET / HTTP/1.1\r\n"
7046 "Host: www.google.com\r\n"
7047 "Connection: keep-alive\r\n"
7048 "referer: www.foo.com\r\n"
7049 "hEllo: Kitty\r\n"
7050 "FoO: bar\r\n\r\n"),
7053 // Lastly, the server responds with the actual content.
7054 MockRead data_reads[] = {
7055 MockRead("HTTP/1.0 200 OK\r\n"),
7056 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7057 MockRead("Content-Length: 100\r\n\r\n"),
7058 MockRead(SYNCHRONOUS, OK),
7061 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7062 data_writes, arraysize(data_writes));
7063 session_deps_.socket_factory->AddSocketDataProvider(&data);
7065 TestCompletionCallback callback;
7067 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7068 EXPECT_EQ(ERR_IO_PENDING, rv);
7070 rv = callback.WaitForResult();
7071 EXPECT_EQ(OK, rv);
7074 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7075 HttpRequestInfo request;
7076 request.method = "GET";
7077 request.url = GURL("http://www.google.com/");
7078 request.load_flags = 0;
7080 session_deps_.proxy_service.reset(
7081 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7082 CapturingNetLog net_log;
7083 session_deps_.net_log = &net_log;
7085 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7086 scoped_ptr<HttpTransaction> trans(
7087 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7089 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7090 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7092 MockWrite data_writes[] = {
7093 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7094 MockWrite("GET / HTTP/1.1\r\n"
7095 "Host: www.google.com\r\n"
7096 "Connection: keep-alive\r\n\r\n")
7099 MockRead data_reads[] = {
7100 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7101 MockRead("HTTP/1.0 200 OK\r\n"),
7102 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7103 MockRead("Payload"),
7104 MockRead(SYNCHRONOUS, OK)
7107 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7108 data_writes, arraysize(data_writes));
7109 session_deps_.socket_factory->AddSocketDataProvider(&data);
7111 TestCompletionCallback callback;
7113 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7114 EXPECT_EQ(ERR_IO_PENDING, rv);
7116 rv = callback.WaitForResult();
7117 EXPECT_EQ(OK, rv);
7119 const HttpResponseInfo* response = trans->GetResponseInfo();
7120 ASSERT_TRUE(response != NULL);
7122 LoadTimingInfo load_timing_info;
7123 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7124 TestLoadTimingNotReusedWithPac(load_timing_info,
7125 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7127 std::string response_text;
7128 rv = ReadTransaction(trans.get(), &response_text);
7129 EXPECT_EQ(OK, rv);
7130 EXPECT_EQ("Payload", response_text);
7133 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7134 HttpRequestInfo request;
7135 request.method = "GET";
7136 request.url = GURL("https://www.google.com/");
7137 request.load_flags = 0;
7139 session_deps_.proxy_service.reset(
7140 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7141 CapturingNetLog net_log;
7142 session_deps_.net_log = &net_log;
7144 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7145 scoped_ptr<HttpTransaction> trans(
7146 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7148 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7149 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7151 MockWrite data_writes[] = {
7152 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7153 arraysize(write_buffer)),
7154 MockWrite("GET / HTTP/1.1\r\n"
7155 "Host: www.google.com\r\n"
7156 "Connection: keep-alive\r\n\r\n")
7159 MockRead data_reads[] = {
7160 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7161 arraysize(read_buffer)),
7162 MockRead("HTTP/1.0 200 OK\r\n"),
7163 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7164 MockRead("Payload"),
7165 MockRead(SYNCHRONOUS, OK)
7168 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7169 data_writes, arraysize(data_writes));
7170 session_deps_.socket_factory->AddSocketDataProvider(&data);
7172 SSLSocketDataProvider ssl(ASYNC, OK);
7173 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7175 TestCompletionCallback callback;
7177 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7178 EXPECT_EQ(ERR_IO_PENDING, rv);
7180 rv = callback.WaitForResult();
7181 EXPECT_EQ(OK, rv);
7183 LoadTimingInfo load_timing_info;
7184 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7185 TestLoadTimingNotReusedWithPac(load_timing_info,
7186 CONNECT_TIMING_HAS_SSL_TIMES);
7188 const HttpResponseInfo* response = trans->GetResponseInfo();
7189 ASSERT_TRUE(response != NULL);
7191 std::string response_text;
7192 rv = ReadTransaction(trans.get(), &response_text);
7193 EXPECT_EQ(OK, rv);
7194 EXPECT_EQ("Payload", response_text);
7197 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7198 HttpRequestInfo request;
7199 request.method = "GET";
7200 request.url = GURL("http://www.google.com/");
7201 request.load_flags = 0;
7203 session_deps_.proxy_service.reset(
7204 ProxyService::CreateFixed("socks4://myproxy:1080"));
7205 CapturingNetLog net_log;
7206 session_deps_.net_log = &net_log;
7208 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7209 scoped_ptr<HttpTransaction> trans(
7210 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7212 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7213 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7215 MockWrite data_writes[] = {
7216 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7217 MockWrite("GET / HTTP/1.1\r\n"
7218 "Host: www.google.com\r\n"
7219 "Connection: keep-alive\r\n\r\n")
7222 MockRead data_reads[] = {
7223 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7224 MockRead("HTTP/1.0 200 OK\r\n"),
7225 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7226 MockRead("Payload"),
7227 MockRead(SYNCHRONOUS, OK)
7230 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7231 data_writes, arraysize(data_writes));
7232 session_deps_.socket_factory->AddSocketDataProvider(&data);
7234 TestCompletionCallback callback;
7236 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7237 EXPECT_EQ(ERR_IO_PENDING, rv);
7239 rv = callback.WaitForResult();
7240 EXPECT_EQ(OK, rv);
7242 const HttpResponseInfo* response = trans->GetResponseInfo();
7243 ASSERT_TRUE(response != NULL);
7245 LoadTimingInfo load_timing_info;
7246 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7247 TestLoadTimingNotReused(load_timing_info,
7248 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7250 std::string response_text;
7251 rv = ReadTransaction(trans.get(), &response_text);
7252 EXPECT_EQ(OK, rv);
7253 EXPECT_EQ("Payload", response_text);
7256 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7257 HttpRequestInfo request;
7258 request.method = "GET";
7259 request.url = GURL("http://www.google.com/");
7260 request.load_flags = 0;
7262 session_deps_.proxy_service.reset(
7263 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7264 CapturingNetLog net_log;
7265 session_deps_.net_log = &net_log;
7267 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7268 scoped_ptr<HttpTransaction> trans(
7269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7271 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7272 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7273 const char kSOCKS5OkRequest[] = {
7274 0x05, // Version
7275 0x01, // Command (CONNECT)
7276 0x00, // Reserved.
7277 0x03, // Address type (DOMAINNAME).
7278 0x0E, // Length of domain (14)
7279 // Domain string:
7280 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7281 0x00, 0x50, // 16-bit port (80)
7283 const char kSOCKS5OkResponse[] =
7284 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7286 MockWrite data_writes[] = {
7287 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7288 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7289 MockWrite("GET / HTTP/1.1\r\n"
7290 "Host: www.google.com\r\n"
7291 "Connection: keep-alive\r\n\r\n")
7294 MockRead data_reads[] = {
7295 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7296 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7297 MockRead("HTTP/1.0 200 OK\r\n"),
7298 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7299 MockRead("Payload"),
7300 MockRead(SYNCHRONOUS, OK)
7303 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7304 data_writes, arraysize(data_writes));
7305 session_deps_.socket_factory->AddSocketDataProvider(&data);
7307 TestCompletionCallback callback;
7309 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7310 EXPECT_EQ(ERR_IO_PENDING, rv);
7312 rv = callback.WaitForResult();
7313 EXPECT_EQ(OK, rv);
7315 const HttpResponseInfo* response = trans->GetResponseInfo();
7316 ASSERT_TRUE(response != NULL);
7318 LoadTimingInfo load_timing_info;
7319 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7320 TestLoadTimingNotReusedWithPac(load_timing_info,
7321 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7323 std::string response_text;
7324 rv = ReadTransaction(trans.get(), &response_text);
7325 EXPECT_EQ(OK, rv);
7326 EXPECT_EQ("Payload", response_text);
7329 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7330 HttpRequestInfo request;
7331 request.method = "GET";
7332 request.url = GURL("https://www.google.com/");
7333 request.load_flags = 0;
7335 session_deps_.proxy_service.reset(
7336 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7337 CapturingNetLog net_log;
7338 session_deps_.net_log = &net_log;
7340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7341 scoped_ptr<HttpTransaction> trans(
7342 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7344 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7345 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7346 const unsigned char kSOCKS5OkRequest[] = {
7347 0x05, // Version
7348 0x01, // Command (CONNECT)
7349 0x00, // Reserved.
7350 0x03, // Address type (DOMAINNAME).
7351 0x0E, // Length of domain (14)
7352 // Domain string:
7353 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7354 0x01, 0xBB, // 16-bit port (443)
7357 const char kSOCKS5OkResponse[] =
7358 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7360 MockWrite data_writes[] = {
7361 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7362 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7363 arraysize(kSOCKS5OkRequest)),
7364 MockWrite("GET / HTTP/1.1\r\n"
7365 "Host: www.google.com\r\n"
7366 "Connection: keep-alive\r\n\r\n")
7369 MockRead data_reads[] = {
7370 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7371 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7372 MockRead("HTTP/1.0 200 OK\r\n"),
7373 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7374 MockRead("Payload"),
7375 MockRead(SYNCHRONOUS, OK)
7378 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7379 data_writes, arraysize(data_writes));
7380 session_deps_.socket_factory->AddSocketDataProvider(&data);
7382 SSLSocketDataProvider ssl(ASYNC, OK);
7383 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7385 TestCompletionCallback callback;
7387 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7388 EXPECT_EQ(ERR_IO_PENDING, rv);
7390 rv = callback.WaitForResult();
7391 EXPECT_EQ(OK, rv);
7393 const HttpResponseInfo* response = trans->GetResponseInfo();
7394 ASSERT_TRUE(response != NULL);
7396 LoadTimingInfo load_timing_info;
7397 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7398 TestLoadTimingNotReusedWithPac(load_timing_info,
7399 CONNECT_TIMING_HAS_SSL_TIMES);
7401 std::string response_text;
7402 rv = ReadTransaction(trans.get(), &response_text);
7403 EXPECT_EQ(OK, rv);
7404 EXPECT_EQ("Payload", response_text);
7407 namespace {
7409 // Tests that for connection endpoints the group names are correctly set.
7411 struct GroupNameTest {
7412 std::string proxy_server;
7413 std::string url;
7414 std::string expected_group_name;
7415 bool ssl;
7418 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7419 NextProto next_proto,
7420 SpdySessionDependencies* session_deps_) {
7421 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7423 base::WeakPtr<HttpServerProperties> http_server_properties =
7424 session->http_server_properties();
7425 http_server_properties->SetAlternateProtocol(
7426 HostPortPair("host.with.alternate", 80), 443,
7427 AlternateProtocolFromNextProto(next_proto));
7429 return session;
7432 int GroupNameTransactionHelper(
7433 const std::string& url,
7434 const scoped_refptr<HttpNetworkSession>& session) {
7435 HttpRequestInfo request;
7436 request.method = "GET";
7437 request.url = GURL(url);
7438 request.load_flags = 0;
7440 scoped_ptr<HttpTransaction> trans(
7441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7443 TestCompletionCallback callback;
7445 // We do not complete this request, the dtor will clean the transaction up.
7446 return trans->Start(&request, callback.callback(), BoundNetLog());
7449 } // namespace
7451 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7452 const GroupNameTest tests[] = {
7454 "", // unused
7455 "http://www.google.com/direct",
7456 "www.google.com:80",
7457 false,
7460 "", // unused
7461 "http://[2001:1418:13:1::25]/direct",
7462 "[2001:1418:13:1::25]:80",
7463 false,
7466 // SSL Tests
7468 "", // unused
7469 "https://www.google.com/direct_ssl",
7470 "ssl/www.google.com:443",
7471 true,
7474 "", // unused
7475 "https://[2001:1418:13:1::25]/direct",
7476 "ssl/[2001:1418:13:1::25]:443",
7477 true,
7480 "", // unused
7481 "http://host.with.alternate/direct",
7482 "ssl/host.with.alternate:443",
7483 true,
7487 HttpStreamFactory::set_use_alternate_protocols(true);
7489 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7490 session_deps_.proxy_service.reset(
7491 ProxyService::CreateFixed(tests[i].proxy_server));
7492 scoped_refptr<HttpNetworkSession> session(
7493 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7495 HttpNetworkSessionPeer peer(session);
7496 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7497 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7498 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7499 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7500 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7501 new MockClientSocketPoolManager);
7502 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7503 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7504 peer.SetClientSocketPoolManager(
7505 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7507 EXPECT_EQ(ERR_IO_PENDING,
7508 GroupNameTransactionHelper(tests[i].url, session));
7509 if (tests[i].ssl)
7510 EXPECT_EQ(tests[i].expected_group_name,
7511 ssl_conn_pool->last_group_name_received());
7512 else
7513 EXPECT_EQ(tests[i].expected_group_name,
7514 transport_conn_pool->last_group_name_received());
7519 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7520 const GroupNameTest tests[] = {
7522 "http_proxy",
7523 "http://www.google.com/http_proxy_normal",
7524 "www.google.com:80",
7525 false,
7528 // SSL Tests
7530 "http_proxy",
7531 "https://www.google.com/http_connect_ssl",
7532 "ssl/www.google.com:443",
7533 true,
7537 "http_proxy",
7538 "http://host.with.alternate/direct",
7539 "ssl/host.with.alternate:443",
7540 true,
7544 "http_proxy",
7545 "ftp://ftp.google.com/http_proxy_normal",
7546 "ftp/ftp.google.com:21",
7547 false,
7551 HttpStreamFactory::set_use_alternate_protocols(true);
7553 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7554 session_deps_.proxy_service.reset(
7555 ProxyService::CreateFixed(tests[i].proxy_server));
7556 scoped_refptr<HttpNetworkSession> session(
7557 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7559 HttpNetworkSessionPeer peer(session);
7561 HostPortPair proxy_host("http_proxy", 80);
7562 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7563 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7564 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7565 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7567 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7568 new MockClientSocketPoolManager);
7569 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7570 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7571 peer.SetClientSocketPoolManager(
7572 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7574 EXPECT_EQ(ERR_IO_PENDING,
7575 GroupNameTransactionHelper(tests[i].url, session));
7576 if (tests[i].ssl)
7577 EXPECT_EQ(tests[i].expected_group_name,
7578 ssl_conn_pool->last_group_name_received());
7579 else
7580 EXPECT_EQ(tests[i].expected_group_name,
7581 http_proxy_pool->last_group_name_received());
7585 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7586 const GroupNameTest tests[] = {
7588 "socks4://socks_proxy:1080",
7589 "http://www.google.com/socks4_direct",
7590 "socks4/www.google.com:80",
7591 false,
7594 "socks5://socks_proxy:1080",
7595 "http://www.google.com/socks5_direct",
7596 "socks5/www.google.com:80",
7597 false,
7600 // SSL Tests
7602 "socks4://socks_proxy:1080",
7603 "https://www.google.com/socks4_ssl",
7604 "socks4/ssl/www.google.com:443",
7605 true,
7608 "socks5://socks_proxy:1080",
7609 "https://www.google.com/socks5_ssl",
7610 "socks5/ssl/www.google.com:443",
7611 true,
7615 "socks4://socks_proxy:1080",
7616 "http://host.with.alternate/direct",
7617 "socks4/ssl/host.with.alternate:443",
7618 true,
7622 HttpStreamFactory::set_use_alternate_protocols(true);
7624 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7625 session_deps_.proxy_service.reset(
7626 ProxyService::CreateFixed(tests[i].proxy_server));
7627 scoped_refptr<HttpNetworkSession> session(
7628 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7630 HttpNetworkSessionPeer peer(session);
7632 HostPortPair proxy_host("socks_proxy", 1080);
7633 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7634 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7635 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7636 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7638 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7639 new MockClientSocketPoolManager);
7640 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7641 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7642 peer.SetClientSocketPoolManager(
7643 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7645 scoped_ptr<HttpTransaction> trans(
7646 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7648 EXPECT_EQ(ERR_IO_PENDING,
7649 GroupNameTransactionHelper(tests[i].url, session));
7650 if (tests[i].ssl)
7651 EXPECT_EQ(tests[i].expected_group_name,
7652 ssl_conn_pool->last_group_name_received());
7653 else
7654 EXPECT_EQ(tests[i].expected_group_name,
7655 socks_conn_pool->last_group_name_received());
7659 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7660 HttpRequestInfo request;
7661 request.method = "GET";
7662 request.url = GURL("http://www.google.com/");
7664 session_deps_.proxy_service.reset(
7665 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7667 // This simulates failure resolving all hostnames; that means we will fail
7668 // connecting to both proxies (myproxy:70 and foobar:80).
7669 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7671 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7672 scoped_ptr<HttpTransaction> trans(
7673 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7675 TestCompletionCallback callback;
7677 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7678 EXPECT_EQ(ERR_IO_PENDING, rv);
7680 rv = callback.WaitForResult();
7681 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7684 // Base test to make sure that when the load flags for a request specify to
7685 // bypass the cache, the DNS cache is not used.
7686 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7687 int load_flags) {
7688 // Issue a request, asking to bypass the cache(s).
7689 HttpRequestInfo request;
7690 request.method = "GET";
7691 request.load_flags = load_flags;
7692 request.url = GURL("http://www.google.com/");
7694 // Select a host resolver that does caching.
7695 session_deps_.host_resolver.reset(new MockCachingHostResolver);
7697 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7698 scoped_ptr<HttpTransaction> trans(
7699 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7701 // Warm up the host cache so it has an entry for "www.google.com".
7702 AddressList addrlist;
7703 TestCompletionCallback callback;
7704 int rv = session_deps_.host_resolver->Resolve(
7705 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7706 DEFAULT_PRIORITY,
7707 &addrlist,
7708 callback.callback(),
7709 NULL,
7710 BoundNetLog());
7711 EXPECT_EQ(ERR_IO_PENDING, rv);
7712 rv = callback.WaitForResult();
7713 EXPECT_EQ(OK, rv);
7715 // Verify that it was added to host cache, by doing a subsequent async lookup
7716 // and confirming it completes synchronously.
7717 rv = session_deps_.host_resolver->Resolve(
7718 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7719 DEFAULT_PRIORITY,
7720 &addrlist,
7721 callback.callback(),
7722 NULL,
7723 BoundNetLog());
7724 ASSERT_EQ(OK, rv);
7726 // Inject a failure the next time that "www.google.com" is resolved. This way
7727 // we can tell if the next lookup hit the cache, or the "network".
7728 // (cache --> success, "network" --> failure).
7729 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7731 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7732 // first read -- this won't be reached as the host resolution will fail first.
7733 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7734 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7735 session_deps_.socket_factory->AddSocketDataProvider(&data);
7737 // Run the request.
7738 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7739 ASSERT_EQ(ERR_IO_PENDING, rv);
7740 rv = callback.WaitForResult();
7742 // If we bypassed the cache, we would have gotten a failure while resolving
7743 // "www.google.com".
7744 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7747 // There are multiple load flags that should trigger the host cache bypass.
7748 // Test each in isolation:
7749 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7750 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7753 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7754 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7757 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7758 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7761 // Make sure we can handle an error when writing the request.
7762 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7763 HttpRequestInfo request;
7764 request.method = "GET";
7765 request.url = GURL("http://www.foo.com/");
7766 request.load_flags = 0;
7768 MockWrite write_failure[] = {
7769 MockWrite(ASYNC, ERR_CONNECTION_RESET),
7771 StaticSocketDataProvider data(NULL, 0,
7772 write_failure, arraysize(write_failure));
7773 session_deps_.socket_factory->AddSocketDataProvider(&data);
7774 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7776 TestCompletionCallback callback;
7778 scoped_ptr<HttpTransaction> trans(
7779 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7781 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7782 EXPECT_EQ(ERR_IO_PENDING, rv);
7784 rv = callback.WaitForResult();
7785 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7788 // Check that a connection closed after the start of the headers finishes ok.
7789 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7790 HttpRequestInfo request;
7791 request.method = "GET";
7792 request.url = GURL("http://www.foo.com/");
7793 request.load_flags = 0;
7795 MockRead data_reads[] = {
7796 MockRead("HTTP/1."),
7797 MockRead(SYNCHRONOUS, OK),
7800 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7801 session_deps_.socket_factory->AddSocketDataProvider(&data);
7802 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7804 TestCompletionCallback callback;
7806 scoped_ptr<HttpTransaction> trans(
7807 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7809 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7810 EXPECT_EQ(ERR_IO_PENDING, rv);
7812 rv = callback.WaitForResult();
7813 EXPECT_EQ(OK, rv);
7815 const HttpResponseInfo* response = trans->GetResponseInfo();
7816 ASSERT_TRUE(response != NULL);
7818 EXPECT_TRUE(response->headers.get() != NULL);
7819 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7821 std::string response_data;
7822 rv = ReadTransaction(trans.get(), &response_data);
7823 EXPECT_EQ(OK, rv);
7824 EXPECT_EQ("", response_data);
7827 // Make sure that a dropped connection while draining the body for auth
7828 // restart does the right thing.
7829 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7830 HttpRequestInfo request;
7831 request.method = "GET";
7832 request.url = GURL("http://www.google.com/");
7833 request.load_flags = 0;
7835 MockWrite data_writes1[] = {
7836 MockWrite("GET / HTTP/1.1\r\n"
7837 "Host: www.google.com\r\n"
7838 "Connection: keep-alive\r\n\r\n"),
7841 MockRead data_reads1[] = {
7842 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7843 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7844 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7845 MockRead("Content-Length: 14\r\n\r\n"),
7846 MockRead("Unauth"),
7847 MockRead(ASYNC, ERR_CONNECTION_RESET),
7850 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7851 data_writes1, arraysize(data_writes1));
7852 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7854 // After calling trans->RestartWithAuth(), this is the request we should
7855 // be issuing -- the final header line contains the credentials.
7856 MockWrite data_writes2[] = {
7857 MockWrite("GET / HTTP/1.1\r\n"
7858 "Host: www.google.com\r\n"
7859 "Connection: keep-alive\r\n"
7860 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7863 // Lastly, the server responds with the actual content.
7864 MockRead data_reads2[] = {
7865 MockRead("HTTP/1.1 200 OK\r\n"),
7866 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7867 MockRead("Content-Length: 100\r\n\r\n"),
7868 MockRead(SYNCHRONOUS, OK),
7871 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7872 data_writes2, arraysize(data_writes2));
7873 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7874 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7876 TestCompletionCallback callback1;
7878 scoped_ptr<HttpTransaction> trans(
7879 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7881 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7882 EXPECT_EQ(ERR_IO_PENDING, rv);
7884 rv = callback1.WaitForResult();
7885 EXPECT_EQ(OK, rv);
7887 const HttpResponseInfo* response = trans->GetResponseInfo();
7888 ASSERT_TRUE(response != NULL);
7889 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7891 TestCompletionCallback callback2;
7893 rv = trans->RestartWithAuth(
7894 AuthCredentials(kFoo, kBar), callback2.callback());
7895 EXPECT_EQ(ERR_IO_PENDING, rv);
7897 rv = callback2.WaitForResult();
7898 EXPECT_EQ(OK, rv);
7900 response = trans->GetResponseInfo();
7901 ASSERT_TRUE(response != NULL);
7902 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7903 EXPECT_EQ(100, response->headers->GetContentLength());
7906 // Test HTTPS connections going through a proxy that sends extra data.
7907 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
7908 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7910 HttpRequestInfo request;
7911 request.method = "GET";
7912 request.url = GURL("https://www.google.com/");
7913 request.load_flags = 0;
7915 MockRead proxy_reads[] = {
7916 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7917 MockRead(SYNCHRONOUS, OK)
7920 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
7921 SSLSocketDataProvider ssl(ASYNC, OK);
7923 session_deps_.socket_factory->AddSocketDataProvider(&data);
7924 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7926 TestCompletionCallback callback;
7928 session_deps_.socket_factory->ResetNextMockIndexes();
7930 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7931 scoped_ptr<HttpTransaction> trans(
7932 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7934 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7935 EXPECT_EQ(ERR_IO_PENDING, rv);
7937 rv = callback.WaitForResult();
7938 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
7941 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
7942 HttpRequestInfo request;
7943 request.method = "GET";
7944 request.url = GURL("http://www.google.com/");
7945 request.load_flags = 0;
7947 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7948 scoped_ptr<HttpTransaction> trans(
7949 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7951 MockRead data_reads[] = {
7952 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7953 MockRead(SYNCHRONOUS, OK),
7956 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7957 session_deps_.socket_factory->AddSocketDataProvider(&data);
7959 TestCompletionCallback callback;
7961 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7962 EXPECT_EQ(ERR_IO_PENDING, rv);
7964 EXPECT_EQ(OK, callback.WaitForResult());
7966 const HttpResponseInfo* response = trans->GetResponseInfo();
7967 ASSERT_TRUE(response != NULL);
7969 EXPECT_TRUE(response->headers.get() != NULL);
7970 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7972 std::string response_data;
7973 rv = ReadTransaction(trans.get(), &response_data);
7974 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
7977 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
7978 base::FilePath temp_file_path;
7979 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
7980 const uint64 kFakeSize = 100000; // file is actually blank
7981 UploadFileElementReader::ScopedOverridingContentLengthForTests
7982 overriding_content_length(kFakeSize);
7984 ScopedVector<UploadElementReader> element_readers;
7985 element_readers.push_back(
7986 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7987 temp_file_path,
7989 kuint64max,
7990 base::Time()));
7991 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7993 HttpRequestInfo request;
7994 request.method = "POST";
7995 request.url = GURL("http://www.google.com/upload");
7996 request.upload_data_stream = &upload_data_stream;
7997 request.load_flags = 0;
7999 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8000 scoped_ptr<HttpTransaction> trans(
8001 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8003 MockRead data_reads[] = {
8004 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8005 MockRead("hello world"),
8006 MockRead(SYNCHRONOUS, OK),
8008 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8009 session_deps_.socket_factory->AddSocketDataProvider(&data);
8011 TestCompletionCallback callback;
8013 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8014 EXPECT_EQ(ERR_IO_PENDING, rv);
8016 rv = callback.WaitForResult();
8017 EXPECT_EQ(OK, rv);
8019 const HttpResponseInfo* response = trans->GetResponseInfo();
8020 ASSERT_TRUE(response != NULL);
8022 EXPECT_TRUE(response->headers.get() != NULL);
8023 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8025 std::string response_data;
8026 rv = ReadTransaction(trans.get(), &response_data);
8027 EXPECT_EQ(OK, rv);
8028 EXPECT_EQ("hello world", response_data);
8030 base::DeleteFile(temp_file_path, false);
8033 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8034 base::FilePath temp_file;
8035 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8036 std::string temp_file_content("Unreadable file.");
8037 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8038 temp_file_content.length()));
8039 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
8041 ScopedVector<UploadElementReader> element_readers;
8042 element_readers.push_back(
8043 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8044 temp_file,
8046 kuint64max,
8047 base::Time()));
8048 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8050 HttpRequestInfo request;
8051 request.method = "POST";
8052 request.url = GURL("http://www.google.com/upload");
8053 request.upload_data_stream = &upload_data_stream;
8054 request.load_flags = 0;
8056 // If we try to upload an unreadable file, the transaction should fail.
8057 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8058 scoped_ptr<HttpTransaction> trans(
8059 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8061 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8062 session_deps_.socket_factory->AddSocketDataProvider(&data);
8064 TestCompletionCallback callback;
8066 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8067 EXPECT_EQ(ERR_IO_PENDING, rv);
8069 rv = callback.WaitForResult();
8070 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8072 const HttpResponseInfo* response = trans->GetResponseInfo();
8073 EXPECT_FALSE(response);
8075 base::DeleteFile(temp_file, false);
8078 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8079 class FakeUploadElementReader : public UploadElementReader {
8080 public:
8081 FakeUploadElementReader() {}
8082 virtual ~FakeUploadElementReader() {}
8084 const CompletionCallback& callback() const { return callback_; }
8086 // UploadElementReader overrides:
8087 virtual int Init(const CompletionCallback& callback) OVERRIDE {
8088 callback_ = callback;
8089 return ERR_IO_PENDING;
8091 virtual uint64 GetContentLength() const OVERRIDE { return 0; }
8092 virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
8093 virtual int Read(IOBuffer* buf,
8094 int buf_length,
8095 const CompletionCallback& callback) OVERRIDE {
8096 return ERR_FAILED;
8099 private:
8100 CompletionCallback callback_;
8103 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8104 ScopedVector<UploadElementReader> element_readers;
8105 element_readers.push_back(fake_reader);
8106 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8108 HttpRequestInfo request;
8109 request.method = "POST";
8110 request.url = GURL("http://www.google.com/upload");
8111 request.upload_data_stream = &upload_data_stream;
8112 request.load_flags = 0;
8114 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8115 scoped_ptr<HttpTransaction> trans(
8116 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8118 StaticSocketDataProvider data;
8119 session_deps_.socket_factory->AddSocketDataProvider(&data);
8121 TestCompletionCallback callback;
8122 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8123 EXPECT_EQ(ERR_IO_PENDING, rv);
8124 base::MessageLoop::current()->RunUntilIdle();
8126 // Transaction is pending on request body initialization.
8127 ASSERT_FALSE(fake_reader->callback().is_null());
8129 // Return Init()'s result after the transaction gets destroyed.
8130 trans.reset();
8131 fake_reader->callback().Run(OK); // Should not crash.
8134 // Tests that changes to Auth realms are treated like auth rejections.
8135 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8137 HttpRequestInfo request;
8138 request.method = "GET";
8139 request.url = GURL("http://www.google.com/");
8140 request.load_flags = 0;
8142 // First transaction will request a resource and receive a Basic challenge
8143 // with realm="first_realm".
8144 MockWrite data_writes1[] = {
8145 MockWrite("GET / HTTP/1.1\r\n"
8146 "Host: www.google.com\r\n"
8147 "Connection: keep-alive\r\n"
8148 "\r\n"),
8150 MockRead data_reads1[] = {
8151 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8152 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8153 "\r\n"),
8156 // After calling trans->RestartWithAuth(), provide an Authentication header
8157 // for first_realm. The server will reject and provide a challenge with
8158 // second_realm.
8159 MockWrite data_writes2[] = {
8160 MockWrite("GET / HTTP/1.1\r\n"
8161 "Host: www.google.com\r\n"
8162 "Connection: keep-alive\r\n"
8163 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8164 "\r\n"),
8166 MockRead data_reads2[] = {
8167 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8168 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8169 "\r\n"),
8172 // This again fails, and goes back to first_realm. Make sure that the
8173 // entry is removed from cache.
8174 MockWrite data_writes3[] = {
8175 MockWrite("GET / HTTP/1.1\r\n"
8176 "Host: www.google.com\r\n"
8177 "Connection: keep-alive\r\n"
8178 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8179 "\r\n"),
8181 MockRead data_reads3[] = {
8182 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8183 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8184 "\r\n"),
8187 // Try one last time (with the correct password) and get the resource.
8188 MockWrite data_writes4[] = {
8189 MockWrite("GET / HTTP/1.1\r\n"
8190 "Host: www.google.com\r\n"
8191 "Connection: keep-alive\r\n"
8192 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8193 "\r\n"),
8195 MockRead data_reads4[] = {
8196 MockRead("HTTP/1.1 200 OK\r\n"
8197 "Content-Type: text/html; charset=iso-8859-1\r\n"
8198 "Content-Length: 5\r\n"
8199 "\r\n"
8200 "hello"),
8203 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8204 data_writes1, arraysize(data_writes1));
8205 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8206 data_writes2, arraysize(data_writes2));
8207 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8208 data_writes3, arraysize(data_writes3));
8209 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8210 data_writes4, arraysize(data_writes4));
8211 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8212 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8213 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8214 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8216 TestCompletionCallback callback1;
8218 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8219 scoped_ptr<HttpTransaction> trans(
8220 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8222 // Issue the first request with Authorize headers. There should be a
8223 // password prompt for first_realm waiting to be filled in after the
8224 // transaction completes.
8225 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8226 EXPECT_EQ(ERR_IO_PENDING, rv);
8227 rv = callback1.WaitForResult();
8228 EXPECT_EQ(OK, rv);
8229 const HttpResponseInfo* response = trans->GetResponseInfo();
8230 ASSERT_TRUE(response != NULL);
8231 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8232 ASSERT_FALSE(challenge == NULL);
8233 EXPECT_FALSE(challenge->is_proxy);
8234 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8235 EXPECT_EQ("first_realm", challenge->realm);
8236 EXPECT_EQ("basic", challenge->scheme);
8238 // Issue the second request with an incorrect password. There should be a
8239 // password prompt for second_realm waiting to be filled in after the
8240 // transaction completes.
8241 TestCompletionCallback callback2;
8242 rv = trans->RestartWithAuth(
8243 AuthCredentials(kFirst, kBaz), callback2.callback());
8244 EXPECT_EQ(ERR_IO_PENDING, rv);
8245 rv = callback2.WaitForResult();
8246 EXPECT_EQ(OK, rv);
8247 response = trans->GetResponseInfo();
8248 ASSERT_TRUE(response != NULL);
8249 challenge = response->auth_challenge.get();
8250 ASSERT_FALSE(challenge == NULL);
8251 EXPECT_FALSE(challenge->is_proxy);
8252 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8253 EXPECT_EQ("second_realm", challenge->realm);
8254 EXPECT_EQ("basic", challenge->scheme);
8256 // Issue the third request with another incorrect password. There should be
8257 // a password prompt for first_realm waiting to be filled in. If the password
8258 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8259 // first_realm was not correctly removed.
8260 TestCompletionCallback callback3;
8261 rv = trans->RestartWithAuth(
8262 AuthCredentials(kSecond, kFou), callback3.callback());
8263 EXPECT_EQ(ERR_IO_PENDING, rv);
8264 rv = callback3.WaitForResult();
8265 EXPECT_EQ(OK, rv);
8266 response = trans->GetResponseInfo();
8267 ASSERT_TRUE(response != NULL);
8268 challenge = response->auth_challenge.get();
8269 ASSERT_FALSE(challenge == NULL);
8270 EXPECT_FALSE(challenge->is_proxy);
8271 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8272 EXPECT_EQ("first_realm", challenge->realm);
8273 EXPECT_EQ("basic", challenge->scheme);
8275 // Issue the fourth request with the correct password and username.
8276 TestCompletionCallback callback4;
8277 rv = trans->RestartWithAuth(
8278 AuthCredentials(kFirst, kBar), callback4.callback());
8279 EXPECT_EQ(ERR_IO_PENDING, rv);
8280 rv = callback4.WaitForResult();
8281 EXPECT_EQ(OK, rv);
8282 response = trans->GetResponseInfo();
8283 ASSERT_TRUE(response != NULL);
8284 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8287 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8288 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8289 HttpStreamFactory::set_use_alternate_protocols(true);
8291 std::string alternate_protocol_http_header =
8292 GetAlternateProtocolHttpHeader();
8294 MockRead data_reads[] = {
8295 MockRead("HTTP/1.1 200 OK\r\n"),
8296 MockRead(alternate_protocol_http_header.c_str()),
8297 MockRead("hello world"),
8298 MockRead(SYNCHRONOUS, OK),
8301 HttpRequestInfo request;
8302 request.method = "GET";
8303 request.url = GURL("http://www.google.com/");
8304 request.load_flags = 0;
8306 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8308 session_deps_.socket_factory->AddSocketDataProvider(&data);
8310 TestCompletionCallback callback;
8312 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8313 scoped_ptr<HttpTransaction> trans(
8314 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8316 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8317 EXPECT_EQ(ERR_IO_PENDING, rv);
8319 HostPortPair http_host_port_pair("www.google.com", 80);
8320 HttpServerProperties& http_server_properties =
8321 *session->http_server_properties();
8322 EXPECT_FALSE(
8323 http_server_properties.HasAlternateProtocol(http_host_port_pair));
8325 EXPECT_EQ(OK, callback.WaitForResult());
8327 const HttpResponseInfo* response = trans->GetResponseInfo();
8328 ASSERT_TRUE(response != NULL);
8329 ASSERT_TRUE(response->headers.get() != NULL);
8330 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8331 EXPECT_FALSE(response->was_fetched_via_spdy);
8332 EXPECT_FALSE(response->was_npn_negotiated);
8334 std::string response_data;
8335 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8336 EXPECT_EQ("hello world", response_data);
8338 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
8339 const PortAlternateProtocolPair alternate =
8340 http_server_properties.GetAlternateProtocol(http_host_port_pair);
8341 PortAlternateProtocolPair expected_alternate;
8342 expected_alternate.port = 443;
8343 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
8344 EXPECT_TRUE(expected_alternate.Equals(alternate));
8347 TEST_P(HttpNetworkTransactionTest,
8348 MarkBrokenAlternateProtocolAndFallback) {
8349 HttpStreamFactory::set_use_alternate_protocols(true);
8351 HttpRequestInfo request;
8352 request.method = "GET";
8353 request.url = GURL("http://www.google.com/");
8354 request.load_flags = 0;
8356 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8357 StaticSocketDataProvider first_data;
8358 first_data.set_connect_data(mock_connect);
8359 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8361 MockRead data_reads[] = {
8362 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8363 MockRead("hello world"),
8364 MockRead(ASYNC, OK),
8366 StaticSocketDataProvider second_data(
8367 data_reads, arraysize(data_reads), NULL, 0);
8368 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8370 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8372 base::WeakPtr<HttpServerProperties> http_server_properties =
8373 session->http_server_properties();
8374 // Port must be < 1024, or the header will be ignored (since initial port was
8375 // port 80 (another restricted port).
8376 http_server_properties->SetAlternateProtocol(
8377 HostPortPair::FromURL(request.url),
8378 666 /* port is ignored by MockConnect anyway */,
8379 AlternateProtocolFromNextProto(GetParam()));
8381 scoped_ptr<HttpTransaction> trans(
8382 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8383 TestCompletionCallback callback;
8385 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8386 EXPECT_EQ(ERR_IO_PENDING, rv);
8387 EXPECT_EQ(OK, callback.WaitForResult());
8389 const HttpResponseInfo* response = trans->GetResponseInfo();
8390 ASSERT_TRUE(response != NULL);
8391 ASSERT_TRUE(response->headers.get() != NULL);
8392 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8394 std::string response_data;
8395 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8396 EXPECT_EQ("hello world", response_data);
8398 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8399 HostPortPair::FromURL(request.url)));
8400 const PortAlternateProtocolPair alternate =
8401 http_server_properties->GetAlternateProtocol(
8402 HostPortPair::FromURL(request.url));
8403 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8406 TEST_P(HttpNetworkTransactionTest,
8407 AlternateProtocolPortRestrictedBlocked) {
8408 // Ensure that we're not allowed to redirect traffic via an alternate
8409 // protocol to an unrestricted (port >= 1024) when the original traffic was
8410 // on a restricted port (port < 1024). Ensure that we can redirect in all
8411 // other cases.
8412 HttpStreamFactory::set_use_alternate_protocols(true);
8414 HttpRequestInfo restricted_port_request;
8415 restricted_port_request.method = "GET";
8416 restricted_port_request.url = GURL("http://www.google.com:1023/");
8417 restricted_port_request.load_flags = 0;
8419 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8420 StaticSocketDataProvider first_data;
8421 first_data.set_connect_data(mock_connect);
8422 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8424 MockRead data_reads[] = {
8425 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8426 MockRead("hello world"),
8427 MockRead(ASYNC, OK),
8429 StaticSocketDataProvider second_data(
8430 data_reads, arraysize(data_reads), NULL, 0);
8431 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8433 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8435 base::WeakPtr<HttpServerProperties> http_server_properties =
8436 session->http_server_properties();
8437 const int kUnrestrictedAlternatePort = 1024;
8438 http_server_properties->SetAlternateProtocol(
8439 HostPortPair::FromURL(restricted_port_request.url),
8440 kUnrestrictedAlternatePort,
8441 AlternateProtocolFromNextProto(GetParam()));
8443 scoped_ptr<HttpTransaction> trans(
8444 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8445 TestCompletionCallback callback;
8447 int rv = trans->Start(
8448 &restricted_port_request,
8449 callback.callback(), BoundNetLog());
8450 EXPECT_EQ(ERR_IO_PENDING, rv);
8451 // Invalid change to unrestricted port should fail.
8452 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8455 TEST_P(HttpNetworkTransactionTest,
8456 AlternateProtocolPortRestrictedPermitted) {
8457 // Ensure that we're allowed to redirect traffic via an alternate
8458 // protocol to an unrestricted (port >= 1024) when the original traffic was
8459 // on a restricted port (port < 1024) if we set
8460 // enable_user_alternate_protocol_ports.
8462 HttpStreamFactory::set_use_alternate_protocols(true);
8463 session_deps_.enable_user_alternate_protocol_ports = true;
8465 HttpRequestInfo restricted_port_request;
8466 restricted_port_request.method = "GET";
8467 restricted_port_request.url = GURL("http://www.google.com:1023/");
8468 restricted_port_request.load_flags = 0;
8470 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8471 StaticSocketDataProvider first_data;
8472 first_data.set_connect_data(mock_connect);
8473 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8475 MockRead data_reads[] = {
8476 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8477 MockRead("hello world"),
8478 MockRead(ASYNC, OK),
8480 StaticSocketDataProvider second_data(
8481 data_reads, arraysize(data_reads), NULL, 0);
8482 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8484 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8486 base::WeakPtr<HttpServerProperties> http_server_properties =
8487 session->http_server_properties();
8488 const int kUnrestrictedAlternatePort = 1024;
8489 http_server_properties->SetAlternateProtocol(
8490 HostPortPair::FromURL(restricted_port_request.url),
8491 kUnrestrictedAlternatePort,
8492 AlternateProtocolFromNextProto(GetParam()));
8494 scoped_ptr<HttpTransaction> trans(
8495 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8496 TestCompletionCallback callback;
8498 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8499 &restricted_port_request,
8500 callback.callback(), BoundNetLog()));
8501 // Change to unrestricted port should succeed.
8502 EXPECT_EQ(OK, callback.WaitForResult());
8505 TEST_P(HttpNetworkTransactionTest,
8506 AlternateProtocolPortRestrictedAllowed) {
8507 // Ensure that we're not allowed to redirect traffic via an alternate
8508 // protocol to an unrestricted (port >= 1024) when the original traffic was
8509 // on a restricted port (port < 1024). Ensure that we can redirect in all
8510 // other cases.
8511 HttpStreamFactory::set_use_alternate_protocols(true);
8513 HttpRequestInfo restricted_port_request;
8514 restricted_port_request.method = "GET";
8515 restricted_port_request.url = GURL("http://www.google.com:1023/");
8516 restricted_port_request.load_flags = 0;
8518 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8519 StaticSocketDataProvider first_data;
8520 first_data.set_connect_data(mock_connect);
8521 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8523 MockRead data_reads[] = {
8524 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8525 MockRead("hello world"),
8526 MockRead(ASYNC, OK),
8528 StaticSocketDataProvider second_data(
8529 data_reads, arraysize(data_reads), NULL, 0);
8530 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8532 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8534 base::WeakPtr<HttpServerProperties> http_server_properties =
8535 session->http_server_properties();
8536 const int kRestrictedAlternatePort = 80;
8537 http_server_properties->SetAlternateProtocol(
8538 HostPortPair::FromURL(restricted_port_request.url),
8539 kRestrictedAlternatePort,
8540 AlternateProtocolFromNextProto(GetParam()));
8542 scoped_ptr<HttpTransaction> trans(
8543 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8544 TestCompletionCallback callback;
8546 int rv = trans->Start(
8547 &restricted_port_request,
8548 callback.callback(), BoundNetLog());
8549 EXPECT_EQ(ERR_IO_PENDING, rv);
8550 // Valid change to restricted port should pass.
8551 EXPECT_EQ(OK, callback.WaitForResult());
8554 TEST_P(HttpNetworkTransactionTest,
8555 AlternateProtocolPortUnrestrictedAllowed1) {
8556 // Ensure that we're not allowed to redirect traffic via an alternate
8557 // protocol to an unrestricted (port >= 1024) when the original traffic was
8558 // on a restricted port (port < 1024). Ensure that we can redirect in all
8559 // other cases.
8560 HttpStreamFactory::set_use_alternate_protocols(true);
8562 HttpRequestInfo unrestricted_port_request;
8563 unrestricted_port_request.method = "GET";
8564 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8565 unrestricted_port_request.load_flags = 0;
8567 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8568 StaticSocketDataProvider first_data;
8569 first_data.set_connect_data(mock_connect);
8570 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8572 MockRead data_reads[] = {
8573 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8574 MockRead("hello world"),
8575 MockRead(ASYNC, OK),
8577 StaticSocketDataProvider second_data(
8578 data_reads, arraysize(data_reads), NULL, 0);
8579 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8581 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8583 base::WeakPtr<HttpServerProperties> http_server_properties =
8584 session->http_server_properties();
8585 const int kRestrictedAlternatePort = 80;
8586 http_server_properties->SetAlternateProtocol(
8587 HostPortPair::FromURL(unrestricted_port_request.url),
8588 kRestrictedAlternatePort,
8589 AlternateProtocolFromNextProto(GetParam()));
8591 scoped_ptr<HttpTransaction> trans(
8592 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8593 TestCompletionCallback callback;
8595 int rv = trans->Start(
8596 &unrestricted_port_request, callback.callback(), BoundNetLog());
8597 EXPECT_EQ(ERR_IO_PENDING, rv);
8598 // Valid change to restricted port should pass.
8599 EXPECT_EQ(OK, callback.WaitForResult());
8602 TEST_P(HttpNetworkTransactionTest,
8603 AlternateProtocolPortUnrestrictedAllowed2) {
8604 // Ensure that we're not allowed to redirect traffic via an alternate
8605 // protocol to an unrestricted (port >= 1024) when the original traffic was
8606 // on a restricted port (port < 1024). Ensure that we can redirect in all
8607 // other cases.
8608 HttpStreamFactory::set_use_alternate_protocols(true);
8610 HttpRequestInfo unrestricted_port_request;
8611 unrestricted_port_request.method = "GET";
8612 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8613 unrestricted_port_request.load_flags = 0;
8615 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8616 StaticSocketDataProvider first_data;
8617 first_data.set_connect_data(mock_connect);
8618 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8620 MockRead data_reads[] = {
8621 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8622 MockRead("hello world"),
8623 MockRead(ASYNC, OK),
8625 StaticSocketDataProvider second_data(
8626 data_reads, arraysize(data_reads), NULL, 0);
8627 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8629 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8631 base::WeakPtr<HttpServerProperties> http_server_properties =
8632 session->http_server_properties();
8633 const int kUnrestrictedAlternatePort = 1024;
8634 http_server_properties->SetAlternateProtocol(
8635 HostPortPair::FromURL(unrestricted_port_request.url),
8636 kUnrestrictedAlternatePort,
8637 AlternateProtocolFromNextProto(GetParam()));
8639 scoped_ptr<HttpTransaction> trans(
8640 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8641 TestCompletionCallback callback;
8643 int rv = trans->Start(
8644 &unrestricted_port_request, callback.callback(), BoundNetLog());
8645 EXPECT_EQ(ERR_IO_PENDING, rv);
8646 // Valid change to an unrestricted port should pass.
8647 EXPECT_EQ(OK, callback.WaitForResult());
8650 TEST_P(HttpNetworkTransactionTest,
8651 AlternateProtocolUnsafeBlocked) {
8652 // Ensure that we're not allowed to redirect traffic via an alternate
8653 // protocol to an unsafe port, and that we resume the second
8654 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8655 HttpStreamFactory::set_use_alternate_protocols(true);
8657 HttpRequestInfo request;
8658 request.method = "GET";
8659 request.url = GURL("http://www.google.com/");
8660 request.load_flags = 0;
8662 // The alternate protocol request will error out before we attempt to connect,
8663 // so only the standard HTTP request will try to connect.
8664 MockRead data_reads[] = {
8665 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8666 MockRead("hello world"),
8667 MockRead(ASYNC, OK),
8669 StaticSocketDataProvider data(
8670 data_reads, arraysize(data_reads), NULL, 0);
8671 session_deps_.socket_factory->AddSocketDataProvider(&data);
8673 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8675 base::WeakPtr<HttpServerProperties> http_server_properties =
8676 session->http_server_properties();
8677 const int kUnsafePort = 7;
8678 http_server_properties->SetAlternateProtocol(
8679 HostPortPair::FromURL(request.url),
8680 kUnsafePort,
8681 AlternateProtocolFromNextProto(GetParam()));
8683 scoped_ptr<HttpTransaction> trans(
8684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8685 TestCompletionCallback callback;
8687 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8688 EXPECT_EQ(ERR_IO_PENDING, rv);
8689 // The HTTP request should succeed.
8690 EXPECT_EQ(OK, callback.WaitForResult());
8692 // Disable alternate protocol before the asserts.
8693 HttpStreamFactory::set_use_alternate_protocols(false);
8695 const HttpResponseInfo* response = trans->GetResponseInfo();
8696 ASSERT_TRUE(response != NULL);
8697 ASSERT_TRUE(response->headers.get() != NULL);
8698 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8700 std::string response_data;
8701 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8702 EXPECT_EQ("hello world", response_data);
8705 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8706 HttpStreamFactory::set_use_alternate_protocols(true);
8707 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8709 HttpRequestInfo request;
8710 request.method = "GET";
8711 request.url = GURL("http://www.google.com/");
8712 request.load_flags = 0;
8714 std::string alternate_protocol_http_header =
8715 GetAlternateProtocolHttpHeader();
8717 MockRead data_reads[] = {
8718 MockRead("HTTP/1.1 200 OK\r\n"),
8719 MockRead(alternate_protocol_http_header.c_str()),
8720 MockRead("hello world"),
8721 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8722 MockRead(ASYNC, OK)
8725 StaticSocketDataProvider first_transaction(
8726 data_reads, arraysize(data_reads), NULL, 0);
8727 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8729 SSLSocketDataProvider ssl(ASYNC, OK);
8730 ssl.SetNextProto(GetParam());
8731 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8733 scoped_ptr<SpdyFrame> req(
8734 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8735 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8737 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8738 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8739 MockRead spdy_reads[] = {
8740 CreateMockRead(*resp),
8741 CreateMockRead(*data),
8742 MockRead(ASYNC, 0, 0),
8745 DelayedSocketData spdy_data(
8746 1, // wait for one write to finish before reading.
8747 spdy_reads, arraysize(spdy_reads),
8748 spdy_writes, arraysize(spdy_writes));
8749 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8751 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8752 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8753 NULL, 0, NULL, 0);
8754 hanging_non_alternate_protocol_socket.set_connect_data(
8755 never_finishing_connect);
8756 session_deps_.socket_factory->AddSocketDataProvider(
8757 &hanging_non_alternate_protocol_socket);
8759 TestCompletionCallback callback;
8761 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8762 scoped_ptr<HttpTransaction> trans(
8763 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8765 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8766 EXPECT_EQ(ERR_IO_PENDING, rv);
8767 EXPECT_EQ(OK, callback.WaitForResult());
8769 const HttpResponseInfo* response = trans->GetResponseInfo();
8770 ASSERT_TRUE(response != NULL);
8771 ASSERT_TRUE(response->headers.get() != NULL);
8772 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8774 std::string response_data;
8775 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8776 EXPECT_EQ("hello world", response_data);
8778 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8780 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8781 EXPECT_EQ(ERR_IO_PENDING, rv);
8782 EXPECT_EQ(OK, callback.WaitForResult());
8784 response = trans->GetResponseInfo();
8785 ASSERT_TRUE(response != NULL);
8786 ASSERT_TRUE(response->headers.get() != NULL);
8787 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8788 EXPECT_TRUE(response->was_fetched_via_spdy);
8789 EXPECT_TRUE(response->was_npn_negotiated);
8791 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8792 EXPECT_EQ("hello!", response_data);
8795 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8796 HttpStreamFactory::set_use_alternate_protocols(true);
8797 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8799 HttpRequestInfo request;
8800 request.method = "GET";
8801 request.url = GURL("http://www.google.com/");
8802 request.load_flags = 0;
8804 std::string alternate_protocol_http_header =
8805 GetAlternateProtocolHttpHeader();
8807 MockRead data_reads[] = {
8808 MockRead("HTTP/1.1 200 OK\r\n"),
8809 MockRead(alternate_protocol_http_header.c_str()),
8810 MockRead("hello world"),
8811 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8812 MockRead(ASYNC, OK),
8815 StaticSocketDataProvider first_transaction(
8816 data_reads, arraysize(data_reads), NULL, 0);
8817 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8818 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8820 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8821 StaticSocketDataProvider hanging_socket(
8822 NULL, 0, NULL, 0);
8823 hanging_socket.set_connect_data(never_finishing_connect);
8824 // Socket 2 and 3 are the hanging Alternate-Protocol and
8825 // non-Alternate-Protocol jobs from the 2nd transaction.
8826 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8827 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8829 SSLSocketDataProvider ssl(ASYNC, OK);
8830 ssl.SetNextProto(GetParam());
8831 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8833 scoped_ptr<SpdyFrame> req1(
8834 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8835 scoped_ptr<SpdyFrame> req2(
8836 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8837 MockWrite spdy_writes[] = {
8838 CreateMockWrite(*req1),
8839 CreateMockWrite(*req2),
8841 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8842 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8843 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8844 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8845 MockRead spdy_reads[] = {
8846 CreateMockRead(*resp1),
8847 CreateMockRead(*data1),
8848 CreateMockRead(*resp2),
8849 CreateMockRead(*data2),
8850 MockRead(ASYNC, 0, 0),
8853 DelayedSocketData spdy_data(
8854 2, // wait for writes to finish before reading.
8855 spdy_reads, arraysize(spdy_reads),
8856 spdy_writes, arraysize(spdy_writes));
8857 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8858 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8860 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8861 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8863 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8864 TestCompletionCallback callback1;
8865 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8867 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8868 EXPECT_EQ(ERR_IO_PENDING, rv);
8869 EXPECT_EQ(OK, callback1.WaitForResult());
8871 const HttpResponseInfo* response = trans1.GetResponseInfo();
8872 ASSERT_TRUE(response != NULL);
8873 ASSERT_TRUE(response->headers.get() != NULL);
8874 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8876 std::string response_data;
8877 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8878 EXPECT_EQ("hello world", response_data);
8880 TestCompletionCallback callback2;
8881 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8882 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8883 EXPECT_EQ(ERR_IO_PENDING, rv);
8885 TestCompletionCallback callback3;
8886 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8887 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8888 EXPECT_EQ(ERR_IO_PENDING, rv);
8890 EXPECT_EQ(OK, callback2.WaitForResult());
8891 EXPECT_EQ(OK, callback3.WaitForResult());
8893 response = trans2.GetResponseInfo();
8894 ASSERT_TRUE(response != NULL);
8895 ASSERT_TRUE(response->headers.get() != NULL);
8896 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8897 EXPECT_TRUE(response->was_fetched_via_spdy);
8898 EXPECT_TRUE(response->was_npn_negotiated);
8899 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8900 EXPECT_EQ("hello!", response_data);
8902 response = trans3.GetResponseInfo();
8903 ASSERT_TRUE(response != NULL);
8904 ASSERT_TRUE(response->headers.get() != NULL);
8905 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8906 EXPECT_TRUE(response->was_fetched_via_spdy);
8907 EXPECT_TRUE(response->was_npn_negotiated);
8908 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
8909 EXPECT_EQ("hello!", response_data);
8912 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
8913 HttpStreamFactory::set_use_alternate_protocols(true);
8914 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8916 HttpRequestInfo request;
8917 request.method = "GET";
8918 request.url = GURL("http://www.google.com/");
8919 request.load_flags = 0;
8921 std::string alternate_protocol_http_header =
8922 GetAlternateProtocolHttpHeader();
8924 MockRead data_reads[] = {
8925 MockRead("HTTP/1.1 200 OK\r\n"),
8926 MockRead(alternate_protocol_http_header.c_str()),
8927 MockRead("hello world"),
8928 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8929 MockRead(ASYNC, OK),
8932 StaticSocketDataProvider first_transaction(
8933 data_reads, arraysize(data_reads), NULL, 0);
8934 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8936 SSLSocketDataProvider ssl(ASYNC, OK);
8937 ssl.SetNextProto(GetParam());
8938 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8940 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8941 StaticSocketDataProvider hanging_alternate_protocol_socket(
8942 NULL, 0, NULL, 0);
8943 hanging_alternate_protocol_socket.set_connect_data(
8944 never_finishing_connect);
8945 session_deps_.socket_factory->AddSocketDataProvider(
8946 &hanging_alternate_protocol_socket);
8948 // 2nd request is just a copy of the first one, over HTTP again.
8949 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8951 TestCompletionCallback callback;
8953 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8954 scoped_ptr<HttpTransaction> trans(
8955 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8957 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8958 EXPECT_EQ(ERR_IO_PENDING, rv);
8959 EXPECT_EQ(OK, callback.WaitForResult());
8961 const HttpResponseInfo* response = trans->GetResponseInfo();
8962 ASSERT_TRUE(response != NULL);
8963 ASSERT_TRUE(response->headers.get() != NULL);
8964 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8966 std::string response_data;
8967 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8968 EXPECT_EQ("hello world", response_data);
8970 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8972 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8973 EXPECT_EQ(ERR_IO_PENDING, rv);
8974 EXPECT_EQ(OK, callback.WaitForResult());
8976 response = trans->GetResponseInfo();
8977 ASSERT_TRUE(response != NULL);
8978 ASSERT_TRUE(response->headers.get() != NULL);
8979 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8980 EXPECT_FALSE(response->was_fetched_via_spdy);
8981 EXPECT_FALSE(response->was_npn_negotiated);
8983 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8984 EXPECT_EQ("hello world", response_data);
8987 class CapturingProxyResolver : public ProxyResolver {
8988 public:
8989 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8990 virtual ~CapturingProxyResolver() {}
8992 virtual int GetProxyForURL(const GURL& url,
8993 ProxyInfo* results,
8994 const CompletionCallback& callback,
8995 RequestHandle* request,
8996 const BoundNetLog& net_log) OVERRIDE {
8997 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
8998 HostPortPair("myproxy", 80));
8999 results->UseProxyServer(proxy_server);
9000 resolved_.push_back(url);
9001 return OK;
9004 virtual void CancelRequest(RequestHandle request) OVERRIDE {
9005 NOTREACHED();
9008 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
9009 NOTREACHED();
9010 return LOAD_STATE_IDLE;
9013 virtual void CancelSetPacScript() OVERRIDE {
9014 NOTREACHED();
9017 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9018 const CompletionCallback& /*callback*/) OVERRIDE {
9019 return OK;
9022 const std::vector<GURL>& resolved() const { return resolved_; }
9024 private:
9025 std::vector<GURL> resolved_;
9027 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9030 TEST_P(HttpNetworkTransactionTest,
9031 UseAlternateProtocolForTunneledNpnSpdy) {
9032 HttpStreamFactory::set_use_alternate_protocols(true);
9033 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9035 ProxyConfig proxy_config;
9036 proxy_config.set_auto_detect(true);
9037 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9039 CapturingProxyResolver* capturing_proxy_resolver =
9040 new CapturingProxyResolver();
9041 session_deps_.proxy_service.reset(new ProxyService(
9042 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
9043 NULL));
9044 CapturingNetLog net_log;
9045 session_deps_.net_log = &net_log;
9047 HttpRequestInfo request;
9048 request.method = "GET";
9049 request.url = GURL("http://www.google.com/");
9050 request.load_flags = 0;
9052 std::string alternate_protocol_http_header =
9053 GetAlternateProtocolHttpHeader();
9055 MockRead data_reads[] = {
9056 MockRead("HTTP/1.1 200 OK\r\n"),
9057 MockRead(alternate_protocol_http_header.c_str()),
9058 MockRead("hello world"),
9059 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9060 MockRead(ASYNC, OK),
9063 StaticSocketDataProvider first_transaction(
9064 data_reads, arraysize(data_reads), NULL, 0);
9065 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9067 SSLSocketDataProvider ssl(ASYNC, OK);
9068 ssl.SetNextProto(GetParam());
9069 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9071 scoped_ptr<SpdyFrame> req(
9072 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9073 MockWrite spdy_writes[] = {
9074 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9075 "Host: www.google.com\r\n"
9076 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9077 CreateMockWrite(*req), // 3
9080 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9082 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9083 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9084 MockRead spdy_reads[] = {
9085 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
9086 CreateMockRead(*resp.get(), 4), // 2, 4
9087 CreateMockRead(*data.get(), 4), // 5
9088 MockRead(ASYNC, 0, 0, 4), // 6
9091 OrderedSocketData spdy_data(
9092 spdy_reads, arraysize(spdy_reads),
9093 spdy_writes, arraysize(spdy_writes));
9094 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9096 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9097 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9098 NULL, 0, NULL, 0);
9099 hanging_non_alternate_protocol_socket.set_connect_data(
9100 never_finishing_connect);
9101 session_deps_.socket_factory->AddSocketDataProvider(
9102 &hanging_non_alternate_protocol_socket);
9104 TestCompletionCallback callback;
9106 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9107 scoped_ptr<HttpTransaction> trans(
9108 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9110 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9111 EXPECT_EQ(ERR_IO_PENDING, rv);
9112 EXPECT_EQ(OK, callback.WaitForResult());
9114 const HttpResponseInfo* response = trans->GetResponseInfo();
9115 ASSERT_TRUE(response != NULL);
9116 ASSERT_TRUE(response->headers.get() != NULL);
9117 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9118 EXPECT_FALSE(response->was_fetched_via_spdy);
9119 EXPECT_FALSE(response->was_npn_negotiated);
9121 std::string response_data;
9122 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9123 EXPECT_EQ("hello world", response_data);
9125 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9127 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9128 EXPECT_EQ(ERR_IO_PENDING, rv);
9129 EXPECT_EQ(OK, callback.WaitForResult());
9131 response = trans->GetResponseInfo();
9132 ASSERT_TRUE(response != NULL);
9133 ASSERT_TRUE(response->headers.get() != NULL);
9134 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9135 EXPECT_TRUE(response->was_fetched_via_spdy);
9136 EXPECT_TRUE(response->was_npn_negotiated);
9138 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9139 EXPECT_EQ("hello!", response_data);
9140 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
9141 EXPECT_EQ("http://www.google.com/",
9142 capturing_proxy_resolver->resolved()[0].spec());
9143 EXPECT_EQ("https://www.google.com/",
9144 capturing_proxy_resolver->resolved()[1].spec());
9146 LoadTimingInfo load_timing_info;
9147 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9148 TestLoadTimingNotReusedWithPac(load_timing_info,
9149 CONNECT_TIMING_HAS_SSL_TIMES);
9152 TEST_P(HttpNetworkTransactionTest,
9153 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9154 HttpStreamFactory::set_use_alternate_protocols(true);
9155 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9157 HttpRequestInfo request;
9158 request.method = "GET";
9159 request.url = GURL("http://www.google.com/");
9160 request.load_flags = 0;
9162 std::string alternate_protocol_http_header =
9163 GetAlternateProtocolHttpHeader();
9165 MockRead data_reads[] = {
9166 MockRead("HTTP/1.1 200 OK\r\n"),
9167 MockRead(alternate_protocol_http_header.c_str()),
9168 MockRead("hello world"),
9169 MockRead(ASYNC, OK),
9172 StaticSocketDataProvider first_transaction(
9173 data_reads, arraysize(data_reads), NULL, 0);
9174 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9176 SSLSocketDataProvider ssl(ASYNC, OK);
9177 ssl.SetNextProto(GetParam());
9178 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9180 scoped_ptr<SpdyFrame> req(
9181 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9182 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9184 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9185 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9186 MockRead spdy_reads[] = {
9187 CreateMockRead(*resp),
9188 CreateMockRead(*data),
9189 MockRead(ASYNC, 0, 0),
9192 DelayedSocketData spdy_data(
9193 1, // wait for one write to finish before reading.
9194 spdy_reads, arraysize(spdy_reads),
9195 spdy_writes, arraysize(spdy_writes));
9196 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9198 TestCompletionCallback callback;
9200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9202 scoped_ptr<HttpTransaction> trans(
9203 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9205 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9206 EXPECT_EQ(ERR_IO_PENDING, rv);
9207 EXPECT_EQ(OK, callback.WaitForResult());
9209 const HttpResponseInfo* response = trans->GetResponseInfo();
9210 ASSERT_TRUE(response != NULL);
9211 ASSERT_TRUE(response->headers.get() != NULL);
9212 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9214 std::string response_data;
9215 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9216 EXPECT_EQ("hello world", response_data);
9218 // Set up an initial SpdySession in the pool to reuse.
9219 HostPortPair host_port_pair("www.google.com", 443);
9220 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9221 PRIVACY_MODE_DISABLED);
9222 base::WeakPtr<SpdySession> spdy_session =
9223 CreateSecureSpdySession(session, key, BoundNetLog());
9225 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9227 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9228 EXPECT_EQ(ERR_IO_PENDING, rv);
9229 EXPECT_EQ(OK, callback.WaitForResult());
9231 response = trans->GetResponseInfo();
9232 ASSERT_TRUE(response != NULL);
9233 ASSERT_TRUE(response->headers.get() != NULL);
9234 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9235 EXPECT_TRUE(response->was_fetched_via_spdy);
9236 EXPECT_TRUE(response->was_npn_negotiated);
9238 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9239 EXPECT_EQ("hello!", response_data);
9242 // GenerateAuthToken is a mighty big test.
9243 // It tests all permutation of GenerateAuthToken behavior:
9244 // - Synchronous and Asynchronous completion.
9245 // - OK or error on completion.
9246 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9247 // - HTTP or HTTPS backend (to include proxy tunneling).
9248 // - Non-authenticating and authenticating backend.
9250 // In all, there are 44 reasonable permuations (for example, if there are
9251 // problems generating an auth token for an authenticating proxy, we don't
9252 // need to test all permutations of the backend server).
9254 // The test proceeds by going over each of the configuration cases, and
9255 // potentially running up to three rounds in each of the tests. The TestConfig
9256 // specifies both the configuration for the test as well as the expectations
9257 // for the results.
9258 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9259 static const char kServer[] = "http://www.example.com";
9260 static const char kSecureServer[] = "https://www.example.com";
9261 static const char kProxy[] = "myproxy:70";
9262 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9264 enum AuthTiming {
9265 AUTH_NONE,
9266 AUTH_SYNC,
9267 AUTH_ASYNC,
9270 const MockWrite kGet(
9271 "GET / HTTP/1.1\r\n"
9272 "Host: www.example.com\r\n"
9273 "Connection: keep-alive\r\n\r\n");
9274 const MockWrite kGetProxy(
9275 "GET http://www.example.com/ HTTP/1.1\r\n"
9276 "Host: www.example.com\r\n"
9277 "Proxy-Connection: keep-alive\r\n\r\n");
9278 const MockWrite kGetAuth(
9279 "GET / HTTP/1.1\r\n"
9280 "Host: www.example.com\r\n"
9281 "Connection: keep-alive\r\n"
9282 "Authorization: auth_token\r\n\r\n");
9283 const MockWrite kGetProxyAuth(
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\r\n");
9288 const MockWrite kGetAuthThroughProxy(
9289 "GET http://www.example.com/ HTTP/1.1\r\n"
9290 "Host: www.example.com\r\n"
9291 "Proxy-Connection: keep-alive\r\n"
9292 "Authorization: auth_token\r\n\r\n");
9293 const MockWrite kGetAuthWithProxyAuth(
9294 "GET http://www.example.com/ 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"
9298 "Authorization: auth_token\r\n\r\n");
9299 const MockWrite kConnect(
9300 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9301 "Host: www.example.com\r\n"
9302 "Proxy-Connection: keep-alive\r\n\r\n");
9303 const MockWrite kConnectProxyAuth(
9304 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9305 "Host: www.example.com\r\n"
9306 "Proxy-Connection: keep-alive\r\n"
9307 "Proxy-Authorization: auth_token\r\n\r\n");
9309 const MockRead kSuccess(
9310 "HTTP/1.1 200 OK\r\n"
9311 "Content-Type: text/html; charset=iso-8859-1\r\n"
9312 "Content-Length: 3\r\n\r\n"
9313 "Yes");
9314 const MockRead kFailure(
9315 "Should not be called.");
9316 const MockRead kServerChallenge(
9317 "HTTP/1.1 401 Unauthorized\r\n"
9318 "WWW-Authenticate: Mock realm=server\r\n"
9319 "Content-Type: text/html; charset=iso-8859-1\r\n"
9320 "Content-Length: 14\r\n\r\n"
9321 "Unauthorized\r\n");
9322 const MockRead kProxyChallenge(
9323 "HTTP/1.1 407 Unauthorized\r\n"
9324 "Proxy-Authenticate: Mock realm=proxy\r\n"
9325 "Proxy-Connection: close\r\n"
9326 "Content-Type: text/html; charset=iso-8859-1\r\n"
9327 "Content-Length: 14\r\n\r\n"
9328 "Unauthorized\r\n");
9329 const MockRead kProxyConnected(
9330 "HTTP/1.1 200 Connection Established\r\n\r\n");
9332 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9333 // no constructors, but the C++ compiler on Windows warns about
9334 // unspecified data in compound literals. So, moved to using constructors,
9335 // and TestRound's created with the default constructor should not be used.
9336 struct TestRound {
9337 TestRound()
9338 : expected_rv(ERR_UNEXPECTED),
9339 extra_write(NULL),
9340 extra_read(NULL) {
9342 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9343 int expected_rv_arg)
9344 : write(write_arg),
9345 read(read_arg),
9346 expected_rv(expected_rv_arg),
9347 extra_write(NULL),
9348 extra_read(NULL) {
9350 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9351 int expected_rv_arg, const MockWrite* extra_write_arg,
9352 const MockRead* extra_read_arg)
9353 : write(write_arg),
9354 read(read_arg),
9355 expected_rv(expected_rv_arg),
9356 extra_write(extra_write_arg),
9357 extra_read(extra_read_arg) {
9359 MockWrite write;
9360 MockRead read;
9361 int expected_rv;
9362 const MockWrite* extra_write;
9363 const MockRead* extra_read;
9366 static const int kNoSSL = 500;
9368 struct TestConfig {
9369 const char* proxy_url;
9370 AuthTiming proxy_auth_timing;
9371 int proxy_auth_rv;
9372 const char* server_url;
9373 AuthTiming server_auth_timing;
9374 int server_auth_rv;
9375 int num_auth_rounds;
9376 int first_ssl_round;
9377 TestRound rounds[3];
9378 } test_configs[] = {
9379 // Non-authenticating HTTP server with a direct connection.
9380 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9381 { TestRound(kGet, kSuccess, OK)}},
9382 // Authenticating HTTP server with a direct connection.
9383 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9384 { TestRound(kGet, kServerChallenge, OK),
9385 TestRound(kGetAuth, kSuccess, OK)}},
9386 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9387 { TestRound(kGet, kServerChallenge, OK),
9388 TestRound(kGetAuth, kFailure, kAuthErr)}},
9389 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9390 { TestRound(kGet, kServerChallenge, OK),
9391 TestRound(kGetAuth, kSuccess, OK)}},
9392 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9393 { TestRound(kGet, kServerChallenge, OK),
9394 TestRound(kGetAuth, kFailure, kAuthErr)}},
9395 // Non-authenticating HTTP server through a non-authenticating proxy.
9396 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9397 { TestRound(kGetProxy, kSuccess, OK)}},
9398 // Authenticating HTTP server through a non-authenticating proxy.
9399 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9400 { TestRound(kGetProxy, kServerChallenge, OK),
9401 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9402 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9403 { TestRound(kGetProxy, kServerChallenge, OK),
9404 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9405 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9406 { TestRound(kGetProxy, kServerChallenge, OK),
9407 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9408 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9409 { TestRound(kGetProxy, kServerChallenge, OK),
9410 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9411 // Non-authenticating HTTP server through an authenticating proxy.
9412 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9413 { TestRound(kGetProxy, kProxyChallenge, OK),
9414 TestRound(kGetProxyAuth, kSuccess, OK)}},
9415 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9416 { TestRound(kGetProxy, kProxyChallenge, OK),
9417 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9418 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9419 { TestRound(kGetProxy, kProxyChallenge, OK),
9420 TestRound(kGetProxyAuth, kSuccess, OK)}},
9421 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9422 { TestRound(kGetProxy, kProxyChallenge, OK),
9423 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9424 // Authenticating HTTP server through an authenticating proxy.
9425 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9426 { TestRound(kGetProxy, kProxyChallenge, OK),
9427 TestRound(kGetProxyAuth, kServerChallenge, OK),
9428 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9429 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9430 { TestRound(kGetProxy, kProxyChallenge, OK),
9431 TestRound(kGetProxyAuth, kServerChallenge, OK),
9432 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9433 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9434 { TestRound(kGetProxy, kProxyChallenge, OK),
9435 TestRound(kGetProxyAuth, kServerChallenge, OK),
9436 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9437 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9438 { TestRound(kGetProxy, kProxyChallenge, OK),
9439 TestRound(kGetProxyAuth, kServerChallenge, OK),
9440 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9441 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9442 { TestRound(kGetProxy, kProxyChallenge, OK),
9443 TestRound(kGetProxyAuth, kServerChallenge, OK),
9444 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9445 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9446 { TestRound(kGetProxy, kProxyChallenge, OK),
9447 TestRound(kGetProxyAuth, kServerChallenge, OK),
9448 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9449 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9450 { TestRound(kGetProxy, kProxyChallenge, OK),
9451 TestRound(kGetProxyAuth, kServerChallenge, OK),
9452 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9453 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9454 { TestRound(kGetProxy, kProxyChallenge, OK),
9455 TestRound(kGetProxyAuth, kServerChallenge, OK),
9456 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9457 // Non-authenticating HTTPS server with a direct connection.
9458 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9459 { TestRound(kGet, kSuccess, OK)}},
9460 // Authenticating HTTPS server with a direct connection.
9461 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9462 { TestRound(kGet, kServerChallenge, OK),
9463 TestRound(kGetAuth, kSuccess, OK)}},
9464 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9465 { TestRound(kGet, kServerChallenge, OK),
9466 TestRound(kGetAuth, kFailure, kAuthErr)}},
9467 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9468 { TestRound(kGet, kServerChallenge, OK),
9469 TestRound(kGetAuth, kSuccess, OK)}},
9470 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9471 { TestRound(kGet, kServerChallenge, OK),
9472 TestRound(kGetAuth, kFailure, kAuthErr)}},
9473 // Non-authenticating HTTPS server with a non-authenticating proxy.
9474 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9475 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9476 // Authenticating HTTPS server through a non-authenticating proxy.
9477 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9478 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9479 TestRound(kGetAuth, kSuccess, OK)}},
9480 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9481 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9482 TestRound(kGetAuth, kFailure, kAuthErr)}},
9483 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9484 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9485 TestRound(kGetAuth, kSuccess, OK)}},
9486 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9487 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9488 TestRound(kGetAuth, kFailure, kAuthErr)}},
9489 // Non-Authenticating HTTPS server through an authenticating proxy.
9490 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9491 { TestRound(kConnect, kProxyChallenge, OK),
9492 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9493 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9494 { TestRound(kConnect, kProxyChallenge, OK),
9495 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9496 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9497 { TestRound(kConnect, kProxyChallenge, OK),
9498 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9499 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9500 { TestRound(kConnect, kProxyChallenge, OK),
9501 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9502 // Authenticating HTTPS server through an authenticating proxy.
9503 { kProxy, AUTH_SYNC, 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_SYNC, 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_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9514 { TestRound(kConnect, kProxyChallenge, OK),
9515 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9516 &kGet, &kServerChallenge),
9517 TestRound(kGetAuth, kSuccess, OK)}},
9518 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9519 { TestRound(kConnect, kProxyChallenge, OK),
9520 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9521 &kGet, &kServerChallenge),
9522 TestRound(kGetAuth, kFailure, kAuthErr)}},
9523 { kProxy, AUTH_SYNC, 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_SYNC, 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)}},
9533 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9534 { TestRound(kConnect, kProxyChallenge, OK),
9535 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9536 &kGet, &kServerChallenge),
9537 TestRound(kGetAuth, kSuccess, OK)}},
9538 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9539 { TestRound(kConnect, kProxyChallenge, OK),
9540 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9541 &kGet, &kServerChallenge),
9542 TestRound(kGetAuth, kFailure, kAuthErr)}},
9545 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9546 HttpAuthHandlerMock::Factory* auth_factory(
9547 new HttpAuthHandlerMock::Factory());
9548 session_deps_.http_auth_handler_factory.reset(auth_factory);
9549 const TestConfig& test_config = test_configs[i];
9551 // Set up authentication handlers as necessary.
9552 if (test_config.proxy_auth_timing != AUTH_NONE) {
9553 for (int n = 0; n < 2; n++) {
9554 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9555 std::string auth_challenge = "Mock realm=proxy";
9556 GURL origin(test_config.proxy_url);
9557 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9558 auth_challenge.end());
9559 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9560 origin, BoundNetLog());
9561 auth_handler->SetGenerateExpectation(
9562 test_config.proxy_auth_timing == AUTH_ASYNC,
9563 test_config.proxy_auth_rv);
9564 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9567 if (test_config.server_auth_timing != AUTH_NONE) {
9568 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9569 std::string auth_challenge = "Mock realm=server";
9570 GURL origin(test_config.server_url);
9571 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9572 auth_challenge.end());
9573 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9574 origin, BoundNetLog());
9575 auth_handler->SetGenerateExpectation(
9576 test_config.server_auth_timing == AUTH_ASYNC,
9577 test_config.server_auth_rv);
9578 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9580 if (test_config.proxy_url) {
9581 session_deps_.proxy_service.reset(
9582 ProxyService::CreateFixed(test_config.proxy_url));
9583 } else {
9584 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9587 HttpRequestInfo request;
9588 request.method = "GET";
9589 request.url = GURL(test_config.server_url);
9590 request.load_flags = 0;
9592 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9593 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
9595 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9596 const TestRound& read_write_round = test_config.rounds[round];
9598 // Set up expected reads and writes.
9599 MockRead reads[2];
9600 reads[0] = read_write_round.read;
9601 size_t length_reads = 1;
9602 if (read_write_round.extra_read) {
9603 reads[1] = *read_write_round.extra_read;
9604 length_reads = 2;
9607 MockWrite writes[2];
9608 writes[0] = read_write_round.write;
9609 size_t length_writes = 1;
9610 if (read_write_round.extra_write) {
9611 writes[1] = *read_write_round.extra_write;
9612 length_writes = 2;
9614 StaticSocketDataProvider data_provider(
9615 reads, length_reads, writes, length_writes);
9616 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9618 // Add an SSL sequence if necessary.
9619 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9620 if (round >= test_config.first_ssl_round)
9621 session_deps_.socket_factory->AddSSLSocketDataProvider(
9622 &ssl_socket_data_provider);
9624 // Start or restart the transaction.
9625 TestCompletionCallback callback;
9626 int rv;
9627 if (round == 0) {
9628 rv = trans.Start(&request, callback.callback(), BoundNetLog());
9629 } else {
9630 rv = trans.RestartWithAuth(
9631 AuthCredentials(kFoo, kBar), callback.callback());
9633 if (rv == ERR_IO_PENDING)
9634 rv = callback.WaitForResult();
9636 // Compare results with expected data.
9637 EXPECT_EQ(read_write_round.expected_rv, rv);
9638 const HttpResponseInfo* response = trans.GetResponseInfo();
9639 if (read_write_round.expected_rv == OK) {
9640 ASSERT_TRUE(response != NULL);
9641 } else {
9642 EXPECT_TRUE(response == NULL);
9643 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9644 continue;
9646 if (round + 1 < test_config.num_auth_rounds) {
9647 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9648 } else {
9649 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9655 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9656 // Do multi-round authentication and make sure it works correctly.
9657 HttpAuthHandlerMock::Factory* auth_factory(
9658 new HttpAuthHandlerMock::Factory());
9659 session_deps_.http_auth_handler_factory.reset(auth_factory);
9660 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9661 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9662 session_deps_.host_resolver->set_synchronous_mode(true);
9664 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9665 auth_handler->set_connection_based(true);
9666 std::string auth_challenge = "Mock realm=server";
9667 GURL origin("http://www.example.com");
9668 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9669 auth_challenge.end());
9670 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9671 origin, BoundNetLog());
9672 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9674 int rv = OK;
9675 const HttpResponseInfo* response = NULL;
9676 HttpRequestInfo request;
9677 request.method = "GET";
9678 request.url = origin;
9679 request.load_flags = 0;
9681 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9683 // Use a TCP Socket Pool with only one connection per group. This is used
9684 // to validate that the TCP socket is not released to the pool between
9685 // each round of multi-round authentication.
9686 HttpNetworkSessionPeer session_peer(session);
9687 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9688 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9689 50, // Max sockets for pool
9690 1, // Max sockets per group
9691 &transport_pool_histograms,
9692 session_deps_.host_resolver.get(),
9693 session_deps_.socket_factory.get(),
9694 session_deps_.net_log);
9695 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
9696 new MockClientSocketPoolManager);
9697 mock_pool_manager->SetTransportSocketPool(transport_pool);
9698 session_peer.SetClientSocketPoolManager(
9699 mock_pool_manager.PassAs<ClientSocketPoolManager>());
9701 scoped_ptr<HttpTransaction> trans(
9702 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9703 TestCompletionCallback callback;
9705 const MockWrite kGet(
9706 "GET / HTTP/1.1\r\n"
9707 "Host: www.example.com\r\n"
9708 "Connection: keep-alive\r\n\r\n");
9709 const MockWrite kGetAuth(
9710 "GET / HTTP/1.1\r\n"
9711 "Host: www.example.com\r\n"
9712 "Connection: keep-alive\r\n"
9713 "Authorization: auth_token\r\n\r\n");
9715 const MockRead kServerChallenge(
9716 "HTTP/1.1 401 Unauthorized\r\n"
9717 "WWW-Authenticate: Mock realm=server\r\n"
9718 "Content-Type: text/html; charset=iso-8859-1\r\n"
9719 "Content-Length: 14\r\n\r\n"
9720 "Unauthorized\r\n");
9721 const MockRead kSuccess(
9722 "HTTP/1.1 200 OK\r\n"
9723 "Content-Type: text/html; charset=iso-8859-1\r\n"
9724 "Content-Length: 3\r\n\r\n"
9725 "Yes");
9727 MockWrite writes[] = {
9728 // First round
9729 kGet,
9730 // Second round
9731 kGetAuth,
9732 // Third round
9733 kGetAuth,
9734 // Fourth round
9735 kGetAuth,
9736 // Competing request
9737 kGet,
9739 MockRead reads[] = {
9740 // First round
9741 kServerChallenge,
9742 // Second round
9743 kServerChallenge,
9744 // Third round
9745 kServerChallenge,
9746 // Fourth round
9747 kSuccess,
9748 // Competing response
9749 kSuccess,
9751 StaticSocketDataProvider data_provider(reads, arraysize(reads),
9752 writes, arraysize(writes));
9753 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9755 const char* const kSocketGroup = "www.example.com:80";
9757 // First round of authentication.
9758 auth_handler->SetGenerateExpectation(false, OK);
9759 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9760 if (rv == ERR_IO_PENDING)
9761 rv = callback.WaitForResult();
9762 EXPECT_EQ(OK, rv);
9763 response = trans->GetResponseInfo();
9764 ASSERT_TRUE(response != NULL);
9765 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9766 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9768 // In between rounds, another request comes in for the same domain.
9769 // It should not be able to grab the TCP socket that trans has already
9770 // claimed.
9771 scoped_ptr<HttpTransaction> trans_compete(
9772 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9773 TestCompletionCallback callback_compete;
9774 rv = trans_compete->Start(
9775 &request, callback_compete.callback(), BoundNetLog());
9776 EXPECT_EQ(ERR_IO_PENDING, rv);
9777 // callback_compete.WaitForResult at this point would stall forever,
9778 // since the HttpNetworkTransaction does not release the request back to
9779 // the pool until after authentication completes.
9781 // Second round of authentication.
9782 auth_handler->SetGenerateExpectation(false, OK);
9783 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9784 if (rv == ERR_IO_PENDING)
9785 rv = callback.WaitForResult();
9786 EXPECT_EQ(OK, rv);
9787 response = trans->GetResponseInfo();
9788 ASSERT_TRUE(response != NULL);
9789 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9790 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9792 // Third round of authentication.
9793 auth_handler->SetGenerateExpectation(false, OK);
9794 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9795 if (rv == ERR_IO_PENDING)
9796 rv = callback.WaitForResult();
9797 EXPECT_EQ(OK, rv);
9798 response = trans->GetResponseInfo();
9799 ASSERT_TRUE(response != NULL);
9800 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9801 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9803 // Fourth round of authentication, which completes successfully.
9804 auth_handler->SetGenerateExpectation(false, OK);
9805 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9806 if (rv == ERR_IO_PENDING)
9807 rv = callback.WaitForResult();
9808 EXPECT_EQ(OK, rv);
9809 response = trans->GetResponseInfo();
9810 ASSERT_TRUE(response != NULL);
9811 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9812 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9814 // Read the body since the fourth round was successful. This will also
9815 // release the socket back to the pool.
9816 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9817 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9818 if (rv == ERR_IO_PENDING)
9819 rv = callback.WaitForResult();
9820 EXPECT_EQ(3, rv);
9821 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9822 EXPECT_EQ(0, rv);
9823 // There are still 0 idle sockets, since the trans_compete transaction
9824 // will be handed it immediately after trans releases it to the group.
9825 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9827 // The competing request can now finish. Wait for the headers and then
9828 // read the body.
9829 rv = callback_compete.WaitForResult();
9830 EXPECT_EQ(OK, rv);
9831 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9832 if (rv == ERR_IO_PENDING)
9833 rv = callback.WaitForResult();
9834 EXPECT_EQ(3, rv);
9835 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9836 EXPECT_EQ(0, rv);
9838 // Finally, the socket is released to the group.
9839 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9842 // This tests the case that a request is issued via http instead of spdy after
9843 // npn is negotiated.
9844 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9845 HttpStreamFactory::set_use_alternate_protocols(true);
9846 std::vector<NextProto> next_protos;
9847 next_protos.push_back(kProtoHTTP11);
9848 HttpStreamFactory::SetNextProtos(next_protos);
9849 HttpRequestInfo request;
9850 request.method = "GET";
9851 request.url = GURL("https://www.google.com/");
9852 request.load_flags = 0;
9854 MockWrite data_writes[] = {
9855 MockWrite("GET / HTTP/1.1\r\n"
9856 "Host: www.google.com\r\n"
9857 "Connection: keep-alive\r\n\r\n"),
9860 std::string alternate_protocol_http_header =
9861 GetAlternateProtocolHttpHeader();
9863 MockRead data_reads[] = {
9864 MockRead("HTTP/1.1 200 OK\r\n"),
9865 MockRead(alternate_protocol_http_header.c_str()),
9866 MockRead("hello world"),
9867 MockRead(SYNCHRONOUS, OK),
9870 SSLSocketDataProvider ssl(ASYNC, OK);
9871 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9872 ssl.next_proto = "http/1.1";
9873 ssl.protocol_negotiated = kProtoHTTP11;
9875 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9877 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9878 data_writes, arraysize(data_writes));
9879 session_deps_.socket_factory->AddSocketDataProvider(&data);
9881 TestCompletionCallback callback;
9883 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9884 scoped_ptr<HttpTransaction> trans(
9885 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9887 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9889 EXPECT_EQ(ERR_IO_PENDING, rv);
9890 EXPECT_EQ(OK, callback.WaitForResult());
9892 const HttpResponseInfo* response = trans->GetResponseInfo();
9893 ASSERT_TRUE(response != NULL);
9894 ASSERT_TRUE(response->headers.get() != NULL);
9895 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9897 std::string response_data;
9898 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9899 EXPECT_EQ("hello world", response_data);
9901 EXPECT_FALSE(response->was_fetched_via_spdy);
9902 EXPECT_TRUE(response->was_npn_negotiated);
9905 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
9906 // Simulate the SSL handshake completing with an NPN negotiation
9907 // followed by an immediate server closing of the socket.
9908 // Fix crash: http://crbug.com/46369
9909 HttpStreamFactory::set_use_alternate_protocols(true);
9910 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9912 HttpRequestInfo request;
9913 request.method = "GET";
9914 request.url = GURL("https://www.google.com/");
9915 request.load_flags = 0;
9917 SSLSocketDataProvider ssl(ASYNC, OK);
9918 ssl.SetNextProto(GetParam());
9919 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9921 scoped_ptr<SpdyFrame> req(
9922 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9923 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9925 MockRead spdy_reads[] = {
9926 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
9929 DelayedSocketData spdy_data(
9930 0, // don't wait in this case, immediate hangup.
9931 spdy_reads, arraysize(spdy_reads),
9932 spdy_writes, arraysize(spdy_writes));
9933 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9935 TestCompletionCallback callback;
9937 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9938 scoped_ptr<HttpTransaction> trans(
9939 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9941 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9942 EXPECT_EQ(ERR_IO_PENDING, rv);
9943 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
9946 // A subclass of HttpAuthHandlerMock that records the request URL when
9947 // it gets it. This is needed since the auth handler may get destroyed
9948 // before we get a chance to query it.
9949 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
9950 public:
9951 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
9953 virtual ~UrlRecordingHttpAuthHandlerMock() {}
9955 protected:
9956 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
9957 const HttpRequestInfo* request,
9958 const CompletionCallback& callback,
9959 std::string* auth_token) OVERRIDE {
9960 *url_ = request->url;
9961 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9962 credentials, request, callback, auth_token);
9965 private:
9966 GURL* url_;
9969 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
9970 // This test ensures that the URL passed into the proxy is upgraded
9971 // to https when doing an Alternate Protocol upgrade.
9972 HttpStreamFactory::set_use_alternate_protocols(true);
9973 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9975 session_deps_.proxy_service.reset(
9976 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9977 CapturingNetLog net_log;
9978 session_deps_.net_log = &net_log;
9979 GURL request_url;
9981 HttpAuthHandlerMock::Factory* auth_factory =
9982 new HttpAuthHandlerMock::Factory();
9983 UrlRecordingHttpAuthHandlerMock* auth_handler =
9984 new UrlRecordingHttpAuthHandlerMock(&request_url);
9985 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9986 auth_factory->set_do_init_from_challenge(true);
9987 session_deps_.http_auth_handler_factory.reset(auth_factory);
9990 HttpRequestInfo request;
9991 request.method = "GET";
9992 request.url = GURL("http://www.google.com");
9993 request.load_flags = 0;
9995 // First round goes unauthenticated through the proxy.
9996 MockWrite data_writes_1[] = {
9997 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9998 "Host: www.google.com\r\n"
9999 "Proxy-Connection: keep-alive\r\n"
10000 "\r\n"),
10002 MockRead data_reads_1[] = {
10003 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10004 MockRead("HTTP/1.1 200 OK\r\n"
10005 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10006 "Proxy-Connection: close\r\n"
10007 "\r\n"),
10009 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10010 data_writes_1, arraysize(data_writes_1));
10012 // Second round tries to tunnel to www.google.com due to the
10013 // Alternate-Protocol announcement in the first round. It fails due
10014 // to a proxy authentication challenge.
10015 // After the failure, a tunnel is established to www.google.com using
10016 // Proxy-Authorization headers. There is then a SPDY request round.
10018 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10019 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10020 // does a Disconnect and Connect on the same socket, rather than trying
10021 // to obtain a new one.
10023 // NOTE: Originally, the proxy response to the second CONNECT request
10024 // simply returned another 407 so the unit test could skip the SSL connection
10025 // establishment and SPDY framing issues. Alas, the
10026 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10027 // complicated to set up expectations for than the SPDY session.
10029 scoped_ptr<SpdyFrame> req(
10030 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10031 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10032 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10034 MockWrite data_writes_2[] = {
10035 // First connection attempt without Proxy-Authorization.
10036 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10037 "Host: www.google.com\r\n"
10038 "Proxy-Connection: keep-alive\r\n"
10039 "\r\n"),
10041 // Second connection attempt with Proxy-Authorization.
10042 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10043 "Host: www.google.com\r\n"
10044 "Proxy-Connection: keep-alive\r\n"
10045 "Proxy-Authorization: auth_token\r\n"
10046 "\r\n"),
10048 // SPDY request
10049 CreateMockWrite(*req),
10051 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10052 "Proxy-Authenticate: Mock\r\n"
10053 "Proxy-Connection: close\r\n"
10054 "\r\n");
10055 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10056 MockRead data_reads_2[] = {
10057 // First connection attempt fails
10058 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
10059 MockRead(ASYNC, kRejectConnectResponse,
10060 arraysize(kRejectConnectResponse) - 1, 1),
10062 // Second connection attempt passes
10063 MockRead(ASYNC, kAcceptConnectResponse,
10064 arraysize(kAcceptConnectResponse) -1, 4),
10066 // SPDY response
10067 CreateMockRead(*resp.get(), 6),
10068 CreateMockRead(*data.get(), 6),
10069 MockRead(ASYNC, 0, 0, 6),
10071 OrderedSocketData data_2(
10072 data_reads_2, arraysize(data_reads_2),
10073 data_writes_2, arraysize(data_writes_2));
10075 SSLSocketDataProvider ssl(ASYNC, OK);
10076 ssl.SetNextProto(GetParam());
10078 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10079 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10080 NULL, 0, NULL, 0);
10081 hanging_non_alternate_protocol_socket.set_connect_data(
10082 never_finishing_connect);
10084 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10085 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10086 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10087 session_deps_.socket_factory->AddSocketDataProvider(
10088 &hanging_non_alternate_protocol_socket);
10089 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10091 // First round should work and provide the Alternate-Protocol state.
10092 TestCompletionCallback callback_1;
10093 scoped_ptr<HttpTransaction> trans_1(
10094 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10095 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10096 EXPECT_EQ(ERR_IO_PENDING, rv);
10097 EXPECT_EQ(OK, callback_1.WaitForResult());
10099 // Second round should attempt a tunnel connect and get an auth challenge.
10100 TestCompletionCallback callback_2;
10101 scoped_ptr<HttpTransaction> trans_2(
10102 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10103 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10104 EXPECT_EQ(ERR_IO_PENDING, rv);
10105 EXPECT_EQ(OK, callback_2.WaitForResult());
10106 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10107 ASSERT_TRUE(response != NULL);
10108 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10110 // Restart with auth. Tunnel should work and response received.
10111 TestCompletionCallback callback_3;
10112 rv = trans_2->RestartWithAuth(
10113 AuthCredentials(kFoo, kBar), callback_3.callback());
10114 EXPECT_EQ(ERR_IO_PENDING, rv);
10115 EXPECT_EQ(OK, callback_3.WaitForResult());
10117 // After all that work, these two lines (or actually, just the scheme) are
10118 // what this test is all about. Make sure it happens correctly.
10119 EXPECT_EQ("https", request_url.scheme());
10120 EXPECT_EQ("www.google.com", request_url.host());
10122 LoadTimingInfo load_timing_info;
10123 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10124 TestLoadTimingNotReusedWithPac(load_timing_info,
10125 CONNECT_TIMING_HAS_SSL_TIMES);
10128 // Test that if we cancel the transaction as the connection is completing, that
10129 // everything tears down correctly.
10130 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10131 // Setup everything about the connection to complete synchronously, so that
10132 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10133 // for is the callback from the HttpStreamRequest.
10134 // Then cancel the transaction.
10135 // Verify that we don't crash.
10136 MockConnect mock_connect(SYNCHRONOUS, OK);
10137 MockRead data_reads[] = {
10138 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10139 MockRead(SYNCHRONOUS, "hello world"),
10140 MockRead(SYNCHRONOUS, OK),
10143 HttpRequestInfo request;
10144 request.method = "GET";
10145 request.url = GURL("http://www.google.com/");
10146 request.load_flags = 0;
10148 session_deps_.host_resolver->set_synchronous_mode(true);
10149 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10150 scoped_ptr<HttpTransaction> trans(
10151 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
10153 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10154 data.set_connect_data(mock_connect);
10155 session_deps_.socket_factory->AddSocketDataProvider(&data);
10157 TestCompletionCallback callback;
10159 CapturingBoundNetLog log;
10160 int rv = trans->Start(&request, callback.callback(), log.bound());
10161 EXPECT_EQ(ERR_IO_PENDING, rv);
10162 trans.reset(); // Cancel the transaction here.
10164 base::MessageLoop::current()->RunUntilIdle();
10167 // Test a basic GET request through a proxy.
10168 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10169 session_deps_.proxy_service.reset(
10170 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10171 CapturingBoundNetLog log;
10172 session_deps_.net_log = log.bound().net_log();
10173 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10175 HttpRequestInfo request;
10176 request.method = "GET";
10177 request.url = GURL("http://www.google.com/");
10179 MockWrite data_writes1[] = {
10180 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10181 "Host: www.google.com\r\n"
10182 "Proxy-Connection: keep-alive\r\n\r\n"),
10185 MockRead data_reads1[] = {
10186 MockRead("HTTP/1.1 200 OK\r\n"),
10187 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10188 MockRead("Content-Length: 100\r\n\r\n"),
10189 MockRead(SYNCHRONOUS, OK),
10192 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10193 data_writes1, arraysize(data_writes1));
10194 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10196 TestCompletionCallback callback1;
10198 scoped_ptr<HttpTransaction> trans(
10199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10201 int rv = trans->Start(&request, callback1.callback(), log.bound());
10202 EXPECT_EQ(ERR_IO_PENDING, rv);
10204 rv = callback1.WaitForResult();
10205 EXPECT_EQ(OK, rv);
10207 const HttpResponseInfo* response = trans->GetResponseInfo();
10208 ASSERT_TRUE(response != NULL);
10210 EXPECT_TRUE(response->headers->IsKeepAlive());
10211 EXPECT_EQ(200, response->headers->response_code());
10212 EXPECT_EQ(100, response->headers->GetContentLength());
10213 EXPECT_TRUE(response->was_fetched_via_proxy);
10214 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10216 LoadTimingInfo load_timing_info;
10217 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10218 TestLoadTimingNotReusedWithPac(load_timing_info,
10219 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10222 // Test a basic HTTPS GET request through a proxy.
10223 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10224 session_deps_.proxy_service.reset(
10225 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10226 CapturingBoundNetLog log;
10227 session_deps_.net_log = log.bound().net_log();
10228 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10230 HttpRequestInfo request;
10231 request.method = "GET";
10232 request.url = GURL("https://www.google.com/");
10234 // Since we have proxy, should try to establish tunnel.
10235 MockWrite data_writes1[] = {
10236 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10237 "Host: www.google.com\r\n"
10238 "Proxy-Connection: keep-alive\r\n\r\n"),
10240 MockWrite("GET / HTTP/1.1\r\n"
10241 "Host: www.google.com\r\n"
10242 "Connection: keep-alive\r\n\r\n"),
10245 MockRead data_reads1[] = {
10246 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10248 MockRead("HTTP/1.1 200 OK\r\n"),
10249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10250 MockRead("Content-Length: 100\r\n\r\n"),
10251 MockRead(SYNCHRONOUS, OK),
10254 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10255 data_writes1, arraysize(data_writes1));
10256 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10257 SSLSocketDataProvider ssl(ASYNC, OK);
10258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10260 TestCompletionCallback callback1;
10262 scoped_ptr<HttpTransaction> trans(
10263 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10265 int rv = trans->Start(&request, callback1.callback(), log.bound());
10266 EXPECT_EQ(ERR_IO_PENDING, rv);
10268 rv = callback1.WaitForResult();
10269 EXPECT_EQ(OK, rv);
10270 net::CapturingNetLog::CapturedEntryList entries;
10271 log.GetEntries(&entries);
10272 size_t pos = ExpectLogContainsSomewhere(
10273 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10274 NetLog::PHASE_NONE);
10275 ExpectLogContainsSomewhere(
10276 entries, pos,
10277 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10278 NetLog::PHASE_NONE);
10280 const HttpResponseInfo* response = trans->GetResponseInfo();
10281 ASSERT_TRUE(response != NULL);
10283 EXPECT_TRUE(response->headers->IsKeepAlive());
10284 EXPECT_EQ(200, response->headers->response_code());
10285 EXPECT_EQ(100, response->headers->GetContentLength());
10286 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10287 EXPECT_TRUE(response->was_fetched_via_proxy);
10289 LoadTimingInfo load_timing_info;
10290 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10291 TestLoadTimingNotReusedWithPac(load_timing_info,
10292 CONNECT_TIMING_HAS_SSL_TIMES);
10295 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10296 // while establishing the tunnel.
10297 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10298 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10299 CapturingBoundNetLog log;
10300 session_deps_.net_log = log.bound().net_log();
10301 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10303 HttpRequestInfo request;
10304 request.method = "GET";
10305 request.url = GURL("https://www.google.com/");
10307 // Since we have proxy, should try to establish tunnel.
10308 MockWrite data_writes1[] = {
10309 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10310 "Host: www.google.com\r\n"
10311 "Proxy-Connection: keep-alive\r\n\r\n"),
10313 MockWrite("GET / HTTP/1.1\r\n"
10314 "Host: www.google.com\r\n"
10315 "Connection: keep-alive\r\n\r\n"),
10318 MockRead data_reads1[] = {
10319 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10320 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10321 MockRead(ASYNC, 0, 0), // EOF
10324 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10325 data_writes1, arraysize(data_writes1));
10326 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10327 SSLSocketDataProvider ssl(ASYNC, OK);
10328 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10330 TestCompletionCallback callback1;
10332 scoped_ptr<HttpTransaction> trans(
10333 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10335 int rv = trans->Start(&request, callback1.callback(), log.bound());
10336 EXPECT_EQ(ERR_IO_PENDING, rv);
10338 rv = callback1.WaitForResult();
10339 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10340 net::CapturingNetLog::CapturedEntryList entries;
10341 log.GetEntries(&entries);
10342 size_t pos = ExpectLogContainsSomewhere(
10343 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10344 NetLog::PHASE_NONE);
10345 ExpectLogContainsSomewhere(
10346 entries, pos,
10347 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10348 NetLog::PHASE_NONE);
10351 // Test for crbug.com/55424.
10352 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10353 scoped_ptr<SpdyFrame> req(
10354 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10355 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10357 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10358 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10359 MockRead spdy_reads[] = {
10360 CreateMockRead(*resp),
10361 CreateMockRead(*data),
10362 MockRead(ASYNC, 0, 0),
10365 DelayedSocketData spdy_data(
10366 1, // wait for one write to finish before reading.
10367 spdy_reads, arraysize(spdy_reads),
10368 spdy_writes, arraysize(spdy_writes));
10369 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10371 SSLSocketDataProvider ssl(ASYNC, OK);
10372 ssl.SetNextProto(GetParam());
10373 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10377 // Set up an initial SpdySession in the pool to reuse.
10378 HostPortPair host_port_pair("www.google.com", 443);
10379 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10380 PRIVACY_MODE_DISABLED);
10381 base::WeakPtr<SpdySession> spdy_session =
10382 CreateInsecureSpdySession(session, key, BoundNetLog());
10384 HttpRequestInfo request;
10385 request.method = "GET";
10386 request.url = GURL("https://www.google.com/");
10387 request.load_flags = 0;
10389 // This is the important line that marks this as a preconnect.
10390 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10392 scoped_ptr<HttpTransaction> trans(
10393 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10395 TestCompletionCallback callback;
10396 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10397 EXPECT_EQ(ERR_IO_PENDING, rv);
10398 EXPECT_EQ(OK, callback.WaitForResult());
10401 // Given a net error, cause that error to be returned from the first Write()
10402 // call and verify that the HttpTransaction fails with that error.
10403 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10404 int error, IoMode mode) {
10405 net::HttpRequestInfo request_info;
10406 request_info.url = GURL("https://www.example.com/");
10407 request_info.method = "GET";
10408 request_info.load_flags = net::LOAD_NORMAL;
10410 SSLSocketDataProvider ssl_data(mode, OK);
10411 net::MockWrite data_writes[] = {
10412 net::MockWrite(mode, error),
10414 net::StaticSocketDataProvider data(NULL, 0,
10415 data_writes, arraysize(data_writes));
10416 session_deps_.socket_factory->AddSocketDataProvider(&data);
10417 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10419 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10420 scoped_ptr<HttpTransaction> trans(
10421 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10423 TestCompletionCallback callback;
10424 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10425 if (rv == net::ERR_IO_PENDING)
10426 rv = callback.WaitForResult();
10427 ASSERT_EQ(error, rv);
10430 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10431 // Just check a grab bag of cert errors.
10432 static const int kErrors[] = {
10433 ERR_CERT_COMMON_NAME_INVALID,
10434 ERR_CERT_AUTHORITY_INVALID,
10435 ERR_CERT_DATE_INVALID,
10437 for (size_t i = 0; i < arraysize(kErrors); i++) {
10438 CheckErrorIsPassedBack(kErrors[i], ASYNC);
10439 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10443 // Ensure that a client certificate is removed from the SSL client auth
10444 // cache when:
10445 // 1) No proxy is involved.
10446 // 2) TLS False Start is disabled.
10447 // 3) The initial TLS handshake requests a client certificate.
10448 // 4) The client supplies an invalid/unacceptable certificate.
10449 TEST_P(HttpNetworkTransactionTest,
10450 ClientAuthCertCache_Direct_NoFalseStart) {
10451 net::HttpRequestInfo request_info;
10452 request_info.url = GURL("https://www.example.com/");
10453 request_info.method = "GET";
10454 request_info.load_flags = net::LOAD_NORMAL;
10456 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10457 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10459 // [ssl_]data1 contains the data for the first SSL handshake. When a
10460 // CertificateRequest is received for the first time, the handshake will
10461 // be aborted to allow the caller to provide a certificate.
10462 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10463 ssl_data1.cert_request_info = cert_request.get();
10464 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10465 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10466 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10468 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10469 // False Start is not being used, the result of the SSL handshake will be
10470 // returned as part of the SSLClientSocket::Connect() call. This test
10471 // matches the result of a server sending a handshake_failure alert,
10472 // rather than a Finished message, because it requires a client
10473 // certificate and none was supplied.
10474 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10475 ssl_data2.cert_request_info = cert_request.get();
10476 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10477 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10478 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10480 // [ssl_]data3 contains the data for the third SSL handshake. When a
10481 // connection to a server fails during an SSL handshake,
10482 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10483 // connection was attempted with TLSv1.1. This is transparent to the caller
10484 // of the HttpNetworkTransaction. Because this test failure is due to
10485 // requiring a client certificate, this fallback handshake should also
10486 // fail.
10487 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10488 ssl_data3.cert_request_info = cert_request.get();
10489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10490 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10491 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10493 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10494 // connection to a server fails during an SSL handshake,
10495 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10496 // connection was attempted with TLSv1. This is transparent to the caller
10497 // of the HttpNetworkTransaction. Because this test failure is due to
10498 // requiring a client certificate, this fallback handshake should also
10499 // fail.
10500 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10501 ssl_data4.cert_request_info = cert_request.get();
10502 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10503 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10504 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10506 // Need one more if TLSv1.2 is enabled.
10507 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10508 ssl_data5.cert_request_info = cert_request.get();
10509 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10510 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10511 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10514 scoped_ptr<HttpTransaction> trans(
10515 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10517 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10518 TestCompletionCallback callback;
10519 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10520 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10522 // Complete the SSL handshake, which should abort due to requiring a
10523 // client certificate.
10524 rv = callback.WaitForResult();
10525 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10527 // Indicate that no certificate should be supplied. From the perspective
10528 // of SSLClientCertCache, NULL is just as meaningful as a real
10529 // certificate, so this is the same as supply a
10530 // legitimate-but-unacceptable certificate.
10531 rv = trans->RestartWithCertificate(NULL, callback.callback());
10532 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10534 // Ensure the certificate was added to the client auth cache before
10535 // allowing the connection to continue restarting.
10536 scoped_refptr<X509Certificate> client_cert;
10537 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10538 HostPortPair("www.example.com", 443), &client_cert));
10539 ASSERT_EQ(NULL, client_cert.get());
10541 // Restart the handshake. This will consume ssl_data2, which fails, and
10542 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10543 // The result code is checked against what ssl_data4 should return.
10544 rv = callback.WaitForResult();
10545 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10547 // Ensure that the client certificate is removed from the cache on a
10548 // handshake failure.
10549 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10550 HostPortPair("www.example.com", 443), &client_cert));
10553 // Ensure that a client certificate is removed from the SSL client auth
10554 // cache when:
10555 // 1) No proxy is involved.
10556 // 2) TLS False Start is enabled.
10557 // 3) The initial TLS handshake requests a client certificate.
10558 // 4) The client supplies an invalid/unacceptable certificate.
10559 TEST_P(HttpNetworkTransactionTest,
10560 ClientAuthCertCache_Direct_FalseStart) {
10561 net::HttpRequestInfo request_info;
10562 request_info.url = GURL("https://www.example.com/");
10563 request_info.method = "GET";
10564 request_info.load_flags = net::LOAD_NORMAL;
10566 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10567 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10569 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10570 // return successfully after reading up to the peer's Certificate message.
10571 // This is to allow the caller to call SSLClientSocket::Write(), which can
10572 // enqueue application data to be sent in the same packet as the
10573 // ChangeCipherSpec and Finished messages.
10574 // The actual handshake will be finished when SSLClientSocket::Read() is
10575 // called, which expects to process the peer's ChangeCipherSpec and
10576 // Finished messages. If there was an error negotiating with the peer,
10577 // such as due to the peer requiring a client certificate when none was
10578 // supplied, the alert sent by the peer won't be processed until Read() is
10579 // called.
10581 // Like the non-False Start case, when a client certificate is requested by
10582 // the peer, the handshake is aborted during the Connect() call.
10583 // [ssl_]data1 represents the initial SSL handshake with the peer.
10584 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10585 ssl_data1.cert_request_info = cert_request.get();
10586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10587 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10588 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10590 // When a client certificate is supplied, Connect() will not be aborted
10591 // when the peer requests the certificate. Instead, the handshake will
10592 // artificially succeed, allowing the caller to write the HTTP request to
10593 // the socket. The handshake messages are not processed until Read() is
10594 // called, which then detects that the handshake was aborted, due to the
10595 // peer sending a handshake_failure because it requires a client
10596 // certificate.
10597 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10598 ssl_data2.cert_request_info = cert_request.get();
10599 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10600 net::MockRead data2_reads[] = {
10601 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10603 net::StaticSocketDataProvider data2(
10604 data2_reads, arraysize(data2_reads), NULL, 0);
10605 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10607 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10608 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10609 // TLSv1. It has the same behaviour as [ssl_]data2.
10610 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10611 ssl_data3.cert_request_info = cert_request.get();
10612 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10613 net::StaticSocketDataProvider data3(
10614 data2_reads, arraysize(data2_reads), NULL, 0);
10615 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10617 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10618 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10619 SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10620 ssl_data4.cert_request_info = cert_request.get();
10621 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10622 net::StaticSocketDataProvider data4(
10623 data2_reads, arraysize(data2_reads), NULL, 0);
10624 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10626 // Need one more if TLSv1.2 is enabled.
10627 SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10628 ssl_data5.cert_request_info = cert_request.get();
10629 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10630 net::StaticSocketDataProvider data5(
10631 data2_reads, arraysize(data2_reads), NULL, 0);
10632 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10634 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10635 scoped_ptr<HttpTransaction> trans(
10636 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10638 // Begin the initial SSL handshake.
10639 TestCompletionCallback callback;
10640 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10641 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10643 // Complete the SSL handshake, which should abort due to requiring a
10644 // client certificate.
10645 rv = callback.WaitForResult();
10646 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10648 // Indicate that no certificate should be supplied. From the perspective
10649 // of SSLClientCertCache, NULL is just as meaningful as a real
10650 // certificate, so this is the same as supply a
10651 // legitimate-but-unacceptable certificate.
10652 rv = trans->RestartWithCertificate(NULL, callback.callback());
10653 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10655 // Ensure the certificate was added to the client auth cache before
10656 // allowing the connection to continue restarting.
10657 scoped_refptr<X509Certificate> client_cert;
10658 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10659 HostPortPair("www.example.com", 443), &client_cert));
10660 ASSERT_EQ(NULL, client_cert.get());
10662 // Restart the handshake. This will consume ssl_data2, which fails, and
10663 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10664 // The result code is checked against what ssl_data4 should return.
10665 rv = callback.WaitForResult();
10666 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10668 // Ensure that the client certificate is removed from the cache on a
10669 // handshake failure.
10670 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10671 HostPortPair("www.example.com", 443), &client_cert));
10674 // Ensure that a client certificate is removed from the SSL client auth
10675 // cache when:
10676 // 1) An HTTPS proxy is involved.
10677 // 3) The HTTPS proxy requests a client certificate.
10678 // 4) The client supplies an invalid/unacceptable certificate for the
10679 // proxy.
10680 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10681 // then for connecting to an HTTP endpoint.
10682 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10683 session_deps_.proxy_service.reset(
10684 ProxyService::CreateFixed("https://proxy:70"));
10685 CapturingBoundNetLog log;
10686 session_deps_.net_log = log.bound().net_log();
10688 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10689 cert_request->host_and_port = HostPortPair("proxy", 70);
10691 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10692 // [ssl_]data[1-3]. Rather than represending the endpoint
10693 // (www.example.com:443), they represent failures with the HTTPS proxy
10694 // (proxy:70).
10695 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10696 ssl_data1.cert_request_info = cert_request.get();
10697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10698 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10699 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10701 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10702 ssl_data2.cert_request_info = cert_request.get();
10703 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10704 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10705 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10707 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10708 #if 0
10709 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10710 ssl_data3.cert_request_info = cert_request.get();
10711 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10712 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10713 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10714 #endif
10716 net::HttpRequestInfo requests[2];
10717 requests[0].url = GURL("https://www.example.com/");
10718 requests[0].method = "GET";
10719 requests[0].load_flags = net::LOAD_NORMAL;
10721 requests[1].url = GURL("http://www.example.com/");
10722 requests[1].method = "GET";
10723 requests[1].load_flags = net::LOAD_NORMAL;
10725 for (size_t i = 0; i < arraysize(requests); ++i) {
10726 session_deps_.socket_factory->ResetNextMockIndexes();
10727 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10728 scoped_ptr<HttpNetworkTransaction> trans(
10729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10731 // Begin the SSL handshake with the proxy.
10732 TestCompletionCallback callback;
10733 int rv = trans->Start(
10734 &requests[i], callback.callback(), net::BoundNetLog());
10735 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10737 // Complete the SSL handshake, which should abort due to requiring a
10738 // client certificate.
10739 rv = callback.WaitForResult();
10740 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10742 // Indicate that no certificate should be supplied. From the perspective
10743 // of SSLClientCertCache, NULL is just as meaningful as a real
10744 // certificate, so this is the same as supply a
10745 // legitimate-but-unacceptable certificate.
10746 rv = trans->RestartWithCertificate(NULL, callback.callback());
10747 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10749 // Ensure the certificate was added to the client auth cache before
10750 // allowing the connection to continue restarting.
10751 scoped_refptr<X509Certificate> client_cert;
10752 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10753 HostPortPair("proxy", 70), &client_cert));
10754 ASSERT_EQ(NULL, client_cert.get());
10755 // Ensure the certificate was NOT cached for the endpoint. This only
10756 // applies to HTTPS requests, but is fine to check for HTTP requests.
10757 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10758 HostPortPair("www.example.com", 443), &client_cert));
10760 // Restart the handshake. This will consume ssl_data2, which fails, and
10761 // then consume ssl_data3, which should also fail. The result code is
10762 // checked against what ssl_data3 should return.
10763 rv = callback.WaitForResult();
10764 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10766 // Now that the new handshake has failed, ensure that the client
10767 // certificate was removed from the client auth cache.
10768 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10769 HostPortPair("proxy", 70), &client_cert));
10770 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10771 HostPortPair("www.example.com", 443), &client_cert));
10775 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10776 // TEST_P is a macro that expands directly to code that stringizes the
10777 // arguments. As a result, macros passed as parameters (such as prefix
10778 // or test_case_name) will not be expanded by the preprocessor. To
10779 // work around this, indirect the macro for TEST_P, so that the
10780 // pre-processor will expand macros such as MAYBE_test_name before
10781 // instantiating the test.
10782 #define WRAPPED_TEST_P(test_case_name, test_name) \
10783 TEST_P(test_case_name, test_name)
10785 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10786 #if defined(OS_WIN)
10787 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10788 #else
10789 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10790 #endif
10791 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10792 HttpStreamFactory::set_use_alternate_protocols(true);
10793 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10795 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10796 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10797 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10798 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10799 pool_peer.DisableDomainAuthenticationVerification();
10801 SSLSocketDataProvider ssl(ASYNC, OK);
10802 ssl.SetNextProto(GetParam());
10803 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10805 scoped_ptr<SpdyFrame> host1_req(
10806 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10807 scoped_ptr<SpdyFrame> host2_req(
10808 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10809 MockWrite spdy_writes[] = {
10810 CreateMockWrite(*host1_req, 1),
10811 CreateMockWrite(*host2_req, 4),
10813 scoped_ptr<SpdyFrame> host1_resp(
10814 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10815 scoped_ptr<SpdyFrame> host1_resp_body(
10816 spdy_util_.ConstructSpdyBodyFrame(1, true));
10817 scoped_ptr<SpdyFrame> host2_resp(
10818 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10819 scoped_ptr<SpdyFrame> host2_resp_body(
10820 spdy_util_.ConstructSpdyBodyFrame(3, true));
10821 MockRead spdy_reads[] = {
10822 CreateMockRead(*host1_resp, 2),
10823 CreateMockRead(*host1_resp_body, 3),
10824 CreateMockRead(*host2_resp, 5),
10825 CreateMockRead(*host2_resp_body, 6),
10826 MockRead(ASYNC, 0, 7),
10829 IPAddressNumber ip;
10830 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10831 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10832 MockConnect connect(ASYNC, OK, peer_addr);
10833 OrderedSocketData spdy_data(
10834 connect,
10835 spdy_reads, arraysize(spdy_reads),
10836 spdy_writes, arraysize(spdy_writes));
10837 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10839 TestCompletionCallback callback;
10840 HttpRequestInfo request1;
10841 request1.method = "GET";
10842 request1.url = GURL("https://www.google.com/");
10843 request1.load_flags = 0;
10844 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10846 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10847 EXPECT_EQ(ERR_IO_PENDING, rv);
10848 EXPECT_EQ(OK, callback.WaitForResult());
10850 const HttpResponseInfo* response = trans1.GetResponseInfo();
10851 ASSERT_TRUE(response != NULL);
10852 ASSERT_TRUE(response->headers.get() != NULL);
10853 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10855 std::string response_data;
10856 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10857 EXPECT_EQ("hello!", response_data);
10859 // Preload www.gmail.com into HostCache.
10860 HostPortPair host_port("www.gmail.com", 443);
10861 HostResolver::RequestInfo resolve_info(host_port);
10862 AddressList ignored;
10863 rv = session_deps_.host_resolver->Resolve(resolve_info,
10864 DEFAULT_PRIORITY,
10865 &ignored,
10866 callback.callback(),
10867 NULL,
10868 BoundNetLog());
10869 EXPECT_EQ(ERR_IO_PENDING, rv);
10870 rv = callback.WaitForResult();
10871 EXPECT_EQ(OK, rv);
10873 HttpRequestInfo request2;
10874 request2.method = "GET";
10875 request2.url = GURL("https://www.gmail.com/");
10876 request2.load_flags = 0;
10877 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10879 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10880 EXPECT_EQ(ERR_IO_PENDING, rv);
10881 EXPECT_EQ(OK, callback.WaitForResult());
10883 response = trans2.GetResponseInfo();
10884 ASSERT_TRUE(response != NULL);
10885 ASSERT_TRUE(response->headers.get() != NULL);
10886 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10887 EXPECT_TRUE(response->was_fetched_via_spdy);
10888 EXPECT_TRUE(response->was_npn_negotiated);
10889 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10890 EXPECT_EQ("hello!", response_data);
10892 #undef MAYBE_UseIPConnectionPooling
10894 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
10895 HttpStreamFactory::set_use_alternate_protocols(true);
10896 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10898 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10899 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10900 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10901 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10902 pool_peer.DisableDomainAuthenticationVerification();
10904 SSLSocketDataProvider ssl(ASYNC, OK);
10905 ssl.SetNextProto(GetParam());
10906 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10908 scoped_ptr<SpdyFrame> host1_req(
10909 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10910 scoped_ptr<SpdyFrame> host2_req(
10911 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10912 MockWrite spdy_writes[] = {
10913 CreateMockWrite(*host1_req, 1),
10914 CreateMockWrite(*host2_req, 4),
10916 scoped_ptr<SpdyFrame> host1_resp(
10917 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10918 scoped_ptr<SpdyFrame> host1_resp_body(
10919 spdy_util_.ConstructSpdyBodyFrame(1, true));
10920 scoped_ptr<SpdyFrame> host2_resp(
10921 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10922 scoped_ptr<SpdyFrame> host2_resp_body(
10923 spdy_util_.ConstructSpdyBodyFrame(3, true));
10924 MockRead spdy_reads[] = {
10925 CreateMockRead(*host1_resp, 2),
10926 CreateMockRead(*host1_resp_body, 3),
10927 CreateMockRead(*host2_resp, 5),
10928 CreateMockRead(*host2_resp_body, 6),
10929 MockRead(ASYNC, 0, 7),
10932 IPAddressNumber ip;
10933 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10934 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10935 MockConnect connect(ASYNC, OK, peer_addr);
10936 OrderedSocketData spdy_data(
10937 connect,
10938 spdy_reads, arraysize(spdy_reads),
10939 spdy_writes, arraysize(spdy_writes));
10940 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10942 TestCompletionCallback callback;
10943 HttpRequestInfo request1;
10944 request1.method = "GET";
10945 request1.url = GURL("https://www.google.com/");
10946 request1.load_flags = 0;
10947 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10949 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10950 EXPECT_EQ(ERR_IO_PENDING, rv);
10951 EXPECT_EQ(OK, callback.WaitForResult());
10953 const HttpResponseInfo* response = trans1.GetResponseInfo();
10954 ASSERT_TRUE(response != NULL);
10955 ASSERT_TRUE(response->headers.get() != NULL);
10956 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10958 std::string response_data;
10959 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10960 EXPECT_EQ("hello!", response_data);
10962 HttpRequestInfo request2;
10963 request2.method = "GET";
10964 request2.url = GURL("https://www.gmail.com/");
10965 request2.load_flags = 0;
10966 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10968 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10969 EXPECT_EQ(ERR_IO_PENDING, rv);
10970 EXPECT_EQ(OK, callback.WaitForResult());
10972 response = trans2.GetResponseInfo();
10973 ASSERT_TRUE(response != NULL);
10974 ASSERT_TRUE(response->headers.get() != NULL);
10975 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10976 EXPECT_TRUE(response->was_fetched_via_spdy);
10977 EXPECT_TRUE(response->was_npn_negotiated);
10978 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10979 EXPECT_EQ("hello!", response_data);
10982 class OneTimeCachingHostResolver : public net::HostResolver {
10983 public:
10984 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
10985 : host_port_(host_port) {}
10986 virtual ~OneTimeCachingHostResolver() {}
10988 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
10990 // HostResolver methods:
10991 virtual int Resolve(const RequestInfo& info,
10992 RequestPriority priority,
10993 AddressList* addresses,
10994 const CompletionCallback& callback,
10995 RequestHandle* out_req,
10996 const BoundNetLog& net_log) OVERRIDE {
10997 return host_resolver_.Resolve(
10998 info, priority, addresses, callback, out_req, net_log);
11001 virtual int ResolveFromCache(const RequestInfo& info,
11002 AddressList* addresses,
11003 const BoundNetLog& net_log) OVERRIDE {
11004 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11005 if (rv == OK && info.host_port_pair().Equals(host_port_))
11006 host_resolver_.GetHostCache()->clear();
11007 return rv;
11010 virtual void CancelRequest(RequestHandle req) OVERRIDE {
11011 host_resolver_.CancelRequest(req);
11014 MockCachingHostResolver* GetMockHostResolver() {
11015 return &host_resolver_;
11018 private:
11019 MockCachingHostResolver host_resolver_;
11020 const HostPortPair host_port_;
11023 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11024 #if defined(OS_WIN)
11025 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11026 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11027 #else
11028 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11029 UseIPConnectionPoolingWithHostCacheExpiration
11030 #endif
11031 WRAPPED_TEST_P(HttpNetworkTransactionTest,
11032 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
11033 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11034 // prefix doesn't work with parametrized tests).
11035 #if defined(OS_WIN)
11036 return;
11037 #else
11038 HttpStreamFactory::set_use_alternate_protocols(true);
11039 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11041 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11042 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11043 HttpNetworkSession::Params params =
11044 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11045 params.host_resolver = &host_resolver;
11046 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11047 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11048 pool_peer.DisableDomainAuthenticationVerification();
11050 SSLSocketDataProvider ssl(ASYNC, OK);
11051 ssl.SetNextProto(GetParam());
11052 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11054 scoped_ptr<SpdyFrame> host1_req(
11055 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
11056 scoped_ptr<SpdyFrame> host2_req(
11057 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11058 MockWrite spdy_writes[] = {
11059 CreateMockWrite(*host1_req, 1),
11060 CreateMockWrite(*host2_req, 4),
11062 scoped_ptr<SpdyFrame> host1_resp(
11063 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11064 scoped_ptr<SpdyFrame> host1_resp_body(
11065 spdy_util_.ConstructSpdyBodyFrame(1, true));
11066 scoped_ptr<SpdyFrame> host2_resp(
11067 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11068 scoped_ptr<SpdyFrame> host2_resp_body(
11069 spdy_util_.ConstructSpdyBodyFrame(3, true));
11070 MockRead spdy_reads[] = {
11071 CreateMockRead(*host1_resp, 2),
11072 CreateMockRead(*host1_resp_body, 3),
11073 CreateMockRead(*host2_resp, 5),
11074 CreateMockRead(*host2_resp_body, 6),
11075 MockRead(ASYNC, 0, 7),
11078 IPAddressNumber ip;
11079 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11080 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11081 MockConnect connect(ASYNC, OK, peer_addr);
11082 OrderedSocketData spdy_data(
11083 connect,
11084 spdy_reads, arraysize(spdy_reads),
11085 spdy_writes, arraysize(spdy_writes));
11086 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11088 TestCompletionCallback callback;
11089 HttpRequestInfo request1;
11090 request1.method = "GET";
11091 request1.url = GURL("https://www.google.com/");
11092 request1.load_flags = 0;
11093 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11095 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11096 EXPECT_EQ(ERR_IO_PENDING, rv);
11097 EXPECT_EQ(OK, callback.WaitForResult());
11099 const HttpResponseInfo* response = trans1.GetResponseInfo();
11100 ASSERT_TRUE(response != NULL);
11101 ASSERT_TRUE(response->headers.get() != NULL);
11102 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11104 std::string response_data;
11105 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11106 EXPECT_EQ("hello!", response_data);
11108 // Preload cache entries into HostCache.
11109 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11110 AddressList ignored;
11111 rv = host_resolver.Resolve(resolve_info,
11112 DEFAULT_PRIORITY,
11113 &ignored,
11114 callback.callback(),
11115 NULL,
11116 BoundNetLog());
11117 EXPECT_EQ(ERR_IO_PENDING, rv);
11118 rv = callback.WaitForResult();
11119 EXPECT_EQ(OK, rv);
11121 HttpRequestInfo request2;
11122 request2.method = "GET";
11123 request2.url = GURL("https://www.gmail.com/");
11124 request2.load_flags = 0;
11125 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11127 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11128 EXPECT_EQ(ERR_IO_PENDING, rv);
11129 EXPECT_EQ(OK, callback.WaitForResult());
11131 response = trans2.GetResponseInfo();
11132 ASSERT_TRUE(response != NULL);
11133 ASSERT_TRUE(response->headers.get() != NULL);
11134 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11135 EXPECT_TRUE(response->was_fetched_via_spdy);
11136 EXPECT_TRUE(response->was_npn_negotiated);
11137 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11138 EXPECT_EQ("hello!", response_data);
11139 #endif
11141 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11143 TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
11144 MockRead data_reads1[] = {
11145 MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
11147 MockRead data_reads2[] = {
11148 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11149 MockRead("hello world"),
11150 MockRead(SYNCHRONOUS, OK),
11152 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
11153 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
11154 StaticSocketDataProvider* data[] = { &data1, &data2 };
11156 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
11158 EXPECT_EQ(OK, out.rv);
11159 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
11160 EXPECT_EQ("hello world", out.response_data);
11163 TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
11164 MockWrite data_writes1[] = {
11165 MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
11167 MockWrite data_writes2[] = {
11168 MockWrite("GET / HTTP/1.1\r\n"
11169 "Host: www.google.com\r\n"
11170 "Connection: keep-alive\r\n\r\n"),
11172 MockRead data_reads2[] = {
11173 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11174 MockRead("hello world"),
11175 MockRead(SYNCHRONOUS, OK),
11177 StaticSocketDataProvider data1(NULL, 0,
11178 data_writes1, arraysize(data_writes1));
11179 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
11180 data_writes2, arraysize(data_writes2));
11181 StaticSocketDataProvider* data[] = { &data1, &data2 };
11183 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
11185 EXPECT_EQ(OK, out.rv);
11186 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
11187 EXPECT_EQ("hello world", out.response_data);
11190 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11191 const std::string https_url = "https://www.google.com/";
11192 const std::string http_url = "http://www.google.com:443/";
11194 // SPDY GET for HTTPS URL
11195 scoped_ptr<SpdyFrame> req1(
11196 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11198 MockWrite writes1[] = {
11199 CreateMockWrite(*req1, 0),
11202 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11203 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11204 MockRead reads1[] = {
11205 CreateMockRead(*resp1, 1),
11206 CreateMockRead(*body1, 2),
11207 MockRead(ASYNC, ERR_IO_PENDING, 3)
11210 DelayedSocketData data1(
11211 1, reads1, arraysize(reads1),
11212 writes1, arraysize(writes1));
11213 MockConnect connect_data1(ASYNC, OK);
11214 data1.set_connect_data(connect_data1);
11216 // HTTP GET for the HTTP URL
11217 MockWrite writes2[] = {
11218 MockWrite(ASYNC, 4,
11219 "GET / HTTP/1.1\r\n"
11220 "Host: www.google.com:443\r\n"
11221 "Connection: keep-alive\r\n\r\n"),
11224 MockRead reads2[] = {
11225 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11226 MockRead(ASYNC, 6, "hello"),
11227 MockRead(ASYNC, 7, OK),
11230 DelayedSocketData data2(
11231 1, reads2, arraysize(reads2),
11232 writes2, arraysize(writes2));
11234 SSLSocketDataProvider ssl(ASYNC, OK);
11235 ssl.SetNextProto(GetParam());
11236 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11237 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11238 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11240 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11242 // Start the first transaction to set up the SpdySession
11243 HttpRequestInfo request1;
11244 request1.method = "GET";
11245 request1.url = GURL(https_url);
11246 request1.load_flags = 0;
11247 HttpNetworkTransaction trans1(LOWEST, session.get());
11248 TestCompletionCallback callback1;
11249 EXPECT_EQ(ERR_IO_PENDING,
11250 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11251 base::MessageLoop::current()->RunUntilIdle();
11253 EXPECT_EQ(OK, callback1.WaitForResult());
11254 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11256 // Now, start the HTTP request
11257 HttpRequestInfo request2;
11258 request2.method = "GET";
11259 request2.url = GURL(http_url);
11260 request2.load_flags = 0;
11261 HttpNetworkTransaction trans2(MEDIUM, session.get());
11262 TestCompletionCallback callback2;
11263 EXPECT_EQ(ERR_IO_PENDING,
11264 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11265 base::MessageLoop::current()->RunUntilIdle();
11267 EXPECT_EQ(OK, callback2.WaitForResult());
11268 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11271 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
11272 const std::string https_url = "https://www.google.com/";
11273 const std::string http_url = "http://www.google.com:443/";
11275 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11276 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
11277 LOWEST));
11278 scoped_ptr<SpdyFrame> req1(
11279 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11281 // SPDY GET for HTTP URL (through the proxy, but not the tunnel)
11282 scoped_ptr<SpdyFrame> wrapped_req1(
11283 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
11284 const char* const headers[] = {
11285 spdy_util_.GetMethodKey(), "GET",
11286 spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/",
11287 spdy_util_.GetHostKey(), "www.google.com:443",
11288 spdy_util_.GetSchemeKey(), "http",
11289 spdy_util_.GetVersionKey(), "HTTP/1.1"
11291 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame(
11292 NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN,
11293 headers, arraysize(headers), 0));
11295 MockWrite writes1[] = {
11296 CreateMockWrite(*connect, 0),
11297 CreateMockWrite(*wrapped_req1, 2),
11298 CreateMockWrite(*req2, 5),
11301 scoped_ptr<SpdyFrame> conn_resp(
11302 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11303 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11304 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11305 scoped_ptr<SpdyFrame> wrapped_resp1(
11306 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
11307 scoped_ptr<SpdyFrame> wrapped_body1(
11308 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
11309 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11310 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11311 MockRead reads1[] = {
11312 CreateMockRead(*conn_resp, 1),
11313 CreateMockRead(*wrapped_resp1, 3),
11314 CreateMockRead(*wrapped_body1, 4),
11315 CreateMockRead(*resp2, 6),
11316 CreateMockRead(*body2, 7),
11317 MockRead(ASYNC, ERR_IO_PENDING, 8)
11320 DeterministicSocketData data1(reads1, arraysize(reads1),
11321 writes1, arraysize(writes1));
11322 MockConnect connect_data1(ASYNC, OK);
11323 data1.set_connect_data(connect_data1);
11325 session_deps_.proxy_service.reset(
11326 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11327 CapturingNetLog log;
11328 session_deps_.net_log = &log;
11329 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11330 ssl1.SetNextProto(GetParam());
11331 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11332 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11333 ssl2.SetNextProto(GetParam());
11334 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11335 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
11337 scoped_refptr<HttpNetworkSession> session(
11338 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11340 // Start the first transaction to set up the SpdySession
11341 HttpRequestInfo request1;
11342 request1.method = "GET";
11343 request1.url = GURL(https_url);
11344 request1.load_flags = 0;
11345 HttpNetworkTransaction trans1(LOWEST, session.get());
11346 TestCompletionCallback callback1;
11347 EXPECT_EQ(ERR_IO_PENDING,
11348 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11349 base::MessageLoop::current()->RunUntilIdle();
11350 data1.RunFor(4);
11352 EXPECT_EQ(OK, callback1.WaitForResult());
11353 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11355 LoadTimingInfo load_timing_info1;
11356 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
11357 TestLoadTimingNotReusedWithPac(load_timing_info1,
11358 CONNECT_TIMING_HAS_SSL_TIMES);
11360 // Now, start the HTTP request
11361 HttpRequestInfo request2;
11362 request2.method = "GET";
11363 request2.url = GURL(http_url);
11364 request2.load_flags = 0;
11365 HttpNetworkTransaction trans2(MEDIUM, session.get());
11366 TestCompletionCallback callback2;
11367 EXPECT_EQ(ERR_IO_PENDING,
11368 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11369 base::MessageLoop::current()->RunUntilIdle();
11370 data1.RunFor(3);
11372 EXPECT_EQ(OK, callback2.WaitForResult());
11373 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11375 LoadTimingInfo load_timing_info2;
11376 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
11377 // The established SPDY sessions is considered reused by the HTTP request.
11378 TestLoadTimingReusedWithPac(load_timing_info2);
11379 // HTTP requests over a SPDY session should have a different connection
11380 // socket_log_id than requests over a tunnel.
11381 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
11384 TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
11385 HttpStreamFactory::set_force_spdy_always(true);
11386 const std::string https_url = "https://www.google.com/";
11387 const std::string http_url = "http://www.google.com:443/";
11389 // SPDY GET for HTTPS URL
11390 scoped_ptr<SpdyFrame> req1(
11391 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11392 // SPDY GET for the HTTP URL
11393 scoped_ptr<SpdyFrame> req2(
11394 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11396 MockWrite writes[] = {
11397 CreateMockWrite(*req1, 1),
11398 CreateMockWrite(*req2, 4),
11401 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11402 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11403 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11404 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11405 MockRead reads[] = {
11406 CreateMockRead(*resp1, 2),
11407 CreateMockRead(*body1, 3),
11408 CreateMockRead(*resp2, 5),
11409 CreateMockRead(*body2, 6),
11410 MockRead(ASYNC, ERR_IO_PENDING, 7)
11413 OrderedSocketData data(reads, arraysize(reads),
11414 writes, arraysize(writes));
11416 SSLSocketDataProvider ssl(ASYNC, OK);
11417 ssl.SetNextProto(GetParam());
11418 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11419 session_deps_.socket_factory->AddSocketDataProvider(&data);
11421 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11423 // Start the first transaction to set up the SpdySession
11424 HttpRequestInfo request1;
11425 request1.method = "GET";
11426 request1.url = GURL(https_url);
11427 request1.load_flags = 0;
11428 HttpNetworkTransaction trans1(LOWEST, session.get());
11429 TestCompletionCallback callback1;
11430 EXPECT_EQ(ERR_IO_PENDING,
11431 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11432 base::MessageLoop::current()->RunUntilIdle();
11434 EXPECT_EQ(OK, callback1.WaitForResult());
11435 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11437 // Now, start the HTTP request
11438 HttpRequestInfo request2;
11439 request2.method = "GET";
11440 request2.url = GURL(http_url);
11441 request2.load_flags = 0;
11442 HttpNetworkTransaction trans2(MEDIUM, session.get());
11443 TestCompletionCallback callback2;
11444 EXPECT_EQ(ERR_IO_PENDING,
11445 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11446 base::MessageLoop::current()->RunUntilIdle();
11448 EXPECT_EQ(OK, callback2.WaitForResult());
11449 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11452 // Test that in the case where we have a SPDY session to a SPDY proxy
11453 // that we do not pool other origins that resolve to the same IP when
11454 // the certificate does not match the new origin.
11455 // http://crbug.com/134690
11456 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11457 const std::string url1 = "http://www.google.com/";
11458 const std::string url2 = "https://mail.google.com/";
11459 const std::string ip_addr = "1.2.3.4";
11461 // SPDY GET for HTTP URL (through SPDY proxy)
11462 scoped_ptr<SpdyHeaderBlock> headers(
11463 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11464 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
11465 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
11467 MockWrite writes1[] = {
11468 CreateMockWrite(*req1, 0),
11471 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11472 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11473 MockRead reads1[] = {
11474 CreateMockRead(*resp1, 1),
11475 CreateMockRead(*body1, 2),
11476 MockRead(ASYNC, OK, 3) // EOF
11479 scoped_ptr<DeterministicSocketData> data1(
11480 new DeterministicSocketData(reads1, arraysize(reads1),
11481 writes1, arraysize(writes1)));
11482 IPAddressNumber ip;
11483 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11484 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11485 MockConnect connect_data1(ASYNC, OK, peer_addr);
11486 data1->set_connect_data(connect_data1);
11488 // SPDY GET for HTTPS URL (direct)
11489 scoped_ptr<SpdyFrame> req2(
11490 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11492 MockWrite writes2[] = {
11493 CreateMockWrite(*req2, 0),
11496 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11497 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11498 MockRead reads2[] = {
11499 CreateMockRead(*resp2, 1),
11500 CreateMockRead(*body2, 2),
11501 MockRead(ASYNC, OK, 3) // EOF
11504 scoped_ptr<DeterministicSocketData> data2(
11505 new DeterministicSocketData(reads2, arraysize(reads2),
11506 writes2, arraysize(writes2)));
11507 MockConnect connect_data2(ASYNC, OK);
11508 data2->set_connect_data(connect_data2);
11510 // Set up a proxy config that sends HTTP requests to a proxy, and
11511 // all others direct.
11512 ProxyConfig proxy_config;
11513 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11514 CapturingProxyResolver* capturing_proxy_resolver =
11515 new CapturingProxyResolver();
11516 session_deps_.proxy_service.reset(new ProxyService(
11517 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11518 NULL));
11520 // Load a valid cert. Note, that this does not need to
11521 // be valid for proxy because the MockSSLClientSocket does
11522 // not actually verify it. But SpdySession will use this
11523 // to see if it is valid for the new origin
11524 base::FilePath certs_dir = GetTestCertsDirectory();
11525 scoped_refptr<X509Certificate> server_cert(
11526 ImportCertFromFile(certs_dir, "ok_cert.pem"));
11527 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11529 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11530 ssl1.SetNextProto(GetParam());
11531 ssl1.cert = server_cert;
11532 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11533 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11534 data1.get());
11536 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11537 ssl2.SetNextProto(GetParam());
11538 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11539 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11540 data2.get());
11542 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11543 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11544 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11546 scoped_refptr<HttpNetworkSession> session(
11547 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11549 // Start the first transaction to set up the SpdySession
11550 HttpRequestInfo request1;
11551 request1.method = "GET";
11552 request1.url = GURL(url1);
11553 request1.load_flags = 0;
11554 HttpNetworkTransaction trans1(LOWEST, session.get());
11555 TestCompletionCallback callback1;
11556 ASSERT_EQ(ERR_IO_PENDING,
11557 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11558 data1->RunFor(3);
11560 ASSERT_TRUE(callback1.have_result());
11561 EXPECT_EQ(OK, callback1.WaitForResult());
11562 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11564 // Now, start the HTTP request
11565 HttpRequestInfo request2;
11566 request2.method = "GET";
11567 request2.url = GURL(url2);
11568 request2.load_flags = 0;
11569 HttpNetworkTransaction trans2(MEDIUM, session.get());
11570 TestCompletionCallback callback2;
11571 EXPECT_EQ(ERR_IO_PENDING,
11572 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11573 base::MessageLoop::current()->RunUntilIdle();
11574 data2->RunFor(3);
11576 ASSERT_TRUE(callback2.have_result());
11577 EXPECT_EQ(OK, callback2.WaitForResult());
11578 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11581 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11582 // error) in SPDY session, removes the socket from pool and closes the SPDY
11583 // session. Verify that new url's from the same HttpNetworkSession (and a new
11584 // SpdySession) do work. http://crbug.com/224701
11585 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11586 const std::string https_url = "https://www.google.com/";
11588 MockRead reads1[] = {
11589 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11592 scoped_ptr<DeterministicSocketData> data1(
11593 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11594 data1->SetStop(1);
11596 scoped_ptr<SpdyFrame> req2(
11597 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11598 MockWrite writes2[] = {
11599 CreateMockWrite(*req2, 0),
11602 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11603 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11604 MockRead reads2[] = {
11605 CreateMockRead(*resp2, 1),
11606 CreateMockRead(*body2, 2),
11607 MockRead(ASYNC, OK, 3) // EOF
11610 scoped_ptr<DeterministicSocketData> data2(
11611 new DeterministicSocketData(reads2, arraysize(reads2),
11612 writes2, arraysize(writes2)));
11614 SSLSocketDataProvider ssl1(ASYNC, OK);
11615 ssl1.SetNextProto(GetParam());
11616 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11617 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11618 data1.get());
11620 SSLSocketDataProvider ssl2(ASYNC, OK);
11621 ssl2.SetNextProto(GetParam());
11622 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11623 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11624 data2.get());
11626 scoped_refptr<HttpNetworkSession> session(
11627 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11629 // Start the first transaction to set up the SpdySession and verify that
11630 // connection was closed.
11631 HttpRequestInfo request1;
11632 request1.method = "GET";
11633 request1.url = GURL(https_url);
11634 request1.load_flags = 0;
11635 HttpNetworkTransaction trans1(MEDIUM, session.get());
11636 TestCompletionCallback callback1;
11637 EXPECT_EQ(ERR_IO_PENDING,
11638 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11639 base::MessageLoop::current()->RunUntilIdle();
11640 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11642 // Now, start the second request and make sure it succeeds.
11643 HttpRequestInfo request2;
11644 request2.method = "GET";
11645 request2.url = GURL(https_url);
11646 request2.load_flags = 0;
11647 HttpNetworkTransaction trans2(MEDIUM, session.get());
11648 TestCompletionCallback callback2;
11649 EXPECT_EQ(ERR_IO_PENDING,
11650 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11651 base::MessageLoop::current()->RunUntilIdle();
11652 data2->RunFor(3);
11654 ASSERT_TRUE(callback2.have_result());
11655 EXPECT_EQ(OK, callback2.WaitForResult());
11656 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11659 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11660 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11661 ClientSocketPoolManager::set_max_sockets_per_group(
11662 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11663 ClientSocketPoolManager::set_max_sockets_per_pool(
11664 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11666 // Use two different hosts with different IPs so they don't get pooled.
11667 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11668 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11669 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11671 SSLSocketDataProvider ssl1(ASYNC, OK);
11672 ssl1.SetNextProto(GetParam());
11673 SSLSocketDataProvider ssl2(ASYNC, OK);
11674 ssl2.SetNextProto(GetParam());
11675 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11676 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11678 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11679 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11680 MockWrite spdy1_writes[] = {
11681 CreateMockWrite(*host1_req, 1),
11683 scoped_ptr<SpdyFrame> host1_resp(
11684 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11685 scoped_ptr<SpdyFrame> host1_resp_body(
11686 spdy_util_.ConstructSpdyBodyFrame(1, true));
11687 MockRead spdy1_reads[] = {
11688 CreateMockRead(*host1_resp, 2),
11689 CreateMockRead(*host1_resp_body, 3),
11690 MockRead(ASYNC, ERR_IO_PENDING, 4),
11693 scoped_ptr<OrderedSocketData> spdy1_data(
11694 new OrderedSocketData(
11695 spdy1_reads, arraysize(spdy1_reads),
11696 spdy1_writes, arraysize(spdy1_writes)));
11697 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11699 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11700 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11701 MockWrite spdy2_writes[] = {
11702 CreateMockWrite(*host2_req, 1),
11704 scoped_ptr<SpdyFrame> host2_resp(
11705 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11706 scoped_ptr<SpdyFrame> host2_resp_body(
11707 spdy_util_.ConstructSpdyBodyFrame(1, true));
11708 MockRead spdy2_reads[] = {
11709 CreateMockRead(*host2_resp, 2),
11710 CreateMockRead(*host2_resp_body, 3),
11711 MockRead(ASYNC, ERR_IO_PENDING, 4),
11714 scoped_ptr<OrderedSocketData> spdy2_data(
11715 new OrderedSocketData(
11716 spdy2_reads, arraysize(spdy2_reads),
11717 spdy2_writes, arraysize(spdy2_writes)));
11718 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11720 MockWrite http_write[] = {
11721 MockWrite("GET / HTTP/1.1\r\n"
11722 "Host: www.a.com\r\n"
11723 "Connection: keep-alive\r\n\r\n"),
11726 MockRead http_read[] = {
11727 MockRead("HTTP/1.1 200 OK\r\n"),
11728 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11729 MockRead("Content-Length: 6\r\n\r\n"),
11730 MockRead("hello!"),
11732 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11733 http_write, arraysize(http_write));
11734 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11736 HostPortPair host_port_pair_a("www.a.com", 443);
11737 SpdySessionKey spdy_session_key_a(
11738 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11739 EXPECT_FALSE(
11740 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11742 TestCompletionCallback callback;
11743 HttpRequestInfo request1;
11744 request1.method = "GET";
11745 request1.url = GURL("https://www.a.com/");
11746 request1.load_flags = 0;
11747 scoped_ptr<HttpNetworkTransaction> trans(
11748 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11750 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11751 EXPECT_EQ(ERR_IO_PENDING, rv);
11752 EXPECT_EQ(OK, callback.WaitForResult());
11754 const HttpResponseInfo* response = trans->GetResponseInfo();
11755 ASSERT_TRUE(response != NULL);
11756 ASSERT_TRUE(response->headers.get() != NULL);
11757 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11758 EXPECT_TRUE(response->was_fetched_via_spdy);
11759 EXPECT_TRUE(response->was_npn_negotiated);
11761 std::string response_data;
11762 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11763 EXPECT_EQ("hello!", response_data);
11764 trans.reset();
11765 EXPECT_TRUE(
11766 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11768 HostPortPair host_port_pair_b("www.b.com", 443);
11769 SpdySessionKey spdy_session_key_b(
11770 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11771 EXPECT_FALSE(
11772 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11773 HttpRequestInfo request2;
11774 request2.method = "GET";
11775 request2.url = GURL("https://www.b.com/");
11776 request2.load_flags = 0;
11777 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11779 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11780 EXPECT_EQ(ERR_IO_PENDING, rv);
11781 EXPECT_EQ(OK, callback.WaitForResult());
11783 response = trans->GetResponseInfo();
11784 ASSERT_TRUE(response != NULL);
11785 ASSERT_TRUE(response->headers.get() != NULL);
11786 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11787 EXPECT_TRUE(response->was_fetched_via_spdy);
11788 EXPECT_TRUE(response->was_npn_negotiated);
11789 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11790 EXPECT_EQ("hello!", response_data);
11791 EXPECT_FALSE(
11792 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11793 EXPECT_TRUE(
11794 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11796 HostPortPair host_port_pair_a1("www.a.com", 80);
11797 SpdySessionKey spdy_session_key_a1(
11798 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11799 EXPECT_FALSE(
11800 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11801 HttpRequestInfo request3;
11802 request3.method = "GET";
11803 request3.url = GURL("http://www.a.com/");
11804 request3.load_flags = 0;
11805 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11807 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11808 EXPECT_EQ(ERR_IO_PENDING, rv);
11809 EXPECT_EQ(OK, callback.WaitForResult());
11811 response = trans->GetResponseInfo();
11812 ASSERT_TRUE(response != NULL);
11813 ASSERT_TRUE(response->headers.get() != NULL);
11814 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11815 EXPECT_FALSE(response->was_fetched_via_spdy);
11816 EXPECT_FALSE(response->was_npn_negotiated);
11817 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11818 EXPECT_EQ("hello!", response_data);
11819 EXPECT_FALSE(
11820 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11821 EXPECT_FALSE(
11822 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11825 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11826 HttpRequestInfo request;
11827 request.method = "GET";
11828 request.url = GURL("http://www.google.com/");
11829 request.load_flags = 0;
11831 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11832 scoped_ptr<HttpTransaction> trans(
11833 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11835 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11836 StaticSocketDataProvider data;
11837 data.set_connect_data(mock_connect);
11838 session_deps_.socket_factory->AddSocketDataProvider(&data);
11840 TestCompletionCallback callback;
11842 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11843 EXPECT_EQ(ERR_IO_PENDING, rv);
11845 rv = callback.WaitForResult();
11846 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11848 EXPECT_EQ(NULL, trans->GetResponseInfo());
11850 // We don't care whether this succeeds or fails, but it shouldn't crash.
11851 HttpRequestHeaders request_headers;
11852 trans->GetFullRequestHeaders(&request_headers);
11855 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11856 HttpRequestInfo request;
11857 request.method = "GET";
11858 request.url = GURL("http://www.google.com/");
11859 request.load_flags = 0;
11861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11862 scoped_ptr<HttpTransaction> trans(
11863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11865 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11866 StaticSocketDataProvider data;
11867 data.set_connect_data(mock_connect);
11868 session_deps_.socket_factory->AddSocketDataProvider(&data);
11870 TestCompletionCallback callback;
11872 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11873 EXPECT_EQ(ERR_IO_PENDING, rv);
11875 rv = callback.WaitForResult();
11876 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11878 EXPECT_EQ(NULL, trans->GetResponseInfo());
11880 // We don't care whether this succeeds or fails, but it shouldn't crash.
11881 HttpRequestHeaders request_headers;
11882 trans->GetFullRequestHeaders(&request_headers);
11885 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
11886 HttpRequestInfo request;
11887 request.method = "GET";
11888 request.url = GURL("http://www.google.com/");
11889 request.load_flags = 0;
11891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11892 scoped_ptr<HttpTransaction> trans(
11893 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11895 MockWrite data_writes[] = {
11896 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
11898 MockRead data_reads[] = {
11899 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11902 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11903 data_writes, arraysize(data_writes));
11904 session_deps_.socket_factory->AddSocketDataProvider(&data);
11906 TestCompletionCallback callback;
11908 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11909 EXPECT_EQ(ERR_IO_PENDING, rv);
11911 rv = callback.WaitForResult();
11912 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11914 EXPECT_EQ(NULL, trans->GetResponseInfo());
11916 HttpRequestHeaders request_headers;
11917 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11918 EXPECT_TRUE(request_headers.HasHeader("Host"));
11921 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
11922 HttpRequestInfo request;
11923 request.method = "GET";
11924 request.url = GURL("http://www.google.com/");
11925 request.load_flags = 0;
11927 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11928 scoped_ptr<HttpTransaction> trans(
11929 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11931 MockWrite data_writes[] = {
11932 MockWrite(ASYNC, ERR_CONNECTION_RESET),
11934 MockRead data_reads[] = {
11935 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11938 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11939 data_writes, arraysize(data_writes));
11940 session_deps_.socket_factory->AddSocketDataProvider(&data);
11942 TestCompletionCallback callback;
11944 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11945 EXPECT_EQ(ERR_IO_PENDING, rv);
11947 rv = callback.WaitForResult();
11948 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11950 EXPECT_EQ(NULL, trans->GetResponseInfo());
11952 HttpRequestHeaders request_headers;
11953 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11954 EXPECT_TRUE(request_headers.HasHeader("Host"));
11957 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
11958 HttpRequestInfo request;
11959 request.method = "GET";
11960 request.url = GURL("http://www.google.com/");
11961 request.load_flags = 0;
11963 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11964 scoped_ptr<HttpTransaction> trans(
11965 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11967 MockWrite data_writes[] = {
11968 MockWrite("GET / HTTP/1.1\r\n"
11969 "Host: www.google.com\r\n"
11970 "Connection: keep-alive\r\n\r\n"),
11972 MockRead data_reads[] = {
11973 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
11976 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11977 data_writes, arraysize(data_writes));
11978 session_deps_.socket_factory->AddSocketDataProvider(&data);
11980 TestCompletionCallback callback;
11982 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11983 EXPECT_EQ(ERR_IO_PENDING, rv);
11985 rv = callback.WaitForResult();
11986 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11988 EXPECT_EQ(NULL, trans->GetResponseInfo());
11990 HttpRequestHeaders request_headers;
11991 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11992 EXPECT_TRUE(request_headers.HasHeader("Host"));
11995 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
11996 HttpRequestInfo request;
11997 request.method = "GET";
11998 request.url = GURL("http://www.google.com/");
11999 request.load_flags = 0;
12001 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12002 scoped_ptr<HttpTransaction> trans(
12003 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12005 MockWrite data_writes[] = {
12006 MockWrite("GET / HTTP/1.1\r\n"
12007 "Host: www.google.com\r\n"
12008 "Connection: keep-alive\r\n\r\n"),
12010 MockRead data_reads[] = {
12011 MockRead(ASYNC, ERR_CONNECTION_RESET),
12014 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12015 data_writes, arraysize(data_writes));
12016 session_deps_.socket_factory->AddSocketDataProvider(&data);
12018 TestCompletionCallback callback;
12020 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12021 EXPECT_EQ(ERR_IO_PENDING, rv);
12023 rv = callback.WaitForResult();
12024 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12026 EXPECT_EQ(NULL, trans->GetResponseInfo());
12028 HttpRequestHeaders request_headers;
12029 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12030 EXPECT_TRUE(request_headers.HasHeader("Host"));
12033 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12034 HttpRequestInfo request;
12035 request.method = "GET";
12036 request.url = GURL("http://www.google.com/");
12037 request.load_flags = 0;
12038 request.extra_headers.SetHeader("X-Foo", "bar");
12040 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12041 scoped_ptr<HttpTransaction> trans(
12042 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12044 MockWrite data_writes[] = {
12045 MockWrite("GET / HTTP/1.1\r\n"
12046 "Host: www.google.com\r\n"
12047 "Connection: keep-alive\r\n"
12048 "X-Foo: bar\r\n\r\n"),
12050 MockRead data_reads[] = {
12051 MockRead("HTTP/1.1 200 OK\r\n"
12052 "Content-Length: 5\r\n\r\n"
12053 "hello"),
12054 MockRead(ASYNC, ERR_UNEXPECTED),
12057 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12058 data_writes, arraysize(data_writes));
12059 session_deps_.socket_factory->AddSocketDataProvider(&data);
12061 TestCompletionCallback callback;
12063 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12064 EXPECT_EQ(ERR_IO_PENDING, rv);
12066 rv = callback.WaitForResult();
12067 EXPECT_EQ(OK, rv);
12069 HttpRequestHeaders request_headers;
12070 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12071 std::string foo;
12072 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12073 EXPECT_EQ("bar", foo);
12076 namespace {
12078 // Fake HttpStreamBase that simply records calls to SetPriority().
12079 class FakeStream : public HttpStreamBase,
12080 public base::SupportsWeakPtr<FakeStream> {
12081 public:
12082 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12083 virtual ~FakeStream() {}
12085 RequestPriority priority() const { return priority_; }
12087 virtual int InitializeStream(const HttpRequestInfo* request_info,
12088 RequestPriority priority,
12089 const BoundNetLog& net_log,
12090 const CompletionCallback& callback) OVERRIDE {
12091 return ERR_IO_PENDING;
12094 virtual int SendRequest(const HttpRequestHeaders& request_headers,
12095 HttpResponseInfo* response,
12096 const CompletionCallback& callback) OVERRIDE {
12097 ADD_FAILURE();
12098 return ERR_UNEXPECTED;
12101 virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
12102 ADD_FAILURE();
12103 return ERR_UNEXPECTED;
12106 virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
12107 ADD_FAILURE();
12108 return NULL;
12111 virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
12112 const CompletionCallback& callback) OVERRIDE {
12113 ADD_FAILURE();
12114 return ERR_UNEXPECTED;
12117 virtual void Close(bool not_reusable) OVERRIDE {}
12119 virtual bool IsResponseBodyComplete() const OVERRIDE {
12120 ADD_FAILURE();
12121 return false;
12124 virtual bool CanFindEndOfResponse() const OVERRIDE {
12125 return false;
12128 virtual bool IsConnectionReused() const OVERRIDE {
12129 ADD_FAILURE();
12130 return false;
12133 virtual void SetConnectionReused() OVERRIDE {
12134 ADD_FAILURE();
12137 virtual bool IsConnectionReusable() const OVERRIDE {
12138 ADD_FAILURE();
12139 return false;
12142 virtual int64 GetTotalReceivedBytes() const OVERRIDE {
12143 ADD_FAILURE();
12144 return 0;
12147 virtual bool GetLoadTimingInfo(
12148 LoadTimingInfo* load_timing_info) const OVERRIDE {
12149 ADD_FAILURE();
12150 return false;
12153 virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
12154 ADD_FAILURE();
12157 virtual void GetSSLCertRequestInfo(
12158 SSLCertRequestInfo* cert_request_info) OVERRIDE {
12159 ADD_FAILURE();
12162 virtual bool IsSpdyHttpStream() const OVERRIDE {
12163 ADD_FAILURE();
12164 return false;
12167 virtual void Drain(HttpNetworkSession* session) OVERRIDE {
12168 ADD_FAILURE();
12171 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12172 priority_ = priority;
12175 private:
12176 RequestPriority priority_;
12178 DISALLOW_COPY_AND_ASSIGN(FakeStream);
12181 // Fake HttpStreamRequest that simply records calls to SetPriority()
12182 // and vends FakeStreams with its current priority.
12183 class FakeStreamRequest : public HttpStreamRequest,
12184 public base::SupportsWeakPtr<FakeStreamRequest> {
12185 public:
12186 FakeStreamRequest(RequestPriority priority,
12187 HttpStreamRequest::Delegate* delegate)
12188 : priority_(priority),
12189 delegate_(delegate),
12190 websocket_stream_create_helper_(NULL) {}
12192 FakeStreamRequest(RequestPriority priority,
12193 HttpStreamRequest::Delegate* delegate,
12194 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
12195 : priority_(priority),
12196 delegate_(delegate),
12197 websocket_stream_create_helper_(create_helper) {}
12199 virtual ~FakeStreamRequest() {}
12201 RequestPriority priority() const { return priority_; }
12203 const WebSocketHandshakeStreamBase::CreateHelper*
12204 websocket_stream_create_helper() const {
12205 return websocket_stream_create_helper_;
12208 // Create a new FakeStream and pass it to the request's
12209 // delegate. Returns a weak pointer to the FakeStream.
12210 base::WeakPtr<FakeStream> FinishStreamRequest() {
12211 FakeStream* fake_stream = new FakeStream(priority_);
12212 // Do this before calling OnStreamReady() as OnStreamReady() may
12213 // immediately delete |fake_stream|.
12214 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
12215 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
12216 return weak_stream;
12219 virtual int RestartTunnelWithProxyAuth(
12220 const AuthCredentials& credentials) OVERRIDE {
12221 ADD_FAILURE();
12222 return ERR_UNEXPECTED;
12225 virtual LoadState GetLoadState() const OVERRIDE {
12226 ADD_FAILURE();
12227 return LoadState();
12230 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12231 priority_ = priority;
12234 virtual bool was_npn_negotiated() const OVERRIDE {
12235 return false;
12238 virtual NextProto protocol_negotiated() const OVERRIDE {
12239 return kProtoUnknown;
12242 virtual bool using_spdy() const OVERRIDE {
12243 return false;
12246 private:
12247 RequestPriority priority_;
12248 HttpStreamRequest::Delegate* const delegate_;
12249 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
12251 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12254 // Fake HttpStreamFactory that vends FakeStreamRequests.
12255 class FakeStreamFactory : public HttpStreamFactory {
12256 public:
12257 FakeStreamFactory() {}
12258 virtual ~FakeStreamFactory() {}
12260 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12261 // RequestStream() (which may be NULL if it was destroyed already).
12262 base::WeakPtr<FakeStreamRequest> last_stream_request() {
12263 return last_stream_request_;
12266 virtual HttpStreamRequest* RequestStream(
12267 const HttpRequestInfo& info,
12268 RequestPriority priority,
12269 const SSLConfig& server_ssl_config,
12270 const SSLConfig& proxy_ssl_config,
12271 HttpStreamRequest::Delegate* delegate,
12272 const BoundNetLog& net_log) OVERRIDE {
12273 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12274 last_stream_request_ = fake_request->AsWeakPtr();
12275 return fake_request;
12278 virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
12279 const HttpRequestInfo& info,
12280 RequestPriority priority,
12281 const SSLConfig& server_ssl_config,
12282 const SSLConfig& proxy_ssl_config,
12283 HttpStreamRequest::Delegate* delegate,
12284 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
12285 const BoundNetLog& net_log) OVERRIDE {
12286 FakeStreamRequest* fake_request =
12287 new FakeStreamRequest(priority, delegate, create_helper);
12288 last_stream_request_ = fake_request->AsWeakPtr();
12289 return fake_request;
12292 virtual void PreconnectStreams(int num_streams,
12293 const HttpRequestInfo& info,
12294 RequestPriority priority,
12295 const SSLConfig& server_ssl_config,
12296 const SSLConfig& proxy_ssl_config) OVERRIDE {
12297 ADD_FAILURE();
12300 virtual base::Value* PipelineInfoToValue() const OVERRIDE {
12301 ADD_FAILURE();
12302 return NULL;
12305 virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
12306 ADD_FAILURE();
12307 return NULL;
12310 private:
12311 base::WeakPtr<FakeStreamRequest> last_stream_request_;
12313 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12316 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12317 // worth doing.
12318 class FakeWebSocketStreamCreateHelper :
12319 public WebSocketHandshakeStreamBase::CreateHelper {
12320 public:
12321 virtual WebSocketHandshakeStreamBase* CreateBasicStream(
12322 scoped_ptr<ClientSocketHandle> connection,
12323 bool using_proxy) OVERRIDE {
12324 NOTREACHED();
12325 return NULL;
12328 virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
12329 const base::WeakPtr<SpdySession>& session,
12330 bool use_relative_url) OVERRIDE {
12331 NOTREACHED();
12332 return NULL;
12335 virtual ~FakeWebSocketStreamCreateHelper() {}
12337 virtual scoped_ptr<WebSocketStream> Upgrade() {
12338 NOTREACHED();
12339 return scoped_ptr<WebSocketStream>();
12343 } // namespace
12345 // Make sure that HttpNetworkTransaction passes on its priority to its
12346 // stream request on start.
12347 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
12348 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12349 HttpNetworkSessionPeer peer(session);
12350 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12351 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12353 HttpNetworkTransaction trans(LOW, session);
12355 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
12357 HttpRequestInfo request;
12358 TestCompletionCallback callback;
12359 EXPECT_EQ(ERR_IO_PENDING,
12360 trans.Start(&request, callback.callback(), BoundNetLog()));
12362 base::WeakPtr<FakeStreamRequest> fake_request =
12363 fake_factory->last_stream_request();
12364 ASSERT_TRUE(fake_request != NULL);
12365 EXPECT_EQ(LOW, fake_request->priority());
12368 // Make sure that HttpNetworkTransaction passes on its priority
12369 // updates to its stream request.
12370 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
12371 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12372 HttpNetworkSessionPeer peer(session);
12373 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12374 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12376 HttpNetworkTransaction trans(LOW, session);
12378 HttpRequestInfo request;
12379 TestCompletionCallback callback;
12380 EXPECT_EQ(ERR_IO_PENDING,
12381 trans.Start(&request, callback.callback(), BoundNetLog()));
12383 base::WeakPtr<FakeStreamRequest> fake_request =
12384 fake_factory->last_stream_request();
12385 ASSERT_TRUE(fake_request != NULL);
12386 EXPECT_EQ(LOW, fake_request->priority());
12388 trans.SetPriority(LOWEST);
12389 ASSERT_TRUE(fake_request != NULL);
12390 EXPECT_EQ(LOWEST, fake_request->priority());
12393 // Make sure that HttpNetworkTransaction passes on its priority
12394 // updates to its stream.
12395 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
12396 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12397 HttpNetworkSessionPeer peer(session);
12398 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12399 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12401 HttpNetworkTransaction trans(LOW, session);
12403 HttpRequestInfo request;
12404 TestCompletionCallback callback;
12405 EXPECT_EQ(ERR_IO_PENDING,
12406 trans.Start(&request, callback.callback(), BoundNetLog()));
12408 base::WeakPtr<FakeStreamRequest> fake_request =
12409 fake_factory->last_stream_request();
12410 ASSERT_TRUE(fake_request != NULL);
12411 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
12412 ASSERT_TRUE(fake_stream != NULL);
12413 EXPECT_EQ(LOW, fake_stream->priority());
12415 trans.SetPriority(LOWEST);
12416 EXPECT_EQ(LOWEST, fake_stream->priority());
12419 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
12420 // The same logic needs to be tested for both ws: and wss: schemes, but this
12421 // test is already parameterised on NextProto, so it uses a loop to verify
12422 // that the different schemes work.
12423 std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"};
12424 for (size_t i = 0; i < arraysize(test_cases); ++i) {
12425 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12426 HttpNetworkSessionPeer peer(session);
12427 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12428 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
12429 peer.SetHttpStreamFactoryForWebSocket(
12430 scoped_ptr<HttpStreamFactory>(fake_factory));
12432 HttpNetworkTransaction trans(LOW, session);
12433 trans.SetWebSocketHandshakeStreamCreateHelper(
12434 &websocket_stream_create_helper);
12436 HttpRequestInfo request;
12437 TestCompletionCallback callback;
12438 request.method = "GET";
12439 request.url = GURL(test_cases[i]);
12441 EXPECT_EQ(ERR_IO_PENDING,
12442 trans.Start(&request, callback.callback(), BoundNetLog()));
12444 base::WeakPtr<FakeStreamRequest> fake_request =
12445 fake_factory->last_stream_request();
12446 ASSERT_TRUE(fake_request != NULL);
12447 EXPECT_EQ(&websocket_stream_create_helper,
12448 fake_request->websocket_stream_create_helper());
12452 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12453 // if the transport socket pool is stalled on the global socket limit.
12454 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
12455 ClientSocketPoolManager::set_max_sockets_per_group(
12456 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12457 ClientSocketPoolManager::set_max_sockets_per_pool(
12458 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12460 // Set up SSL request.
12462 HttpRequestInfo ssl_request;
12463 ssl_request.method = "GET";
12464 ssl_request.url = GURL("https://www.google.com/");
12466 MockWrite ssl_writes[] = {
12467 MockWrite("GET / HTTP/1.1\r\n"
12468 "Host: www.google.com\r\n"
12469 "Connection: keep-alive\r\n\r\n"),
12471 MockRead ssl_reads[] = {
12472 MockRead("HTTP/1.1 200 OK\r\n"),
12473 MockRead("Content-Length: 11\r\n\r\n"),
12474 MockRead("hello world"),
12475 MockRead(SYNCHRONOUS, OK),
12477 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
12478 ssl_writes, arraysize(ssl_writes));
12479 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12481 SSLSocketDataProvider ssl(ASYNC, OK);
12482 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12484 // Set up HTTP request.
12486 HttpRequestInfo http_request;
12487 http_request.method = "GET";
12488 http_request.url = GURL("http://www.google.com/");
12490 MockWrite http_writes[] = {
12491 MockWrite("GET / HTTP/1.1\r\n"
12492 "Host: www.google.com\r\n"
12493 "Connection: keep-alive\r\n\r\n"),
12495 MockRead http_reads[] = {
12496 MockRead("HTTP/1.1 200 OK\r\n"),
12497 MockRead("Content-Length: 7\r\n\r\n"),
12498 MockRead("falafel"),
12499 MockRead(SYNCHRONOUS, OK),
12501 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12502 http_writes, arraysize(http_writes));
12503 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12505 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12507 // Start the SSL request.
12508 TestCompletionCallback ssl_callback;
12509 scoped_ptr<HttpTransaction> ssl_trans(
12510 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12511 ASSERT_EQ(ERR_IO_PENDING,
12512 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
12513 BoundNetLog()));
12515 // Start the HTTP request. Pool should stall.
12516 TestCompletionCallback http_callback;
12517 scoped_ptr<HttpTransaction> http_trans(
12518 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12519 ASSERT_EQ(ERR_IO_PENDING,
12520 http_trans->Start(&http_request, http_callback.callback(),
12521 BoundNetLog()));
12522 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12524 // Wait for response from SSL request.
12525 ASSERT_EQ(OK, ssl_callback.WaitForResult());
12526 std::string response_data;
12527 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
12528 EXPECT_EQ("hello world", response_data);
12530 // The SSL socket should automatically be closed, so the HTTP request can
12531 // start.
12532 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12533 ASSERT_FALSE(IsTransportSocketPoolStalled(session));
12535 // The HTTP request can now complete.
12536 ASSERT_EQ(OK, http_callback.WaitForResult());
12537 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12538 EXPECT_EQ("falafel", response_data);
12540 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12543 // Tests that when a SSL connection is established but there's no corresponding
12544 // request that needs it, the new socket is closed if the transport socket pool
12545 // is stalled on the global socket limit.
12546 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
12547 ClientSocketPoolManager::set_max_sockets_per_group(
12548 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12549 ClientSocketPoolManager::set_max_sockets_per_pool(
12550 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12552 // Set up an ssl request.
12554 HttpRequestInfo ssl_request;
12555 ssl_request.method = "GET";
12556 ssl_request.url = GURL("https://www.foopy.com/");
12558 // No data will be sent on the SSL socket.
12559 StaticSocketDataProvider ssl_data;
12560 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12562 SSLSocketDataProvider ssl(ASYNC, OK);
12563 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12565 // Set up HTTP request.
12567 HttpRequestInfo http_request;
12568 http_request.method = "GET";
12569 http_request.url = GURL("http://www.google.com/");
12571 MockWrite http_writes[] = {
12572 MockWrite("GET / HTTP/1.1\r\n"
12573 "Host: www.google.com\r\n"
12574 "Connection: keep-alive\r\n\r\n"),
12576 MockRead http_reads[] = {
12577 MockRead("HTTP/1.1 200 OK\r\n"),
12578 MockRead("Content-Length: 7\r\n\r\n"),
12579 MockRead("falafel"),
12580 MockRead(SYNCHRONOUS, OK),
12582 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12583 http_writes, arraysize(http_writes));
12584 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12586 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12588 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12589 // cancelled when a normal transaction is cancelled.
12590 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
12591 net::SSLConfig ssl_config;
12592 session->ssl_config_service()->GetSSLConfig(&ssl_config);
12593 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
12594 ssl_config, ssl_config);
12595 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12597 // Start the HTTP request. Pool should stall.
12598 TestCompletionCallback http_callback;
12599 scoped_ptr<HttpTransaction> http_trans(
12600 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12601 ASSERT_EQ(ERR_IO_PENDING,
12602 http_trans->Start(&http_request, http_callback.callback(),
12603 BoundNetLog()));
12604 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12606 // The SSL connection will automatically be closed once the connection is
12607 // established, to let the HTTP request start.
12608 ASSERT_EQ(OK, http_callback.WaitForResult());
12609 std::string response_data;
12610 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12611 EXPECT_EQ("falafel", response_data);
12613 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12616 } // namespace net