Returning scoped_ptr instead of raw pointer in QuicInfoToValue in net/
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blobfcfba01eae71b75ce542a8f3994059b2529ca9ed
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/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/json/json_writer.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/run_loop.h"
21 #include "base/stl_util.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/test/test_file_util.h"
25 #include "net/base/auth.h"
26 #include "net/base/chunked_upload_data_stream.h"
27 #include "net/base/completion_callback.h"
28 #include "net/base/elements_upload_data_stream.h"
29 #include "net/base/load_timing_info.h"
30 #include "net/base/load_timing_info_test_util.h"
31 #include "net/base/net_errors.h"
32 #include "net/base/request_priority.h"
33 #include "net/base/test_completion_callback.h"
34 #include "net/base/test_data_directory.h"
35 #include "net/base/upload_bytes_element_reader.h"
36 #include "net/base/upload_file_element_reader.h"
37 #include "net/cert/mock_cert_verifier.h"
38 #include "net/dns/host_cache.h"
39 #include "net/dns/mock_host_resolver.h"
40 #include "net/http/http_auth_challenge_tokenizer.h"
41 #include "net/http/http_auth_handler_digest.h"
42 #include "net/http/http_auth_handler_mock.h"
43 #include "net/http/http_auth_handler_ntlm.h"
44 #include "net/http/http_basic_state.h"
45 #include "net/http/http_basic_stream.h"
46 #include "net/http/http_network_session.h"
47 #include "net/http/http_network_session_peer.h"
48 #include "net/http/http_request_headers.h"
49 #include "net/http/http_server_properties_impl.h"
50 #include "net/http/http_stream.h"
51 #include "net/http/http_stream_factory.h"
52 #include "net/http/http_stream_parser.h"
53 #include "net/http/http_transaction_test_util.h"
54 #include "net/log/net_log.h"
55 #include "net/log/test_net_log.h"
56 #include "net/log/test_net_log_entry.h"
57 #include "net/log/test_net_log_util.h"
58 #include "net/proxy/mock_proxy_resolver.h"
59 #include "net/proxy/proxy_config_service_fixed.h"
60 #include "net/proxy/proxy_info.h"
61 #include "net/proxy/proxy_resolver.h"
62 #include "net/proxy/proxy_service.h"
63 #include "net/socket/client_socket_factory.h"
64 #include "net/socket/client_socket_pool_manager.h"
65 #include "net/socket/connection_attempts.h"
66 #include "net/socket/mock_client_socket_pool_manager.h"
67 #include "net/socket/next_proto.h"
68 #include "net/socket/socket_test_util.h"
69 #include "net/socket/ssl_client_socket.h"
70 #include "net/spdy/spdy_framer.h"
71 #include "net/spdy/spdy_session.h"
72 #include "net/spdy/spdy_session_pool.h"
73 #include "net/spdy/spdy_test_util_common.h"
74 #include "net/ssl/ssl_cert_request_info.h"
75 #include "net/ssl/ssl_config_service.h"
76 #include "net/ssl/ssl_config_service_defaults.h"
77 #include "net/ssl/ssl_info.h"
78 #include "net/test/cert_test_util.h"
79 #include "net/websockets/websocket_handshake_stream_base.h"
80 #include "testing/gtest/include/gtest/gtest.h"
81 #include "testing/platform_test.h"
82 #include "url/gurl.h"
84 using base::ASCIIToUTF16;
86 //-----------------------------------------------------------------------------
88 namespace net {
90 namespace {
92 const base::string16 kBar(ASCIIToUTF16("bar"));
93 const base::string16 kBar2(ASCIIToUTF16("bar2"));
94 const base::string16 kBar3(ASCIIToUTF16("bar3"));
95 const base::string16 kBaz(ASCIIToUTF16("baz"));
96 const base::string16 kFirst(ASCIIToUTF16("first"));
97 const base::string16 kFoo(ASCIIToUTF16("foo"));
98 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
99 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
100 const base::string16 kFou(ASCIIToUTF16("fou"));
101 const base::string16 kSecond(ASCIIToUTF16("second"));
102 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
103 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
105 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
106 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
107 ->IdleSocketCount();
110 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
111 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
112 ->IdleSocketCount();
115 bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
116 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
117 ->IsStalled();
120 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
121 // a JSONified list of headers as a single string. Uses single quotes instead
122 // of double quotes for easier comparison. Returns false on failure.
123 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
124 if (!params)
125 return false;
126 base::ListValue* header_list;
127 if (!params->GetList("headers", &header_list))
128 return false;
129 std::string double_quote_headers;
130 base::JSONWriter::Write(*header_list, &double_quote_headers);
131 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
132 return true;
135 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
136 // used.
137 void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
138 EXPECT_TRUE(load_timing_info.socket_reused);
139 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
141 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
142 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
144 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
145 EXPECT_FALSE(load_timing_info.send_start.is_null());
147 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
149 // Set at a higher level.
150 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
151 EXPECT_TRUE(load_timing_info.request_start.is_null());
152 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
155 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
156 // used.
157 void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
158 int connect_timing_flags) {
159 EXPECT_FALSE(load_timing_info.socket_reused);
160 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
162 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
163 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
165 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
166 connect_timing_flags);
167 EXPECT_LE(load_timing_info.connect_timing.connect_end,
168 load_timing_info.send_start);
170 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
172 // Set at a higher level.
173 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
174 EXPECT_TRUE(load_timing_info.request_start.is_null());
175 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
178 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
179 // used.
180 void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
181 EXPECT_TRUE(load_timing_info.socket_reused);
182 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
184 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
186 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
187 EXPECT_LE(load_timing_info.proxy_resolve_start,
188 load_timing_info.proxy_resolve_end);
189 EXPECT_LE(load_timing_info.proxy_resolve_end,
190 load_timing_info.send_start);
191 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
193 // Set at a higher level.
194 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
195 EXPECT_TRUE(load_timing_info.request_start.is_null());
196 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
199 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
200 // used.
201 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
202 int connect_timing_flags) {
203 EXPECT_FALSE(load_timing_info.socket_reused);
204 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
206 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
207 EXPECT_LE(load_timing_info.proxy_resolve_start,
208 load_timing_info.proxy_resolve_end);
209 EXPECT_LE(load_timing_info.proxy_resolve_end,
210 load_timing_info.connect_timing.connect_start);
211 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
212 connect_timing_flags);
213 EXPECT_LE(load_timing_info.connect_timing.connect_end,
214 load_timing_info.send_start);
216 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
218 // Set at a higher level.
219 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
220 EXPECT_TRUE(load_timing_info.request_start.is_null());
221 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
224 void AddWebSocketHeaders(HttpRequestHeaders* headers) {
225 headers->SetHeader("Connection", "Upgrade");
226 headers->SetHeader("Upgrade", "websocket");
227 headers->SetHeader("Origin", "http://www.example.org");
228 headers->SetHeader("Sec-WebSocket-Version", "13");
229 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
232 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
233 return SpdySessionDependencies::SpdyCreateSession(session_deps);
236 } // namespace
238 class HttpNetworkTransactionTest
239 : public PlatformTest,
240 public ::testing::WithParamInterface<NextProto> {
241 public:
242 virtual ~HttpNetworkTransactionTest() {
243 // Important to restore the per-pool limit first, since the pool limit must
244 // always be greater than group limit, and the tests reduce both limits.
245 ClientSocketPoolManager::set_max_sockets_per_pool(
246 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
247 ClientSocketPoolManager::set_max_sockets_per_group(
248 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
251 protected:
252 HttpNetworkTransactionTest()
253 : spdy_util_(GetParam()),
254 session_deps_(GetParam()),
255 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
256 HttpNetworkSession::NORMAL_SOCKET_POOL)),
257 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
258 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
261 struct SimpleGetHelperResult {
262 int rv;
263 std::string status_line;
264 std::string response_data;
265 int64 totalReceivedBytes;
266 LoadTimingInfo load_timing_info;
267 ConnectionAttempts connection_attempts;
270 void SetUp() override {
271 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
272 base::MessageLoop::current()->RunUntilIdle();
275 void TearDown() override {
276 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
277 base::MessageLoop::current()->RunUntilIdle();
278 // Empty the current queue.
279 base::MessageLoop::current()->RunUntilIdle();
280 PlatformTest::TearDown();
281 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
282 base::MessageLoop::current()->RunUntilIdle();
285 const char* GetAlternateProtocolFromParam() {
286 return
287 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
290 // This is the expected return from a current server advertising SPDY.
291 std::string GetAlternateProtocolHttpHeader() {
292 return std::string("Alternate-Protocol: 443:") +
293 GetAlternateProtocolFromParam() + "\r\n\r\n";
296 // Either |write_failure| specifies a write failure or |read_failure|
297 // specifies a read failure when using a reused socket. In either case, the
298 // failure should cause the network transaction to resend the request, and the
299 // other argument should be NULL.
300 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
301 const MockRead* read_failure);
303 // Either |write_failure| specifies a write failure or |read_failure|
304 // specifies a read failure when using a reused socket. In either case, the
305 // failure should cause the network transaction to resend the request, and the
306 // other argument should be NULL.
307 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
308 const MockRead* read_failure,
309 bool use_spdy);
311 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
312 size_t data_count) {
313 SimpleGetHelperResult out;
315 HttpRequestInfo request;
316 request.method = "GET";
317 request.url = GURL("http://www.example.org/");
318 request.load_flags = 0;
320 BoundTestNetLog log;
321 session_deps_.net_log = log.bound().net_log();
322 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
323 scoped_ptr<HttpTransaction> trans(
324 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
326 for (size_t i = 0; i < data_count; ++i) {
327 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
330 TestCompletionCallback callback;
332 EXPECT_TRUE(log.bound().IsCapturing());
333 int rv = trans->Start(&request, callback.callback(), log.bound());
334 EXPECT_EQ(ERR_IO_PENDING, rv);
336 out.rv = callback.WaitForResult();
338 // Even in the failure cases that use this function, connections are always
339 // successfully established before the error.
340 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
341 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
343 if (out.rv != OK)
344 return out;
346 const HttpResponseInfo* response = trans->GetResponseInfo();
347 // Can't use ASSERT_* inside helper functions like this, so
348 // return an error.
349 if (response == NULL || response->headers.get() == NULL) {
350 out.rv = ERR_UNEXPECTED;
351 return out;
353 out.status_line = response->headers->GetStatusLine();
355 EXPECT_EQ("127.0.0.1", response->socket_address.host());
356 EXPECT_EQ(80, response->socket_address.port());
358 rv = ReadTransaction(trans.get(), &out.response_data);
359 EXPECT_EQ(OK, rv);
361 TestNetLogEntry::List entries;
362 log.GetEntries(&entries);
363 size_t pos = ExpectLogContainsSomewhere(
364 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
365 NetLog::PHASE_NONE);
366 ExpectLogContainsSomewhere(
367 entries, pos,
368 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
369 NetLog::PHASE_NONE);
371 std::string line;
372 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
373 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
375 HttpRequestHeaders request_headers;
376 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
377 std::string value;
378 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
379 EXPECT_EQ("www.example.org", value);
380 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
381 EXPECT_EQ("keep-alive", value);
383 std::string response_headers;
384 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
385 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
386 response_headers);
388 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
389 trans->GetConnectionAttempts(&out.connection_attempts);
390 return out;
393 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
394 size_t reads_count) {
395 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
396 StaticSocketDataProvider* data[] = { &reads };
397 return SimpleGetHelperForData(data, 1);
400 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
401 int64 size = 0;
402 for (size_t i = 0; i < reads_count; ++i)
403 size += data_reads[i].data_len;
404 return size;
407 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
408 int expected_status);
410 void ConnectStatusHelper(const MockRead& status);
412 void BypassHostCacheOnRefreshHelper(int load_flags);
414 void CheckErrorIsPassedBack(int error, IoMode mode);
416 SpdyTestUtil spdy_util_;
417 SpdySessionDependencies session_deps_;
419 // Original socket limits. Some tests set these. Safest to always restore
420 // them once each test has been run.
421 int old_max_group_sockets_;
422 int old_max_pool_sockets_;
425 INSTANTIATE_TEST_CASE_P(NextProto,
426 HttpNetworkTransactionTest,
427 testing::Values(kProtoSPDY31,
428 kProtoSPDY4_14,
429 kProtoSPDY4));
431 namespace {
433 class BeforeNetworkStartHandler {
434 public:
435 explicit BeforeNetworkStartHandler(bool defer)
436 : defer_on_before_network_start_(defer),
437 observed_before_network_start_(false) {}
439 void OnBeforeNetworkStart(bool* defer) {
440 *defer = defer_on_before_network_start_;
441 observed_before_network_start_ = true;
444 bool observed_before_network_start() const {
445 return observed_before_network_start_;
448 private:
449 const bool defer_on_before_network_start_;
450 bool observed_before_network_start_;
452 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
455 class BeforeProxyHeadersSentHandler {
456 public:
457 BeforeProxyHeadersSentHandler()
458 : observed_before_proxy_headers_sent_(false) {}
460 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
461 HttpRequestHeaders* request_headers) {
462 observed_before_proxy_headers_sent_ = true;
463 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
466 bool observed_before_proxy_headers_sent() const {
467 return observed_before_proxy_headers_sent_;
470 std::string observed_proxy_server_uri() const {
471 return observed_proxy_server_uri_;
474 private:
475 bool observed_before_proxy_headers_sent_;
476 std::string observed_proxy_server_uri_;
478 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
481 // Fill |str| with a long header list that consumes >= |size| bytes.
482 void FillLargeHeadersString(std::string* str, int size) {
483 const char row[] =
484 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
485 const int sizeof_row = strlen(row);
486 const int num_rows = static_cast<int>(
487 ceil(static_cast<float>(size) / sizeof_row));
488 const int sizeof_data = num_rows * sizeof_row;
489 DCHECK(sizeof_data >= size);
490 str->reserve(sizeof_data);
492 for (int i = 0; i < num_rows; ++i)
493 str->append(row, sizeof_row);
496 // Alternative functions that eliminate randomness and dependency on the local
497 // host name so that the generated NTLM messages are reproducible.
498 void MockGenerateRandom1(uint8* output, size_t n) {
499 static const uint8 bytes[] = {
500 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
502 static size_t current_byte = 0;
503 for (size_t i = 0; i < n; ++i) {
504 output[i] = bytes[current_byte++];
505 current_byte %= arraysize(bytes);
509 void MockGenerateRandom2(uint8* output, size_t n) {
510 static const uint8 bytes[] = {
511 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
512 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
514 static size_t current_byte = 0;
515 for (size_t i = 0; i < n; ++i) {
516 output[i] = bytes[current_byte++];
517 current_byte %= arraysize(bytes);
521 std::string MockGetHostName() {
522 return "WTC-WIN7";
525 template<typename ParentPool>
526 class CaptureGroupNameSocketPool : public ParentPool {
527 public:
528 CaptureGroupNameSocketPool(HostResolver* host_resolver,
529 CertVerifier* cert_verifier);
531 const std::string last_group_name_received() const {
532 return last_group_name_;
535 int RequestSocket(const std::string& group_name,
536 const void* socket_params,
537 RequestPriority priority,
538 ClientSocketHandle* handle,
539 const CompletionCallback& callback,
540 const BoundNetLog& net_log) override {
541 last_group_name_ = group_name;
542 return ERR_IO_PENDING;
544 void CancelRequest(const std::string& group_name,
545 ClientSocketHandle* handle) override {}
546 void ReleaseSocket(const std::string& group_name,
547 scoped_ptr<StreamSocket> socket,
548 int id) override {}
549 void CloseIdleSockets() override {}
550 int IdleSocketCount() const override { return 0; }
551 int IdleSocketCountInGroup(const std::string& group_name) const override {
552 return 0;
554 LoadState GetLoadState(const std::string& group_name,
555 const ClientSocketHandle* handle) const override {
556 return LOAD_STATE_IDLE;
558 base::TimeDelta ConnectionTimeout() const override {
559 return base::TimeDelta();
562 private:
563 std::string last_group_name_;
566 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
567 CaptureGroupNameTransportSocketPool;
568 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
569 CaptureGroupNameHttpProxySocketPool;
570 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
571 CaptureGroupNameSOCKSSocketPool;
572 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
573 CaptureGroupNameSSLSocketPool;
575 template <typename ParentPool>
576 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
577 HostResolver* host_resolver,
578 CertVerifier* /* cert_verifier */)
579 : ParentPool(0, 0, host_resolver, NULL, NULL) {
582 template <>
583 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
584 HostResolver* /* host_resolver */,
585 CertVerifier* /* cert_verifier */)
586 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
589 template <>
590 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
591 HostResolver* /* host_resolver */,
592 CertVerifier* cert_verifier)
593 : SSLClientSocketPool(0,
595 cert_verifier,
596 NULL,
597 NULL,
598 NULL,
599 NULL,
600 std::string(),
601 NULL,
602 NULL,
603 NULL,
604 NULL,
605 NULL,
606 NULL) {
609 //-----------------------------------------------------------------------------
611 // Helper functions for validating that AuthChallengeInfo's are correctly
612 // configured for common cases.
613 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
614 if (!auth_challenge)
615 return false;
616 EXPECT_FALSE(auth_challenge->is_proxy);
617 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
618 EXPECT_EQ("MyRealm1", auth_challenge->realm);
619 EXPECT_EQ("basic", auth_challenge->scheme);
620 return true;
623 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
624 if (!auth_challenge)
625 return false;
626 EXPECT_TRUE(auth_challenge->is_proxy);
627 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
628 EXPECT_EQ("MyRealm1", auth_challenge->realm);
629 EXPECT_EQ("basic", auth_challenge->scheme);
630 return true;
633 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
634 if (!auth_challenge)
635 return false;
636 EXPECT_FALSE(auth_challenge->is_proxy);
637 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
638 EXPECT_EQ("digestive", auth_challenge->realm);
639 EXPECT_EQ("digest", auth_challenge->scheme);
640 return true;
643 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
644 if (!auth_challenge)
645 return false;
646 EXPECT_FALSE(auth_challenge->is_proxy);
647 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
648 EXPECT_EQ(std::string(), auth_challenge->realm);
649 EXPECT_EQ("ntlm", auth_challenge->scheme);
650 return true;
653 } // namespace
655 TEST_P(HttpNetworkTransactionTest, Basic) {
656 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
657 scoped_ptr<HttpTransaction> trans(
658 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
661 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
662 MockRead data_reads[] = {
663 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
664 MockRead("hello world"),
665 MockRead(SYNCHRONOUS, OK),
667 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
668 arraysize(data_reads));
669 EXPECT_EQ(OK, out.rv);
670 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
671 EXPECT_EQ("hello world", out.response_data);
672 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
673 EXPECT_EQ(reads_size, out.totalReceivedBytes);
674 EXPECT_EQ(0u, out.connection_attempts.size());
677 // Response with no status line.
678 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
679 MockRead data_reads[] = {
680 MockRead("hello world"),
681 MockRead(SYNCHRONOUS, OK),
683 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
684 arraysize(data_reads));
685 EXPECT_EQ(OK, out.rv);
686 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
687 EXPECT_EQ("hello world", out.response_data);
688 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
689 EXPECT_EQ(reads_size, out.totalReceivedBytes);
692 // Allow up to 4 bytes of junk to precede status line.
693 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
694 MockRead data_reads[] = {
695 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
696 MockRead(SYNCHRONOUS, OK),
698 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
699 arraysize(data_reads));
700 EXPECT_EQ(OK, out.rv);
701 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
702 EXPECT_EQ("DATA", out.response_data);
703 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
704 EXPECT_EQ(reads_size, out.totalReceivedBytes);
707 // Allow up to 4 bytes of junk to precede status line.
708 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
709 MockRead data_reads[] = {
710 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
711 MockRead(SYNCHRONOUS, OK),
713 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
714 arraysize(data_reads));
715 EXPECT_EQ(OK, out.rv);
716 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
717 EXPECT_EQ("DATA", out.response_data);
718 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
719 EXPECT_EQ(reads_size, out.totalReceivedBytes);
722 // Beyond 4 bytes of slop and it should fail to find a status line.
723 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
724 MockRead data_reads[] = {
725 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
726 MockRead(SYNCHRONOUS, OK),
728 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
729 arraysize(data_reads));
730 EXPECT_EQ(OK, out.rv);
731 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
732 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
733 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
734 EXPECT_EQ(reads_size, out.totalReceivedBytes);
737 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
738 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
739 MockRead data_reads[] = {
740 MockRead("\n"),
741 MockRead("\n"),
742 MockRead("Q"),
743 MockRead("J"),
744 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
745 MockRead(SYNCHRONOUS, OK),
747 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
748 arraysize(data_reads));
749 EXPECT_EQ(OK, out.rv);
750 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
751 EXPECT_EQ("DATA", out.response_data);
752 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
753 EXPECT_EQ(reads_size, out.totalReceivedBytes);
756 // Close the connection before enough bytes to have a status line.
757 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
758 MockRead data_reads[] = {
759 MockRead("HTT"),
760 MockRead(SYNCHRONOUS, OK),
762 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
763 arraysize(data_reads));
764 EXPECT_EQ(OK, out.rv);
765 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
766 EXPECT_EQ("HTT", out.response_data);
767 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
768 EXPECT_EQ(reads_size, out.totalReceivedBytes);
771 // Simulate a 204 response, lacking a Content-Length header, sent over a
772 // persistent connection. The response should still terminate since a 204
773 // cannot have a response body.
774 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
775 char junk[] = "junk";
776 MockRead data_reads[] = {
777 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
778 MockRead(junk), // Should not be read!!
779 MockRead(SYNCHRONOUS, OK),
781 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
782 arraysize(data_reads));
783 EXPECT_EQ(OK, out.rv);
784 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
785 EXPECT_EQ("", out.response_data);
786 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
787 int64 response_size = reads_size - strlen(junk);
788 EXPECT_EQ(response_size, out.totalReceivedBytes);
791 // A simple request using chunked encoding with some extra data after.
792 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
793 std::string final_chunk = "0\r\n\r\n";
794 std::string extra_data = "HTTP/1.1 200 OK\r\n";
795 std::string last_read = final_chunk + extra_data;
796 MockRead data_reads[] = {
797 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
798 MockRead("5\r\nHello\r\n"),
799 MockRead("1\r\n"),
800 MockRead(" \r\n"),
801 MockRead("5\r\nworld\r\n"),
802 MockRead(last_read.data()),
803 MockRead(SYNCHRONOUS, OK),
805 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
806 arraysize(data_reads));
807 EXPECT_EQ(OK, out.rv);
808 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
809 EXPECT_EQ("Hello world", out.response_data);
810 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
811 int64 response_size = reads_size - extra_data.size();
812 EXPECT_EQ(response_size, out.totalReceivedBytes);
815 // Next tests deal with http://crbug.com/56344.
817 TEST_P(HttpNetworkTransactionTest,
818 MultipleContentLengthHeadersNoTransferEncoding) {
819 MockRead data_reads[] = {
820 MockRead("HTTP/1.1 200 OK\r\n"),
821 MockRead("Content-Length: 10\r\n"),
822 MockRead("Content-Length: 5\r\n\r\n"),
824 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
825 arraysize(data_reads));
826 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
829 TEST_P(HttpNetworkTransactionTest,
830 DuplicateContentLengthHeadersNoTransferEncoding) {
831 MockRead data_reads[] = {
832 MockRead("HTTP/1.1 200 OK\r\n"),
833 MockRead("Content-Length: 5\r\n"),
834 MockRead("Content-Length: 5\r\n\r\n"),
835 MockRead("Hello"),
837 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
838 arraysize(data_reads));
839 EXPECT_EQ(OK, out.rv);
840 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
841 EXPECT_EQ("Hello", out.response_data);
844 TEST_P(HttpNetworkTransactionTest,
845 ComplexContentLengthHeadersNoTransferEncoding) {
846 // More than 2 dupes.
848 MockRead data_reads[] = {
849 MockRead("HTTP/1.1 200 OK\r\n"),
850 MockRead("Content-Length: 5\r\n"),
851 MockRead("Content-Length: 5\r\n"),
852 MockRead("Content-Length: 5\r\n\r\n"),
853 MockRead("Hello"),
855 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
856 arraysize(data_reads));
857 EXPECT_EQ(OK, out.rv);
858 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
859 EXPECT_EQ("Hello", out.response_data);
861 // HTTP/1.0
863 MockRead data_reads[] = {
864 MockRead("HTTP/1.0 200 OK\r\n"),
865 MockRead("Content-Length: 5\r\n"),
866 MockRead("Content-Length: 5\r\n"),
867 MockRead("Content-Length: 5\r\n\r\n"),
868 MockRead("Hello"),
870 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
871 arraysize(data_reads));
872 EXPECT_EQ(OK, out.rv);
873 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
874 EXPECT_EQ("Hello", out.response_data);
876 // 2 dupes and one mismatched.
878 MockRead data_reads[] = {
879 MockRead("HTTP/1.1 200 OK\r\n"),
880 MockRead("Content-Length: 10\r\n"),
881 MockRead("Content-Length: 10\r\n"),
882 MockRead("Content-Length: 5\r\n\r\n"),
884 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
885 arraysize(data_reads));
886 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
890 TEST_P(HttpNetworkTransactionTest,
891 MultipleContentLengthHeadersTransferEncoding) {
892 MockRead data_reads[] = {
893 MockRead("HTTP/1.1 200 OK\r\n"),
894 MockRead("Content-Length: 666\r\n"),
895 MockRead("Content-Length: 1337\r\n"),
896 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
897 MockRead("5\r\nHello\r\n"),
898 MockRead("1\r\n"),
899 MockRead(" \r\n"),
900 MockRead("5\r\nworld\r\n"),
901 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
902 MockRead(SYNCHRONOUS, OK),
904 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
905 arraysize(data_reads));
906 EXPECT_EQ(OK, out.rv);
907 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
908 EXPECT_EQ("Hello world", out.response_data);
911 // Next tests deal with http://crbug.com/98895.
913 // Checks that a single Content-Disposition header results in no error.
914 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
915 MockRead data_reads[] = {
916 MockRead("HTTP/1.1 200 OK\r\n"),
917 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
918 MockRead("Content-Length: 5\r\n\r\n"),
919 MockRead("Hello"),
921 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
922 arraysize(data_reads));
923 EXPECT_EQ(OK, out.rv);
924 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
925 EXPECT_EQ("Hello", out.response_data);
928 // Checks that two identical Content-Disposition headers result in no error.
929 TEST_P(HttpNetworkTransactionTest,
930 TwoIdenticalContentDispositionHeaders) {
931 MockRead data_reads[] = {
932 MockRead("HTTP/1.1 200 OK\r\n"),
933 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
934 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
935 MockRead("Content-Length: 5\r\n\r\n"),
936 MockRead("Hello"),
938 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
939 arraysize(data_reads));
940 EXPECT_EQ(OK, out.rv);
941 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
942 EXPECT_EQ("Hello", out.response_data);
945 // Checks that two distinct Content-Disposition headers result in an error.
946 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
947 MockRead data_reads[] = {
948 MockRead("HTTP/1.1 200 OK\r\n"),
949 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
950 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
951 MockRead("Content-Length: 5\r\n\r\n"),
952 MockRead("Hello"),
954 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
955 arraysize(data_reads));
956 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
959 // Checks that two identical Location headers result in no error.
960 // Also tests Location header behavior.
961 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
962 MockRead data_reads[] = {
963 MockRead("HTTP/1.1 302 Redirect\r\n"),
964 MockRead("Location: http://good.com/\r\n"),
965 MockRead("Location: http://good.com/\r\n"),
966 MockRead("Content-Length: 0\r\n\r\n"),
967 MockRead(SYNCHRONOUS, OK),
970 HttpRequestInfo request;
971 request.method = "GET";
972 request.url = GURL("http://redirect.com/");
973 request.load_flags = 0;
975 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
976 scoped_ptr<HttpTransaction> trans(
977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
979 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
980 session_deps_.socket_factory->AddSocketDataProvider(&data);
982 TestCompletionCallback callback;
984 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
985 EXPECT_EQ(ERR_IO_PENDING, rv);
987 EXPECT_EQ(OK, callback.WaitForResult());
989 const HttpResponseInfo* response = trans->GetResponseInfo();
990 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
991 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
992 std::string url;
993 EXPECT_TRUE(response->headers->IsRedirect(&url));
994 EXPECT_EQ("http://good.com/", url);
995 EXPECT_TRUE(response->proxy_server.IsEmpty());
998 // Checks that two distinct Location headers result in an error.
999 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
1000 MockRead data_reads[] = {
1001 MockRead("HTTP/1.1 302 Redirect\r\n"),
1002 MockRead("Location: http://good.com/\r\n"),
1003 MockRead("Location: http://evil.com/\r\n"),
1004 MockRead("Content-Length: 0\r\n\r\n"),
1005 MockRead(SYNCHRONOUS, OK),
1007 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1008 arraysize(data_reads));
1009 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1012 // Do a request using the HEAD method. Verify that we don't try to read the
1013 // message body (since HEAD has none).
1014 TEST_P(HttpNetworkTransactionTest, Head) {
1015 HttpRequestInfo request;
1016 request.method = "HEAD";
1017 request.url = GURL("http://www.example.org/");
1018 request.load_flags = 0;
1020 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1021 scoped_ptr<HttpTransaction> trans(
1022 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1023 BeforeProxyHeadersSentHandler proxy_headers_handler;
1024 trans->SetBeforeProxyHeadersSentCallback(
1025 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1026 base::Unretained(&proxy_headers_handler)));
1028 MockWrite data_writes1[] = {
1029 MockWrite(
1030 "HEAD / HTTP/1.1\r\n"
1031 "Host: www.example.org\r\n"
1032 "Connection: keep-alive\r\n"
1033 "Content-Length: 0\r\n\r\n"),
1035 MockRead data_reads1[] = {
1036 MockRead("HTTP/1.1 404 Not Found\r\n"),
1037 MockRead("Server: Blah\r\n"),
1038 MockRead("Content-Length: 1234\r\n\r\n"),
1040 // No response body because the test stops reading here.
1041 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1044 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1045 data_writes1, arraysize(data_writes1));
1046 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1048 TestCompletionCallback callback1;
1050 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1051 EXPECT_EQ(ERR_IO_PENDING, rv);
1053 rv = callback1.WaitForResult();
1054 EXPECT_EQ(OK, rv);
1056 const HttpResponseInfo* response = trans->GetResponseInfo();
1057 ASSERT_TRUE(response != NULL);
1059 // Check that the headers got parsed.
1060 EXPECT_TRUE(response->headers.get() != NULL);
1061 EXPECT_EQ(1234, response->headers->GetContentLength());
1062 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1063 EXPECT_TRUE(response->proxy_server.IsEmpty());
1064 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1066 std::string server_header;
1067 void* iter = NULL;
1068 bool has_server_header = response->headers->EnumerateHeader(
1069 &iter, "Server", &server_header);
1070 EXPECT_TRUE(has_server_header);
1071 EXPECT_EQ("Blah", server_header);
1073 // Reading should give EOF right away, since there is no message body
1074 // (despite non-zero content-length).
1075 std::string response_data;
1076 rv = ReadTransaction(trans.get(), &response_data);
1077 EXPECT_EQ(OK, rv);
1078 EXPECT_EQ("", response_data);
1081 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1082 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1084 MockRead data_reads[] = {
1085 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1086 MockRead("hello"),
1087 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1088 MockRead("world"),
1089 MockRead(SYNCHRONOUS, OK),
1091 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1092 session_deps_.socket_factory->AddSocketDataProvider(&data);
1094 const char* const kExpectedResponseData[] = {
1095 "hello", "world"
1098 for (int i = 0; i < 2; ++i) {
1099 HttpRequestInfo request;
1100 request.method = "GET";
1101 request.url = GURL("http://www.example.org/");
1102 request.load_flags = 0;
1104 scoped_ptr<HttpTransaction> trans(
1105 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1107 TestCompletionCallback callback;
1109 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1110 EXPECT_EQ(ERR_IO_PENDING, rv);
1112 rv = callback.WaitForResult();
1113 EXPECT_EQ(OK, rv);
1115 const HttpResponseInfo* response = trans->GetResponseInfo();
1116 ASSERT_TRUE(response != NULL);
1118 EXPECT_TRUE(response->headers.get() != NULL);
1119 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1120 EXPECT_TRUE(response->proxy_server.IsEmpty());
1122 std::string response_data;
1123 rv = ReadTransaction(trans.get(), &response_data);
1124 EXPECT_EQ(OK, rv);
1125 EXPECT_EQ(kExpectedResponseData[i], response_data);
1129 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1130 ScopedVector<UploadElementReader> element_readers;
1131 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1132 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
1134 HttpRequestInfo request;
1135 request.method = "POST";
1136 request.url = GURL("http://www.foo.com/");
1137 request.upload_data_stream = &upload_data_stream;
1138 request.load_flags = 0;
1140 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1141 scoped_ptr<HttpTransaction> trans(
1142 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1144 MockRead data_reads[] = {
1145 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1146 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1147 MockRead("hello world"),
1148 MockRead(SYNCHRONOUS, OK),
1150 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1151 session_deps_.socket_factory->AddSocketDataProvider(&data);
1153 TestCompletionCallback callback;
1155 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1156 EXPECT_EQ(ERR_IO_PENDING, rv);
1158 rv = callback.WaitForResult();
1159 EXPECT_EQ(OK, rv);
1161 const HttpResponseInfo* response = trans->GetResponseInfo();
1162 ASSERT_TRUE(response != NULL);
1164 EXPECT_TRUE(response->headers.get() != NULL);
1165 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1167 std::string response_data;
1168 rv = ReadTransaction(trans.get(), &response_data);
1169 EXPECT_EQ(OK, rv);
1170 EXPECT_EQ("hello world", response_data);
1173 // This test is almost the same as Ignores100 above, but the response contains
1174 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1175 // HTTP/1.1 and the two status headers are read in one read.
1176 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1177 HttpRequestInfo request;
1178 request.method = "GET";
1179 request.url = GURL("http://www.foo.com/");
1180 request.load_flags = 0;
1182 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1183 scoped_ptr<HttpTransaction> trans(
1184 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1186 MockRead data_reads[] = {
1187 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1188 "HTTP/1.1 200 OK\r\n\r\n"),
1189 MockRead("hello world"),
1190 MockRead(SYNCHRONOUS, OK),
1192 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1193 session_deps_.socket_factory->AddSocketDataProvider(&data);
1195 TestCompletionCallback callback;
1197 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1198 EXPECT_EQ(ERR_IO_PENDING, rv);
1200 rv = callback.WaitForResult();
1201 EXPECT_EQ(OK, rv);
1203 const HttpResponseInfo* response = trans->GetResponseInfo();
1204 ASSERT_TRUE(response != NULL);
1206 EXPECT_TRUE(response->headers.get() != NULL);
1207 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1209 std::string response_data;
1210 rv = ReadTransaction(trans.get(), &response_data);
1211 EXPECT_EQ(OK, rv);
1212 EXPECT_EQ("hello world", response_data);
1215 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1216 HttpRequestInfo request;
1217 request.method = "POST";
1218 request.url = GURL("http://www.foo.com/");
1219 request.load_flags = 0;
1221 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1222 scoped_ptr<HttpTransaction> trans(
1223 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1225 MockRead data_reads[] = {
1226 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1227 MockRead(ASYNC, 0),
1229 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1230 session_deps_.socket_factory->AddSocketDataProvider(&data);
1232 TestCompletionCallback callback;
1234 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1235 EXPECT_EQ(ERR_IO_PENDING, rv);
1237 rv = callback.WaitForResult();
1238 EXPECT_EQ(OK, rv);
1240 std::string response_data;
1241 rv = ReadTransaction(trans.get(), &response_data);
1242 EXPECT_EQ(OK, rv);
1243 EXPECT_EQ("", response_data);
1246 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1247 HttpRequestInfo request;
1248 request.method = "POST";
1249 request.url = GURL("http://www.foo.com/");
1250 request.load_flags = 0;
1252 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1253 scoped_ptr<HttpTransaction> trans(
1254 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1256 MockRead data_reads[] = {
1257 MockRead(ASYNC, 0),
1259 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1260 session_deps_.socket_factory->AddSocketDataProvider(&data);
1262 TestCompletionCallback callback;
1264 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1265 EXPECT_EQ(ERR_IO_PENDING, rv);
1267 rv = callback.WaitForResult();
1268 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1271 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1272 const MockWrite* write_failure,
1273 const MockRead* read_failure) {
1274 HttpRequestInfo request;
1275 request.method = "GET";
1276 request.url = GURL("http://www.foo.com/");
1277 request.load_flags = 0;
1279 TestNetLog net_log;
1280 session_deps_.net_log = &net_log;
1281 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1283 // Written data for successfully sending both requests.
1284 MockWrite data1_writes[] = {
1285 MockWrite("GET / HTTP/1.1\r\n"
1286 "Host: www.foo.com\r\n"
1287 "Connection: keep-alive\r\n\r\n"),
1288 MockWrite("GET / HTTP/1.1\r\n"
1289 "Host: www.foo.com\r\n"
1290 "Connection: keep-alive\r\n\r\n")
1293 // Read results for the first request.
1294 MockRead data1_reads[] = {
1295 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1296 MockRead("hello"),
1297 MockRead(ASYNC, OK),
1300 if (write_failure) {
1301 ASSERT_FALSE(read_failure);
1302 data1_writes[1] = *write_failure;
1303 } else {
1304 ASSERT_TRUE(read_failure);
1305 data1_reads[2] = *read_failure;
1308 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1309 data1_writes, arraysize(data1_writes));
1310 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1312 MockRead data2_reads[] = {
1313 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1314 MockRead("world"),
1315 MockRead(ASYNC, OK),
1317 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1318 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1320 const char* const kExpectedResponseData[] = {
1321 "hello", "world"
1324 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1325 for (int i = 0; i < 2; ++i) {
1326 TestCompletionCallback callback;
1328 scoped_ptr<HttpTransaction> trans(
1329 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1331 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1332 EXPECT_EQ(ERR_IO_PENDING, rv);
1334 rv = callback.WaitForResult();
1335 EXPECT_EQ(OK, rv);
1337 LoadTimingInfo load_timing_info;
1338 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1339 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1340 if (i == 0) {
1341 first_socket_log_id = load_timing_info.socket_log_id;
1342 } else {
1343 // The second request should be using a new socket.
1344 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1347 const HttpResponseInfo* response = trans->GetResponseInfo();
1348 ASSERT_TRUE(response != NULL);
1350 EXPECT_TRUE(response->headers.get() != NULL);
1351 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1353 std::string response_data;
1354 rv = ReadTransaction(trans.get(), &response_data);
1355 EXPECT_EQ(OK, rv);
1356 EXPECT_EQ(kExpectedResponseData[i], response_data);
1360 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1361 const MockWrite* write_failure,
1362 const MockRead* read_failure,
1363 bool use_spdy) {
1364 HttpRequestInfo request;
1365 request.method = "GET";
1366 request.url = GURL("https://www.foo.com/");
1367 request.load_flags = 0;
1369 TestNetLog net_log;
1370 session_deps_.net_log = &net_log;
1371 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1373 SSLSocketDataProvider ssl1(ASYNC, OK);
1374 SSLSocketDataProvider ssl2(ASYNC, OK);
1375 if (use_spdy) {
1376 ssl1.SetNextProto(GetParam());
1377 ssl2.SetNextProto(GetParam());
1379 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1380 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1382 // SPDY versions of the request and response.
1383 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1384 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1385 scoped_ptr<SpdyFrame> spdy_response(
1386 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1387 scoped_ptr<SpdyFrame> spdy_data(
1388 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1390 // HTTP/1.1 versions of the request and response.
1391 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1392 "Host: www.foo.com\r\n"
1393 "Connection: keep-alive\r\n\r\n";
1394 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1395 const char kHttpData[] = "hello";
1397 std::vector<MockRead> data1_reads;
1398 std::vector<MockWrite> data1_writes;
1399 if (write_failure) {
1400 ASSERT_FALSE(read_failure);
1401 data1_writes.push_back(*write_failure);
1402 data1_reads.push_back(MockRead(ASYNC, OK));
1403 } else {
1404 ASSERT_TRUE(read_failure);
1405 if (use_spdy) {
1406 data1_writes.push_back(CreateMockWrite(*spdy_request));
1407 } else {
1408 data1_writes.push_back(MockWrite(kHttpRequest));
1410 data1_reads.push_back(*read_failure);
1413 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1414 &data1_writes[0], data1_writes.size());
1415 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1417 std::vector<MockRead> data2_reads;
1418 std::vector<MockWrite> data2_writes;
1420 if (use_spdy) {
1421 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1423 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1424 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1425 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1426 } else {
1427 data2_writes.push_back(
1428 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1430 data2_reads.push_back(
1431 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1432 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1433 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1435 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1436 &data2_writes[0], data2_writes.size());
1437 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1439 // Preconnect a socket.
1440 SSLConfig ssl_config;
1441 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1442 session->GetNextProtos(&ssl_config.next_protos);
1443 session->http_stream_factory()->PreconnectStreams(
1444 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1445 // Wait for the preconnect to complete.
1446 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1447 base::RunLoop().RunUntilIdle();
1448 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1450 // Make the request.
1451 TestCompletionCallback callback;
1453 scoped_ptr<HttpTransaction> trans(
1454 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1456 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1457 EXPECT_EQ(ERR_IO_PENDING, rv);
1459 rv = callback.WaitForResult();
1460 EXPECT_EQ(OK, rv);
1462 LoadTimingInfo load_timing_info;
1463 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1464 TestLoadTimingNotReused(
1465 load_timing_info,
1466 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1468 const HttpResponseInfo* response = trans->GetResponseInfo();
1469 ASSERT_TRUE(response != NULL);
1471 EXPECT_TRUE(response->headers.get() != NULL);
1472 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1474 std::string response_data;
1475 rv = ReadTransaction(trans.get(), &response_data);
1476 EXPECT_EQ(OK, rv);
1477 EXPECT_EQ(kHttpData, response_data);
1480 TEST_P(HttpNetworkTransactionTest,
1481 KeepAliveConnectionNotConnectedOnWrite) {
1482 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1483 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1486 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1487 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1488 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1491 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1492 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1493 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1496 // Make sure that on a 408 response (Request Timeout), the request is retried,
1497 // if the socket was a reused keep alive socket.
1498 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1499 MockRead read_failure(SYNCHRONOUS,
1500 "HTTP/1.1 408 Request Timeout\r\n"
1501 "Connection: Keep-Alive\r\n"
1502 "Content-Length: 6\r\n\r\n"
1503 "Pickle");
1504 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1507 TEST_P(HttpNetworkTransactionTest,
1508 PreconnectErrorNotConnectedOnWrite) {
1509 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1510 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1513 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1514 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1515 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1518 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1519 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1520 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1523 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1524 MockRead read_failure(ASYNC, OK); // EOF
1525 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1528 // Make sure that on a 408 response (Request Timeout), the request is retried,
1529 // if the socket was a preconnected (UNUSED_IDLE) socket.
1530 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1531 MockRead read_failure(SYNCHRONOUS,
1532 "HTTP/1.1 408 Request Timeout\r\n"
1533 "Connection: Keep-Alive\r\n"
1534 "Content-Length: 6\r\n\r\n"
1535 "Pickle");
1536 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1537 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1540 TEST_P(HttpNetworkTransactionTest,
1541 SpdyPreconnectErrorNotConnectedOnWrite) {
1542 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1543 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1546 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1547 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1548 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1551 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1552 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1553 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1556 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1557 MockRead read_failure(ASYNC, OK); // EOF
1558 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1561 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1562 HttpRequestInfo request;
1563 request.method = "GET";
1564 request.url = GURL("http://www.example.org/");
1565 request.load_flags = 0;
1567 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1568 scoped_ptr<HttpTransaction> trans(
1569 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1571 MockRead data_reads[] = {
1572 MockRead(ASYNC, ERR_CONNECTION_RESET),
1573 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1574 MockRead("hello world"),
1575 MockRead(SYNCHRONOUS, OK),
1577 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1578 session_deps_.socket_factory->AddSocketDataProvider(&data);
1580 TestCompletionCallback callback;
1582 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1583 EXPECT_EQ(ERR_IO_PENDING, rv);
1585 rv = callback.WaitForResult();
1586 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1589 // What do various browsers do when the server closes a non-keepalive
1590 // connection without sending any response header or body?
1592 // IE7: error page
1593 // Safari 3.1.2 (Windows): error page
1594 // Firefox 3.0.1: blank page
1595 // Opera 9.52: after five attempts, blank page
1596 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1597 // Us: error page (EMPTY_RESPONSE)
1598 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1599 MockRead data_reads[] = {
1600 MockRead(SYNCHRONOUS, OK), // EOF
1601 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1602 MockRead("hello world"),
1603 MockRead(SYNCHRONOUS, OK),
1605 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1606 arraysize(data_reads));
1607 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1610 // Test that network access can be deferred and resumed.
1611 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1612 HttpRequestInfo request;
1613 request.method = "GET";
1614 request.url = GURL("http://www.example.org/");
1615 request.load_flags = 0;
1617 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1618 scoped_ptr<HttpTransaction> trans(
1619 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1621 // Defer on OnBeforeNetworkStart.
1622 BeforeNetworkStartHandler net_start_handler(true); // defer
1623 trans->SetBeforeNetworkStartCallback(
1624 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1625 base::Unretained(&net_start_handler)));
1627 MockRead data_reads[] = {
1628 MockRead("HTTP/1.0 200 OK\r\n"),
1629 MockRead("Content-Length: 5\r\n\r\n"),
1630 MockRead("hello"),
1631 MockRead(SYNCHRONOUS, 0),
1633 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1634 session_deps_.socket_factory->AddSocketDataProvider(&data);
1636 TestCompletionCallback callback;
1638 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1639 EXPECT_EQ(ERR_IO_PENDING, rv);
1640 base::MessageLoop::current()->RunUntilIdle();
1642 // Should have deferred for network start.
1643 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1644 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1646 trans->ResumeNetworkStart();
1647 rv = callback.WaitForResult();
1648 EXPECT_EQ(OK, rv);
1649 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1651 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1652 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1653 if (rv == ERR_IO_PENDING)
1654 rv = callback.WaitForResult();
1655 EXPECT_EQ(5, rv);
1656 trans.reset();
1659 // Test that network use can be deferred and canceled.
1660 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1661 HttpRequestInfo request;
1662 request.method = "GET";
1663 request.url = GURL("http://www.example.org/");
1664 request.load_flags = 0;
1666 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1667 scoped_ptr<HttpTransaction> trans(
1668 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1670 // Defer on OnBeforeNetworkStart.
1671 BeforeNetworkStartHandler net_start_handler(true); // defer
1672 trans->SetBeforeNetworkStartCallback(
1673 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1674 base::Unretained(&net_start_handler)));
1676 TestCompletionCallback callback;
1678 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1679 EXPECT_EQ(ERR_IO_PENDING, rv);
1680 base::MessageLoop::current()->RunUntilIdle();
1682 // Should have deferred for network start.
1683 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1684 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1687 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1688 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1689 // destructor in such situations.
1690 // See http://crbug.com/154712 and http://crbug.com/156609.
1691 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1692 HttpRequestInfo request;
1693 request.method = "GET";
1694 request.url = GURL("http://www.example.org/");
1695 request.load_flags = 0;
1697 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1698 scoped_ptr<HttpTransaction> trans(
1699 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1701 MockRead data_reads[] = {
1702 MockRead("HTTP/1.0 200 OK\r\n"),
1703 MockRead("Connection: keep-alive\r\n"),
1704 MockRead("Content-Length: 100\r\n\r\n"),
1705 MockRead("hello"),
1706 MockRead(SYNCHRONOUS, 0),
1708 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1709 session_deps_.socket_factory->AddSocketDataProvider(&data);
1711 TestCompletionCallback callback;
1713 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1714 EXPECT_EQ(ERR_IO_PENDING, rv);
1716 rv = callback.WaitForResult();
1717 EXPECT_EQ(OK, rv);
1719 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1720 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1721 if (rv == ERR_IO_PENDING)
1722 rv = callback.WaitForResult();
1723 EXPECT_EQ(5, rv);
1724 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1725 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1727 trans.reset();
1728 base::MessageLoop::current()->RunUntilIdle();
1729 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1732 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1733 HttpRequestInfo request;
1734 request.method = "GET";
1735 request.url = GURL("http://www.example.org/");
1736 request.load_flags = 0;
1738 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1739 scoped_ptr<HttpTransaction> trans(
1740 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1742 MockRead data_reads[] = {
1743 MockRead("HTTP/1.0 200 OK\r\n"),
1744 MockRead("Connection: keep-alive\r\n"),
1745 MockRead("Content-Length: 100\r\n\r\n"),
1746 MockRead(SYNCHRONOUS, 0),
1748 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1749 session_deps_.socket_factory->AddSocketDataProvider(&data);
1751 TestCompletionCallback callback;
1753 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1754 EXPECT_EQ(ERR_IO_PENDING, rv);
1756 rv = callback.WaitForResult();
1757 EXPECT_EQ(OK, rv);
1759 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1760 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1761 if (rv == ERR_IO_PENDING)
1762 rv = callback.WaitForResult();
1763 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1765 trans.reset();
1766 base::MessageLoop::current()->RunUntilIdle();
1767 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1770 // Test that we correctly reuse a keep-alive connection after not explicitly
1771 // reading the body.
1772 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1773 HttpRequestInfo request;
1774 request.method = "GET";
1775 request.url = GURL("http://www.foo.com/");
1776 request.load_flags = 0;
1778 TestNetLog net_log;
1779 session_deps_.net_log = &net_log;
1780 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1782 // Note that because all these reads happen in the same
1783 // StaticSocketDataProvider, it shows that the same socket is being reused for
1784 // all transactions.
1785 MockRead data1_reads[] = {
1786 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1787 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1788 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1789 MockRead("HTTP/1.1 302 Found\r\n"
1790 "Content-Length: 0\r\n\r\n"),
1791 MockRead("HTTP/1.1 302 Found\r\n"
1792 "Content-Length: 5\r\n\r\n"
1793 "hello"),
1794 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1795 "Content-Length: 0\r\n\r\n"),
1796 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1797 "Content-Length: 5\r\n\r\n"
1798 "hello"),
1799 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1800 MockRead("hello"),
1802 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1803 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1805 MockRead data2_reads[] = {
1806 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1808 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1809 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1811 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1812 std::string response_lines[kNumUnreadBodies];
1814 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1815 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1816 TestCompletionCallback callback;
1818 scoped_ptr<HttpTransaction> trans(
1819 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1821 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1822 EXPECT_EQ(ERR_IO_PENDING, rv);
1824 rv = callback.WaitForResult();
1825 EXPECT_EQ(OK, rv);
1827 LoadTimingInfo load_timing_info;
1828 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1829 if (i == 0) {
1830 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1831 first_socket_log_id = load_timing_info.socket_log_id;
1832 } else {
1833 TestLoadTimingReused(load_timing_info);
1834 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1837 const HttpResponseInfo* response = trans->GetResponseInfo();
1838 ASSERT_TRUE(response != NULL);
1840 ASSERT_TRUE(response->headers.get() != NULL);
1841 response_lines[i] = response->headers->GetStatusLine();
1843 // We intentionally don't read the response bodies.
1846 const char* const kStatusLines[] = {
1847 "HTTP/1.1 204 No Content",
1848 "HTTP/1.1 205 Reset Content",
1849 "HTTP/1.1 304 Not Modified",
1850 "HTTP/1.1 302 Found",
1851 "HTTP/1.1 302 Found",
1852 "HTTP/1.1 301 Moved Permanently",
1853 "HTTP/1.1 301 Moved Permanently",
1856 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1857 "forgot to update kStatusLines");
1859 for (int i = 0; i < kNumUnreadBodies; ++i)
1860 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1862 TestCompletionCallback callback;
1863 scoped_ptr<HttpTransaction> trans(
1864 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1865 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1866 EXPECT_EQ(ERR_IO_PENDING, rv);
1867 rv = callback.WaitForResult();
1868 EXPECT_EQ(OK, rv);
1869 const HttpResponseInfo* response = trans->GetResponseInfo();
1870 ASSERT_TRUE(response != NULL);
1871 ASSERT_TRUE(response->headers.get() != NULL);
1872 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1873 std::string response_data;
1874 rv = ReadTransaction(trans.get(), &response_data);
1875 EXPECT_EQ(OK, rv);
1876 EXPECT_EQ("hello", response_data);
1879 // Test the request-challenge-retry sequence for basic auth.
1880 // (basic auth is the easiest to mock, because it has no randomness).
1881 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1882 HttpRequestInfo request;
1883 request.method = "GET";
1884 request.url = GURL("http://www.example.org/");
1885 request.load_flags = 0;
1887 TestNetLog log;
1888 session_deps_.net_log = &log;
1889 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1890 scoped_ptr<HttpTransaction> trans(
1891 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1893 MockWrite data_writes1[] = {
1894 MockWrite(
1895 "GET / HTTP/1.1\r\n"
1896 "Host: www.example.org\r\n"
1897 "Connection: keep-alive\r\n\r\n"),
1900 MockRead data_reads1[] = {
1901 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1902 // Give a couple authenticate options (only the middle one is actually
1903 // supported).
1904 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1905 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1906 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1907 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1908 // Large content-length -- won't matter, as connection will be reset.
1909 MockRead("Content-Length: 10000\r\n\r\n"),
1910 MockRead(SYNCHRONOUS, ERR_FAILED),
1913 // After calling trans->RestartWithAuth(), this is the request we should
1914 // be issuing -- the final header line contains the credentials.
1915 MockWrite data_writes2[] = {
1916 MockWrite(
1917 "GET / HTTP/1.1\r\n"
1918 "Host: www.example.org\r\n"
1919 "Connection: keep-alive\r\n"
1920 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1923 // Lastly, the server responds with the actual content.
1924 MockRead data_reads2[] = {
1925 MockRead("HTTP/1.0 200 OK\r\n"),
1926 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1927 MockRead("Content-Length: 100\r\n\r\n"),
1928 MockRead(SYNCHRONOUS, OK),
1931 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1932 data_writes1, arraysize(data_writes1));
1933 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1934 data_writes2, arraysize(data_writes2));
1935 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1936 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1938 TestCompletionCallback callback1;
1940 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1941 EXPECT_EQ(ERR_IO_PENDING, rv);
1943 rv = callback1.WaitForResult();
1944 EXPECT_EQ(OK, rv);
1946 LoadTimingInfo load_timing_info1;
1947 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1948 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1950 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1951 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1953 const HttpResponseInfo* response = trans->GetResponseInfo();
1954 ASSERT_TRUE(response != NULL);
1955 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1957 TestCompletionCallback callback2;
1959 rv = trans->RestartWithAuth(
1960 AuthCredentials(kFoo, kBar), callback2.callback());
1961 EXPECT_EQ(ERR_IO_PENDING, rv);
1963 rv = callback2.WaitForResult();
1964 EXPECT_EQ(OK, rv);
1966 LoadTimingInfo load_timing_info2;
1967 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1968 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1969 // The load timing after restart should have a new socket ID, and times after
1970 // those of the first load timing.
1971 EXPECT_LE(load_timing_info1.receive_headers_end,
1972 load_timing_info2.connect_timing.connect_start);
1973 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1975 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1976 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1978 response = trans->GetResponseInfo();
1979 ASSERT_TRUE(response != NULL);
1980 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1981 EXPECT_EQ(100, response->headers->GetContentLength());
1984 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1985 HttpRequestInfo request;
1986 request.method = "GET";
1987 request.url = GURL("http://www.example.org/");
1988 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
1990 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1991 scoped_ptr<HttpTransaction> trans(
1992 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1994 MockWrite data_writes[] = {
1995 MockWrite(
1996 "GET / HTTP/1.1\r\n"
1997 "Host: www.example.org\r\n"
1998 "Connection: keep-alive\r\n\r\n"),
2001 MockRead data_reads[] = {
2002 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2003 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2004 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2005 // Large content-length -- won't matter, as connection will be reset.
2006 MockRead("Content-Length: 10000\r\n\r\n"),
2007 MockRead(SYNCHRONOUS, ERR_FAILED),
2010 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2011 data_writes, arraysize(data_writes));
2012 session_deps_.socket_factory->AddSocketDataProvider(&data);
2013 TestCompletionCallback callback;
2015 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2016 EXPECT_EQ(ERR_IO_PENDING, rv);
2018 rv = callback.WaitForResult();
2019 EXPECT_EQ(0, rv);
2021 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2022 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2024 const HttpResponseInfo* response = trans->GetResponseInfo();
2025 ASSERT_TRUE(response != NULL);
2026 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2029 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2030 // connection.
2031 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2032 HttpRequestInfo request;
2033 request.method = "GET";
2034 request.url = GURL("http://www.example.org/");
2035 request.load_flags = 0;
2037 TestNetLog log;
2038 session_deps_.net_log = &log;
2039 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2041 MockWrite data_writes1[] = {
2042 MockWrite(
2043 "GET / HTTP/1.1\r\n"
2044 "Host: www.example.org\r\n"
2045 "Connection: keep-alive\r\n\r\n"),
2047 // After calling trans->RestartWithAuth(), this is the request we should
2048 // be issuing -- the final header line contains the credentials.
2049 MockWrite(
2050 "GET / HTTP/1.1\r\n"
2051 "Host: www.example.org\r\n"
2052 "Connection: keep-alive\r\n"
2053 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2056 MockRead data_reads1[] = {
2057 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2058 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2059 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2060 MockRead("Content-Length: 14\r\n\r\n"),
2061 MockRead("Unauthorized\r\n"),
2063 // Lastly, the server responds with the actual content.
2064 MockRead("HTTP/1.1 200 OK\r\n"),
2065 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2066 MockRead("Content-Length: 5\r\n\r\n"),
2067 MockRead("Hello"),
2070 // If there is a regression where we disconnect a Keep-Alive
2071 // connection during an auth roundtrip, we'll end up reading this.
2072 MockRead data_reads2[] = {
2073 MockRead(SYNCHRONOUS, ERR_FAILED),
2076 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2077 data_writes1, arraysize(data_writes1));
2078 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2079 NULL, 0);
2080 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2081 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2083 TestCompletionCallback callback1;
2085 scoped_ptr<HttpTransaction> trans(
2086 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2087 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2088 EXPECT_EQ(ERR_IO_PENDING, rv);
2090 rv = callback1.WaitForResult();
2091 EXPECT_EQ(OK, rv);
2093 LoadTimingInfo load_timing_info1;
2094 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2095 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2097 const HttpResponseInfo* response = trans->GetResponseInfo();
2098 ASSERT_TRUE(response != NULL);
2099 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2101 TestCompletionCallback callback2;
2103 rv = trans->RestartWithAuth(
2104 AuthCredentials(kFoo, kBar), callback2.callback());
2105 EXPECT_EQ(ERR_IO_PENDING, rv);
2107 rv = callback2.WaitForResult();
2108 EXPECT_EQ(OK, rv);
2110 LoadTimingInfo load_timing_info2;
2111 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2112 TestLoadTimingReused(load_timing_info2);
2113 // The load timing after restart should have the same socket ID, and times
2114 // those of the first load timing.
2115 EXPECT_LE(load_timing_info1.receive_headers_end,
2116 load_timing_info2.send_start);
2117 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2119 response = trans->GetResponseInfo();
2120 ASSERT_TRUE(response != NULL);
2121 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2122 EXPECT_EQ(5, response->headers->GetContentLength());
2124 std::string response_data;
2125 rv = ReadTransaction(trans.get(), &response_data);
2126 EXPECT_EQ(OK, rv);
2127 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2128 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2131 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2132 // connection and with no response body to drain.
2133 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2134 HttpRequestInfo request;
2135 request.method = "GET";
2136 request.url = GURL("http://www.example.org/");
2137 request.load_flags = 0;
2139 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2141 MockWrite data_writes1[] = {
2142 MockWrite(
2143 "GET / HTTP/1.1\r\n"
2144 "Host: www.example.org\r\n"
2145 "Connection: keep-alive\r\n\r\n"),
2147 // After calling trans->RestartWithAuth(), this is the request we should
2148 // be issuing -- the final header line contains the credentials.
2149 MockWrite(
2150 "GET / HTTP/1.1\r\n"
2151 "Host: www.example.org\r\n"
2152 "Connection: keep-alive\r\n"
2153 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2156 MockRead data_reads1[] = {
2157 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2158 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2159 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2161 // Lastly, the server responds with the actual content.
2162 MockRead("HTTP/1.1 200 OK\r\n"),
2163 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2164 MockRead("Content-Length: 5\r\n\r\n"),
2165 MockRead("hello"),
2168 // An incorrect reconnect would cause this to be read.
2169 MockRead data_reads2[] = {
2170 MockRead(SYNCHRONOUS, ERR_FAILED),
2173 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2174 data_writes1, arraysize(data_writes1));
2175 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2176 NULL, 0);
2177 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2178 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2180 TestCompletionCallback callback1;
2182 scoped_ptr<HttpTransaction> trans(
2183 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2184 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2185 EXPECT_EQ(ERR_IO_PENDING, rv);
2187 rv = callback1.WaitForResult();
2188 EXPECT_EQ(OK, rv);
2190 const HttpResponseInfo* response = trans->GetResponseInfo();
2191 ASSERT_TRUE(response != NULL);
2192 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2194 TestCompletionCallback callback2;
2196 rv = trans->RestartWithAuth(
2197 AuthCredentials(kFoo, kBar), callback2.callback());
2198 EXPECT_EQ(ERR_IO_PENDING, rv);
2200 rv = callback2.WaitForResult();
2201 EXPECT_EQ(OK, rv);
2203 response = trans->GetResponseInfo();
2204 ASSERT_TRUE(response != NULL);
2205 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2206 EXPECT_EQ(5, response->headers->GetContentLength());
2209 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2210 // connection and with a large response body to drain.
2211 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2212 HttpRequestInfo request;
2213 request.method = "GET";
2214 request.url = GURL("http://www.example.org/");
2215 request.load_flags = 0;
2217 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2219 MockWrite data_writes1[] = {
2220 MockWrite(
2221 "GET / HTTP/1.1\r\n"
2222 "Host: www.example.org\r\n"
2223 "Connection: keep-alive\r\n\r\n"),
2225 // After calling trans->RestartWithAuth(), this is the request we should
2226 // be issuing -- the final header line contains the credentials.
2227 MockWrite(
2228 "GET / HTTP/1.1\r\n"
2229 "Host: www.example.org\r\n"
2230 "Connection: keep-alive\r\n"
2231 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2234 // Respond with 5 kb of response body.
2235 std::string large_body_string("Unauthorized");
2236 large_body_string.append(5 * 1024, ' ');
2237 large_body_string.append("\r\n");
2239 MockRead data_reads1[] = {
2240 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2241 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2242 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2243 // 5134 = 12 + 5 * 1024 + 2
2244 MockRead("Content-Length: 5134\r\n\r\n"),
2245 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2247 // Lastly, the server responds with the actual content.
2248 MockRead("HTTP/1.1 200 OK\r\n"),
2249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2250 MockRead("Content-Length: 5\r\n\r\n"),
2251 MockRead("hello"),
2254 // An incorrect reconnect would cause this to be read.
2255 MockRead data_reads2[] = {
2256 MockRead(SYNCHRONOUS, ERR_FAILED),
2259 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2260 data_writes1, arraysize(data_writes1));
2261 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2262 NULL, 0);
2263 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2264 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2266 TestCompletionCallback callback1;
2268 scoped_ptr<HttpTransaction> trans(
2269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2270 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2271 EXPECT_EQ(ERR_IO_PENDING, rv);
2273 rv = callback1.WaitForResult();
2274 EXPECT_EQ(OK, rv);
2276 const HttpResponseInfo* response = trans->GetResponseInfo();
2277 ASSERT_TRUE(response != NULL);
2278 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2280 TestCompletionCallback callback2;
2282 rv = trans->RestartWithAuth(
2283 AuthCredentials(kFoo, kBar), callback2.callback());
2284 EXPECT_EQ(ERR_IO_PENDING, rv);
2286 rv = callback2.WaitForResult();
2287 EXPECT_EQ(OK, rv);
2289 response = trans->GetResponseInfo();
2290 ASSERT_TRUE(response != NULL);
2291 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2292 EXPECT_EQ(5, response->headers->GetContentLength());
2295 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2296 // connection, but the server gets impatient and closes the connection.
2297 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2298 HttpRequestInfo request;
2299 request.method = "GET";
2300 request.url = GURL("http://www.example.org/");
2301 request.load_flags = 0;
2303 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2305 MockWrite data_writes1[] = {
2306 MockWrite(
2307 "GET / HTTP/1.1\r\n"
2308 "Host: www.example.org\r\n"
2309 "Connection: keep-alive\r\n\r\n"),
2310 // This simulates the seemingly successful write to a closed connection
2311 // if the bug is not fixed.
2312 MockWrite(
2313 "GET / HTTP/1.1\r\n"
2314 "Host: www.example.org\r\n"
2315 "Connection: keep-alive\r\n"
2316 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2319 MockRead data_reads1[] = {
2320 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2321 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2322 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2323 MockRead("Content-Length: 14\r\n\r\n"),
2324 // Tell MockTCPClientSocket to simulate the server closing the connection.
2325 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2326 MockRead("Unauthorized\r\n"),
2327 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2330 // After calling trans->RestartWithAuth(), this is the request we should
2331 // be issuing -- the final header line contains the credentials.
2332 MockWrite data_writes2[] = {
2333 MockWrite(
2334 "GET / HTTP/1.1\r\n"
2335 "Host: www.example.org\r\n"
2336 "Connection: keep-alive\r\n"
2337 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2340 // Lastly, the server responds with the actual content.
2341 MockRead data_reads2[] = {
2342 MockRead("HTTP/1.1 200 OK\r\n"),
2343 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2344 MockRead("Content-Length: 5\r\n\r\n"),
2345 MockRead("hello"),
2348 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2349 data_writes1, arraysize(data_writes1));
2350 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2351 data_writes2, arraysize(data_writes2));
2352 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2353 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2355 TestCompletionCallback callback1;
2357 scoped_ptr<HttpTransaction> trans(
2358 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2359 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2360 EXPECT_EQ(ERR_IO_PENDING, rv);
2362 rv = callback1.WaitForResult();
2363 EXPECT_EQ(OK, rv);
2365 const HttpResponseInfo* response = trans->GetResponseInfo();
2366 ASSERT_TRUE(response != NULL);
2367 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2369 TestCompletionCallback callback2;
2371 rv = trans->RestartWithAuth(
2372 AuthCredentials(kFoo, kBar), callback2.callback());
2373 EXPECT_EQ(ERR_IO_PENDING, rv);
2375 rv = callback2.WaitForResult();
2376 EXPECT_EQ(OK, rv);
2378 response = trans->GetResponseInfo();
2379 ASSERT_TRUE(response != NULL);
2380 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2381 EXPECT_EQ(5, response->headers->GetContentLength());
2384 // Test the request-challenge-retry sequence for basic auth, over a connection
2385 // that requires a restart when setting up an SSL tunnel.
2386 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2387 HttpRequestInfo request;
2388 request.method = "GET";
2389 request.url = GURL("https://www.example.org/");
2390 // when the no authentication data flag is set.
2391 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2393 // Configure against proxy server "myproxy:70".
2394 session_deps_.proxy_service.reset(
2395 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2396 BoundTestNetLog log;
2397 session_deps_.net_log = log.bound().net_log();
2398 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2400 // Since we have proxy, should try to establish tunnel.
2401 MockWrite data_writes1[] = {
2402 MockWrite(
2403 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2404 "Host: www.example.org\r\n"
2405 "Proxy-Connection: keep-alive\r\n\r\n"),
2407 // After calling trans->RestartWithAuth(), this is the request we should
2408 // be issuing -- the final header line contains the credentials.
2409 MockWrite(
2410 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2411 "Host: www.example.org\r\n"
2412 "Proxy-Connection: keep-alive\r\n"
2413 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2415 MockWrite(
2416 "GET / HTTP/1.1\r\n"
2417 "Host: www.example.org\r\n"
2418 "Connection: keep-alive\r\n\r\n"),
2421 // The proxy responds to the connect with a 407, using a persistent
2422 // connection.
2423 MockRead data_reads1[] = {
2424 // No credentials.
2425 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2426 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2428 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2430 MockRead("HTTP/1.1 200 OK\r\n"),
2431 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2432 MockRead("Content-Length: 5\r\n\r\n"),
2433 MockRead(SYNCHRONOUS, "hello"),
2436 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2437 data_writes1, arraysize(data_writes1));
2438 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2439 SSLSocketDataProvider ssl(ASYNC, OK);
2440 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2442 TestCompletionCallback callback1;
2444 scoped_ptr<HttpTransaction> trans(
2445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2447 int rv = trans->Start(&request, callback1.callback(), log.bound());
2448 EXPECT_EQ(ERR_IO_PENDING, rv);
2450 rv = callback1.WaitForResult();
2451 EXPECT_EQ(OK, rv);
2452 TestNetLogEntry::List entries;
2453 log.GetEntries(&entries);
2454 size_t pos = ExpectLogContainsSomewhere(
2455 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2456 NetLog::PHASE_NONE);
2457 ExpectLogContainsSomewhere(
2458 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2459 NetLog::PHASE_NONE);
2461 const HttpResponseInfo* response = trans->GetResponseInfo();
2462 ASSERT_TRUE(response != NULL);
2463 EXPECT_FALSE(response->headers->IsKeepAlive());
2464 ASSERT_FALSE(response->headers.get() == NULL);
2465 EXPECT_EQ(407, response->headers->response_code());
2466 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2467 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2469 LoadTimingInfo load_timing_info;
2470 // CONNECT requests and responses are handled at the connect job level, so
2471 // the transaction does not yet have a connection.
2472 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2474 TestCompletionCallback callback2;
2476 rv =
2477 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2478 EXPECT_EQ(ERR_IO_PENDING, rv);
2480 rv = callback2.WaitForResult();
2481 EXPECT_EQ(OK, rv);
2483 response = trans->GetResponseInfo();
2484 ASSERT_TRUE(response != NULL);
2486 EXPECT_TRUE(response->headers->IsKeepAlive());
2487 EXPECT_EQ(200, response->headers->response_code());
2488 EXPECT_EQ(5, response->headers->GetContentLength());
2489 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2491 // The password prompt info should not be set.
2492 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2494 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2495 TestLoadTimingNotReusedWithPac(load_timing_info,
2496 CONNECT_TIMING_HAS_SSL_TIMES);
2498 trans.reset();
2499 session->CloseAllConnections();
2502 // Test the request-challenge-retry sequence for basic auth, over a connection
2503 // that requires a restart when setting up an SSL tunnel.
2504 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
2505 HttpRequestInfo request;
2506 request.method = "GET";
2507 request.url = GURL("https://www.example.org/");
2508 // when the no authentication data flag is set.
2509 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2511 // Configure against proxy server "myproxy:70".
2512 session_deps_.proxy_service.reset(
2513 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2514 BoundTestNetLog log;
2515 session_deps_.net_log = log.bound().net_log();
2516 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2518 // Since we have proxy, should try to establish tunnel.
2519 MockWrite data_writes1[] = {
2520 MockWrite(
2521 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2522 "Host: www.example.org\r\n"
2523 "Proxy-Connection: keep-alive\r\n\r\n"),
2525 // After calling trans->RestartWithAuth(), this is the request we should
2526 // be issuing -- the final header line contains the credentials.
2527 MockWrite(
2528 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2529 "Host: www.example.org\r\n"
2530 "Proxy-Connection: keep-alive\r\n"
2531 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2533 MockWrite(
2534 "GET / HTTP/1.1\r\n"
2535 "Host: www.example.org\r\n"
2536 "Connection: keep-alive\r\n\r\n"),
2539 // The proxy responds to the connect with a 407, using a persistent
2540 // connection.
2541 MockRead data_reads1[] = {
2542 // No credentials.
2543 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2544 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2545 MockRead("Proxy-Connection: close\r\n\r\n"),
2547 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2549 MockRead("HTTP/1.1 200 OK\r\n"),
2550 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2551 MockRead("Content-Length: 5\r\n\r\n"),
2552 MockRead(SYNCHRONOUS, "hello"),
2555 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2556 data_writes1, arraysize(data_writes1));
2557 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2558 SSLSocketDataProvider ssl(ASYNC, OK);
2559 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2561 TestCompletionCallback callback1;
2563 scoped_ptr<HttpTransaction> trans(
2564 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2566 int rv = trans->Start(&request, callback1.callback(), log.bound());
2567 EXPECT_EQ(ERR_IO_PENDING, rv);
2569 rv = callback1.WaitForResult();
2570 EXPECT_EQ(OK, rv);
2571 TestNetLogEntry::List entries;
2572 log.GetEntries(&entries);
2573 size_t pos = ExpectLogContainsSomewhere(
2574 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2575 NetLog::PHASE_NONE);
2576 ExpectLogContainsSomewhere(
2577 entries, pos,
2578 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2579 NetLog::PHASE_NONE);
2581 const HttpResponseInfo* response = trans->GetResponseInfo();
2582 ASSERT_TRUE(response != NULL);
2583 EXPECT_FALSE(response->headers->IsKeepAlive());
2584 ASSERT_FALSE(response->headers.get() == NULL);
2585 EXPECT_EQ(407, response->headers->response_code());
2586 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2587 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2589 LoadTimingInfo load_timing_info;
2590 // CONNECT requests and responses are handled at the connect job level, so
2591 // the transaction does not yet have a connection.
2592 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2594 TestCompletionCallback callback2;
2596 rv = trans->RestartWithAuth(
2597 AuthCredentials(kFoo, kBar), callback2.callback());
2598 EXPECT_EQ(ERR_IO_PENDING, rv);
2600 rv = callback2.WaitForResult();
2601 EXPECT_EQ(OK, rv);
2603 response = trans->GetResponseInfo();
2604 ASSERT_TRUE(response != NULL);
2606 EXPECT_TRUE(response->headers->IsKeepAlive());
2607 EXPECT_EQ(200, response->headers->response_code());
2608 EXPECT_EQ(5, response->headers->GetContentLength());
2609 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2611 // The password prompt info should not be set.
2612 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2614 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2615 TestLoadTimingNotReusedWithPac(load_timing_info,
2616 CONNECT_TIMING_HAS_SSL_TIMES);
2618 trans.reset();
2619 session->CloseAllConnections();
2622 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2623 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2624 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2625 HttpRequestInfo request;
2626 request.method = "GET";
2627 request.url = GURL("https://www.example.org/");
2628 // Ensure that proxy authentication is attempted even
2629 // when the no authentication data flag is set.
2630 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2632 // Configure against proxy server "myproxy:70".
2633 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2634 BoundTestNetLog log;
2635 session_deps_.net_log = log.bound().net_log();
2636 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2638 scoped_ptr<HttpTransaction> trans(
2639 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2641 // Since we have proxy, should try to establish tunnel.
2642 MockWrite data_writes1[] = {
2643 MockWrite(
2644 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2645 "Host: www.example.org\r\n"
2646 "Proxy-Connection: keep-alive\r\n\r\n"),
2648 // After calling trans->RestartWithAuth(), this is the request we should
2649 // be issuing -- the final header line contains the credentials.
2650 MockWrite(
2651 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2652 "Host: www.example.org\r\n"
2653 "Proxy-Connection: keep-alive\r\n"
2654 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2657 // The proxy responds to the connect with a 407, using a persistent
2658 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2659 MockRead data_reads1[] = {
2660 // No credentials.
2661 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2662 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2663 MockRead("Proxy-Connection: keep-alive\r\n"),
2664 MockRead("Content-Length: 10\r\n\r\n"),
2665 MockRead("0123456789"),
2667 // Wrong credentials (wrong password).
2668 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2669 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2670 MockRead("Proxy-Connection: keep-alive\r\n"),
2671 MockRead("Content-Length: 10\r\n\r\n"),
2672 // No response body because the test stops reading here.
2673 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2676 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2677 data_writes1, arraysize(data_writes1));
2678 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2680 TestCompletionCallback callback1;
2682 int rv = trans->Start(&request, callback1.callback(), log.bound());
2683 EXPECT_EQ(ERR_IO_PENDING, rv);
2685 rv = callback1.WaitForResult();
2686 EXPECT_EQ(OK, rv);
2687 TestNetLogEntry::List entries;
2688 log.GetEntries(&entries);
2689 size_t pos = ExpectLogContainsSomewhere(
2690 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2691 NetLog::PHASE_NONE);
2692 ExpectLogContainsSomewhere(
2693 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2694 NetLog::PHASE_NONE);
2696 const HttpResponseInfo* response = trans->GetResponseInfo();
2697 ASSERT_TRUE(response);
2698 ASSERT_TRUE(response->headers);
2699 EXPECT_TRUE(response->headers->IsKeepAlive());
2700 EXPECT_EQ(407, response->headers->response_code());
2701 EXPECT_EQ(10, response->headers->GetContentLength());
2702 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2703 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2705 TestCompletionCallback callback2;
2707 // Wrong password (should be "bar").
2708 rv =
2709 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2710 EXPECT_EQ(ERR_IO_PENDING, rv);
2712 rv = callback2.WaitForResult();
2713 EXPECT_EQ(OK, rv);
2715 response = trans->GetResponseInfo();
2716 ASSERT_TRUE(response);
2717 ASSERT_TRUE(response->headers);
2718 EXPECT_TRUE(response->headers->IsKeepAlive());
2719 EXPECT_EQ(407, response->headers->response_code());
2720 EXPECT_EQ(10, response->headers->GetContentLength());
2721 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2722 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2724 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2725 // out of scope.
2726 session->CloseAllConnections();
2729 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2730 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2731 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
2732 HttpRequestInfo request;
2733 request.method = "GET";
2734 request.url = GURL("https://www.example.org/");
2735 // Ensure that proxy authentication is attempted even
2736 // when the no authentication data flag is set.
2737 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2739 // Configure against proxy server "myproxy:70".
2740 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2741 BoundTestNetLog log;
2742 session_deps_.net_log = log.bound().net_log();
2743 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2745 scoped_ptr<HttpTransaction> trans(
2746 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2748 // Since we have proxy, should try to establish tunnel.
2749 MockWrite data_writes1[] = {
2750 MockWrite(
2751 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2752 "Host: www.example.org\r\n"
2753 "Proxy-Connection: keep-alive\r\n\r\n"),
2755 // After calling trans->RestartWithAuth(), this is the request we should
2756 // be issuing -- the final header line contains the credentials.
2757 MockWrite(
2758 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2759 "Host: www.example.org\r\n"
2760 "Proxy-Connection: keep-alive\r\n"
2761 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2764 // The proxy responds to the connect with a 407, using a persistent
2765 // connection.
2766 MockRead data_reads1[] = {
2767 // No credentials.
2768 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2769 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2770 MockRead("Content-Length: 10\r\n\r\n"),
2771 MockRead("0123456789"),
2773 // Wrong credentials (wrong password).
2774 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2775 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2776 MockRead("Content-Length: 10\r\n\r\n"),
2777 // No response body because the test stops reading here.
2778 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2781 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2782 data_writes1, arraysize(data_writes1));
2783 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2785 TestCompletionCallback callback1;
2787 int rv = trans->Start(&request, callback1.callback(), log.bound());
2788 EXPECT_EQ(ERR_IO_PENDING, rv);
2790 rv = callback1.WaitForResult();
2791 EXPECT_EQ(OK, rv);
2792 TestNetLogEntry::List entries;
2793 log.GetEntries(&entries);
2794 size_t pos = ExpectLogContainsSomewhere(
2795 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2796 NetLog::PHASE_NONE);
2797 ExpectLogContainsSomewhere(
2798 entries, pos,
2799 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2800 NetLog::PHASE_NONE);
2802 const HttpResponseInfo* response = trans->GetResponseInfo();
2803 ASSERT_TRUE(response);
2804 ASSERT_TRUE(response->headers);
2805 EXPECT_TRUE(response->headers->IsKeepAlive());
2806 EXPECT_EQ(407, response->headers->response_code());
2807 EXPECT_EQ(10, response->headers->GetContentLength());
2808 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2809 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2811 TestCompletionCallback callback2;
2813 // Wrong password (should be "bar").
2814 rv = trans->RestartWithAuth(
2815 AuthCredentials(kFoo, kBaz), callback2.callback());
2816 EXPECT_EQ(ERR_IO_PENDING, rv);
2818 rv = callback2.WaitForResult();
2819 EXPECT_EQ(OK, rv);
2821 response = trans->GetResponseInfo();
2822 ASSERT_TRUE(response);
2823 ASSERT_TRUE(response->headers);
2824 EXPECT_TRUE(response->headers->IsKeepAlive());
2825 EXPECT_EQ(407, response->headers->response_code());
2826 EXPECT_EQ(10, response->headers->GetContentLength());
2827 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2828 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2830 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2831 // out of scope.
2832 session->CloseAllConnections();
2835 // Test that we don't read the response body when we fail to establish a tunnel,
2836 // even if the user cancels the proxy's auth attempt.
2837 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2838 HttpRequestInfo request;
2839 request.method = "GET";
2840 request.url = GURL("https://www.example.org/");
2841 request.load_flags = 0;
2843 // Configure against proxy server "myproxy:70".
2844 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2846 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2848 scoped_ptr<HttpTransaction> trans(
2849 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2851 // Since we have proxy, should try to establish tunnel.
2852 MockWrite data_writes[] = {
2853 MockWrite(
2854 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2855 "Host: www.example.org\r\n"
2856 "Proxy-Connection: keep-alive\r\n\r\n"),
2859 // The proxy responds to the connect with a 407.
2860 MockRead data_reads[] = {
2861 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2862 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2863 MockRead("Content-Length: 10\r\n\r\n"),
2864 MockRead("0123456789"), // Should not be reached.
2865 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
2868 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2869 data_writes, arraysize(data_writes));
2870 session_deps_.socket_factory->AddSocketDataProvider(&data);
2872 TestCompletionCallback callback;
2874 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2875 EXPECT_EQ(ERR_IO_PENDING, rv);
2877 rv = callback.WaitForResult();
2878 EXPECT_EQ(OK, rv);
2880 const HttpResponseInfo* response = trans->GetResponseInfo();
2881 ASSERT_TRUE(response);
2882 ASSERT_TRUE(response->headers);
2883 EXPECT_TRUE(response->headers->IsKeepAlive());
2884 EXPECT_EQ(407, response->headers->response_code());
2885 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2887 std::string response_data;
2888 rv = ReadTransaction(trans.get(), &response_data);
2889 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2891 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2892 session->CloseAllConnections();
2895 // Test that we don't pass extraneous headers from the proxy's response to the
2896 // caller when the proxy responds to CONNECT with 407.
2897 TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
2898 HttpRequestInfo request;
2899 request.method = "GET";
2900 request.url = GURL("https://www.example.org/");
2901 request.load_flags = 0;
2903 // Configure against proxy server "myproxy:70".
2904 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2906 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2908 scoped_ptr<HttpTransaction> trans(
2909 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2911 // Since we have proxy, should try to establish tunnel.
2912 MockWrite data_writes[] = {
2913 MockWrite(
2914 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2915 "Host: www.example.org\r\n"
2916 "Proxy-Connection: keep-alive\r\n\r\n"),
2919 // The proxy responds to the connect with a 407.
2920 MockRead data_reads[] = {
2921 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2922 MockRead("X-Foo: bar\r\n"),
2923 MockRead("Set-Cookie: foo=bar\r\n"),
2924 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2925 MockRead("Content-Length: 10\r\n\r\n"),
2926 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2929 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
2930 arraysize(data_writes));
2931 session_deps_.socket_factory->AddSocketDataProvider(&data);
2933 TestCompletionCallback callback;
2935 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2936 EXPECT_EQ(ERR_IO_PENDING, rv);
2938 rv = callback.WaitForResult();
2939 EXPECT_EQ(OK, rv);
2941 const HttpResponseInfo* response = trans->GetResponseInfo();
2942 ASSERT_TRUE(response);
2943 ASSERT_TRUE(response->headers);
2944 EXPECT_TRUE(response->headers->IsKeepAlive());
2945 EXPECT_EQ(407, response->headers->response_code());
2946 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2947 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
2948 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
2950 std::string response_data;
2951 rv = ReadTransaction(trans.get(), &response_data);
2952 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2954 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2955 session->CloseAllConnections();
2958 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2959 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2960 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2961 HttpRequestInfo request;
2962 request.method = "GET";
2963 request.url = GURL("http://www.example.org/");
2964 request.load_flags = 0;
2966 // We are using a DIRECT connection (i.e. no proxy) for this session.
2967 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2968 scoped_ptr<HttpTransaction> trans(
2969 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2971 MockWrite data_writes1[] = {
2972 MockWrite(
2973 "GET / HTTP/1.1\r\n"
2974 "Host: www.example.org\r\n"
2975 "Connection: keep-alive\r\n\r\n"),
2978 MockRead data_reads1[] = {
2979 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2980 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2981 // Large content-length -- won't matter, as connection will be reset.
2982 MockRead("Content-Length: 10000\r\n\r\n"),
2983 MockRead(SYNCHRONOUS, ERR_FAILED),
2986 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2987 data_writes1, arraysize(data_writes1));
2988 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2990 TestCompletionCallback callback;
2992 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2993 EXPECT_EQ(ERR_IO_PENDING, rv);
2995 rv = callback.WaitForResult();
2996 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2999 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3000 // through a non-authenticating proxy. The request should fail with
3001 // ERR_UNEXPECTED_PROXY_AUTH.
3002 // Note that it is impossible to detect if an HTTP server returns a 407 through
3003 // a non-authenticating proxy - there is nothing to indicate whether the
3004 // response came from the proxy or the server, so it is treated as if the proxy
3005 // issued the challenge.
3006 TEST_P(HttpNetworkTransactionTest,
3007 HttpsServerRequestsProxyAuthThroughProxy) {
3008 HttpRequestInfo request;
3009 request.method = "GET";
3010 request.url = GURL("https://www.example.org/");
3012 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3013 BoundTestNetLog log;
3014 session_deps_.net_log = log.bound().net_log();
3015 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3017 // Since we have proxy, should try to establish tunnel.
3018 MockWrite data_writes1[] = {
3019 MockWrite(
3020 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3021 "Host: www.example.org\r\n"
3022 "Proxy-Connection: keep-alive\r\n\r\n"),
3024 MockWrite(
3025 "GET / HTTP/1.1\r\n"
3026 "Host: www.example.org\r\n"
3027 "Connection: keep-alive\r\n\r\n"),
3030 MockRead data_reads1[] = {
3031 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3033 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3034 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3035 MockRead("\r\n"),
3036 MockRead(SYNCHRONOUS, OK),
3039 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3040 data_writes1, arraysize(data_writes1));
3041 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3042 SSLSocketDataProvider ssl(ASYNC, OK);
3043 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3045 TestCompletionCallback callback1;
3047 scoped_ptr<HttpTransaction> trans(
3048 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3050 int rv = trans->Start(&request, callback1.callback(), log.bound());
3051 EXPECT_EQ(ERR_IO_PENDING, rv);
3053 rv = callback1.WaitForResult();
3054 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3055 TestNetLogEntry::List entries;
3056 log.GetEntries(&entries);
3057 size_t pos = ExpectLogContainsSomewhere(
3058 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3059 NetLog::PHASE_NONE);
3060 ExpectLogContainsSomewhere(
3061 entries, pos,
3062 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3063 NetLog::PHASE_NONE);
3066 // Test the load timing for HTTPS requests with an HTTP proxy.
3067 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
3068 HttpRequestInfo request1;
3069 request1.method = "GET";
3070 request1.url = GURL("https://www.example.org/1");
3072 HttpRequestInfo request2;
3073 request2.method = "GET";
3074 request2.url = GURL("https://www.example.org/2");
3076 // Configure against proxy server "myproxy:70".
3077 session_deps_.proxy_service.reset(
3078 ProxyService::CreateFixed("PROXY myproxy:70"));
3079 BoundTestNetLog log;
3080 session_deps_.net_log = log.bound().net_log();
3081 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3083 // Since we have proxy, should try to establish tunnel.
3084 MockWrite data_writes1[] = {
3085 MockWrite(
3086 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3087 "Host: www.example.org\r\n"
3088 "Proxy-Connection: keep-alive\r\n\r\n"),
3090 MockWrite(
3091 "GET /1 HTTP/1.1\r\n"
3092 "Host: www.example.org\r\n"
3093 "Connection: keep-alive\r\n\r\n"),
3095 MockWrite(
3096 "GET /2 HTTP/1.1\r\n"
3097 "Host: www.example.org\r\n"
3098 "Connection: keep-alive\r\n\r\n"),
3101 // The proxy responds to the connect with a 407, using a persistent
3102 // connection.
3103 MockRead data_reads1[] = {
3104 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3106 MockRead("HTTP/1.1 200 OK\r\n"),
3107 MockRead("Content-Length: 1\r\n\r\n"),
3108 MockRead(SYNCHRONOUS, "1"),
3110 MockRead("HTTP/1.1 200 OK\r\n"),
3111 MockRead("Content-Length: 2\r\n\r\n"),
3112 MockRead(SYNCHRONOUS, "22"),
3115 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3116 data_writes1, arraysize(data_writes1));
3117 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3118 SSLSocketDataProvider ssl(ASYNC, OK);
3119 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3121 TestCompletionCallback callback1;
3122 scoped_ptr<HttpTransaction> trans1(
3123 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3125 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3126 EXPECT_EQ(ERR_IO_PENDING, rv);
3128 rv = callback1.WaitForResult();
3129 EXPECT_EQ(OK, rv);
3131 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3132 ASSERT_TRUE(response1 != NULL);
3133 ASSERT_TRUE(response1->headers.get() != NULL);
3134 EXPECT_EQ(1, response1->headers->GetContentLength());
3136 LoadTimingInfo load_timing_info1;
3137 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3138 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3140 trans1.reset();
3142 TestCompletionCallback callback2;
3143 scoped_ptr<HttpTransaction> trans2(
3144 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3146 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3147 EXPECT_EQ(ERR_IO_PENDING, rv);
3149 rv = callback2.WaitForResult();
3150 EXPECT_EQ(OK, rv);
3152 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3153 ASSERT_TRUE(response2 != NULL);
3154 ASSERT_TRUE(response2->headers.get() != NULL);
3155 EXPECT_EQ(2, response2->headers->GetContentLength());
3157 LoadTimingInfo load_timing_info2;
3158 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3159 TestLoadTimingReused(load_timing_info2);
3161 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3163 trans2.reset();
3164 session->CloseAllConnections();
3167 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3168 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
3169 HttpRequestInfo request1;
3170 request1.method = "GET";
3171 request1.url = GURL("https://www.example.org/1");
3173 HttpRequestInfo request2;
3174 request2.method = "GET";
3175 request2.url = GURL("https://www.example.org/2");
3177 // Configure against proxy server "myproxy:70".
3178 session_deps_.proxy_service.reset(
3179 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3180 BoundTestNetLog log;
3181 session_deps_.net_log = log.bound().net_log();
3182 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3184 // Since we have proxy, should try to establish tunnel.
3185 MockWrite data_writes1[] = {
3186 MockWrite(
3187 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3188 "Host: www.example.org\r\n"
3189 "Proxy-Connection: keep-alive\r\n\r\n"),
3191 MockWrite(
3192 "GET /1 HTTP/1.1\r\n"
3193 "Host: www.example.org\r\n"
3194 "Connection: keep-alive\r\n\r\n"),
3196 MockWrite(
3197 "GET /2 HTTP/1.1\r\n"
3198 "Host: www.example.org\r\n"
3199 "Connection: keep-alive\r\n\r\n"),
3202 // The proxy responds to the connect with a 407, using a persistent
3203 // connection.
3204 MockRead data_reads1[] = {
3205 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3207 MockRead("HTTP/1.1 200 OK\r\n"),
3208 MockRead("Content-Length: 1\r\n\r\n"),
3209 MockRead(SYNCHRONOUS, "1"),
3211 MockRead("HTTP/1.1 200 OK\r\n"),
3212 MockRead("Content-Length: 2\r\n\r\n"),
3213 MockRead(SYNCHRONOUS, "22"),
3216 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3217 data_writes1, arraysize(data_writes1));
3218 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3219 SSLSocketDataProvider ssl(ASYNC, OK);
3220 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3222 TestCompletionCallback callback1;
3223 scoped_ptr<HttpTransaction> trans1(
3224 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3226 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3227 EXPECT_EQ(ERR_IO_PENDING, rv);
3229 rv = callback1.WaitForResult();
3230 EXPECT_EQ(OK, rv);
3232 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3233 ASSERT_TRUE(response1 != NULL);
3234 ASSERT_TRUE(response1->headers.get() != NULL);
3235 EXPECT_EQ(1, response1->headers->GetContentLength());
3237 LoadTimingInfo load_timing_info1;
3238 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3239 TestLoadTimingNotReusedWithPac(load_timing_info1,
3240 CONNECT_TIMING_HAS_SSL_TIMES);
3242 trans1.reset();
3244 TestCompletionCallback callback2;
3245 scoped_ptr<HttpTransaction> trans2(
3246 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3248 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3249 EXPECT_EQ(ERR_IO_PENDING, rv);
3251 rv = callback2.WaitForResult();
3252 EXPECT_EQ(OK, rv);
3254 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3255 ASSERT_TRUE(response2 != NULL);
3256 ASSERT_TRUE(response2->headers.get() != NULL);
3257 EXPECT_EQ(2, response2->headers->GetContentLength());
3259 LoadTimingInfo load_timing_info2;
3260 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3261 TestLoadTimingReusedWithPac(load_timing_info2);
3263 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3265 trans2.reset();
3266 session->CloseAllConnections();
3269 // Test a simple get through an HTTPS Proxy.
3270 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
3271 HttpRequestInfo request;
3272 request.method = "GET";
3273 request.url = GURL("http://www.example.org/");
3275 // Configure against https proxy server "proxy:70".
3276 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3277 "https://proxy:70"));
3278 BoundTestNetLog log;
3279 session_deps_.net_log = log.bound().net_log();
3280 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3282 // Since we have proxy, should use full url
3283 MockWrite data_writes1[] = {
3284 MockWrite(
3285 "GET http://www.example.org/ HTTP/1.1\r\n"
3286 "Host: www.example.org\r\n"
3287 "Proxy-Connection: keep-alive\r\n\r\n"),
3290 MockRead data_reads1[] = {
3291 MockRead("HTTP/1.1 200 OK\r\n"),
3292 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3293 MockRead("Content-Length: 100\r\n\r\n"),
3294 MockRead(SYNCHRONOUS, OK),
3297 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3298 data_writes1, arraysize(data_writes1));
3299 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3300 SSLSocketDataProvider ssl(ASYNC, OK);
3301 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3303 TestCompletionCallback callback1;
3305 scoped_ptr<HttpTransaction> trans(
3306 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3308 int rv = trans->Start(&request, callback1.callback(), log.bound());
3309 EXPECT_EQ(ERR_IO_PENDING, rv);
3311 rv = callback1.WaitForResult();
3312 EXPECT_EQ(OK, rv);
3314 LoadTimingInfo load_timing_info;
3315 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3316 TestLoadTimingNotReused(load_timing_info,
3317 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3319 const HttpResponseInfo* response = trans->GetResponseInfo();
3320 ASSERT_TRUE(response != NULL);
3322 EXPECT_TRUE(response->headers->IsKeepAlive());
3323 EXPECT_EQ(200, response->headers->response_code());
3324 EXPECT_EQ(100, response->headers->GetContentLength());
3325 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3327 // The password prompt info should not be set.
3328 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3331 // Test a SPDY get through an HTTPS Proxy.
3332 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3333 HttpRequestInfo request;
3334 request.method = "GET";
3335 request.url = GURL("http://www.example.org/");
3336 request.load_flags = 0;
3338 // Configure against https proxy server "proxy:70".
3339 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3340 "https://proxy:70"));
3341 BoundTestNetLog log;
3342 session_deps_.net_log = log.bound().net_log();
3343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3345 // fetch http://www.example.org/ via SPDY
3346 scoped_ptr<SpdyFrame> req(
3347 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3348 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3350 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3351 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3352 MockRead spdy_reads[] = {
3353 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3356 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3357 arraysize(spdy_writes));
3358 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3360 SSLSocketDataProvider ssl(ASYNC, OK);
3361 ssl.SetNextProto(GetParam());
3362 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3364 TestCompletionCallback callback1;
3366 scoped_ptr<HttpTransaction> trans(
3367 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3369 int rv = trans->Start(&request, callback1.callback(), log.bound());
3370 EXPECT_EQ(ERR_IO_PENDING, rv);
3372 rv = callback1.WaitForResult();
3373 EXPECT_EQ(OK, rv);
3375 LoadTimingInfo load_timing_info;
3376 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3377 TestLoadTimingNotReused(load_timing_info,
3378 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3380 const HttpResponseInfo* response = trans->GetResponseInfo();
3381 ASSERT_TRUE(response != NULL);
3382 ASSERT_TRUE(response->headers.get() != NULL);
3383 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3385 std::string response_data;
3386 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3387 EXPECT_EQ(kUploadData, response_data);
3390 // Verifies that a session which races and wins against the owning transaction
3391 // (completing prior to host resolution), doesn't fail the transaction.
3392 // Regression test for crbug.com/334413.
3393 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3394 HttpRequestInfo request;
3395 request.method = "GET";
3396 request.url = GURL("http://www.example.org/");
3397 request.load_flags = 0;
3399 // Configure SPDY proxy server "proxy:70".
3400 session_deps_.proxy_service.reset(
3401 ProxyService::CreateFixed("https://proxy:70"));
3402 BoundTestNetLog log;
3403 session_deps_.net_log = log.bound().net_log();
3404 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3406 // Fetch http://www.example.org/ through the SPDY proxy.
3407 scoped_ptr<SpdyFrame> req(
3408 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3409 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3411 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3412 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3413 MockRead spdy_reads[] = {
3414 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3417 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3418 arraysize(spdy_writes));
3419 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3421 SSLSocketDataProvider ssl(ASYNC, OK);
3422 ssl.SetNextProto(GetParam());
3423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3425 TestCompletionCallback callback1;
3427 scoped_ptr<HttpTransaction> trans(
3428 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3430 // Stall the hostname resolution begun by the transaction.
3431 session_deps_.host_resolver->set_synchronous_mode(false);
3432 session_deps_.host_resolver->set_ondemand_mode(true);
3434 int rv = trans->Start(&request, callback1.callback(), log.bound());
3435 EXPECT_EQ(ERR_IO_PENDING, rv);
3437 // Race a session to the proxy, which completes first.
3438 session_deps_.host_resolver->set_ondemand_mode(false);
3439 SpdySessionKey key(
3440 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3441 base::WeakPtr<SpdySession> spdy_session =
3442 CreateSecureSpdySession(session, key, log.bound());
3444 // Unstall the resolution begun by the transaction.
3445 session_deps_.host_resolver->set_ondemand_mode(true);
3446 session_deps_.host_resolver->ResolveAllPending();
3448 EXPECT_FALSE(callback1.have_result());
3449 rv = callback1.WaitForResult();
3450 EXPECT_EQ(OK, rv);
3452 const HttpResponseInfo* response = trans->GetResponseInfo();
3453 ASSERT_TRUE(response != NULL);
3454 ASSERT_TRUE(response->headers.get() != NULL);
3455 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3457 std::string response_data;
3458 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3459 EXPECT_EQ(kUploadData, response_data);
3462 // Test a SPDY get through an HTTPS Proxy.
3463 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3464 HttpRequestInfo request;
3465 request.method = "GET";
3466 request.url = GURL("http://www.example.org/");
3467 request.load_flags = 0;
3469 // Configure against https proxy server "myproxy:70".
3470 session_deps_.proxy_service.reset(
3471 ProxyService::CreateFixed("https://myproxy:70"));
3472 BoundTestNetLog log;
3473 session_deps_.net_log = log.bound().net_log();
3474 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3476 // The first request will be a bare GET, the second request will be a
3477 // GET with a Proxy-Authorization header.
3478 scoped_ptr<SpdyFrame> req_get(
3479 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3480 const char* const kExtraAuthorizationHeaders[] = {
3481 "proxy-authorization", "Basic Zm9vOmJhcg=="
3483 scoped_ptr<SpdyFrame> req_get_authorization(
3484 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3485 arraysize(kExtraAuthorizationHeaders) / 2,
3486 false,
3488 LOWEST,
3489 false));
3490 MockWrite spdy_writes[] = {
3491 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
3494 // The first response is a 407 proxy authentication challenge, and the second
3495 // response will be a 200 response since the second request includes a valid
3496 // Authorization header.
3497 const char* const kExtraAuthenticationHeaders[] = {
3498 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3500 scoped_ptr<SpdyFrame> resp_authentication(
3501 spdy_util_.ConstructSpdySynReplyError(
3502 "407 Proxy Authentication Required",
3503 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3504 1));
3505 scoped_ptr<SpdyFrame> body_authentication(
3506 spdy_util_.ConstructSpdyBodyFrame(1, true));
3507 scoped_ptr<SpdyFrame> resp_data(
3508 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3509 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3510 MockRead spdy_reads[] = {
3511 CreateMockRead(*resp_authentication, 1),
3512 CreateMockRead(*body_authentication, 2),
3513 CreateMockRead(*resp_data, 4),
3514 CreateMockRead(*body_data, 5),
3515 MockRead(ASYNC, 0, 6),
3518 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3519 arraysize(spdy_writes));
3520 session_deps_.socket_factory->AddSocketDataProvider(&data);
3522 SSLSocketDataProvider ssl(ASYNC, OK);
3523 ssl.SetNextProto(GetParam());
3524 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3526 TestCompletionCallback callback1;
3528 scoped_ptr<HttpTransaction> trans(
3529 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3531 int rv = trans->Start(&request, callback1.callback(), log.bound());
3532 EXPECT_EQ(ERR_IO_PENDING, rv);
3534 rv = callback1.WaitForResult();
3535 EXPECT_EQ(OK, rv);
3537 const HttpResponseInfo* const response = trans->GetResponseInfo();
3539 ASSERT_TRUE(response != NULL);
3540 ASSERT_TRUE(response->headers.get() != NULL);
3541 EXPECT_EQ(407, response->headers->response_code());
3542 EXPECT_TRUE(response->was_fetched_via_spdy);
3543 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3545 TestCompletionCallback callback2;
3547 rv = trans->RestartWithAuth(
3548 AuthCredentials(kFoo, kBar), callback2.callback());
3549 EXPECT_EQ(ERR_IO_PENDING, rv);
3551 rv = callback2.WaitForResult();
3552 EXPECT_EQ(OK, rv);
3554 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3556 ASSERT_TRUE(response_restart != NULL);
3557 ASSERT_TRUE(response_restart->headers.get() != NULL);
3558 EXPECT_EQ(200, response_restart->headers->response_code());
3559 // The password prompt info should not be set.
3560 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3563 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3564 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3565 HttpRequestInfo request;
3566 request.method = "GET";
3567 request.url = GURL("https://www.example.org/");
3568 request.load_flags = 0;
3570 // Configure against https proxy server "proxy:70".
3571 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3572 "https://proxy:70"));
3573 BoundTestNetLog log;
3574 session_deps_.net_log = log.bound().net_log();
3575 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3577 scoped_ptr<HttpTransaction> trans(
3578 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3580 // CONNECT to www.example.org:443 via SPDY
3581 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3582 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3583 // fetch https://www.example.org/ via HTTP
3585 const char get[] =
3586 "GET / HTTP/1.1\r\n"
3587 "Host: www.example.org\r\n"
3588 "Connection: keep-alive\r\n\r\n";
3589 scoped_ptr<SpdyFrame> wrapped_get(
3590 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3591 scoped_ptr<SpdyFrame> conn_resp(
3592 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3593 const char resp[] = "HTTP/1.1 200 OK\r\n"
3594 "Content-Length: 10\r\n\r\n";
3595 scoped_ptr<SpdyFrame> wrapped_get_resp(
3596 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3597 scoped_ptr<SpdyFrame> wrapped_body(
3598 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3599 scoped_ptr<SpdyFrame> window_update(
3600 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3602 MockWrite spdy_writes[] = {
3603 CreateMockWrite(*connect, 0),
3604 CreateMockWrite(*wrapped_get, 2),
3605 CreateMockWrite(*window_update, 6),
3608 MockRead spdy_reads[] = {
3609 CreateMockRead(*conn_resp, 1, ASYNC),
3610 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
3611 CreateMockRead(*wrapped_body, 4, ASYNC),
3612 CreateMockRead(*wrapped_body, 5, ASYNC),
3613 MockRead(ASYNC, 0, 7),
3616 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3617 arraysize(spdy_writes));
3618 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3620 SSLSocketDataProvider ssl(ASYNC, OK);
3621 ssl.SetNextProto(GetParam());
3622 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3623 SSLSocketDataProvider ssl2(ASYNC, OK);
3624 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3626 TestCompletionCallback callback1;
3628 int rv = trans->Start(&request, callback1.callback(), log.bound());
3629 EXPECT_EQ(ERR_IO_PENDING, rv);
3631 rv = callback1.WaitForResult();
3632 ASSERT_EQ(OK, rv);
3634 LoadTimingInfo load_timing_info;
3635 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3636 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3638 const HttpResponseInfo* response = trans->GetResponseInfo();
3639 ASSERT_TRUE(response != NULL);
3640 ASSERT_TRUE(response->headers.get() != NULL);
3641 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3643 std::string response_data;
3644 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3645 EXPECT_EQ("1234567890", response_data);
3648 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3649 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3650 HttpRequestInfo request;
3651 request.method = "GET";
3652 request.url = GURL("https://www.example.org/");
3653 request.load_flags = 0;
3655 // Configure against https proxy server "proxy:70".
3656 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3657 "https://proxy:70"));
3658 BoundTestNetLog log;
3659 session_deps_.net_log = log.bound().net_log();
3660 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3662 scoped_ptr<HttpTransaction> trans(
3663 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3665 // CONNECT to www.example.org:443 via SPDY
3666 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3667 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3668 // fetch https://www.example.org/ via SPDY
3669 const char kMyUrl[] = "https://www.example.org/";
3670 scoped_ptr<SpdyFrame> get(
3671 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3672 scoped_ptr<SpdyFrame> wrapped_get(
3673 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3674 scoped_ptr<SpdyFrame> conn_resp(
3675 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3676 scoped_ptr<SpdyFrame> get_resp(
3677 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3678 scoped_ptr<SpdyFrame> wrapped_get_resp(
3679 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3680 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3681 scoped_ptr<SpdyFrame> wrapped_body(
3682 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3683 scoped_ptr<SpdyFrame> window_update_get_resp(
3684 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3685 scoped_ptr<SpdyFrame> window_update_body(
3686 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3688 MockWrite spdy_writes[] = {
3689 CreateMockWrite(*connect, 0),
3690 CreateMockWrite(*wrapped_get, 2),
3691 CreateMockWrite(*window_update_get_resp, 6),
3692 CreateMockWrite(*window_update_body, 7),
3695 MockRead spdy_reads[] = {
3696 CreateMockRead(*conn_resp, 1, ASYNC),
3697 MockRead(ASYNC, ERR_IO_PENDING, 3),
3698 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3699 CreateMockRead(*wrapped_body, 5, ASYNC),
3700 MockRead(ASYNC, 0, 8),
3703 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3704 arraysize(spdy_writes));
3705 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3707 SSLSocketDataProvider ssl(ASYNC, OK);
3708 ssl.SetNextProto(GetParam());
3709 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3710 SSLSocketDataProvider ssl2(ASYNC, OK);
3711 ssl2.SetNextProto(GetParam());
3712 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3714 TestCompletionCallback callback1;
3716 int rv = trans->Start(&request, callback1.callback(), log.bound());
3717 EXPECT_EQ(ERR_IO_PENDING, rv);
3719 // Allow the SpdyProxyClientSocket's write callback to complete.
3720 base::MessageLoop::current()->RunUntilIdle();
3721 // Now allow the read of the response to complete.
3722 spdy_data.CompleteRead();
3723 rv = callback1.WaitForResult();
3724 EXPECT_EQ(OK, rv);
3726 LoadTimingInfo load_timing_info;
3727 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3728 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3730 const HttpResponseInfo* response = trans->GetResponseInfo();
3731 ASSERT_TRUE(response != NULL);
3732 ASSERT_TRUE(response->headers.get() != NULL);
3733 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3735 std::string response_data;
3736 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3737 EXPECT_EQ(kUploadData, response_data);
3740 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3741 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3742 HttpRequestInfo request;
3743 request.method = "GET";
3744 request.url = GURL("https://www.example.org/");
3745 request.load_flags = 0;
3747 // Configure against https proxy server "proxy:70".
3748 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3749 "https://proxy:70"));
3750 BoundTestNetLog log;
3751 session_deps_.net_log = log.bound().net_log();
3752 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3754 scoped_ptr<HttpTransaction> trans(
3755 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3757 // CONNECT to www.example.org:443 via SPDY
3758 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3759 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3760 scoped_ptr<SpdyFrame> get(
3761 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3763 MockWrite spdy_writes[] = {
3764 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
3767 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3768 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3769 MockRead spdy_reads[] = {
3770 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
3773 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3774 arraysize(spdy_writes));
3775 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3777 SSLSocketDataProvider ssl(ASYNC, OK);
3778 ssl.SetNextProto(GetParam());
3779 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3780 SSLSocketDataProvider ssl2(ASYNC, OK);
3781 ssl2.SetNextProto(GetParam());
3782 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3784 TestCompletionCallback callback1;
3786 int rv = trans->Start(&request, callback1.callback(), log.bound());
3787 EXPECT_EQ(ERR_IO_PENDING, rv);
3789 rv = callback1.WaitForResult();
3790 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3792 // TODO(ttuttle): Anything else to check here?
3795 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3796 // HTTPS Proxy to different servers.
3797 TEST_P(HttpNetworkTransactionTest,
3798 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3799 // Configure against https proxy server "proxy:70".
3800 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3801 "https://proxy:70"));
3802 BoundTestNetLog log;
3803 session_deps_.net_log = log.bound().net_log();
3804 scoped_refptr<HttpNetworkSession> session(
3805 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3807 HttpRequestInfo request1;
3808 request1.method = "GET";
3809 request1.url = GURL("https://www.example.org/");
3810 request1.load_flags = 0;
3812 HttpRequestInfo request2;
3813 request2.method = "GET";
3814 request2.url = GURL("https://mail.example.org/");
3815 request2.load_flags = 0;
3817 // CONNECT to www.example.org:443 via SPDY.
3818 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3819 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3820 scoped_ptr<SpdyFrame> conn_resp1(
3821 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3823 // Fetch https://www.example.org/ via HTTP.
3824 const char get1[] =
3825 "GET / HTTP/1.1\r\n"
3826 "Host: www.example.org\r\n"
3827 "Connection: keep-alive\r\n\r\n";
3828 scoped_ptr<SpdyFrame> wrapped_get1(
3829 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3830 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3831 "Content-Length: 1\r\n\r\n";
3832 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3833 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3834 scoped_ptr<SpdyFrame> wrapped_body1(
3835 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3836 scoped_ptr<SpdyFrame> window_update(
3837 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3839 // CONNECT to mail.example.org:443 via SPDY.
3840 SpdyHeaderBlock connect2_block;
3841 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3842 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
3843 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
3844 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3845 scoped_ptr<SpdyFrame> connect2(
3846 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3848 scoped_ptr<SpdyFrame> conn_resp2(
3849 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3851 // Fetch https://mail.example.org/ via HTTP.
3852 const char get2[] =
3853 "GET / HTTP/1.1\r\n"
3854 "Host: mail.example.org\r\n"
3855 "Connection: keep-alive\r\n\r\n";
3856 scoped_ptr<SpdyFrame> wrapped_get2(
3857 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3858 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3859 "Content-Length: 2\r\n\r\n";
3860 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3861 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3862 scoped_ptr<SpdyFrame> wrapped_body2(
3863 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3865 MockWrite spdy_writes[] = {
3866 CreateMockWrite(*connect1, 0),
3867 CreateMockWrite(*wrapped_get1, 2),
3868 CreateMockWrite(*connect2, 5),
3869 CreateMockWrite(*wrapped_get2, 7),
3872 MockRead spdy_reads[] = {
3873 CreateMockRead(*conn_resp1, 1, ASYNC),
3874 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3875 CreateMockRead(*wrapped_body1, 4, ASYNC),
3876 CreateMockRead(*conn_resp2, 6, ASYNC),
3877 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3878 CreateMockRead(*wrapped_body2, 9, ASYNC),
3879 MockRead(ASYNC, 0, 10),
3882 DeterministicSocketData spdy_data(
3883 spdy_reads, arraysize(spdy_reads),
3884 spdy_writes, arraysize(spdy_writes));
3885 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3887 SSLSocketDataProvider ssl(ASYNC, OK);
3888 ssl.SetNextProto(GetParam());
3889 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3890 SSLSocketDataProvider ssl2(ASYNC, OK);
3891 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3892 SSLSocketDataProvider ssl3(ASYNC, OK);
3893 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3895 TestCompletionCallback callback;
3897 scoped_ptr<HttpTransaction> trans(
3898 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3899 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3900 EXPECT_EQ(ERR_IO_PENDING, rv);
3901 // The first connect and request, each of their responses, and the body.
3902 spdy_data.RunFor(5);
3904 rv = callback.WaitForResult();
3905 EXPECT_EQ(OK, rv);
3907 LoadTimingInfo load_timing_info;
3908 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3909 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3911 const HttpResponseInfo* response = trans->GetResponseInfo();
3912 ASSERT_TRUE(response != NULL);
3913 ASSERT_TRUE(response->headers.get() != NULL);
3914 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3916 std::string response_data;
3917 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
3918 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3920 scoped_ptr<HttpTransaction> trans2(
3921 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3922 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3923 EXPECT_EQ(ERR_IO_PENDING, rv);
3925 // The second connect and request, each of their responses, and the body.
3926 spdy_data.RunFor(5);
3927 rv = callback.WaitForResult();
3928 EXPECT_EQ(OK, rv);
3930 LoadTimingInfo load_timing_info2;
3931 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3932 // Even though the SPDY connection is reused, a new tunnelled connection has
3933 // to be created, so the socket's load timing looks like a fresh connection.
3934 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3936 // The requests should have different IDs, since they each are using their own
3937 // separate stream.
3938 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3940 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3943 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3944 // HTTPS Proxy to the same server.
3945 TEST_P(HttpNetworkTransactionTest,
3946 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3947 // Configure against https proxy server "proxy:70".
3948 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3949 "https://proxy:70"));
3950 BoundTestNetLog log;
3951 session_deps_.net_log = log.bound().net_log();
3952 scoped_refptr<HttpNetworkSession> session(
3953 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3955 HttpRequestInfo request1;
3956 request1.method = "GET";
3957 request1.url = GURL("https://www.example.org/");
3958 request1.load_flags = 0;
3960 HttpRequestInfo request2;
3961 request2.method = "GET";
3962 request2.url = GURL("https://www.example.org/2");
3963 request2.load_flags = 0;
3965 // CONNECT to www.example.org:443 via SPDY.
3966 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3967 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3968 scoped_ptr<SpdyFrame> conn_resp1(
3969 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3971 // Fetch https://www.example.org/ via HTTP.
3972 const char get1[] =
3973 "GET / HTTP/1.1\r\n"
3974 "Host: www.example.org\r\n"
3975 "Connection: keep-alive\r\n\r\n";
3976 scoped_ptr<SpdyFrame> wrapped_get1(
3977 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3978 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3979 "Content-Length: 1\r\n\r\n";
3980 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3981 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3982 scoped_ptr<SpdyFrame> wrapped_body1(
3983 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3984 scoped_ptr<SpdyFrame> window_update(
3985 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3987 // Fetch https://www.example.org/2 via HTTP.
3988 const char get2[] =
3989 "GET /2 HTTP/1.1\r\n"
3990 "Host: www.example.org\r\n"
3991 "Connection: keep-alive\r\n\r\n";
3992 scoped_ptr<SpdyFrame> wrapped_get2(
3993 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3994 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3995 "Content-Length: 2\r\n\r\n";
3996 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3997 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3998 scoped_ptr<SpdyFrame> wrapped_body2(
3999 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
4001 MockWrite spdy_writes[] = {
4002 CreateMockWrite(*connect1, 0),
4003 CreateMockWrite(*wrapped_get1, 2),
4004 CreateMockWrite(*wrapped_get2, 5),
4007 MockRead spdy_reads[] = {
4008 CreateMockRead(*conn_resp1, 1, ASYNC),
4009 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4010 CreateMockRead(*wrapped_body1, 4, ASYNC),
4011 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4012 CreateMockRead(*wrapped_body2, 7, ASYNC),
4013 MockRead(ASYNC, 0, 8),
4016 DeterministicSocketData spdy_data(
4017 spdy_reads, arraysize(spdy_reads),
4018 spdy_writes, arraysize(spdy_writes));
4019 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
4021 SSLSocketDataProvider ssl(ASYNC, OK);
4022 ssl.SetNextProto(GetParam());
4023 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
4024 SSLSocketDataProvider ssl2(ASYNC, OK);
4025 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
4027 TestCompletionCallback callback;
4029 scoped_ptr<HttpTransaction> trans(
4030 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4031 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4032 EXPECT_EQ(ERR_IO_PENDING, rv);
4033 // The first connect and request, each of their responses, and the body.
4034 spdy_data.RunFor(5);
4036 rv = callback.WaitForResult();
4037 EXPECT_EQ(OK, rv);
4039 LoadTimingInfo load_timing_info;
4040 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4041 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4043 const HttpResponseInfo* response = trans->GetResponseInfo();
4044 ASSERT_TRUE(response != NULL);
4045 ASSERT_TRUE(response->headers.get() != NULL);
4046 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4048 std::string response_data;
4049 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4050 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
4051 trans.reset();
4053 scoped_ptr<HttpTransaction> trans2(
4054 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4055 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4056 EXPECT_EQ(ERR_IO_PENDING, rv);
4058 // The second request, response, and body. There should not be a second
4059 // connect.
4060 spdy_data.RunFor(3);
4061 rv = callback.WaitForResult();
4062 EXPECT_EQ(OK, rv);
4064 LoadTimingInfo load_timing_info2;
4065 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4066 TestLoadTimingReused(load_timing_info2);
4068 // The requests should have the same ID.
4069 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4071 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
4074 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4075 // Proxy to different servers.
4076 TEST_P(HttpNetworkTransactionTest,
4077 HttpsProxySpdyLoadTimingTwoHttpRequests) {
4078 // Configure against https proxy server "proxy:70".
4079 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
4080 "https://proxy:70"));
4081 BoundTestNetLog log;
4082 session_deps_.net_log = log.bound().net_log();
4083 scoped_refptr<HttpNetworkSession> session(
4084 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
4086 HttpRequestInfo request1;
4087 request1.method = "GET";
4088 request1.url = GURL("http://www.example.org/");
4089 request1.load_flags = 0;
4091 HttpRequestInfo request2;
4092 request2.method = "GET";
4093 request2.url = GURL("http://mail.example.org/");
4094 request2.load_flags = 0;
4096 // http://www.example.org/
4097 scoped_ptr<SpdyHeaderBlock> headers(
4098 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4099 scoped_ptr<SpdyFrame> get1(
4100 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4101 scoped_ptr<SpdyFrame> get_resp1(
4102 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4103 scoped_ptr<SpdyFrame> body1(
4104 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
4106 // http://mail.example.org/
4107 scoped_ptr<SpdyHeaderBlock> headers2(
4108 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4109 scoped_ptr<SpdyFrame> get2(
4110 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
4111 scoped_ptr<SpdyFrame> get_resp2(
4112 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4113 scoped_ptr<SpdyFrame> body2(
4114 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
4116 MockWrite spdy_writes[] = {
4117 CreateMockWrite(*get1, 0),
4118 CreateMockWrite(*get2, 3),
4121 MockRead spdy_reads[] = {
4122 CreateMockRead(*get_resp1, 1, ASYNC),
4123 CreateMockRead(*body1, 2, ASYNC),
4124 CreateMockRead(*get_resp2, 4, ASYNC),
4125 CreateMockRead(*body2, 5, ASYNC),
4126 MockRead(ASYNC, 0, 6),
4129 DeterministicSocketData spdy_data(
4130 spdy_reads, arraysize(spdy_reads),
4131 spdy_writes, arraysize(spdy_writes));
4132 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
4134 SSLSocketDataProvider ssl(ASYNC, OK);
4135 ssl.SetNextProto(GetParam());
4136 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
4138 TestCompletionCallback callback;
4140 scoped_ptr<HttpTransaction> trans(
4141 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4142 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4143 EXPECT_EQ(ERR_IO_PENDING, rv);
4144 spdy_data.RunFor(2);
4146 rv = callback.WaitForResult();
4147 EXPECT_EQ(OK, rv);
4149 LoadTimingInfo load_timing_info;
4150 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4151 TestLoadTimingNotReused(load_timing_info,
4152 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4154 const HttpResponseInfo* response = trans->GetResponseInfo();
4155 ASSERT_TRUE(response != NULL);
4156 ASSERT_TRUE(response->headers.get() != NULL);
4157 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4159 std::string response_data;
4160 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4161 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
4162 spdy_data.RunFor(1);
4163 EXPECT_EQ(1, callback.WaitForResult());
4164 // Delete the first request, so the second one can reuse the socket.
4165 trans.reset();
4167 scoped_ptr<HttpTransaction> trans2(
4168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4169 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4170 EXPECT_EQ(ERR_IO_PENDING, rv);
4172 spdy_data.RunFor(2);
4173 rv = callback.WaitForResult();
4174 EXPECT_EQ(OK, rv);
4176 LoadTimingInfo load_timing_info2;
4177 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4178 TestLoadTimingReused(load_timing_info2);
4180 // The requests should have the same ID.
4181 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4183 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
4184 spdy_data.RunFor(1);
4185 EXPECT_EQ(2, callback.WaitForResult());
4188 // Test the challenge-response-retry sequence through an HTTPS Proxy
4189 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
4190 HttpRequestInfo request;
4191 request.method = "GET";
4192 request.url = GURL("http://www.example.org/");
4193 // when the no authentication data flag is set.
4194 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
4196 // Configure against https proxy server "myproxy:70".
4197 session_deps_.proxy_service.reset(
4198 ProxyService::CreateFixed("https://myproxy:70"));
4199 BoundTestNetLog log;
4200 session_deps_.net_log = log.bound().net_log();
4201 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4203 // Since we have proxy, should use full url
4204 MockWrite data_writes1[] = {
4205 MockWrite(
4206 "GET http://www.example.org/ HTTP/1.1\r\n"
4207 "Host: www.example.org\r\n"
4208 "Proxy-Connection: keep-alive\r\n\r\n"),
4210 // After calling trans->RestartWithAuth(), this is the request we should
4211 // be issuing -- the final header line contains the credentials.
4212 MockWrite(
4213 "GET http://www.example.org/ HTTP/1.1\r\n"
4214 "Host: www.example.org\r\n"
4215 "Proxy-Connection: keep-alive\r\n"
4216 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4219 // The proxy responds to the GET with a 407, using a persistent
4220 // connection.
4221 MockRead data_reads1[] = {
4222 // No credentials.
4223 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4224 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4225 MockRead("Proxy-Connection: keep-alive\r\n"),
4226 MockRead("Content-Length: 0\r\n\r\n"),
4228 MockRead("HTTP/1.1 200 OK\r\n"),
4229 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4230 MockRead("Content-Length: 100\r\n\r\n"),
4231 MockRead(SYNCHRONOUS, OK),
4234 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4235 data_writes1, arraysize(data_writes1));
4236 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4237 SSLSocketDataProvider ssl(ASYNC, OK);
4238 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4240 TestCompletionCallback callback1;
4242 scoped_ptr<HttpTransaction> trans(
4243 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4245 int rv = trans->Start(&request, callback1.callback(), log.bound());
4246 EXPECT_EQ(ERR_IO_PENDING, rv);
4248 rv = callback1.WaitForResult();
4249 EXPECT_EQ(OK, rv);
4251 LoadTimingInfo load_timing_info;
4252 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4253 TestLoadTimingNotReused(load_timing_info,
4254 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4256 const HttpResponseInfo* response = trans->GetResponseInfo();
4257 ASSERT_TRUE(response != NULL);
4258 ASSERT_FALSE(response->headers.get() == NULL);
4259 EXPECT_EQ(407, response->headers->response_code());
4260 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4261 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4263 TestCompletionCallback callback2;
4265 rv = trans->RestartWithAuth(
4266 AuthCredentials(kFoo, kBar), callback2.callback());
4267 EXPECT_EQ(ERR_IO_PENDING, rv);
4269 rv = callback2.WaitForResult();
4270 EXPECT_EQ(OK, rv);
4272 load_timing_info = LoadTimingInfo();
4273 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4274 // Retrying with HTTP AUTH is considered to be reusing a socket.
4275 TestLoadTimingReused(load_timing_info);
4277 response = trans->GetResponseInfo();
4278 ASSERT_TRUE(response != NULL);
4280 EXPECT_TRUE(response->headers->IsKeepAlive());
4281 EXPECT_EQ(200, response->headers->response_code());
4282 EXPECT_EQ(100, response->headers->GetContentLength());
4283 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4285 // The password prompt info should not be set.
4286 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4289 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4290 const MockRead& status, int expected_status) {
4291 HttpRequestInfo request;
4292 request.method = "GET";
4293 request.url = GURL("https://www.example.org/");
4294 request.load_flags = 0;
4296 // Configure against proxy server "myproxy:70".
4297 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4298 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4300 // Since we have proxy, should try to establish tunnel.
4301 MockWrite data_writes[] = {
4302 MockWrite(
4303 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4304 "Host: www.example.org\r\n"
4305 "Proxy-Connection: keep-alive\r\n\r\n"),
4308 MockRead data_reads[] = {
4309 status,
4310 MockRead("Content-Length: 10\r\n\r\n"),
4311 // No response body because the test stops reading here.
4312 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4315 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4316 data_writes, arraysize(data_writes));
4317 session_deps_.socket_factory->AddSocketDataProvider(&data);
4319 TestCompletionCallback callback;
4321 scoped_ptr<HttpTransaction> trans(
4322 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4324 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4325 EXPECT_EQ(ERR_IO_PENDING, rv);
4327 rv = callback.WaitForResult();
4328 EXPECT_EQ(expected_status, rv);
4331 void HttpNetworkTransactionTest::ConnectStatusHelper(
4332 const MockRead& status) {
4333 ConnectStatusHelperWithExpectedStatus(
4334 status, ERR_TUNNEL_CONNECTION_FAILED);
4337 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4338 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4341 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4342 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4345 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4346 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4349 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4350 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4353 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4354 ConnectStatusHelper(
4355 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4358 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4359 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4362 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4363 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4366 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4367 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4370 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4371 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4374 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4375 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4378 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4379 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4382 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4383 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4386 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4387 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4390 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4391 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4394 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4395 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4398 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4399 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4402 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4403 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4406 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4407 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4410 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4411 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4414 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4415 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4418 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4419 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4422 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4423 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4426 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4427 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4430 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4431 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4434 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4435 ConnectStatusHelperWithExpectedStatus(
4436 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4437 ERR_PROXY_AUTH_UNSUPPORTED);
4440 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4441 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4444 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4445 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4448 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4449 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4452 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4453 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4456 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4457 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4460 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4461 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4464 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4465 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4468 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4469 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4472 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4473 ConnectStatusHelper(
4474 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4477 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4478 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4481 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4482 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4485 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4486 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4489 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4490 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4493 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4494 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4497 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4498 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4501 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4502 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4505 // Test the flow when both the proxy server AND origin server require
4506 // authentication. Again, this uses basic auth for both since that is
4507 // the simplest to mock.
4508 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4509 HttpRequestInfo request;
4510 request.method = "GET";
4511 request.url = GURL("http://www.example.org/");
4512 request.load_flags = 0;
4514 // Configure against proxy server "myproxy:70".
4515 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4516 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4518 scoped_ptr<HttpTransaction> trans(
4519 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4521 MockWrite data_writes1[] = {
4522 MockWrite(
4523 "GET http://www.example.org/ HTTP/1.1\r\n"
4524 "Host: www.example.org\r\n"
4525 "Proxy-Connection: keep-alive\r\n\r\n"),
4528 MockRead data_reads1[] = {
4529 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4530 // Give a couple authenticate options (only the middle one is actually
4531 // supported).
4532 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4533 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4534 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4535 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4536 // Large content-length -- won't matter, as connection will be reset.
4537 MockRead("Content-Length: 10000\r\n\r\n"),
4538 MockRead(SYNCHRONOUS, ERR_FAILED),
4541 // After calling trans->RestartWithAuth() the first time, this is the
4542 // request we should be issuing -- the final header line contains the
4543 // proxy's credentials.
4544 MockWrite data_writes2[] = {
4545 MockWrite(
4546 "GET http://www.example.org/ HTTP/1.1\r\n"
4547 "Host: www.example.org\r\n"
4548 "Proxy-Connection: keep-alive\r\n"
4549 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4552 // Now the proxy server lets the request pass through to origin server.
4553 // The origin server responds with a 401.
4554 MockRead data_reads2[] = {
4555 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4556 // Note: We are using the same realm-name as the proxy server. This is
4557 // completely valid, as realms are unique across hosts.
4558 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4559 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4560 MockRead("Content-Length: 2000\r\n\r\n"),
4561 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4564 // After calling trans->RestartWithAuth() the second time, we should send
4565 // the credentials for both the proxy and origin server.
4566 MockWrite data_writes3[] = {
4567 MockWrite(
4568 "GET http://www.example.org/ HTTP/1.1\r\n"
4569 "Host: www.example.org\r\n"
4570 "Proxy-Connection: keep-alive\r\n"
4571 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4572 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4575 // Lastly we get the desired content.
4576 MockRead data_reads3[] = {
4577 MockRead("HTTP/1.0 200 OK\r\n"),
4578 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4579 MockRead("Content-Length: 100\r\n\r\n"),
4580 MockRead(SYNCHRONOUS, OK),
4583 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4584 data_writes1, arraysize(data_writes1));
4585 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4586 data_writes2, arraysize(data_writes2));
4587 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4588 data_writes3, arraysize(data_writes3));
4589 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4590 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4591 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4593 TestCompletionCallback callback1;
4595 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4596 EXPECT_EQ(ERR_IO_PENDING, rv);
4598 rv = callback1.WaitForResult();
4599 EXPECT_EQ(OK, rv);
4601 const HttpResponseInfo* response = trans->GetResponseInfo();
4602 ASSERT_TRUE(response != NULL);
4603 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4605 TestCompletionCallback callback2;
4607 rv = trans->RestartWithAuth(
4608 AuthCredentials(kFoo, kBar), callback2.callback());
4609 EXPECT_EQ(ERR_IO_PENDING, rv);
4611 rv = callback2.WaitForResult();
4612 EXPECT_EQ(OK, rv);
4614 response = trans->GetResponseInfo();
4615 ASSERT_TRUE(response != NULL);
4616 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4618 TestCompletionCallback callback3;
4620 rv = trans->RestartWithAuth(
4621 AuthCredentials(kFoo2, kBar2), callback3.callback());
4622 EXPECT_EQ(ERR_IO_PENDING, rv);
4624 rv = callback3.WaitForResult();
4625 EXPECT_EQ(OK, rv);
4627 response = trans->GetResponseInfo();
4628 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4629 EXPECT_EQ(100, response->headers->GetContentLength());
4632 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4633 // can't hook into its internals to cause it to generate predictable NTLM
4634 // authorization headers.
4635 #if defined(NTLM_PORTABLE)
4636 // The NTLM authentication unit tests were generated by capturing the HTTP
4637 // requests and responses using Fiddler 2 and inspecting the generated random
4638 // bytes in the debugger.
4640 // Enter the correct password and authenticate successfully.
4641 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4642 HttpRequestInfo request;
4643 request.method = "GET";
4644 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4646 // Ensure load is not disrupted by flags which suppress behaviour specific
4647 // to other auth schemes.
4648 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4650 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4651 MockGetHostName);
4652 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4654 MockWrite data_writes1[] = {
4655 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4656 "Host: 172.22.68.17\r\n"
4657 "Connection: keep-alive\r\n\r\n"),
4660 MockRead data_reads1[] = {
4661 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4662 // Negotiate and NTLM are often requested together. However, we only want
4663 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4664 // the header that requests Negotiate for this test.
4665 MockRead("WWW-Authenticate: NTLM\r\n"),
4666 MockRead("Connection: close\r\n"),
4667 MockRead("Content-Length: 42\r\n"),
4668 MockRead("Content-Type: text/html\r\n\r\n"),
4669 // Missing content -- won't matter, as connection will be reset.
4670 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4673 MockWrite data_writes2[] = {
4674 // After restarting with a null identity, this is the
4675 // request we should be issuing -- the final header line contains a Type
4676 // 1 message.
4677 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4678 "Host: 172.22.68.17\r\n"
4679 "Connection: keep-alive\r\n"
4680 "Authorization: NTLM "
4681 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4683 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4684 // (the credentials for the origin server). The second request continues
4685 // on the same connection.
4686 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4687 "Host: 172.22.68.17\r\n"
4688 "Connection: keep-alive\r\n"
4689 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4690 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4691 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4692 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4693 "ahlhx5I=\r\n\r\n"),
4696 MockRead data_reads2[] = {
4697 // The origin server responds with a Type 2 message.
4698 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4699 MockRead("WWW-Authenticate: NTLM "
4700 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4701 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4702 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4703 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4704 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4705 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4706 "BtAAAAAAA=\r\n"),
4707 MockRead("Content-Length: 42\r\n"),
4708 MockRead("Content-Type: text/html\r\n\r\n"),
4709 MockRead("You are not authorized to view this page\r\n"),
4711 // Lastly we get the desired content.
4712 MockRead("HTTP/1.1 200 OK\r\n"),
4713 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4714 MockRead("Content-Length: 13\r\n\r\n"),
4715 MockRead("Please Login\r\n"),
4716 MockRead(SYNCHRONOUS, OK),
4719 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4720 data_writes1, arraysize(data_writes1));
4721 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4722 data_writes2, arraysize(data_writes2));
4723 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4724 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4726 TestCompletionCallback callback1;
4728 scoped_ptr<HttpTransaction> trans(
4729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4731 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4732 EXPECT_EQ(ERR_IO_PENDING, rv);
4734 rv = callback1.WaitForResult();
4735 EXPECT_EQ(OK, rv);
4737 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4739 const HttpResponseInfo* response = trans->GetResponseInfo();
4740 ASSERT_FALSE(response == NULL);
4741 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4743 TestCompletionCallback callback2;
4745 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4746 callback2.callback());
4747 EXPECT_EQ(ERR_IO_PENDING, rv);
4749 rv = callback2.WaitForResult();
4750 EXPECT_EQ(OK, rv);
4752 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4754 response = trans->GetResponseInfo();
4755 ASSERT_TRUE(response != NULL);
4756 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4758 TestCompletionCallback callback3;
4760 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4761 EXPECT_EQ(ERR_IO_PENDING, rv);
4763 rv = callback3.WaitForResult();
4764 EXPECT_EQ(OK, rv);
4766 response = trans->GetResponseInfo();
4767 ASSERT_TRUE(response != NULL);
4768 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4769 EXPECT_EQ(13, response->headers->GetContentLength());
4772 // Enter a wrong password, and then the correct one.
4773 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4774 HttpRequestInfo request;
4775 request.method = "GET";
4776 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4777 request.load_flags = 0;
4779 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4780 MockGetHostName);
4781 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4783 MockWrite data_writes1[] = {
4784 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4785 "Host: 172.22.68.17\r\n"
4786 "Connection: keep-alive\r\n\r\n"),
4789 MockRead data_reads1[] = {
4790 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4791 // Negotiate and NTLM are often requested together. However, we only want
4792 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4793 // the header that requests Negotiate for this test.
4794 MockRead("WWW-Authenticate: NTLM\r\n"),
4795 MockRead("Connection: close\r\n"),
4796 MockRead("Content-Length: 42\r\n"),
4797 MockRead("Content-Type: text/html\r\n\r\n"),
4798 // Missing content -- won't matter, as connection will be reset.
4799 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4802 MockWrite data_writes2[] = {
4803 // After restarting with a null identity, this is the
4804 // request we should be issuing -- the final header line contains a Type
4805 // 1 message.
4806 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4807 "Host: 172.22.68.17\r\n"
4808 "Connection: keep-alive\r\n"
4809 "Authorization: NTLM "
4810 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4812 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4813 // (the credentials for the origin server). The second request continues
4814 // on the same connection.
4815 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4816 "Host: 172.22.68.17\r\n"
4817 "Connection: keep-alive\r\n"
4818 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4819 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4820 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4821 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4822 "4Ww7b7E=\r\n\r\n"),
4825 MockRead data_reads2[] = {
4826 // The origin server responds with a Type 2 message.
4827 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4828 MockRead("WWW-Authenticate: NTLM "
4829 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4830 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4831 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4832 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4833 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4834 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4835 "BtAAAAAAA=\r\n"),
4836 MockRead("Content-Length: 42\r\n"),
4837 MockRead("Content-Type: text/html\r\n\r\n"),
4838 MockRead("You are not authorized to view this page\r\n"),
4840 // Wrong password.
4841 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4842 MockRead("WWW-Authenticate: NTLM\r\n"),
4843 MockRead("Connection: close\r\n"),
4844 MockRead("Content-Length: 42\r\n"),
4845 MockRead("Content-Type: text/html\r\n\r\n"),
4846 // Missing content -- won't matter, as connection will be reset.
4847 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4850 MockWrite data_writes3[] = {
4851 // After restarting with a null identity, this is the
4852 // request we should be issuing -- the final header line contains a Type
4853 // 1 message.
4854 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4855 "Host: 172.22.68.17\r\n"
4856 "Connection: keep-alive\r\n"
4857 "Authorization: NTLM "
4858 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4860 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4861 // (the credentials for the origin server). The second request continues
4862 // on the same connection.
4863 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4864 "Host: 172.22.68.17\r\n"
4865 "Connection: keep-alive\r\n"
4866 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4867 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4868 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4869 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4870 "+4MUm7c=\r\n\r\n"),
4873 MockRead data_reads3[] = {
4874 // The origin server responds with a Type 2 message.
4875 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4876 MockRead("WWW-Authenticate: NTLM "
4877 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4878 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4879 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4880 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4881 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4882 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4883 "BtAAAAAAA=\r\n"),
4884 MockRead("Content-Length: 42\r\n"),
4885 MockRead("Content-Type: text/html\r\n\r\n"),
4886 MockRead("You are not authorized to view this page\r\n"),
4888 // Lastly we get the desired content.
4889 MockRead("HTTP/1.1 200 OK\r\n"),
4890 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4891 MockRead("Content-Length: 13\r\n\r\n"),
4892 MockRead("Please Login\r\n"),
4893 MockRead(SYNCHRONOUS, OK),
4896 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4897 data_writes1, arraysize(data_writes1));
4898 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4899 data_writes2, arraysize(data_writes2));
4900 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4901 data_writes3, arraysize(data_writes3));
4902 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4903 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4904 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4906 TestCompletionCallback callback1;
4908 scoped_ptr<HttpTransaction> trans(
4909 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4911 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4912 EXPECT_EQ(ERR_IO_PENDING, rv);
4914 rv = callback1.WaitForResult();
4915 EXPECT_EQ(OK, rv);
4917 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4919 const HttpResponseInfo* response = trans->GetResponseInfo();
4920 ASSERT_TRUE(response != NULL);
4921 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4923 TestCompletionCallback callback2;
4925 // Enter the wrong password.
4926 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4927 callback2.callback());
4928 EXPECT_EQ(ERR_IO_PENDING, rv);
4930 rv = callback2.WaitForResult();
4931 EXPECT_EQ(OK, rv);
4933 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4934 TestCompletionCallback callback3;
4935 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4936 EXPECT_EQ(ERR_IO_PENDING, rv);
4937 rv = callback3.WaitForResult();
4938 EXPECT_EQ(OK, rv);
4939 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4941 response = trans->GetResponseInfo();
4942 ASSERT_FALSE(response == NULL);
4943 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4945 TestCompletionCallback callback4;
4947 // Now enter the right password.
4948 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4949 callback4.callback());
4950 EXPECT_EQ(ERR_IO_PENDING, rv);
4952 rv = callback4.WaitForResult();
4953 EXPECT_EQ(OK, rv);
4955 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4957 TestCompletionCallback callback5;
4959 // One more roundtrip
4960 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4961 EXPECT_EQ(ERR_IO_PENDING, rv);
4963 rv = callback5.WaitForResult();
4964 EXPECT_EQ(OK, rv);
4966 response = trans->GetResponseInfo();
4967 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4968 EXPECT_EQ(13, response->headers->GetContentLength());
4970 #endif // NTLM_PORTABLE
4972 // Test reading a server response which has only headers, and no body.
4973 // After some maximum number of bytes is consumed, the transaction should
4974 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4975 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4976 HttpRequestInfo request;
4977 request.method = "GET";
4978 request.url = GURL("http://www.example.org/");
4979 request.load_flags = 0;
4981 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4982 scoped_ptr<HttpTransaction> trans(
4983 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4985 // Respond with 300 kb of headers (we should fail after 256 kb).
4986 std::string large_headers_string;
4987 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4989 MockRead data_reads[] = {
4990 MockRead("HTTP/1.0 200 OK\r\n"),
4991 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4992 MockRead("\r\nBODY"),
4993 MockRead(SYNCHRONOUS, OK),
4995 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4996 session_deps_.socket_factory->AddSocketDataProvider(&data);
4998 TestCompletionCallback callback;
5000 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5001 EXPECT_EQ(ERR_IO_PENDING, rv);
5003 rv = callback.WaitForResult();
5004 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
5007 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5008 // establish tunnel.
5009 // http://code.google.com/p/chromium/issues/detail?id=3772
5010 TEST_P(HttpNetworkTransactionTest,
5011 DontRecycleTransportSocketForSSLTunnel) {
5012 HttpRequestInfo request;
5013 request.method = "GET";
5014 request.url = GURL("https://www.example.org/");
5015 request.load_flags = 0;
5017 // Configure against proxy server "myproxy:70".
5018 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5020 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5022 scoped_ptr<HttpTransaction> trans(
5023 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5025 // Since we have proxy, should try to establish tunnel.
5026 MockWrite data_writes1[] = {
5027 MockWrite(
5028 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5029 "Host: www.example.org\r\n"
5030 "Proxy-Connection: keep-alive\r\n\r\n"),
5033 // The proxy responds to the connect with a 404, using a persistent
5034 // connection. Usually a proxy would return 501 (not implemented),
5035 // or 200 (tunnel established).
5036 MockRead data_reads1[] = {
5037 MockRead("HTTP/1.1 404 Not Found\r\n"),
5038 MockRead("Content-Length: 10\r\n\r\n"),
5039 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
5042 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5043 data_writes1, arraysize(data_writes1));
5044 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5046 TestCompletionCallback callback1;
5048 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5049 EXPECT_EQ(ERR_IO_PENDING, rv);
5051 rv = callback1.WaitForResult();
5052 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5054 // Empty the current queue. This is necessary because idle sockets are
5055 // added to the connection pool asynchronously with a PostTask.
5056 base::MessageLoop::current()->RunUntilIdle();
5058 // We now check to make sure the TCPClientSocket was not added back to
5059 // the pool.
5060 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5061 trans.reset();
5062 base::MessageLoop::current()->RunUntilIdle();
5063 // Make sure that the socket didn't get recycled after calling the destructor.
5064 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5067 // Make sure that we recycle a socket after reading all of the response body.
5068 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
5069 HttpRequestInfo request;
5070 request.method = "GET";
5071 request.url = GURL("http://www.example.org/");
5072 request.load_flags = 0;
5074 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5076 scoped_ptr<HttpTransaction> trans(
5077 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5079 MockRead data_reads[] = {
5080 // A part of the response body is received with the response headers.
5081 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5082 // The rest of the response body is received in two parts.
5083 MockRead("lo"),
5084 MockRead(" world"),
5085 MockRead("junk"), // Should not be read!!
5086 MockRead(SYNCHRONOUS, OK),
5089 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5090 session_deps_.socket_factory->AddSocketDataProvider(&data);
5092 TestCompletionCallback callback;
5094 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5095 EXPECT_EQ(ERR_IO_PENDING, rv);
5097 rv = callback.WaitForResult();
5098 EXPECT_EQ(OK, rv);
5100 const HttpResponseInfo* response = trans->GetResponseInfo();
5101 ASSERT_TRUE(response != NULL);
5103 EXPECT_TRUE(response->headers.get() != NULL);
5104 std::string status_line = response->headers->GetStatusLine();
5105 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5107 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5109 std::string response_data;
5110 rv = ReadTransaction(trans.get(), &response_data);
5111 EXPECT_EQ(OK, rv);
5112 EXPECT_EQ("hello world", response_data);
5114 // Empty the current queue. This is necessary because idle sockets are
5115 // added to the connection pool asynchronously with a PostTask.
5116 base::MessageLoop::current()->RunUntilIdle();
5118 // We now check to make sure the socket was added back to the pool.
5119 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5122 // Make sure that we recycle a SSL socket after reading all of the response
5123 // body.
5124 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
5125 HttpRequestInfo request;
5126 request.method = "GET";
5127 request.url = GURL("https://www.example.org/");
5128 request.load_flags = 0;
5130 MockWrite data_writes[] = {
5131 MockWrite(
5132 "GET / HTTP/1.1\r\n"
5133 "Host: www.example.org\r\n"
5134 "Connection: keep-alive\r\n\r\n"),
5137 MockRead data_reads[] = {
5138 MockRead("HTTP/1.1 200 OK\r\n"),
5139 MockRead("Content-Length: 11\r\n\r\n"),
5140 MockRead("hello world"),
5141 MockRead(SYNCHRONOUS, OK),
5144 SSLSocketDataProvider ssl(ASYNC, OK);
5145 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5147 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5148 data_writes, arraysize(data_writes));
5149 session_deps_.socket_factory->AddSocketDataProvider(&data);
5151 TestCompletionCallback callback;
5153 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5154 scoped_ptr<HttpTransaction> trans(
5155 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5157 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5159 EXPECT_EQ(ERR_IO_PENDING, rv);
5160 EXPECT_EQ(OK, callback.WaitForResult());
5162 const HttpResponseInfo* response = trans->GetResponseInfo();
5163 ASSERT_TRUE(response != NULL);
5164 ASSERT_TRUE(response->headers.get() != NULL);
5165 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5167 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5169 std::string response_data;
5170 rv = ReadTransaction(trans.get(), &response_data);
5171 EXPECT_EQ(OK, rv);
5172 EXPECT_EQ("hello world", response_data);
5174 // Empty the current queue. This is necessary because idle sockets are
5175 // added to the connection pool asynchronously with a PostTask.
5176 base::MessageLoop::current()->RunUntilIdle();
5178 // We now check to make sure the socket was added back to the pool.
5179 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5182 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5183 // from the pool and make sure that we recover okay.
5184 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
5185 HttpRequestInfo request;
5186 request.method = "GET";
5187 request.url = GURL("https://www.example.org/");
5188 request.load_flags = 0;
5190 MockWrite data_writes[] = {
5191 MockWrite(
5192 "GET / HTTP/1.1\r\n"
5193 "Host: www.example.org\r\n"
5194 "Connection: keep-alive\r\n\r\n"),
5195 MockWrite(
5196 "GET / HTTP/1.1\r\n"
5197 "Host: www.example.org\r\n"
5198 "Connection: keep-alive\r\n\r\n"),
5201 MockRead data_reads[] = {
5202 MockRead("HTTP/1.1 200 OK\r\n"),
5203 MockRead("Content-Length: 11\r\n\r\n"),
5204 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
5205 MockRead("hello world"),
5206 MockRead(ASYNC, 0, 0) // EOF
5209 SSLSocketDataProvider ssl(ASYNC, OK);
5210 SSLSocketDataProvider ssl2(ASYNC, OK);
5211 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5212 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5214 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5215 data_writes, arraysize(data_writes));
5216 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5217 data_writes, arraysize(data_writes));
5218 session_deps_.socket_factory->AddSocketDataProvider(&data);
5219 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5221 TestCompletionCallback callback;
5223 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5224 scoped_ptr<HttpTransaction> trans(
5225 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5227 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5229 EXPECT_EQ(ERR_IO_PENDING, rv);
5230 EXPECT_EQ(OK, callback.WaitForResult());
5232 const HttpResponseInfo* response = trans->GetResponseInfo();
5233 ASSERT_TRUE(response != NULL);
5234 ASSERT_TRUE(response->headers.get() != NULL);
5235 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5237 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5239 std::string response_data;
5240 rv = ReadTransaction(trans.get(), &response_data);
5241 EXPECT_EQ(OK, rv);
5242 EXPECT_EQ("hello world", response_data);
5244 // Empty the current queue. This is necessary because idle sockets are
5245 // added to the connection pool asynchronously with a PostTask.
5246 base::MessageLoop::current()->RunUntilIdle();
5248 // We now check to make sure the socket was added back to the pool.
5249 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5251 // Now start the second transaction, which should reuse the previous socket.
5253 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5255 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5257 EXPECT_EQ(ERR_IO_PENDING, rv);
5258 EXPECT_EQ(OK, callback.WaitForResult());
5260 response = trans->GetResponseInfo();
5261 ASSERT_TRUE(response != NULL);
5262 ASSERT_TRUE(response->headers.get() != NULL);
5263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5265 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5267 rv = ReadTransaction(trans.get(), &response_data);
5268 EXPECT_EQ(OK, rv);
5269 EXPECT_EQ("hello world", response_data);
5271 // Empty the current queue. This is necessary because idle sockets are
5272 // added to the connection pool asynchronously with a PostTask.
5273 base::MessageLoop::current()->RunUntilIdle();
5275 // We now check to make sure the socket was added back to the pool.
5276 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5279 // Make sure that we recycle a socket after a zero-length response.
5280 // http://crbug.com/9880
5281 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
5282 HttpRequestInfo request;
5283 request.method = "GET";
5284 request.url = GURL(
5285 "http://www.example.org/csi?v=3&s=web&action=&"
5286 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5287 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5288 "rt=prt.2642,ol.2649,xjs.2951");
5289 request.load_flags = 0;
5291 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5293 scoped_ptr<HttpTransaction> trans(
5294 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5296 MockRead data_reads[] = {
5297 MockRead("HTTP/1.1 204 No Content\r\n"
5298 "Content-Length: 0\r\n"
5299 "Content-Type: text/html\r\n\r\n"),
5300 MockRead("junk"), // Should not be read!!
5301 MockRead(SYNCHRONOUS, OK),
5304 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5305 session_deps_.socket_factory->AddSocketDataProvider(&data);
5307 TestCompletionCallback callback;
5309 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5310 EXPECT_EQ(ERR_IO_PENDING, rv);
5312 rv = callback.WaitForResult();
5313 EXPECT_EQ(OK, rv);
5315 const HttpResponseInfo* response = trans->GetResponseInfo();
5316 ASSERT_TRUE(response != NULL);
5318 EXPECT_TRUE(response->headers.get() != NULL);
5319 std::string status_line = response->headers->GetStatusLine();
5320 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5322 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5324 std::string response_data;
5325 rv = ReadTransaction(trans.get(), &response_data);
5326 EXPECT_EQ(OK, rv);
5327 EXPECT_EQ("", response_data);
5329 // Empty the current queue. This is necessary because idle sockets are
5330 // added to the connection pool asynchronously with a PostTask.
5331 base::MessageLoop::current()->RunUntilIdle();
5333 // We now check to make sure the socket was added back to the pool.
5334 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5337 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5338 ScopedVector<UploadElementReader> element_readers;
5339 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5340 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
5342 HttpRequestInfo request[2];
5343 // Transaction 1: a GET request that succeeds. The socket is recycled
5344 // after use.
5345 request[0].method = "GET";
5346 request[0].url = GURL("http://www.google.com/");
5347 request[0].load_flags = 0;
5348 // Transaction 2: a POST request. Reuses the socket kept alive from
5349 // transaction 1. The first attempts fails when writing the POST data.
5350 // This causes the transaction to retry with a new socket. The second
5351 // attempt succeeds.
5352 request[1].method = "POST";
5353 request[1].url = GURL("http://www.google.com/login.cgi");
5354 request[1].upload_data_stream = &upload_data_stream;
5355 request[1].load_flags = 0;
5357 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5359 // The first socket is used for transaction 1 and the first attempt of
5360 // transaction 2.
5362 // The response of transaction 1.
5363 MockRead data_reads1[] = {
5364 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5365 MockRead("hello world"),
5366 MockRead(SYNCHRONOUS, OK),
5368 // The mock write results of transaction 1 and the first attempt of
5369 // transaction 2.
5370 MockWrite data_writes1[] = {
5371 MockWrite(SYNCHRONOUS, 64), // GET
5372 MockWrite(SYNCHRONOUS, 93), // POST
5373 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5375 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5376 data_writes1, arraysize(data_writes1));
5378 // The second socket is used for the second attempt of transaction 2.
5380 // The response of transaction 2.
5381 MockRead data_reads2[] = {
5382 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5383 MockRead("welcome"),
5384 MockRead(SYNCHRONOUS, OK),
5386 // The mock write results of the second attempt of transaction 2.
5387 MockWrite data_writes2[] = {
5388 MockWrite(SYNCHRONOUS, 93), // POST
5389 MockWrite(SYNCHRONOUS, 3), // POST data
5391 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5392 data_writes2, arraysize(data_writes2));
5394 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5395 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5397 const char* const kExpectedResponseData[] = {
5398 "hello world", "welcome"
5401 for (int i = 0; i < 2; ++i) {
5402 scoped_ptr<HttpTransaction> trans(
5403 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5405 TestCompletionCallback callback;
5407 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5408 EXPECT_EQ(ERR_IO_PENDING, rv);
5410 rv = callback.WaitForResult();
5411 EXPECT_EQ(OK, rv);
5413 const HttpResponseInfo* response = trans->GetResponseInfo();
5414 ASSERT_TRUE(response != NULL);
5416 EXPECT_TRUE(response->headers.get() != NULL);
5417 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5419 std::string response_data;
5420 rv = ReadTransaction(trans.get(), &response_data);
5421 EXPECT_EQ(OK, rv);
5422 EXPECT_EQ(kExpectedResponseData[i], response_data);
5426 // Test the request-challenge-retry sequence for basic auth when there is
5427 // an identity in the URL. The request should be sent as normal, but when
5428 // it fails the identity from the URL is used to answer the challenge.
5429 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5430 HttpRequestInfo request;
5431 request.method = "GET";
5432 request.url = GURL("http://foo:b@r@www.example.org/");
5433 request.load_flags = LOAD_NORMAL;
5435 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5436 scoped_ptr<HttpTransaction> trans(
5437 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5439 // The password contains an escaped character -- for this test to pass it
5440 // will need to be unescaped by HttpNetworkTransaction.
5441 EXPECT_EQ("b%40r", request.url.password());
5443 MockWrite data_writes1[] = {
5444 MockWrite(
5445 "GET / HTTP/1.1\r\n"
5446 "Host: www.example.org\r\n"
5447 "Connection: keep-alive\r\n\r\n"),
5450 MockRead data_reads1[] = {
5451 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5452 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5453 MockRead("Content-Length: 10\r\n\r\n"),
5454 MockRead(SYNCHRONOUS, ERR_FAILED),
5457 // After the challenge above, the transaction will be restarted using the
5458 // identity from the url (foo, b@r) to answer the challenge.
5459 MockWrite data_writes2[] = {
5460 MockWrite(
5461 "GET / HTTP/1.1\r\n"
5462 "Host: www.example.org\r\n"
5463 "Connection: keep-alive\r\n"
5464 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5467 MockRead data_reads2[] = {
5468 MockRead("HTTP/1.0 200 OK\r\n"),
5469 MockRead("Content-Length: 100\r\n\r\n"),
5470 MockRead(SYNCHRONOUS, OK),
5473 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5474 data_writes1, arraysize(data_writes1));
5475 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5476 data_writes2, arraysize(data_writes2));
5477 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5478 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5480 TestCompletionCallback callback1;
5481 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5482 EXPECT_EQ(ERR_IO_PENDING, rv);
5483 rv = callback1.WaitForResult();
5484 EXPECT_EQ(OK, rv);
5485 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5487 TestCompletionCallback callback2;
5488 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5489 EXPECT_EQ(ERR_IO_PENDING, rv);
5490 rv = callback2.WaitForResult();
5491 EXPECT_EQ(OK, rv);
5492 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5494 const HttpResponseInfo* response = trans->GetResponseInfo();
5495 ASSERT_TRUE(response != NULL);
5497 // There is no challenge info, since the identity in URL worked.
5498 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5500 EXPECT_EQ(100, response->headers->GetContentLength());
5502 // Empty the current queue.
5503 base::MessageLoop::current()->RunUntilIdle();
5506 // Test the request-challenge-retry sequence for basic auth when there is an
5507 // incorrect identity in the URL. The identity from the URL should be used only
5508 // once.
5509 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5510 HttpRequestInfo request;
5511 request.method = "GET";
5512 // Note: the URL has a username:password in it. The password "baz" is
5513 // wrong (should be "bar").
5514 request.url = GURL("http://foo:baz@www.example.org/");
5516 request.load_flags = LOAD_NORMAL;
5518 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5519 scoped_ptr<HttpTransaction> trans(
5520 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5522 MockWrite data_writes1[] = {
5523 MockWrite(
5524 "GET / HTTP/1.1\r\n"
5525 "Host: www.example.org\r\n"
5526 "Connection: keep-alive\r\n\r\n"),
5529 MockRead data_reads1[] = {
5530 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5531 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5532 MockRead("Content-Length: 10\r\n\r\n"),
5533 MockRead(SYNCHRONOUS, ERR_FAILED),
5536 // After the challenge above, the transaction will be restarted using the
5537 // identity from the url (foo, baz) to answer the challenge.
5538 MockWrite data_writes2[] = {
5539 MockWrite(
5540 "GET / HTTP/1.1\r\n"
5541 "Host: www.example.org\r\n"
5542 "Connection: keep-alive\r\n"
5543 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5546 MockRead data_reads2[] = {
5547 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5548 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5549 MockRead("Content-Length: 10\r\n\r\n"),
5550 MockRead(SYNCHRONOUS, ERR_FAILED),
5553 // After the challenge above, the transaction will be restarted using the
5554 // identity supplied by the user (foo, bar) to answer the challenge.
5555 MockWrite data_writes3[] = {
5556 MockWrite(
5557 "GET / HTTP/1.1\r\n"
5558 "Host: www.example.org\r\n"
5559 "Connection: keep-alive\r\n"
5560 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5563 MockRead data_reads3[] = {
5564 MockRead("HTTP/1.0 200 OK\r\n"),
5565 MockRead("Content-Length: 100\r\n\r\n"),
5566 MockRead(SYNCHRONOUS, OK),
5569 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5570 data_writes1, arraysize(data_writes1));
5571 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5572 data_writes2, arraysize(data_writes2));
5573 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5574 data_writes3, arraysize(data_writes3));
5575 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5576 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5577 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5579 TestCompletionCallback callback1;
5581 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5582 EXPECT_EQ(ERR_IO_PENDING, rv);
5584 rv = callback1.WaitForResult();
5585 EXPECT_EQ(OK, rv);
5587 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5588 TestCompletionCallback callback2;
5589 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5590 EXPECT_EQ(ERR_IO_PENDING, rv);
5591 rv = callback2.WaitForResult();
5592 EXPECT_EQ(OK, rv);
5593 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5595 const HttpResponseInfo* response = trans->GetResponseInfo();
5596 ASSERT_TRUE(response != NULL);
5597 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5599 TestCompletionCallback callback3;
5600 rv = trans->RestartWithAuth(
5601 AuthCredentials(kFoo, kBar), callback3.callback());
5602 EXPECT_EQ(ERR_IO_PENDING, rv);
5603 rv = callback3.WaitForResult();
5604 EXPECT_EQ(OK, rv);
5605 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5607 response = trans->GetResponseInfo();
5608 ASSERT_TRUE(response != NULL);
5610 // There is no challenge info, since the identity worked.
5611 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5613 EXPECT_EQ(100, response->headers->GetContentLength());
5615 // Empty the current queue.
5616 base::MessageLoop::current()->RunUntilIdle();
5620 // Test the request-challenge-retry sequence for basic auth when there is a
5621 // correct identity in the URL, but its use is being suppressed. The identity
5622 // from the URL should never be used.
5623 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5624 HttpRequestInfo request;
5625 request.method = "GET";
5626 request.url = GURL("http://foo:bar@www.example.org/");
5627 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5629 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5630 scoped_ptr<HttpTransaction> trans(
5631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5633 MockWrite data_writes1[] = {
5634 MockWrite(
5635 "GET / HTTP/1.1\r\n"
5636 "Host: www.example.org\r\n"
5637 "Connection: keep-alive\r\n\r\n"),
5640 MockRead data_reads1[] = {
5641 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5642 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5643 MockRead("Content-Length: 10\r\n\r\n"),
5644 MockRead(SYNCHRONOUS, ERR_FAILED),
5647 // After the challenge above, the transaction will be restarted using the
5648 // identity supplied by the user, not the one in the URL, to answer the
5649 // challenge.
5650 MockWrite data_writes3[] = {
5651 MockWrite(
5652 "GET / HTTP/1.1\r\n"
5653 "Host: www.example.org\r\n"
5654 "Connection: keep-alive\r\n"
5655 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5658 MockRead data_reads3[] = {
5659 MockRead("HTTP/1.0 200 OK\r\n"),
5660 MockRead("Content-Length: 100\r\n\r\n"),
5661 MockRead(SYNCHRONOUS, OK),
5664 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5665 data_writes1, arraysize(data_writes1));
5666 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5667 data_writes3, arraysize(data_writes3));
5668 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5669 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5671 TestCompletionCallback callback1;
5672 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5673 EXPECT_EQ(ERR_IO_PENDING, rv);
5674 rv = callback1.WaitForResult();
5675 EXPECT_EQ(OK, rv);
5676 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5678 const HttpResponseInfo* response = trans->GetResponseInfo();
5679 ASSERT_TRUE(response != NULL);
5680 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5682 TestCompletionCallback callback3;
5683 rv = trans->RestartWithAuth(
5684 AuthCredentials(kFoo, kBar), callback3.callback());
5685 EXPECT_EQ(ERR_IO_PENDING, rv);
5686 rv = callback3.WaitForResult();
5687 EXPECT_EQ(OK, rv);
5688 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5690 response = trans->GetResponseInfo();
5691 ASSERT_TRUE(response != NULL);
5693 // There is no challenge info, since the identity worked.
5694 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5695 EXPECT_EQ(100, response->headers->GetContentLength());
5697 // Empty the current queue.
5698 base::MessageLoop::current()->RunUntilIdle();
5701 // Test that previously tried username/passwords for a realm get re-used.
5702 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5703 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5705 // Transaction 1: authenticate (foo, bar) on MyRealm1
5707 HttpRequestInfo request;
5708 request.method = "GET";
5709 request.url = GURL("http://www.example.org/x/y/z");
5710 request.load_flags = 0;
5712 scoped_ptr<HttpTransaction> trans(
5713 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5715 MockWrite data_writes1[] = {
5716 MockWrite(
5717 "GET /x/y/z HTTP/1.1\r\n"
5718 "Host: www.example.org\r\n"
5719 "Connection: keep-alive\r\n\r\n"),
5722 MockRead data_reads1[] = {
5723 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5724 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5725 MockRead("Content-Length: 10000\r\n\r\n"),
5726 MockRead(SYNCHRONOUS, ERR_FAILED),
5729 // Resend with authorization (username=foo, password=bar)
5730 MockWrite data_writes2[] = {
5731 MockWrite(
5732 "GET /x/y/z HTTP/1.1\r\n"
5733 "Host: www.example.org\r\n"
5734 "Connection: keep-alive\r\n"
5735 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5738 // Sever accepts the authorization.
5739 MockRead data_reads2[] = {
5740 MockRead("HTTP/1.0 200 OK\r\n"),
5741 MockRead("Content-Length: 100\r\n\r\n"),
5742 MockRead(SYNCHRONOUS, OK),
5745 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5746 data_writes1, arraysize(data_writes1));
5747 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5748 data_writes2, arraysize(data_writes2));
5749 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5750 session_deps_.socket_factory->AddSocketDataProvider(&data2);
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(CheckBasicServerAuth(response->auth_challenge.get()));
5764 TestCompletionCallback callback2;
5766 rv = trans->RestartWithAuth(
5767 AuthCredentials(kFoo, kBar), callback2.callback());
5768 EXPECT_EQ(ERR_IO_PENDING, rv);
5770 rv = callback2.WaitForResult();
5771 EXPECT_EQ(OK, rv);
5773 response = trans->GetResponseInfo();
5774 ASSERT_TRUE(response != NULL);
5775 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5776 EXPECT_EQ(100, response->headers->GetContentLength());
5779 // ------------------------------------------------------------------------
5781 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5783 HttpRequestInfo request;
5784 request.method = "GET";
5785 // Note that Transaction 1 was at /x/y/z, so this is in the same
5786 // protection space as MyRealm1.
5787 request.url = GURL("http://www.example.org/x/y/a/b");
5788 request.load_flags = 0;
5790 scoped_ptr<HttpTransaction> trans(
5791 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5793 MockWrite data_writes1[] = {
5794 MockWrite(
5795 "GET /x/y/a/b HTTP/1.1\r\n"
5796 "Host: www.example.org\r\n"
5797 "Connection: keep-alive\r\n"
5798 // Send preemptive authorization for MyRealm1
5799 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5802 // The server didn't like the preemptive authorization, and
5803 // challenges us for a different realm (MyRealm2).
5804 MockRead data_reads1[] = {
5805 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5806 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5807 MockRead("Content-Length: 10000\r\n\r\n"),
5808 MockRead(SYNCHRONOUS, ERR_FAILED),
5811 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5812 MockWrite data_writes2[] = {
5813 MockWrite(
5814 "GET /x/y/a/b HTTP/1.1\r\n"
5815 "Host: www.example.org\r\n"
5816 "Connection: keep-alive\r\n"
5817 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5820 // Sever accepts the authorization.
5821 MockRead data_reads2[] = {
5822 MockRead("HTTP/1.0 200 OK\r\n"),
5823 MockRead("Content-Length: 100\r\n\r\n"),
5824 MockRead(SYNCHRONOUS, OK),
5827 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5828 data_writes1, arraysize(data_writes1));
5829 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5830 data_writes2, arraysize(data_writes2));
5831 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5832 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5834 TestCompletionCallback callback1;
5836 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5837 EXPECT_EQ(ERR_IO_PENDING, rv);
5839 rv = callback1.WaitForResult();
5840 EXPECT_EQ(OK, rv);
5842 const HttpResponseInfo* response = trans->GetResponseInfo();
5843 ASSERT_TRUE(response != NULL);
5844 ASSERT_TRUE(response->auth_challenge.get());
5845 EXPECT_FALSE(response->auth_challenge->is_proxy);
5846 EXPECT_EQ("www.example.org:80",
5847 response->auth_challenge->challenger.ToString());
5848 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5849 EXPECT_EQ("basic", response->auth_challenge->scheme);
5851 TestCompletionCallback callback2;
5853 rv = trans->RestartWithAuth(
5854 AuthCredentials(kFoo2, kBar2), callback2.callback());
5855 EXPECT_EQ(ERR_IO_PENDING, rv);
5857 rv = callback2.WaitForResult();
5858 EXPECT_EQ(OK, rv);
5860 response = trans->GetResponseInfo();
5861 ASSERT_TRUE(response != NULL);
5862 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5863 EXPECT_EQ(100, response->headers->GetContentLength());
5866 // ------------------------------------------------------------------------
5868 // Transaction 3: Resend a request in MyRealm's protection space --
5869 // succeed with preemptive authorization.
5871 HttpRequestInfo request;
5872 request.method = "GET";
5873 request.url = GURL("http://www.example.org/x/y/z2");
5874 request.load_flags = 0;
5876 scoped_ptr<HttpTransaction> trans(
5877 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5879 MockWrite data_writes1[] = {
5880 MockWrite(
5881 "GET /x/y/z2 HTTP/1.1\r\n"
5882 "Host: www.example.org\r\n"
5883 "Connection: keep-alive\r\n"
5884 // The authorization for MyRealm1 gets sent preemptively
5885 // (since the url is in the same protection space)
5886 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5889 // Sever accepts the preemptive authorization
5890 MockRead data_reads1[] = {
5891 MockRead("HTTP/1.0 200 OK\r\n"),
5892 MockRead("Content-Length: 100\r\n\r\n"),
5893 MockRead(SYNCHRONOUS, OK),
5896 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5897 data_writes1, arraysize(data_writes1));
5898 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5900 TestCompletionCallback callback1;
5902 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5903 EXPECT_EQ(ERR_IO_PENDING, rv);
5905 rv = callback1.WaitForResult();
5906 EXPECT_EQ(OK, rv);
5908 const HttpResponseInfo* response = trans->GetResponseInfo();
5909 ASSERT_TRUE(response != NULL);
5911 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5912 EXPECT_EQ(100, response->headers->GetContentLength());
5915 // ------------------------------------------------------------------------
5917 // Transaction 4: request another URL in MyRealm (however the
5918 // url is not known to belong to the protection space, so no pre-auth).
5920 HttpRequestInfo request;
5921 request.method = "GET";
5922 request.url = GURL("http://www.example.org/x/1");
5923 request.load_flags = 0;
5925 scoped_ptr<HttpTransaction> trans(
5926 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5928 MockWrite data_writes1[] = {
5929 MockWrite(
5930 "GET /x/1 HTTP/1.1\r\n"
5931 "Host: www.example.org\r\n"
5932 "Connection: keep-alive\r\n\r\n"),
5935 MockRead data_reads1[] = {
5936 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5937 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5938 MockRead("Content-Length: 10000\r\n\r\n"),
5939 MockRead(SYNCHRONOUS, ERR_FAILED),
5942 // Resend with authorization from MyRealm's cache.
5943 MockWrite data_writes2[] = {
5944 MockWrite(
5945 "GET /x/1 HTTP/1.1\r\n"
5946 "Host: www.example.org\r\n"
5947 "Connection: keep-alive\r\n"
5948 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5951 // Sever accepts the authorization.
5952 MockRead data_reads2[] = {
5953 MockRead("HTTP/1.0 200 OK\r\n"),
5954 MockRead("Content-Length: 100\r\n\r\n"),
5955 MockRead(SYNCHRONOUS, OK),
5958 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5959 data_writes1, arraysize(data_writes1));
5960 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5961 data_writes2, arraysize(data_writes2));
5962 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5963 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5965 TestCompletionCallback callback1;
5967 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5968 EXPECT_EQ(ERR_IO_PENDING, rv);
5970 rv = callback1.WaitForResult();
5971 EXPECT_EQ(OK, rv);
5973 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5974 TestCompletionCallback callback2;
5975 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5976 EXPECT_EQ(ERR_IO_PENDING, rv);
5977 rv = callback2.WaitForResult();
5978 EXPECT_EQ(OK, rv);
5979 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5981 const HttpResponseInfo* response = trans->GetResponseInfo();
5982 ASSERT_TRUE(response != NULL);
5983 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5984 EXPECT_EQ(100, response->headers->GetContentLength());
5987 // ------------------------------------------------------------------------
5989 // Transaction 5: request a URL in MyRealm, but the server rejects the
5990 // cached identity. Should invalidate and re-prompt.
5992 HttpRequestInfo request;
5993 request.method = "GET";
5994 request.url = GURL("http://www.example.org/p/q/t");
5995 request.load_flags = 0;
5997 scoped_ptr<HttpTransaction> trans(
5998 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6000 MockWrite data_writes1[] = {
6001 MockWrite(
6002 "GET /p/q/t HTTP/1.1\r\n"
6003 "Host: www.example.org\r\n"
6004 "Connection: keep-alive\r\n\r\n"),
6007 MockRead data_reads1[] = {
6008 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6009 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6010 MockRead("Content-Length: 10000\r\n\r\n"),
6011 MockRead(SYNCHRONOUS, ERR_FAILED),
6014 // Resend with authorization from cache for MyRealm.
6015 MockWrite data_writes2[] = {
6016 MockWrite(
6017 "GET /p/q/t HTTP/1.1\r\n"
6018 "Host: www.example.org\r\n"
6019 "Connection: keep-alive\r\n"
6020 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6023 // Sever rejects the authorization.
6024 MockRead data_reads2[] = {
6025 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6026 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6027 MockRead("Content-Length: 10000\r\n\r\n"),
6028 MockRead(SYNCHRONOUS, ERR_FAILED),
6031 // At this point we should prompt for new credentials for MyRealm.
6032 // Restart with username=foo3, password=foo4.
6033 MockWrite data_writes3[] = {
6034 MockWrite(
6035 "GET /p/q/t HTTP/1.1\r\n"
6036 "Host: www.example.org\r\n"
6037 "Connection: keep-alive\r\n"
6038 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6041 // Sever accepts the authorization.
6042 MockRead data_reads3[] = {
6043 MockRead("HTTP/1.0 200 OK\r\n"),
6044 MockRead("Content-Length: 100\r\n\r\n"),
6045 MockRead(SYNCHRONOUS, OK),
6048 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6049 data_writes1, arraysize(data_writes1));
6050 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6051 data_writes2, arraysize(data_writes2));
6052 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6053 data_writes3, arraysize(data_writes3));
6054 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6055 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6056 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6058 TestCompletionCallback callback1;
6060 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6061 EXPECT_EQ(ERR_IO_PENDING, rv);
6063 rv = callback1.WaitForResult();
6064 EXPECT_EQ(OK, rv);
6066 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6067 TestCompletionCallback callback2;
6068 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6069 EXPECT_EQ(ERR_IO_PENDING, rv);
6070 rv = callback2.WaitForResult();
6071 EXPECT_EQ(OK, rv);
6072 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6074 const HttpResponseInfo* response = trans->GetResponseInfo();
6075 ASSERT_TRUE(response != NULL);
6076 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6078 TestCompletionCallback callback3;
6080 rv = trans->RestartWithAuth(
6081 AuthCredentials(kFoo3, kBar3), callback3.callback());
6082 EXPECT_EQ(ERR_IO_PENDING, rv);
6084 rv = callback3.WaitForResult();
6085 EXPECT_EQ(OK, rv);
6087 response = trans->GetResponseInfo();
6088 ASSERT_TRUE(response != NULL);
6089 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6090 EXPECT_EQ(100, response->headers->GetContentLength());
6094 // Tests that nonce count increments when multiple auth attempts
6095 // are started with the same nonce.
6096 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
6097 HttpAuthHandlerDigest::Factory* digest_factory =
6098 new HttpAuthHandlerDigest::Factory();
6099 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6100 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6101 digest_factory->set_nonce_generator(nonce_generator);
6102 session_deps_.http_auth_handler_factory.reset(digest_factory);
6103 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6105 // Transaction 1: authenticate (foo, bar) on MyRealm1
6107 HttpRequestInfo request;
6108 request.method = "GET";
6109 request.url = GURL("http://www.example.org/x/y/z");
6110 request.load_flags = 0;
6112 scoped_ptr<HttpTransaction> trans(
6113 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6115 MockWrite data_writes1[] = {
6116 MockWrite(
6117 "GET /x/y/z HTTP/1.1\r\n"
6118 "Host: www.example.org\r\n"
6119 "Connection: keep-alive\r\n\r\n"),
6122 MockRead data_reads1[] = {
6123 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6124 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6125 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6126 MockRead(SYNCHRONOUS, OK),
6129 // Resend with authorization (username=foo, password=bar)
6130 MockWrite data_writes2[] = {
6131 MockWrite(
6132 "GET /x/y/z HTTP/1.1\r\n"
6133 "Host: www.example.org\r\n"
6134 "Connection: keep-alive\r\n"
6135 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6136 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6137 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6138 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6141 // Sever accepts the authorization.
6142 MockRead data_reads2[] = {
6143 MockRead("HTTP/1.0 200 OK\r\n"),
6144 MockRead(SYNCHRONOUS, OK),
6147 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6148 data_writes1, arraysize(data_writes1));
6149 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6150 data_writes2, arraysize(data_writes2));
6151 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6152 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6154 TestCompletionCallback callback1;
6156 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6157 EXPECT_EQ(ERR_IO_PENDING, rv);
6159 rv = callback1.WaitForResult();
6160 EXPECT_EQ(OK, rv);
6162 const HttpResponseInfo* response = trans->GetResponseInfo();
6163 ASSERT_TRUE(response != NULL);
6164 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
6166 TestCompletionCallback callback2;
6168 rv = trans->RestartWithAuth(
6169 AuthCredentials(kFoo, kBar), callback2.callback());
6170 EXPECT_EQ(ERR_IO_PENDING, rv);
6172 rv = callback2.WaitForResult();
6173 EXPECT_EQ(OK, rv);
6175 response = trans->GetResponseInfo();
6176 ASSERT_TRUE(response != NULL);
6177 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6180 // ------------------------------------------------------------------------
6182 // Transaction 2: Request another resource in digestive's protection space.
6183 // This will preemptively add an Authorization header which should have an
6184 // "nc" value of 2 (as compared to 1 in the first use.
6186 HttpRequestInfo request;
6187 request.method = "GET";
6188 // Note that Transaction 1 was at /x/y/z, so this is in the same
6189 // protection space as digest.
6190 request.url = GURL("http://www.example.org/x/y/a/b");
6191 request.load_flags = 0;
6193 scoped_ptr<HttpTransaction> trans(
6194 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6196 MockWrite data_writes1[] = {
6197 MockWrite(
6198 "GET /x/y/a/b HTTP/1.1\r\n"
6199 "Host: www.example.org\r\n"
6200 "Connection: keep-alive\r\n"
6201 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6202 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6203 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6204 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6207 // Sever accepts the authorization.
6208 MockRead data_reads1[] = {
6209 MockRead("HTTP/1.0 200 OK\r\n"),
6210 MockRead("Content-Length: 100\r\n\r\n"),
6211 MockRead(SYNCHRONOUS, OK),
6214 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6215 data_writes1, arraysize(data_writes1));
6216 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6218 TestCompletionCallback callback1;
6220 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6221 EXPECT_EQ(ERR_IO_PENDING, rv);
6223 rv = callback1.WaitForResult();
6224 EXPECT_EQ(OK, rv);
6226 const HttpResponseInfo* response = trans->GetResponseInfo();
6227 ASSERT_TRUE(response != NULL);
6228 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6232 // Test the ResetStateForRestart() private method.
6233 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
6234 // Create a transaction (the dependencies aren't important).
6235 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6236 scoped_ptr<HttpNetworkTransaction> trans(
6237 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6239 // Setup some state (which we expect ResetStateForRestart() will clear).
6240 trans->read_buf_ = new IOBuffer(15);
6241 trans->read_buf_len_ = 15;
6242 trans->request_headers_.SetHeader("Authorization", "NTLM");
6244 // Setup state in response_
6245 HttpResponseInfo* response = &trans->response_;
6246 response->auth_challenge = new AuthChallengeInfo();
6247 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
6248 response->response_time = base::Time::Now();
6249 response->was_cached = true; // (Wouldn't ever actually be true...)
6251 { // Setup state for response_.vary_data
6252 HttpRequestInfo request;
6253 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6254 std::replace(temp.begin(), temp.end(), '\n', '\0');
6255 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
6256 request.extra_headers.SetHeader("Foo", "1");
6257 request.extra_headers.SetHeader("bar", "23");
6258 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
6261 // Cause the above state to be reset.
6262 trans->ResetStateForRestart();
6264 // Verify that the state that needed to be reset, has been reset.
6265 EXPECT_TRUE(trans->read_buf_.get() == NULL);
6266 EXPECT_EQ(0, trans->read_buf_len_);
6267 EXPECT_TRUE(trans->request_headers_.IsEmpty());
6268 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6269 EXPECT_TRUE(response->headers.get() == NULL);
6270 EXPECT_FALSE(response->was_cached);
6271 EXPECT_EQ(0U, response->ssl_info.cert_status);
6272 EXPECT_FALSE(response->vary_data.is_valid());
6275 // Test HTTPS connections to a site with a bad certificate
6276 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
6277 HttpRequestInfo request;
6278 request.method = "GET";
6279 request.url = GURL("https://www.example.org/");
6280 request.load_flags = 0;
6282 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6283 scoped_ptr<HttpTransaction> trans(
6284 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6286 MockWrite data_writes[] = {
6287 MockWrite(
6288 "GET / HTTP/1.1\r\n"
6289 "Host: www.example.org\r\n"
6290 "Connection: keep-alive\r\n\r\n"),
6293 MockRead data_reads[] = {
6294 MockRead("HTTP/1.0 200 OK\r\n"),
6295 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6296 MockRead("Content-Length: 100\r\n\r\n"),
6297 MockRead(SYNCHRONOUS, OK),
6300 StaticSocketDataProvider ssl_bad_certificate;
6301 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6302 data_writes, arraysize(data_writes));
6303 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6304 SSLSocketDataProvider ssl(ASYNC, OK);
6306 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6307 session_deps_.socket_factory->AddSocketDataProvider(&data);
6308 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6309 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6311 TestCompletionCallback callback;
6313 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6314 EXPECT_EQ(ERR_IO_PENDING, rv);
6316 rv = callback.WaitForResult();
6317 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6319 rv = trans->RestartIgnoringLastError(callback.callback());
6320 EXPECT_EQ(ERR_IO_PENDING, rv);
6322 rv = callback.WaitForResult();
6323 EXPECT_EQ(OK, rv);
6325 const HttpResponseInfo* response = trans->GetResponseInfo();
6327 ASSERT_TRUE(response != NULL);
6328 EXPECT_EQ(100, response->headers->GetContentLength());
6331 // Test HTTPS connections to a site with a bad certificate, going through a
6332 // proxy
6333 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
6334 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6336 HttpRequestInfo request;
6337 request.method = "GET";
6338 request.url = GURL("https://www.example.org/");
6339 request.load_flags = 0;
6341 MockWrite proxy_writes[] = {
6342 MockWrite(
6343 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6344 "Host: www.example.org\r\n"
6345 "Proxy-Connection: keep-alive\r\n\r\n"),
6348 MockRead proxy_reads[] = {
6349 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6350 MockRead(SYNCHRONOUS, OK)
6353 MockWrite data_writes[] = {
6354 MockWrite(
6355 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6356 "Host: www.example.org\r\n"
6357 "Proxy-Connection: keep-alive\r\n\r\n"),
6358 MockWrite(
6359 "GET / HTTP/1.1\r\n"
6360 "Host: www.example.org\r\n"
6361 "Connection: keep-alive\r\n\r\n"),
6364 MockRead data_reads[] = {
6365 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6366 MockRead("HTTP/1.0 200 OK\r\n"),
6367 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6368 MockRead("Content-Length: 100\r\n\r\n"),
6369 MockRead(SYNCHRONOUS, OK),
6372 StaticSocketDataProvider ssl_bad_certificate(
6373 proxy_reads, arraysize(proxy_reads),
6374 proxy_writes, arraysize(proxy_writes));
6375 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6376 data_writes, arraysize(data_writes));
6377 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6378 SSLSocketDataProvider ssl(ASYNC, OK);
6380 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6381 session_deps_.socket_factory->AddSocketDataProvider(&data);
6382 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6383 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6385 TestCompletionCallback callback;
6387 for (int i = 0; i < 2; i++) {
6388 session_deps_.socket_factory->ResetNextMockIndexes();
6390 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6391 scoped_ptr<HttpTransaction> trans(
6392 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6394 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6395 EXPECT_EQ(ERR_IO_PENDING, rv);
6397 rv = callback.WaitForResult();
6398 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6400 rv = trans->RestartIgnoringLastError(callback.callback());
6401 EXPECT_EQ(ERR_IO_PENDING, rv);
6403 rv = callback.WaitForResult();
6404 EXPECT_EQ(OK, rv);
6406 const HttpResponseInfo* response = trans->GetResponseInfo();
6408 ASSERT_TRUE(response != NULL);
6409 EXPECT_EQ(100, response->headers->GetContentLength());
6414 // Test HTTPS connections to a site, going through an HTTPS proxy
6415 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6416 session_deps_.proxy_service.reset(
6417 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6418 TestNetLog net_log;
6419 session_deps_.net_log = &net_log;
6421 HttpRequestInfo request;
6422 request.method = "GET";
6423 request.url = GURL("https://www.example.org/");
6424 request.load_flags = 0;
6426 MockWrite data_writes[] = {
6427 MockWrite(
6428 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6429 "Host: www.example.org\r\n"
6430 "Proxy-Connection: keep-alive\r\n\r\n"),
6431 MockWrite(
6432 "GET / HTTP/1.1\r\n"
6433 "Host: www.example.org\r\n"
6434 "Connection: keep-alive\r\n\r\n"),
6437 MockRead data_reads[] = {
6438 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6439 MockRead("HTTP/1.1 200 OK\r\n"),
6440 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6441 MockRead("Content-Length: 100\r\n\r\n"),
6442 MockRead(SYNCHRONOUS, OK),
6445 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6446 data_writes, arraysize(data_writes));
6447 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6448 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6450 session_deps_.socket_factory->AddSocketDataProvider(&data);
6451 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6452 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6454 TestCompletionCallback callback;
6456 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6457 scoped_ptr<HttpTransaction> trans(
6458 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6460 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6461 EXPECT_EQ(ERR_IO_PENDING, rv);
6463 rv = callback.WaitForResult();
6464 EXPECT_EQ(OK, rv);
6465 const HttpResponseInfo* response = trans->GetResponseInfo();
6467 ASSERT_TRUE(response != NULL);
6469 EXPECT_TRUE(response->headers->IsKeepAlive());
6470 EXPECT_EQ(200, response->headers->response_code());
6471 EXPECT_EQ(100, response->headers->GetContentLength());
6472 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6474 LoadTimingInfo load_timing_info;
6475 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6476 TestLoadTimingNotReusedWithPac(load_timing_info,
6477 CONNECT_TIMING_HAS_SSL_TIMES);
6480 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6481 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6482 session_deps_.proxy_service.reset(
6483 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6484 TestNetLog net_log;
6485 session_deps_.net_log = &net_log;
6487 HttpRequestInfo request;
6488 request.method = "GET";
6489 request.url = GURL("https://www.example.org/");
6490 request.load_flags = 0;
6492 MockWrite data_writes[] = {
6493 MockWrite(
6494 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6495 "Host: www.example.org\r\n"
6496 "Proxy-Connection: keep-alive\r\n\r\n"),
6499 MockRead data_reads[] = {
6500 MockRead("HTTP/1.1 302 Redirect\r\n"),
6501 MockRead("Location: http://login.example.com/\r\n"),
6502 MockRead("Content-Length: 0\r\n\r\n"),
6503 MockRead(SYNCHRONOUS, OK),
6506 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6507 data_writes, arraysize(data_writes));
6508 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6510 session_deps_.socket_factory->AddSocketDataProvider(&data);
6511 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6513 TestCompletionCallback callback;
6515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6516 scoped_ptr<HttpTransaction> trans(
6517 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6519 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6520 EXPECT_EQ(ERR_IO_PENDING, rv);
6522 rv = callback.WaitForResult();
6523 EXPECT_EQ(OK, rv);
6524 const HttpResponseInfo* response = trans->GetResponseInfo();
6526 ASSERT_TRUE(response != NULL);
6528 EXPECT_EQ(302, response->headers->response_code());
6529 std::string url;
6530 EXPECT_TRUE(response->headers->IsRedirect(&url));
6531 EXPECT_EQ("http://login.example.com/", url);
6533 // In the case of redirects from proxies, HttpNetworkTransaction returns
6534 // timing for the proxy connection instead of the connection to the host,
6535 // and no send / receive times.
6536 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6537 LoadTimingInfo load_timing_info;
6538 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6540 EXPECT_FALSE(load_timing_info.socket_reused);
6541 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6543 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6544 EXPECT_LE(load_timing_info.proxy_resolve_start,
6545 load_timing_info.proxy_resolve_end);
6546 EXPECT_LE(load_timing_info.proxy_resolve_end,
6547 load_timing_info.connect_timing.connect_start);
6548 ExpectConnectTimingHasTimes(
6549 load_timing_info.connect_timing,
6550 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6552 EXPECT_TRUE(load_timing_info.send_start.is_null());
6553 EXPECT_TRUE(load_timing_info.send_end.is_null());
6554 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6557 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6558 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6559 session_deps_.proxy_service.reset(
6560 ProxyService::CreateFixed("https://proxy:70"));
6562 HttpRequestInfo request;
6563 request.method = "GET";
6564 request.url = GURL("https://www.example.org/");
6565 request.load_flags = 0;
6567 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6568 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6569 scoped_ptr<SpdyFrame> goaway(
6570 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6571 MockWrite data_writes[] = {
6572 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6573 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
6576 static const char* const kExtraHeaders[] = {
6577 "location",
6578 "http://login.example.com/",
6580 scoped_ptr<SpdyFrame> resp(
6581 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6582 arraysize(kExtraHeaders)/2, 1));
6583 MockRead data_reads[] = {
6584 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
6587 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6588 arraysize(data_writes));
6589 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6590 proxy_ssl.SetNextProto(GetParam());
6592 session_deps_.socket_factory->AddSocketDataProvider(&data);
6593 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6595 TestCompletionCallback callback;
6597 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6598 scoped_ptr<HttpTransaction> trans(
6599 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6601 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6602 EXPECT_EQ(ERR_IO_PENDING, rv);
6604 rv = callback.WaitForResult();
6605 EXPECT_EQ(OK, rv);
6606 const HttpResponseInfo* response = trans->GetResponseInfo();
6608 ASSERT_TRUE(response != NULL);
6610 EXPECT_EQ(302, response->headers->response_code());
6611 std::string url;
6612 EXPECT_TRUE(response->headers->IsRedirect(&url));
6613 EXPECT_EQ("http://login.example.com/", url);
6616 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6617 TEST_P(HttpNetworkTransactionTest,
6618 ErrorResponseToHttpsConnectViaHttpsProxy) {
6619 session_deps_.proxy_service.reset(
6620 ProxyService::CreateFixed("https://proxy:70"));
6622 HttpRequestInfo request;
6623 request.method = "GET";
6624 request.url = GURL("https://www.example.org/");
6625 request.load_flags = 0;
6627 MockWrite data_writes[] = {
6628 MockWrite(
6629 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6630 "Host: www.example.org\r\n"
6631 "Proxy-Connection: keep-alive\r\n\r\n"),
6634 MockRead data_reads[] = {
6635 MockRead("HTTP/1.1 404 Not Found\r\n"),
6636 MockRead("Content-Length: 23\r\n\r\n"),
6637 MockRead("The host does not exist"),
6638 MockRead(SYNCHRONOUS, OK),
6641 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6642 data_writes, arraysize(data_writes));
6643 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6645 session_deps_.socket_factory->AddSocketDataProvider(&data);
6646 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6648 TestCompletionCallback callback;
6650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6651 scoped_ptr<HttpTransaction> trans(
6652 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6654 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6655 EXPECT_EQ(ERR_IO_PENDING, rv);
6657 rv = callback.WaitForResult();
6658 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6660 // TODO(ttuttle): Anything else to check here?
6663 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6664 TEST_P(HttpNetworkTransactionTest,
6665 ErrorResponseToHttpsConnectViaSpdyProxy) {
6666 session_deps_.proxy_service.reset(
6667 ProxyService::CreateFixed("https://proxy:70"));
6669 HttpRequestInfo request;
6670 request.method = "GET";
6671 request.url = GURL("https://www.example.org/");
6672 request.load_flags = 0;
6674 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6675 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6676 scoped_ptr<SpdyFrame> rst(
6677 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6678 MockWrite data_writes[] = {
6679 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
6682 static const char* const kExtraHeaders[] = {
6683 "location",
6684 "http://login.example.com/",
6686 scoped_ptr<SpdyFrame> resp(
6687 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6688 arraysize(kExtraHeaders)/2, 1));
6689 scoped_ptr<SpdyFrame> body(
6690 spdy_util_.ConstructSpdyBodyFrame(
6691 1, "The host does not exist", 23, true));
6692 MockRead data_reads[] = {
6693 CreateMockRead(*resp.get(), 1),
6694 CreateMockRead(*body.get(), 2),
6695 MockRead(ASYNC, 0, 4), // EOF
6698 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6699 arraysize(data_writes));
6700 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6701 proxy_ssl.SetNextProto(GetParam());
6703 session_deps_.socket_factory->AddSocketDataProvider(&data);
6704 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6706 TestCompletionCallback callback;
6708 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6709 scoped_ptr<HttpTransaction> trans(
6710 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6712 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6713 EXPECT_EQ(ERR_IO_PENDING, rv);
6715 rv = callback.WaitForResult();
6716 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6718 // TODO(ttuttle): Anything else to check here?
6721 // Test the request-challenge-retry sequence for basic auth, through
6722 // a SPDY proxy over a single SPDY session.
6723 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6724 HttpRequestInfo request;
6725 request.method = "GET";
6726 request.url = GURL("https://www.example.org/");
6727 // when the no authentication data flag is set.
6728 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
6730 // Configure against https proxy server "myproxy:70".
6731 session_deps_.proxy_service.reset(
6732 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6733 BoundTestNetLog log;
6734 session_deps_.net_log = log.bound().net_log();
6735 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6737 // Since we have proxy, should try to establish tunnel.
6738 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
6739 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6740 scoped_ptr<SpdyFrame> rst(
6741 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6743 // After calling trans->RestartWithAuth(), this is the request we should
6744 // be issuing -- the final header line contains the credentials.
6745 const char* const kAuthCredentials[] = {
6746 "proxy-authorization", "Basic Zm9vOmJhcg==",
6748 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6749 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
6750 HostPortPair("www.example.org", 443)));
6751 // fetch https://www.example.org/ via HTTP
6752 const char get[] =
6753 "GET / HTTP/1.1\r\n"
6754 "Host: www.example.org\r\n"
6755 "Connection: keep-alive\r\n\r\n";
6756 scoped_ptr<SpdyFrame> wrapped_get(
6757 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6759 MockWrite spdy_writes[] = {
6760 CreateMockWrite(*req, 0, ASYNC),
6761 CreateMockWrite(*rst, 2, ASYNC),
6762 CreateMockWrite(*connect2, 3),
6763 CreateMockWrite(*wrapped_get, 5),
6766 // The proxy responds to the connect with a 407, using a persistent
6767 // connection.
6768 const char kAuthStatus[] = "407";
6769 const char* const kAuthChallenge[] = {
6770 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6772 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6773 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6775 scoped_ptr<SpdyFrame> conn_resp(
6776 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6777 const char resp[] = "HTTP/1.1 200 OK\r\n"
6778 "Content-Length: 5\r\n\r\n";
6780 scoped_ptr<SpdyFrame> wrapped_get_resp(
6781 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6782 scoped_ptr<SpdyFrame> wrapped_body(
6783 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6784 MockRead spdy_reads[] = {
6785 CreateMockRead(*conn_auth_resp, 1, ASYNC),
6786 CreateMockRead(*conn_resp, 4, ASYNC),
6787 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
6788 CreateMockRead(*wrapped_body, 7, ASYNC),
6789 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
6792 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6793 arraysize(spdy_writes));
6794 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6795 // Negotiate SPDY to the proxy
6796 SSLSocketDataProvider proxy(ASYNC, OK);
6797 proxy.SetNextProto(GetParam());
6798 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6799 // Vanilla SSL to the server
6800 SSLSocketDataProvider server(ASYNC, OK);
6801 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6803 TestCompletionCallback callback1;
6805 scoped_ptr<HttpTransaction> trans(
6806 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6808 int rv = trans->Start(&request, callback1.callback(), log.bound());
6809 EXPECT_EQ(ERR_IO_PENDING, rv);
6811 rv = callback1.WaitForResult();
6812 EXPECT_EQ(OK, rv);
6813 TestNetLogEntry::List entries;
6814 log.GetEntries(&entries);
6815 size_t pos = ExpectLogContainsSomewhere(
6816 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6817 NetLog::PHASE_NONE);
6818 ExpectLogContainsSomewhere(
6819 entries, pos,
6820 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6821 NetLog::PHASE_NONE);
6823 const HttpResponseInfo* response = trans->GetResponseInfo();
6824 ASSERT_TRUE(response != NULL);
6825 ASSERT_FALSE(response->headers.get() == NULL);
6826 EXPECT_EQ(407, response->headers->response_code());
6827 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6828 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6829 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6831 TestCompletionCallback callback2;
6833 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6834 callback2.callback());
6835 EXPECT_EQ(ERR_IO_PENDING, rv);
6837 rv = callback2.WaitForResult();
6838 EXPECT_EQ(OK, rv);
6840 response = trans->GetResponseInfo();
6841 ASSERT_TRUE(response != NULL);
6843 EXPECT_TRUE(response->headers->IsKeepAlive());
6844 EXPECT_EQ(200, response->headers->response_code());
6845 EXPECT_EQ(5, response->headers->GetContentLength());
6846 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6848 // The password prompt info should not be set.
6849 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6851 LoadTimingInfo load_timing_info;
6852 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6853 TestLoadTimingNotReusedWithPac(load_timing_info,
6854 CONNECT_TIMING_HAS_SSL_TIMES);
6856 trans.reset();
6857 session->CloseAllConnections();
6860 // Test that an explicitly trusted SPDY proxy can push a resource from an
6861 // origin that is different from that of its associated resource.
6862 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6863 HttpRequestInfo request;
6864 HttpRequestInfo push_request;
6866 request.method = "GET";
6867 request.url = GURL("http://www.example.org/");
6868 push_request.method = "GET";
6869 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6871 // Configure against https proxy server "myproxy:70".
6872 session_deps_.proxy_service.reset(
6873 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6874 BoundTestNetLog log;
6875 session_deps_.net_log = log.bound().net_log();
6877 // Enable cross-origin push.
6878 session_deps_.trusted_spdy_proxy = "myproxy:70";
6880 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6882 scoped_ptr<SpdyFrame> stream1_syn(
6883 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6885 MockWrite spdy_writes[] = {
6886 CreateMockWrite(*stream1_syn, 0, ASYNC),
6889 scoped_ptr<SpdyFrame>
6890 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6892 scoped_ptr<SpdyFrame>
6893 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6895 scoped_ptr<SpdyFrame>
6896 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6900 "http://www.another-origin.com/foo.dat"));
6901 const char kPushedData[] = "pushed";
6902 scoped_ptr<SpdyFrame> stream2_body(
6903 spdy_util_.ConstructSpdyBodyFrame(
6904 2, kPushedData, strlen(kPushedData), true));
6906 MockRead spdy_reads[] = {
6907 CreateMockRead(*stream1_reply, 1, ASYNC),
6908 CreateMockRead(*stream2_syn, 2, ASYNC),
6909 CreateMockRead(*stream1_body, 3, ASYNC),
6910 CreateMockRead(*stream2_body, 4, ASYNC),
6911 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
6914 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6915 arraysize(spdy_writes));
6916 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6917 // Negotiate SPDY to the proxy
6918 SSLSocketDataProvider proxy(ASYNC, OK);
6919 proxy.SetNextProto(GetParam());
6920 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6922 scoped_ptr<HttpTransaction> trans(
6923 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6924 TestCompletionCallback callback;
6925 int rv = trans->Start(&request, callback.callback(), log.bound());
6926 EXPECT_EQ(ERR_IO_PENDING, rv);
6928 rv = callback.WaitForResult();
6929 EXPECT_EQ(OK, rv);
6930 const HttpResponseInfo* response = trans->GetResponseInfo();
6932 scoped_ptr<HttpTransaction> push_trans(
6933 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6934 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6935 EXPECT_EQ(ERR_IO_PENDING, rv);
6937 rv = callback.WaitForResult();
6938 EXPECT_EQ(OK, rv);
6939 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6941 ASSERT_TRUE(response != NULL);
6942 EXPECT_TRUE(response->headers->IsKeepAlive());
6944 EXPECT_EQ(200, response->headers->response_code());
6945 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6947 std::string response_data;
6948 rv = ReadTransaction(trans.get(), &response_data);
6949 EXPECT_EQ(OK, rv);
6950 EXPECT_EQ("hello!", response_data);
6952 LoadTimingInfo load_timing_info;
6953 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6954 TestLoadTimingNotReusedWithPac(load_timing_info,
6955 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6957 // Verify the pushed stream.
6958 EXPECT_TRUE(push_response->headers.get() != NULL);
6959 EXPECT_EQ(200, push_response->headers->response_code());
6961 rv = ReadTransaction(push_trans.get(), &response_data);
6962 EXPECT_EQ(OK, rv);
6963 EXPECT_EQ("pushed", response_data);
6965 LoadTimingInfo push_load_timing_info;
6966 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6967 TestLoadTimingReusedWithPac(push_load_timing_info);
6968 // The transactions should share a socket ID, despite being for different
6969 // origins.
6970 EXPECT_EQ(load_timing_info.socket_log_id,
6971 push_load_timing_info.socket_log_id);
6973 trans.reset();
6974 push_trans.reset();
6975 session->CloseAllConnections();
6978 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6979 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6980 HttpRequestInfo request;
6982 request.method = "GET";
6983 request.url = GURL("http://www.example.org/");
6985 // Configure against https proxy server "myproxy:70".
6986 session_deps_.proxy_service.reset(
6987 ProxyService::CreateFixed("https://myproxy:70"));
6988 BoundTestNetLog log;
6989 session_deps_.net_log = log.bound().net_log();
6991 // Enable cross-origin push.
6992 session_deps_.trusted_spdy_proxy = "myproxy:70";
6994 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6996 scoped_ptr<SpdyFrame> stream1_syn(
6997 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6999 scoped_ptr<SpdyFrame> push_rst(
7000 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
7002 MockWrite spdy_writes[] = {
7003 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
7006 scoped_ptr<SpdyFrame>
7007 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
7009 scoped_ptr<SpdyFrame>
7010 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
7012 scoped_ptr<SpdyFrame>
7013 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
7017 "https://www.another-origin.com/foo.dat"));
7019 MockRead spdy_reads[] = {
7020 CreateMockRead(*stream1_reply, 1, ASYNC),
7021 CreateMockRead(*stream2_syn, 2, ASYNC),
7022 CreateMockRead(*stream1_body, 4, ASYNC),
7023 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
7026 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7027 arraysize(spdy_writes));
7028 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7029 // Negotiate SPDY to the proxy
7030 SSLSocketDataProvider proxy(ASYNC, OK);
7031 proxy.SetNextProto(GetParam());
7032 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7034 scoped_ptr<HttpTransaction> trans(
7035 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7036 TestCompletionCallback callback;
7037 int rv = trans->Start(&request, callback.callback(), log.bound());
7038 EXPECT_EQ(ERR_IO_PENDING, rv);
7040 rv = callback.WaitForResult();
7041 EXPECT_EQ(OK, rv);
7042 const HttpResponseInfo* response = trans->GetResponseInfo();
7044 ASSERT_TRUE(response != NULL);
7045 EXPECT_TRUE(response->headers->IsKeepAlive());
7047 EXPECT_EQ(200, response->headers->response_code());
7048 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7050 std::string response_data;
7051 rv = ReadTransaction(trans.get(), &response_data);
7052 EXPECT_EQ(OK, rv);
7053 EXPECT_EQ("hello!", response_data);
7055 trans.reset();
7056 session->CloseAllConnections();
7059 // Test HTTPS connections to a site with a bad certificate, going through an
7060 // HTTPS proxy
7061 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
7062 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
7063 "https://proxy:70"));
7065 HttpRequestInfo request;
7066 request.method = "GET";
7067 request.url = GURL("https://www.example.org/");
7068 request.load_flags = 0;
7070 // Attempt to fetch the URL from a server with a bad cert
7071 MockWrite bad_cert_writes[] = {
7072 MockWrite(
7073 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7074 "Host: www.example.org\r\n"
7075 "Proxy-Connection: keep-alive\r\n\r\n"),
7078 MockRead bad_cert_reads[] = {
7079 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7080 MockRead(SYNCHRONOUS, OK)
7083 // Attempt to fetch the URL with a good cert
7084 MockWrite good_data_writes[] = {
7085 MockWrite(
7086 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7087 "Host: www.example.org\r\n"
7088 "Proxy-Connection: keep-alive\r\n\r\n"),
7089 MockWrite(
7090 "GET / HTTP/1.1\r\n"
7091 "Host: www.example.org\r\n"
7092 "Connection: keep-alive\r\n\r\n"),
7095 MockRead good_cert_reads[] = {
7096 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7097 MockRead("HTTP/1.0 200 OK\r\n"),
7098 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7099 MockRead("Content-Length: 100\r\n\r\n"),
7100 MockRead(SYNCHRONOUS, OK),
7103 StaticSocketDataProvider ssl_bad_certificate(
7104 bad_cert_reads, arraysize(bad_cert_reads),
7105 bad_cert_writes, arraysize(bad_cert_writes));
7106 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7107 good_data_writes, arraysize(good_data_writes));
7108 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7109 SSLSocketDataProvider ssl(ASYNC, OK);
7111 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7112 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7113 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7114 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7116 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7117 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7118 session_deps_.socket_factory->AddSocketDataProvider(&data);
7119 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7121 TestCompletionCallback callback;
7123 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7124 scoped_ptr<HttpTransaction> trans(
7125 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7127 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7128 EXPECT_EQ(ERR_IO_PENDING, rv);
7130 rv = callback.WaitForResult();
7131 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7133 rv = trans->RestartIgnoringLastError(callback.callback());
7134 EXPECT_EQ(ERR_IO_PENDING, rv);
7136 rv = callback.WaitForResult();
7137 EXPECT_EQ(OK, rv);
7139 const HttpResponseInfo* response = trans->GetResponseInfo();
7141 ASSERT_TRUE(response != NULL);
7142 EXPECT_EQ(100, response->headers->GetContentLength());
7145 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
7146 HttpRequestInfo request;
7147 request.method = "GET";
7148 request.url = GURL("http://www.example.org/");
7149 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7150 "Chromium Ultra Awesome X Edition");
7152 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7153 scoped_ptr<HttpTransaction> trans(
7154 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7156 MockWrite data_writes[] = {
7157 MockWrite(
7158 "GET / HTTP/1.1\r\n"
7159 "Host: www.example.org\r\n"
7160 "Connection: keep-alive\r\n"
7161 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7164 // Lastly, the server responds with the actual content.
7165 MockRead data_reads[] = {
7166 MockRead("HTTP/1.0 200 OK\r\n"),
7167 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7168 MockRead("Content-Length: 100\r\n\r\n"),
7169 MockRead(SYNCHRONOUS, OK),
7172 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7173 data_writes, arraysize(data_writes));
7174 session_deps_.socket_factory->AddSocketDataProvider(&data);
7176 TestCompletionCallback callback;
7178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7179 EXPECT_EQ(ERR_IO_PENDING, rv);
7181 rv = callback.WaitForResult();
7182 EXPECT_EQ(OK, rv);
7185 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
7186 HttpRequestInfo request;
7187 request.method = "GET";
7188 request.url = GURL("https://www.example.org/");
7189 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7190 "Chromium Ultra Awesome X Edition");
7192 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7193 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7194 scoped_ptr<HttpTransaction> trans(
7195 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7197 MockWrite data_writes[] = {
7198 MockWrite(
7199 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7200 "Host: www.example.org\r\n"
7201 "Proxy-Connection: keep-alive\r\n"
7202 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7204 MockRead data_reads[] = {
7205 // Return an error, so the transaction stops here (this test isn't
7206 // interested in the rest).
7207 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7208 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7209 MockRead("Proxy-Connection: close\r\n\r\n"),
7212 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7213 data_writes, arraysize(data_writes));
7214 session_deps_.socket_factory->AddSocketDataProvider(&data);
7216 TestCompletionCallback callback;
7218 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7219 EXPECT_EQ(ERR_IO_PENDING, rv);
7221 rv = callback.WaitForResult();
7222 EXPECT_EQ(OK, rv);
7225 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
7226 HttpRequestInfo request;
7227 request.method = "GET";
7228 request.url = GURL("http://www.example.org/");
7229 request.load_flags = 0;
7230 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7231 "http://the.previous.site.com/");
7233 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7234 scoped_ptr<HttpTransaction> trans(
7235 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7237 MockWrite data_writes[] = {
7238 MockWrite(
7239 "GET / HTTP/1.1\r\n"
7240 "Host: www.example.org\r\n"
7241 "Connection: keep-alive\r\n"
7242 "Referer: http://the.previous.site.com/\r\n\r\n"),
7245 // Lastly, the server responds with the actual content.
7246 MockRead data_reads[] = {
7247 MockRead("HTTP/1.0 200 OK\r\n"),
7248 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7249 MockRead("Content-Length: 100\r\n\r\n"),
7250 MockRead(SYNCHRONOUS, OK),
7253 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7254 data_writes, arraysize(data_writes));
7255 session_deps_.socket_factory->AddSocketDataProvider(&data);
7257 TestCompletionCallback callback;
7259 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7260 EXPECT_EQ(ERR_IO_PENDING, rv);
7262 rv = callback.WaitForResult();
7263 EXPECT_EQ(OK, rv);
7266 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
7267 HttpRequestInfo request;
7268 request.method = "POST";
7269 request.url = GURL("http://www.example.org/");
7271 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7272 scoped_ptr<HttpTransaction> trans(
7273 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7275 MockWrite data_writes[] = {
7276 MockWrite(
7277 "POST / HTTP/1.1\r\n"
7278 "Host: www.example.org\r\n"
7279 "Connection: keep-alive\r\n"
7280 "Content-Length: 0\r\n\r\n"),
7283 // Lastly, the server responds with the actual content.
7284 MockRead data_reads[] = {
7285 MockRead("HTTP/1.0 200 OK\r\n"),
7286 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7287 MockRead("Content-Length: 100\r\n\r\n"),
7288 MockRead(SYNCHRONOUS, OK),
7291 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7292 data_writes, arraysize(data_writes));
7293 session_deps_.socket_factory->AddSocketDataProvider(&data);
7295 TestCompletionCallback callback;
7297 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7298 EXPECT_EQ(ERR_IO_PENDING, rv);
7300 rv = callback.WaitForResult();
7301 EXPECT_EQ(OK, rv);
7304 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
7305 HttpRequestInfo request;
7306 request.method = "PUT";
7307 request.url = GURL("http://www.example.org/");
7309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7310 scoped_ptr<HttpTransaction> trans(
7311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7313 MockWrite data_writes[] = {
7314 MockWrite(
7315 "PUT / HTTP/1.1\r\n"
7316 "Host: www.example.org\r\n"
7317 "Connection: keep-alive\r\n"
7318 "Content-Length: 0\r\n\r\n"),
7321 // Lastly, the server responds with the actual content.
7322 MockRead data_reads[] = {
7323 MockRead("HTTP/1.0 200 OK\r\n"),
7324 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7325 MockRead("Content-Length: 100\r\n\r\n"),
7326 MockRead(SYNCHRONOUS, OK),
7329 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7330 data_writes, arraysize(data_writes));
7331 session_deps_.socket_factory->AddSocketDataProvider(&data);
7333 TestCompletionCallback callback;
7335 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7336 EXPECT_EQ(ERR_IO_PENDING, rv);
7338 rv = callback.WaitForResult();
7339 EXPECT_EQ(OK, rv);
7342 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
7343 HttpRequestInfo request;
7344 request.method = "HEAD";
7345 request.url = GURL("http://www.example.org/");
7347 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7348 scoped_ptr<HttpTransaction> trans(
7349 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7351 MockWrite data_writes[] = {
7352 MockWrite(
7353 "HEAD / HTTP/1.1\r\n"
7354 "Host: www.example.org\r\n"
7355 "Connection: keep-alive\r\n"
7356 "Content-Length: 0\r\n\r\n"),
7359 // Lastly, the server responds with the actual content.
7360 MockRead data_reads[] = {
7361 MockRead("HTTP/1.0 200 OK\r\n"),
7362 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7363 MockRead("Content-Length: 100\r\n\r\n"),
7364 MockRead(SYNCHRONOUS, OK),
7367 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7368 data_writes, arraysize(data_writes));
7369 session_deps_.socket_factory->AddSocketDataProvider(&data);
7371 TestCompletionCallback callback;
7373 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7374 EXPECT_EQ(ERR_IO_PENDING, rv);
7376 rv = callback.WaitForResult();
7377 EXPECT_EQ(OK, rv);
7380 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7381 HttpRequestInfo request;
7382 request.method = "GET";
7383 request.url = GURL("http://www.example.org/");
7384 request.load_flags = LOAD_BYPASS_CACHE;
7386 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7387 scoped_ptr<HttpTransaction> trans(
7388 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7390 MockWrite data_writes[] = {
7391 MockWrite(
7392 "GET / HTTP/1.1\r\n"
7393 "Host: www.example.org\r\n"
7394 "Connection: keep-alive\r\n"
7395 "Pragma: no-cache\r\n"
7396 "Cache-Control: no-cache\r\n\r\n"),
7399 // Lastly, the server responds with the actual content.
7400 MockRead data_reads[] = {
7401 MockRead("HTTP/1.0 200 OK\r\n"),
7402 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7403 MockRead("Content-Length: 100\r\n\r\n"),
7404 MockRead(SYNCHRONOUS, OK),
7407 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7408 data_writes, arraysize(data_writes));
7409 session_deps_.socket_factory->AddSocketDataProvider(&data);
7411 TestCompletionCallback callback;
7413 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7414 EXPECT_EQ(ERR_IO_PENDING, rv);
7416 rv = callback.WaitForResult();
7417 EXPECT_EQ(OK, rv);
7420 TEST_P(HttpNetworkTransactionTest,
7421 BuildRequest_CacheControlValidateCache) {
7422 HttpRequestInfo request;
7423 request.method = "GET";
7424 request.url = GURL("http://www.example.org/");
7425 request.load_flags = LOAD_VALIDATE_CACHE;
7427 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7428 scoped_ptr<HttpTransaction> trans(
7429 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7431 MockWrite data_writes[] = {
7432 MockWrite(
7433 "GET / HTTP/1.1\r\n"
7434 "Host: www.example.org\r\n"
7435 "Connection: keep-alive\r\n"
7436 "Cache-Control: max-age=0\r\n\r\n"),
7439 // Lastly, the server responds with the actual content.
7440 MockRead data_reads[] = {
7441 MockRead("HTTP/1.0 200 OK\r\n"),
7442 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7443 MockRead("Content-Length: 100\r\n\r\n"),
7444 MockRead(SYNCHRONOUS, OK),
7447 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7448 data_writes, arraysize(data_writes));
7449 session_deps_.socket_factory->AddSocketDataProvider(&data);
7451 TestCompletionCallback callback;
7453 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7454 EXPECT_EQ(ERR_IO_PENDING, rv);
7456 rv = callback.WaitForResult();
7457 EXPECT_EQ(OK, rv);
7460 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7461 HttpRequestInfo request;
7462 request.method = "GET";
7463 request.url = GURL("http://www.example.org/");
7464 request.extra_headers.SetHeader("FooHeader", "Bar");
7466 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7467 scoped_ptr<HttpTransaction> trans(
7468 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7470 MockWrite data_writes[] = {
7471 MockWrite(
7472 "GET / HTTP/1.1\r\n"
7473 "Host: www.example.org\r\n"
7474 "Connection: keep-alive\r\n"
7475 "FooHeader: Bar\r\n\r\n"),
7478 // Lastly, the server responds with the actual content.
7479 MockRead data_reads[] = {
7480 MockRead("HTTP/1.0 200 OK\r\n"),
7481 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7482 MockRead("Content-Length: 100\r\n\r\n"),
7483 MockRead(SYNCHRONOUS, OK),
7486 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7487 data_writes, arraysize(data_writes));
7488 session_deps_.socket_factory->AddSocketDataProvider(&data);
7490 TestCompletionCallback callback;
7492 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7493 EXPECT_EQ(ERR_IO_PENDING, rv);
7495 rv = callback.WaitForResult();
7496 EXPECT_EQ(OK, rv);
7499 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7500 HttpRequestInfo request;
7501 request.method = "GET";
7502 request.url = GURL("http://www.example.org/");
7503 request.extra_headers.SetHeader("referer", "www.foo.com");
7504 request.extra_headers.SetHeader("hEllo", "Kitty");
7505 request.extra_headers.SetHeader("FoO", "bar");
7507 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7508 scoped_ptr<HttpTransaction> trans(
7509 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7511 MockWrite data_writes[] = {
7512 MockWrite(
7513 "GET / HTTP/1.1\r\n"
7514 "Host: www.example.org\r\n"
7515 "Connection: keep-alive\r\n"
7516 "referer: www.foo.com\r\n"
7517 "hEllo: Kitty\r\n"
7518 "FoO: bar\r\n\r\n"),
7521 // Lastly, the server responds with the actual content.
7522 MockRead data_reads[] = {
7523 MockRead("HTTP/1.0 200 OK\r\n"),
7524 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7525 MockRead("Content-Length: 100\r\n\r\n"),
7526 MockRead(SYNCHRONOUS, OK),
7529 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7530 data_writes, arraysize(data_writes));
7531 session_deps_.socket_factory->AddSocketDataProvider(&data);
7533 TestCompletionCallback callback;
7535 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7536 EXPECT_EQ(ERR_IO_PENDING, rv);
7538 rv = callback.WaitForResult();
7539 EXPECT_EQ(OK, rv);
7542 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7543 HttpRequestInfo request;
7544 request.method = "GET";
7545 request.url = GURL("http://www.example.org/");
7546 request.load_flags = 0;
7548 session_deps_.proxy_service.reset(
7549 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7550 TestNetLog net_log;
7551 session_deps_.net_log = &net_log;
7553 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7554 scoped_ptr<HttpTransaction> trans(
7555 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7557 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7558 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7560 MockWrite data_writes[] = {
7561 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7562 MockWrite(
7563 "GET / HTTP/1.1\r\n"
7564 "Host: www.example.org\r\n"
7565 "Connection: keep-alive\r\n\r\n")};
7567 MockRead data_reads[] = {
7568 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7569 MockRead("HTTP/1.0 200 OK\r\n"),
7570 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7571 MockRead("Payload"),
7572 MockRead(SYNCHRONOUS, OK)
7575 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7576 data_writes, arraysize(data_writes));
7577 session_deps_.socket_factory->AddSocketDataProvider(&data);
7579 TestCompletionCallback callback;
7581 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7582 EXPECT_EQ(ERR_IO_PENDING, rv);
7584 rv = callback.WaitForResult();
7585 EXPECT_EQ(OK, rv);
7587 const HttpResponseInfo* response = trans->GetResponseInfo();
7588 ASSERT_TRUE(response != NULL);
7590 LoadTimingInfo load_timing_info;
7591 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7592 TestLoadTimingNotReusedWithPac(load_timing_info,
7593 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7595 std::string response_text;
7596 rv = ReadTransaction(trans.get(), &response_text);
7597 EXPECT_EQ(OK, rv);
7598 EXPECT_EQ("Payload", response_text);
7601 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7602 HttpRequestInfo request;
7603 request.method = "GET";
7604 request.url = GURL("https://www.example.org/");
7605 request.load_flags = 0;
7607 session_deps_.proxy_service.reset(
7608 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7609 TestNetLog net_log;
7610 session_deps_.net_log = &net_log;
7612 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7613 scoped_ptr<HttpTransaction> trans(
7614 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7616 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7617 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7619 MockWrite data_writes[] = {
7620 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7621 arraysize(write_buffer)),
7622 MockWrite(
7623 "GET / HTTP/1.1\r\n"
7624 "Host: www.example.org\r\n"
7625 "Connection: keep-alive\r\n\r\n")};
7627 MockRead data_reads[] = {
7628 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7629 arraysize(read_buffer)),
7630 MockRead("HTTP/1.0 200 OK\r\n"),
7631 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7632 MockRead("Payload"),
7633 MockRead(SYNCHRONOUS, OK)
7636 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7637 data_writes, arraysize(data_writes));
7638 session_deps_.socket_factory->AddSocketDataProvider(&data);
7640 SSLSocketDataProvider ssl(ASYNC, OK);
7641 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7643 TestCompletionCallback callback;
7645 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7646 EXPECT_EQ(ERR_IO_PENDING, rv);
7648 rv = callback.WaitForResult();
7649 EXPECT_EQ(OK, rv);
7651 LoadTimingInfo load_timing_info;
7652 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7653 TestLoadTimingNotReusedWithPac(load_timing_info,
7654 CONNECT_TIMING_HAS_SSL_TIMES);
7656 const HttpResponseInfo* response = trans->GetResponseInfo();
7657 ASSERT_TRUE(response != NULL);
7659 std::string response_text;
7660 rv = ReadTransaction(trans.get(), &response_text);
7661 EXPECT_EQ(OK, rv);
7662 EXPECT_EQ("Payload", response_text);
7665 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7666 HttpRequestInfo request;
7667 request.method = "GET";
7668 request.url = GURL("http://www.example.org/");
7669 request.load_flags = 0;
7671 session_deps_.proxy_service.reset(
7672 ProxyService::CreateFixed("socks4://myproxy:1080"));
7673 TestNetLog net_log;
7674 session_deps_.net_log = &net_log;
7676 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7677 scoped_ptr<HttpTransaction> trans(
7678 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7680 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7681 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7683 MockWrite data_writes[] = {
7684 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7685 MockWrite(
7686 "GET / HTTP/1.1\r\n"
7687 "Host: www.example.org\r\n"
7688 "Connection: keep-alive\r\n\r\n")};
7690 MockRead data_reads[] = {
7691 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7692 MockRead("HTTP/1.0 200 OK\r\n"),
7693 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7694 MockRead("Payload"),
7695 MockRead(SYNCHRONOUS, OK)
7698 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7699 data_writes, arraysize(data_writes));
7700 session_deps_.socket_factory->AddSocketDataProvider(&data);
7702 TestCompletionCallback callback;
7704 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7705 EXPECT_EQ(ERR_IO_PENDING, rv);
7707 rv = callback.WaitForResult();
7708 EXPECT_EQ(OK, rv);
7710 const HttpResponseInfo* response = trans->GetResponseInfo();
7711 ASSERT_TRUE(response != NULL);
7713 LoadTimingInfo load_timing_info;
7714 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7715 TestLoadTimingNotReused(load_timing_info,
7716 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7718 std::string response_text;
7719 rv = ReadTransaction(trans.get(), &response_text);
7720 EXPECT_EQ(OK, rv);
7721 EXPECT_EQ("Payload", response_text);
7724 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7725 HttpRequestInfo request;
7726 request.method = "GET";
7727 request.url = GURL("http://www.example.org/");
7728 request.load_flags = 0;
7730 session_deps_.proxy_service.reset(
7731 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7732 TestNetLog net_log;
7733 session_deps_.net_log = &net_log;
7735 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7736 scoped_ptr<HttpTransaction> trans(
7737 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7739 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7740 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7741 const char kSOCKS5OkRequest[] = {
7742 0x05, // Version
7743 0x01, // Command (CONNECT)
7744 0x00, // Reserved.
7745 0x03, // Address type (DOMAINNAME).
7746 0x0F, // Length of domain (15)
7747 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7748 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7750 const char kSOCKS5OkResponse[] =
7751 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7753 MockWrite data_writes[] = {
7754 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7755 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7756 MockWrite(
7757 "GET / HTTP/1.1\r\n"
7758 "Host: www.example.org\r\n"
7759 "Connection: keep-alive\r\n\r\n")};
7761 MockRead data_reads[] = {
7762 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7763 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7764 MockRead("HTTP/1.0 200 OK\r\n"),
7765 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7766 MockRead("Payload"),
7767 MockRead(SYNCHRONOUS, OK)
7770 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7771 data_writes, arraysize(data_writes));
7772 session_deps_.socket_factory->AddSocketDataProvider(&data);
7774 TestCompletionCallback callback;
7776 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7777 EXPECT_EQ(ERR_IO_PENDING, rv);
7779 rv = callback.WaitForResult();
7780 EXPECT_EQ(OK, rv);
7782 const HttpResponseInfo* response = trans->GetResponseInfo();
7783 ASSERT_TRUE(response != NULL);
7785 LoadTimingInfo load_timing_info;
7786 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7787 TestLoadTimingNotReusedWithPac(load_timing_info,
7788 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7790 std::string response_text;
7791 rv = ReadTransaction(trans.get(), &response_text);
7792 EXPECT_EQ(OK, rv);
7793 EXPECT_EQ("Payload", response_text);
7796 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7797 HttpRequestInfo request;
7798 request.method = "GET";
7799 request.url = GURL("https://www.example.org/");
7800 request.load_flags = 0;
7802 session_deps_.proxy_service.reset(
7803 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7804 TestNetLog net_log;
7805 session_deps_.net_log = &net_log;
7807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7808 scoped_ptr<HttpTransaction> trans(
7809 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7811 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7812 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7813 const unsigned char kSOCKS5OkRequest[] = {
7814 0x05, // Version
7815 0x01, // Command (CONNECT)
7816 0x00, // Reserved.
7817 0x03, // Address type (DOMAINNAME).
7818 0x0F, // Length of domain (15)
7819 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7820 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7823 const char kSOCKS5OkResponse[] =
7824 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7826 MockWrite data_writes[] = {
7827 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7828 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7829 arraysize(kSOCKS5OkRequest)),
7830 MockWrite(
7831 "GET / HTTP/1.1\r\n"
7832 "Host: www.example.org\r\n"
7833 "Connection: keep-alive\r\n\r\n")};
7835 MockRead data_reads[] = {
7836 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7837 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7838 MockRead("HTTP/1.0 200 OK\r\n"),
7839 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7840 MockRead("Payload"),
7841 MockRead(SYNCHRONOUS, OK)
7844 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7845 data_writes, arraysize(data_writes));
7846 session_deps_.socket_factory->AddSocketDataProvider(&data);
7848 SSLSocketDataProvider ssl(ASYNC, OK);
7849 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7851 TestCompletionCallback callback;
7853 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7854 EXPECT_EQ(ERR_IO_PENDING, rv);
7856 rv = callback.WaitForResult();
7857 EXPECT_EQ(OK, rv);
7859 const HttpResponseInfo* response = trans->GetResponseInfo();
7860 ASSERT_TRUE(response != NULL);
7862 LoadTimingInfo load_timing_info;
7863 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7864 TestLoadTimingNotReusedWithPac(load_timing_info,
7865 CONNECT_TIMING_HAS_SSL_TIMES);
7867 std::string response_text;
7868 rv = ReadTransaction(trans.get(), &response_text);
7869 EXPECT_EQ(OK, rv);
7870 EXPECT_EQ("Payload", response_text);
7873 namespace {
7875 // Tests that for connection endpoints the group names are correctly set.
7877 struct GroupNameTest {
7878 std::string proxy_server;
7879 std::string url;
7880 std::string expected_group_name;
7881 bool ssl;
7884 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7885 NextProto next_proto,
7886 SpdySessionDependencies* session_deps_) {
7887 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7889 base::WeakPtr<HttpServerProperties> http_server_properties =
7890 session->http_server_properties();
7891 AlternativeService alternative_service(
7892 AlternateProtocolFromNextProto(next_proto), "", 443);
7893 http_server_properties->SetAlternativeService(
7894 HostPortPair("host.with.alternate", 80), alternative_service, 1.0);
7896 return session;
7899 int GroupNameTransactionHelper(
7900 const std::string& url,
7901 const scoped_refptr<HttpNetworkSession>& session) {
7902 HttpRequestInfo request;
7903 request.method = "GET";
7904 request.url = GURL(url);
7905 request.load_flags = 0;
7907 scoped_ptr<HttpTransaction> trans(
7908 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7910 TestCompletionCallback callback;
7912 // We do not complete this request, the dtor will clean the transaction up.
7913 return trans->Start(&request, callback.callback(), BoundNetLog());
7916 } // namespace
7918 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7919 const GroupNameTest tests[] = {
7921 "", // unused
7922 "http://www.example.org/direct",
7923 "www.example.org:80",
7924 false,
7927 "", // unused
7928 "http://[2001:1418:13:1::25]/direct",
7929 "[2001:1418:13:1::25]:80",
7930 false,
7933 // SSL Tests
7935 "", // unused
7936 "https://www.example.org/direct_ssl",
7937 "ssl/www.example.org:443",
7938 true,
7941 "", // unused
7942 "https://[2001:1418:13:1::25]/direct",
7943 "ssl/[2001:1418:13:1::25]:443",
7944 true,
7947 "", // unused
7948 "http://host.with.alternate/direct",
7949 "ssl/host.with.alternate:443",
7950 true,
7954 session_deps_.use_alternate_protocols = true;
7956 for (size_t i = 0; i < arraysize(tests); ++i) {
7957 session_deps_.proxy_service.reset(
7958 ProxyService::CreateFixed(tests[i].proxy_server));
7959 scoped_refptr<HttpNetworkSession> session(
7960 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7962 HttpNetworkSessionPeer peer(session);
7963 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7964 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7965 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7966 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7967 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7968 new MockClientSocketPoolManager);
7969 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7970 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7971 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
7973 EXPECT_EQ(ERR_IO_PENDING,
7974 GroupNameTransactionHelper(tests[i].url, session));
7975 if (tests[i].ssl)
7976 EXPECT_EQ(tests[i].expected_group_name,
7977 ssl_conn_pool->last_group_name_received());
7978 else
7979 EXPECT_EQ(tests[i].expected_group_name,
7980 transport_conn_pool->last_group_name_received());
7985 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7986 const GroupNameTest tests[] = {
7988 "http_proxy",
7989 "http://www.example.org/http_proxy_normal",
7990 "www.example.org:80",
7991 false,
7994 // SSL Tests
7996 "http_proxy",
7997 "https://www.example.org/http_connect_ssl",
7998 "ssl/www.example.org:443",
7999 true,
8003 "http_proxy",
8004 "http://host.with.alternate/direct",
8005 "ssl/host.with.alternate:443",
8006 true,
8010 "http_proxy",
8011 "ftp://ftp.google.com/http_proxy_normal",
8012 "ftp/ftp.google.com:21",
8013 false,
8017 session_deps_.use_alternate_protocols = true;
8019 for (size_t i = 0; i < arraysize(tests); ++i) {
8020 session_deps_.proxy_service.reset(
8021 ProxyService::CreateFixed(tests[i].proxy_server));
8022 scoped_refptr<HttpNetworkSession> session(
8023 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8025 HttpNetworkSessionPeer peer(session);
8027 HostPortPair proxy_host("http_proxy", 80);
8028 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
8029 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
8030 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8031 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8033 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8034 new MockClientSocketPoolManager);
8035 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8036 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8037 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8039 EXPECT_EQ(ERR_IO_PENDING,
8040 GroupNameTransactionHelper(tests[i].url, session));
8041 if (tests[i].ssl)
8042 EXPECT_EQ(tests[i].expected_group_name,
8043 ssl_conn_pool->last_group_name_received());
8044 else
8045 EXPECT_EQ(tests[i].expected_group_name,
8046 http_proxy_pool->last_group_name_received());
8050 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
8051 const GroupNameTest tests[] = {
8053 "socks4://socks_proxy:1080",
8054 "http://www.example.org/socks4_direct",
8055 "socks4/www.example.org:80",
8056 false,
8059 "socks5://socks_proxy:1080",
8060 "http://www.example.org/socks5_direct",
8061 "socks5/www.example.org:80",
8062 false,
8065 // SSL Tests
8067 "socks4://socks_proxy:1080",
8068 "https://www.example.org/socks4_ssl",
8069 "socks4/ssl/www.example.org:443",
8070 true,
8073 "socks5://socks_proxy:1080",
8074 "https://www.example.org/socks5_ssl",
8075 "socks5/ssl/www.example.org:443",
8076 true,
8080 "socks4://socks_proxy:1080",
8081 "http://host.with.alternate/direct",
8082 "socks4/ssl/host.with.alternate:443",
8083 true,
8087 session_deps_.use_alternate_protocols = true;
8089 for (size_t i = 0; i < arraysize(tests); ++i) {
8090 session_deps_.proxy_service.reset(
8091 ProxyService::CreateFixed(tests[i].proxy_server));
8092 scoped_refptr<HttpNetworkSession> session(
8093 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8095 HttpNetworkSessionPeer peer(session);
8097 HostPortPair proxy_host("socks_proxy", 1080);
8098 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
8099 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
8100 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8101 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8103 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8104 new MockClientSocketPoolManager);
8105 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8106 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8107 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8109 scoped_ptr<HttpTransaction> trans(
8110 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8112 EXPECT_EQ(ERR_IO_PENDING,
8113 GroupNameTransactionHelper(tests[i].url, session));
8114 if (tests[i].ssl)
8115 EXPECT_EQ(tests[i].expected_group_name,
8116 ssl_conn_pool->last_group_name_received());
8117 else
8118 EXPECT_EQ(tests[i].expected_group_name,
8119 socks_conn_pool->last_group_name_received());
8123 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
8124 HttpRequestInfo request;
8125 request.method = "GET";
8126 request.url = GURL("http://www.example.org/");
8128 session_deps_.proxy_service.reset(
8129 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8131 // This simulates failure resolving all hostnames; that means we will fail
8132 // connecting to both proxies (myproxy:70 and foobar:80).
8133 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
8135 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8136 scoped_ptr<HttpTransaction> trans(
8137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8139 TestCompletionCallback callback;
8141 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8142 EXPECT_EQ(ERR_IO_PENDING, rv);
8144 rv = callback.WaitForResult();
8145 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
8148 // Base test to make sure that when the load flags for a request specify to
8149 // bypass the cache, the DNS cache is not used.
8150 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8151 int load_flags) {
8152 // Issue a request, asking to bypass the cache(s).
8153 HttpRequestInfo request;
8154 request.method = "GET";
8155 request.load_flags = load_flags;
8156 request.url = GURL("http://www.example.org/");
8158 // Select a host resolver that does caching.
8159 session_deps_.host_resolver.reset(new MockCachingHostResolver);
8161 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8162 scoped_ptr<HttpTransaction> trans(
8163 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8165 // Warm up the host cache so it has an entry for "www.example.org".
8166 AddressList addrlist;
8167 TestCompletionCallback callback;
8168 int rv = session_deps_.host_resolver->Resolve(
8169 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8170 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8171 EXPECT_EQ(ERR_IO_PENDING, rv);
8172 rv = callback.WaitForResult();
8173 EXPECT_EQ(OK, rv);
8175 // Verify that it was added to host cache, by doing a subsequent async lookup
8176 // and confirming it completes synchronously.
8177 rv = session_deps_.host_resolver->Resolve(
8178 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8179 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8180 ASSERT_EQ(OK, rv);
8182 // Inject a failure the next time that "www.example.org" is resolved. This way
8183 // we can tell if the next lookup hit the cache, or the "network".
8184 // (cache --> success, "network" --> failure).
8185 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
8187 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8188 // first read -- this won't be reached as the host resolution will fail first.
8189 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
8190 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8191 session_deps_.socket_factory->AddSocketDataProvider(&data);
8193 // Run the request.
8194 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8195 ASSERT_EQ(ERR_IO_PENDING, rv);
8196 rv = callback.WaitForResult();
8198 // If we bypassed the cache, we would have gotten a failure while resolving
8199 // "www.example.org".
8200 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8203 // There are multiple load flags that should trigger the host cache bypass.
8204 // Test each in isolation:
8205 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
8206 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8209 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
8210 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8213 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
8214 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8217 // Make sure we can handle an error when writing the request.
8218 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
8219 HttpRequestInfo request;
8220 request.method = "GET";
8221 request.url = GURL("http://www.foo.com/");
8222 request.load_flags = 0;
8224 MockWrite write_failure[] = {
8225 MockWrite(ASYNC, ERR_CONNECTION_RESET),
8227 StaticSocketDataProvider data(NULL, 0,
8228 write_failure, arraysize(write_failure));
8229 session_deps_.socket_factory->AddSocketDataProvider(&data);
8230 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8232 TestCompletionCallback callback;
8234 scoped_ptr<HttpTransaction> trans(
8235 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8237 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8238 EXPECT_EQ(ERR_IO_PENDING, rv);
8240 rv = callback.WaitForResult();
8241 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
8244 // Check that a connection closed after the start of the headers finishes ok.
8245 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
8246 HttpRequestInfo request;
8247 request.method = "GET";
8248 request.url = GURL("http://www.foo.com/");
8249 request.load_flags = 0;
8251 MockRead data_reads[] = {
8252 MockRead("HTTP/1."),
8253 MockRead(SYNCHRONOUS, OK),
8256 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8257 session_deps_.socket_factory->AddSocketDataProvider(&data);
8258 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8260 TestCompletionCallback callback;
8262 scoped_ptr<HttpTransaction> trans(
8263 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8265 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8266 EXPECT_EQ(ERR_IO_PENDING, rv);
8268 rv = callback.WaitForResult();
8269 EXPECT_EQ(OK, rv);
8271 const HttpResponseInfo* response = trans->GetResponseInfo();
8272 ASSERT_TRUE(response != NULL);
8274 EXPECT_TRUE(response->headers.get() != NULL);
8275 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8277 std::string response_data;
8278 rv = ReadTransaction(trans.get(), &response_data);
8279 EXPECT_EQ(OK, rv);
8280 EXPECT_EQ("", response_data);
8283 // Make sure that a dropped connection while draining the body for auth
8284 // restart does the right thing.
8285 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
8286 HttpRequestInfo request;
8287 request.method = "GET";
8288 request.url = GURL("http://www.example.org/");
8289 request.load_flags = 0;
8291 MockWrite data_writes1[] = {
8292 MockWrite(
8293 "GET / HTTP/1.1\r\n"
8294 "Host: www.example.org\r\n"
8295 "Connection: keep-alive\r\n\r\n"),
8298 MockRead data_reads1[] = {
8299 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8300 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8301 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8302 MockRead("Content-Length: 14\r\n\r\n"),
8303 MockRead("Unauth"),
8304 MockRead(ASYNC, ERR_CONNECTION_RESET),
8307 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8308 data_writes1, arraysize(data_writes1));
8309 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8311 // After calling trans->RestartWithAuth(), this is the request we should
8312 // be issuing -- the final header line contains the credentials.
8313 MockWrite data_writes2[] = {
8314 MockWrite(
8315 "GET / HTTP/1.1\r\n"
8316 "Host: www.example.org\r\n"
8317 "Connection: keep-alive\r\n"
8318 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8321 // Lastly, the server responds with the actual content.
8322 MockRead data_reads2[] = {
8323 MockRead("HTTP/1.1 200 OK\r\n"),
8324 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8325 MockRead("Content-Length: 100\r\n\r\n"),
8326 MockRead(SYNCHRONOUS, OK),
8329 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8330 data_writes2, arraysize(data_writes2));
8331 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8334 TestCompletionCallback callback1;
8336 scoped_ptr<HttpTransaction> trans(
8337 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8339 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8340 EXPECT_EQ(ERR_IO_PENDING, rv);
8342 rv = callback1.WaitForResult();
8343 EXPECT_EQ(OK, rv);
8345 const HttpResponseInfo* response = trans->GetResponseInfo();
8346 ASSERT_TRUE(response != NULL);
8347 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8349 TestCompletionCallback callback2;
8351 rv = trans->RestartWithAuth(
8352 AuthCredentials(kFoo, kBar), callback2.callback());
8353 EXPECT_EQ(ERR_IO_PENDING, rv);
8355 rv = callback2.WaitForResult();
8356 EXPECT_EQ(OK, rv);
8358 response = trans->GetResponseInfo();
8359 ASSERT_TRUE(response != NULL);
8360 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8361 EXPECT_EQ(100, response->headers->GetContentLength());
8364 // Test HTTPS connections going through a proxy that sends extra data.
8365 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8366 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8368 HttpRequestInfo request;
8369 request.method = "GET";
8370 request.url = GURL("https://www.example.org/");
8371 request.load_flags = 0;
8373 MockRead proxy_reads[] = {
8374 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8375 MockRead(SYNCHRONOUS, OK)
8378 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8379 SSLSocketDataProvider ssl(ASYNC, OK);
8381 session_deps_.socket_factory->AddSocketDataProvider(&data);
8382 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8384 TestCompletionCallback callback;
8386 session_deps_.socket_factory->ResetNextMockIndexes();
8388 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8389 scoped_ptr<HttpTransaction> trans(
8390 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8392 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8393 EXPECT_EQ(ERR_IO_PENDING, rv);
8395 rv = callback.WaitForResult();
8396 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8399 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8400 HttpRequestInfo request;
8401 request.method = "GET";
8402 request.url = GURL("http://www.example.org/");
8403 request.load_flags = 0;
8405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8406 scoped_ptr<HttpTransaction> trans(
8407 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8409 MockRead data_reads[] = {
8410 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8411 MockRead(SYNCHRONOUS, OK),
8414 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8415 session_deps_.socket_factory->AddSocketDataProvider(&data);
8417 TestCompletionCallback callback;
8419 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8420 EXPECT_EQ(ERR_IO_PENDING, rv);
8422 EXPECT_EQ(OK, callback.WaitForResult());
8424 const HttpResponseInfo* response = trans->GetResponseInfo();
8425 ASSERT_TRUE(response != NULL);
8427 EXPECT_TRUE(response->headers.get() != NULL);
8428 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8430 std::string response_data;
8431 rv = ReadTransaction(trans.get(), &response_data);
8432 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8435 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8436 base::FilePath temp_file_path;
8437 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8438 const uint64 kFakeSize = 100000; // file is actually blank
8439 UploadFileElementReader::ScopedOverridingContentLengthForTests
8440 overriding_content_length(kFakeSize);
8442 ScopedVector<UploadElementReader> element_readers;
8443 element_readers.push_back(
8444 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8445 temp_file_path,
8447 kuint64max,
8448 base::Time()));
8449 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8451 HttpRequestInfo request;
8452 request.method = "POST";
8453 request.url = GURL("http://www.example.org/upload");
8454 request.upload_data_stream = &upload_data_stream;
8455 request.load_flags = 0;
8457 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8458 scoped_ptr<HttpTransaction> trans(
8459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8461 MockRead data_reads[] = {
8462 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8463 MockRead("hello world"),
8464 MockRead(SYNCHRONOUS, OK),
8466 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8467 session_deps_.socket_factory->AddSocketDataProvider(&data);
8469 TestCompletionCallback callback;
8471 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8472 EXPECT_EQ(ERR_IO_PENDING, rv);
8474 rv = callback.WaitForResult();
8475 EXPECT_EQ(OK, rv);
8477 const HttpResponseInfo* response = trans->GetResponseInfo();
8478 ASSERT_TRUE(response != NULL);
8480 EXPECT_TRUE(response->headers.get() != NULL);
8481 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8483 std::string response_data;
8484 rv = ReadTransaction(trans.get(), &response_data);
8485 EXPECT_EQ(OK, rv);
8486 EXPECT_EQ("hello world", response_data);
8488 base::DeleteFile(temp_file_path, false);
8491 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8492 base::FilePath temp_file;
8493 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8494 std::string temp_file_content("Unreadable file.");
8495 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8496 temp_file_content.length()));
8497 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
8499 ScopedVector<UploadElementReader> element_readers;
8500 element_readers.push_back(
8501 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8502 temp_file,
8504 kuint64max,
8505 base::Time()));
8506 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8508 HttpRequestInfo request;
8509 request.method = "POST";
8510 request.url = GURL("http://www.example.org/upload");
8511 request.upload_data_stream = &upload_data_stream;
8512 request.load_flags = 0;
8514 // If we try to upload an unreadable file, the transaction should fail.
8515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8516 scoped_ptr<HttpTransaction> trans(
8517 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8519 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8520 session_deps_.socket_factory->AddSocketDataProvider(&data);
8522 TestCompletionCallback callback;
8524 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8525 EXPECT_EQ(ERR_IO_PENDING, rv);
8527 rv = callback.WaitForResult();
8528 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8530 base::DeleteFile(temp_file, false);
8533 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8534 class FakeUploadElementReader : public UploadElementReader {
8535 public:
8536 FakeUploadElementReader() {}
8537 ~FakeUploadElementReader() override {}
8539 const CompletionCallback& callback() const { return callback_; }
8541 // UploadElementReader overrides:
8542 int Init(const CompletionCallback& callback) override {
8543 callback_ = callback;
8544 return ERR_IO_PENDING;
8546 uint64 GetContentLength() const override { return 0; }
8547 uint64 BytesRemaining() const override { return 0; }
8548 int Read(IOBuffer* buf,
8549 int buf_length,
8550 const CompletionCallback& callback) override {
8551 return ERR_FAILED;
8554 private:
8555 CompletionCallback callback_;
8558 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8559 ScopedVector<UploadElementReader> element_readers;
8560 element_readers.push_back(fake_reader);
8561 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8563 HttpRequestInfo request;
8564 request.method = "POST";
8565 request.url = GURL("http://www.example.org/upload");
8566 request.upload_data_stream = &upload_data_stream;
8567 request.load_flags = 0;
8569 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8570 scoped_ptr<HttpTransaction> trans(
8571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8573 StaticSocketDataProvider data;
8574 session_deps_.socket_factory->AddSocketDataProvider(&data);
8576 TestCompletionCallback callback;
8577 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8578 EXPECT_EQ(ERR_IO_PENDING, rv);
8579 base::MessageLoop::current()->RunUntilIdle();
8581 // Transaction is pending on request body initialization.
8582 ASSERT_FALSE(fake_reader->callback().is_null());
8584 // Return Init()'s result after the transaction gets destroyed.
8585 trans.reset();
8586 fake_reader->callback().Run(OK); // Should not crash.
8589 // Tests that changes to Auth realms are treated like auth rejections.
8590 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8592 HttpRequestInfo request;
8593 request.method = "GET";
8594 request.url = GURL("http://www.example.org/");
8595 request.load_flags = 0;
8597 // First transaction will request a resource and receive a Basic challenge
8598 // with realm="first_realm".
8599 MockWrite data_writes1[] = {
8600 MockWrite(
8601 "GET / HTTP/1.1\r\n"
8602 "Host: www.example.org\r\n"
8603 "Connection: keep-alive\r\n"
8604 "\r\n"),
8606 MockRead data_reads1[] = {
8607 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8608 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8609 "\r\n"),
8612 // After calling trans->RestartWithAuth(), provide an Authentication header
8613 // for first_realm. The server will reject and provide a challenge with
8614 // second_realm.
8615 MockWrite data_writes2[] = {
8616 MockWrite(
8617 "GET / HTTP/1.1\r\n"
8618 "Host: www.example.org\r\n"
8619 "Connection: keep-alive\r\n"
8620 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8621 "\r\n"),
8623 MockRead data_reads2[] = {
8624 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8625 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8626 "\r\n"),
8629 // This again fails, and goes back to first_realm. Make sure that the
8630 // entry is removed from cache.
8631 MockWrite data_writes3[] = {
8632 MockWrite(
8633 "GET / HTTP/1.1\r\n"
8634 "Host: www.example.org\r\n"
8635 "Connection: keep-alive\r\n"
8636 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8637 "\r\n"),
8639 MockRead data_reads3[] = {
8640 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8641 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8642 "\r\n"),
8645 // Try one last time (with the correct password) and get the resource.
8646 MockWrite data_writes4[] = {
8647 MockWrite(
8648 "GET / HTTP/1.1\r\n"
8649 "Host: www.example.org\r\n"
8650 "Connection: keep-alive\r\n"
8651 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8652 "\r\n"),
8654 MockRead data_reads4[] = {
8655 MockRead("HTTP/1.1 200 OK\r\n"
8656 "Content-Type: text/html; charset=iso-8859-1\r\n"
8657 "Content-Length: 5\r\n"
8658 "\r\n"
8659 "hello"),
8662 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8663 data_writes1, arraysize(data_writes1));
8664 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8665 data_writes2, arraysize(data_writes2));
8666 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8667 data_writes3, arraysize(data_writes3));
8668 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8669 data_writes4, arraysize(data_writes4));
8670 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8671 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8672 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8673 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8675 TestCompletionCallback callback1;
8677 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8678 scoped_ptr<HttpTransaction> trans(
8679 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8681 // Issue the first request with Authorize headers. There should be a
8682 // password prompt for first_realm waiting to be filled in after the
8683 // transaction completes.
8684 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8685 EXPECT_EQ(ERR_IO_PENDING, rv);
8686 rv = callback1.WaitForResult();
8687 EXPECT_EQ(OK, rv);
8688 const HttpResponseInfo* response = trans->GetResponseInfo();
8689 ASSERT_TRUE(response != NULL);
8690 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8691 ASSERT_FALSE(challenge == NULL);
8692 EXPECT_FALSE(challenge->is_proxy);
8693 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8694 EXPECT_EQ("first_realm", challenge->realm);
8695 EXPECT_EQ("basic", challenge->scheme);
8697 // Issue the second request with an incorrect password. There should be a
8698 // password prompt for second_realm waiting to be filled in after the
8699 // transaction completes.
8700 TestCompletionCallback callback2;
8701 rv = trans->RestartWithAuth(
8702 AuthCredentials(kFirst, kBaz), callback2.callback());
8703 EXPECT_EQ(ERR_IO_PENDING, rv);
8704 rv = callback2.WaitForResult();
8705 EXPECT_EQ(OK, rv);
8706 response = trans->GetResponseInfo();
8707 ASSERT_TRUE(response != NULL);
8708 challenge = response->auth_challenge.get();
8709 ASSERT_FALSE(challenge == NULL);
8710 EXPECT_FALSE(challenge->is_proxy);
8711 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8712 EXPECT_EQ("second_realm", challenge->realm);
8713 EXPECT_EQ("basic", challenge->scheme);
8715 // Issue the third request with another incorrect password. There should be
8716 // a password prompt for first_realm waiting to be filled in. If the password
8717 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8718 // first_realm was not correctly removed.
8719 TestCompletionCallback callback3;
8720 rv = trans->RestartWithAuth(
8721 AuthCredentials(kSecond, kFou), callback3.callback());
8722 EXPECT_EQ(ERR_IO_PENDING, rv);
8723 rv = callback3.WaitForResult();
8724 EXPECT_EQ(OK, rv);
8725 response = trans->GetResponseInfo();
8726 ASSERT_TRUE(response != NULL);
8727 challenge = response->auth_challenge.get();
8728 ASSERT_FALSE(challenge == NULL);
8729 EXPECT_FALSE(challenge->is_proxy);
8730 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8731 EXPECT_EQ("first_realm", challenge->realm);
8732 EXPECT_EQ("basic", challenge->scheme);
8734 // Issue the fourth request with the correct password and username.
8735 TestCompletionCallback callback4;
8736 rv = trans->RestartWithAuth(
8737 AuthCredentials(kFirst, kBar), callback4.callback());
8738 EXPECT_EQ(ERR_IO_PENDING, rv);
8739 rv = callback4.WaitForResult();
8740 EXPECT_EQ(OK, rv);
8741 response = trans->GetResponseInfo();
8742 ASSERT_TRUE(response != NULL);
8743 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8746 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8747 session_deps_.next_protos = SpdyNextProtos();
8748 session_deps_.use_alternate_protocols = true;
8750 std::string alternate_protocol_http_header =
8751 GetAlternateProtocolHttpHeader();
8753 MockRead data_reads[] = {
8754 MockRead("HTTP/1.1 200 OK\r\n"),
8755 MockRead(alternate_protocol_http_header.c_str()),
8756 MockRead("hello world"),
8757 MockRead(SYNCHRONOUS, OK),
8760 HttpRequestInfo request;
8761 request.method = "GET";
8762 request.url = GURL("http://www.example.org/");
8763 request.load_flags = 0;
8765 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8767 session_deps_.socket_factory->AddSocketDataProvider(&data);
8769 TestCompletionCallback callback;
8771 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8772 scoped_ptr<HttpTransaction> trans(
8773 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8775 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8776 EXPECT_EQ(ERR_IO_PENDING, rv);
8778 HostPortPair http_host_port_pair("www.example.org", 80);
8779 HttpServerProperties& http_server_properties =
8780 *session->http_server_properties();
8781 AlternativeService alternative_service =
8782 http_server_properties.GetAlternativeService(http_host_port_pair);
8783 EXPECT_EQ(alternative_service.protocol, UNINITIALIZED_ALTERNATE_PROTOCOL);
8785 EXPECT_EQ(OK, callback.WaitForResult());
8787 const HttpResponseInfo* response = trans->GetResponseInfo();
8788 ASSERT_TRUE(response != NULL);
8789 ASSERT_TRUE(response->headers.get() != NULL);
8790 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8791 EXPECT_FALSE(response->was_fetched_via_spdy);
8792 EXPECT_FALSE(response->was_npn_negotiated);
8794 std::string response_data;
8795 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8796 EXPECT_EQ("hello world", response_data);
8798 alternative_service =
8799 http_server_properties.GetAlternativeService(http_host_port_pair);
8800 EXPECT_EQ(443, alternative_service.port);
8801 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8802 alternative_service.protocol);
8805 TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
8806 session_deps_.next_protos = SpdyNextProtos();
8807 session_deps_.use_alternate_protocols = true;
8809 MockRead data_reads[] = {
8810 MockRead("HTTP/1.1 200 OK\r\n"),
8811 MockRead("Alternate-Protocol: \r\n\r\n"),
8812 MockRead("hello world"),
8813 MockRead(SYNCHRONOUS, OK),
8816 HttpRequestInfo request;
8817 request.method = "GET";
8818 request.url = GURL("http://www.example.org/");
8819 request.load_flags = 0;
8821 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8823 session_deps_.socket_factory->AddSocketDataProvider(&data);
8825 TestCompletionCallback callback;
8827 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8829 HostPortPair http_host_port_pair("www.example.org", 80);
8830 HttpServerProperties& http_server_properties =
8831 *session->http_server_properties();
8832 AlternativeService alternative_service(QUIC, "", 80);
8833 http_server_properties.SetAlternativeService(http_host_port_pair,
8834 alternative_service, 1.0);
8836 alternative_service =
8837 http_server_properties.GetAlternativeService(http_host_port_pair);
8838 EXPECT_EQ(alternative_service.protocol, QUIC);
8840 scoped_ptr<HttpTransaction> trans(
8841 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8843 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8844 EXPECT_EQ(ERR_IO_PENDING, rv);
8846 EXPECT_EQ(OK, callback.WaitForResult());
8848 const HttpResponseInfo* response = trans->GetResponseInfo();
8849 ASSERT_TRUE(response != NULL);
8850 ASSERT_TRUE(response->headers.get() != NULL);
8851 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8852 EXPECT_FALSE(response->was_fetched_via_spdy);
8853 EXPECT_FALSE(response->was_npn_negotiated);
8855 std::string response_data;
8856 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8857 EXPECT_EQ("hello world", response_data);
8859 alternative_service =
8860 http_server_properties.GetAlternativeService(http_host_port_pair);
8861 EXPECT_EQ(alternative_service.protocol, UNINITIALIZED_ALTERNATE_PROTOCOL);
8864 TEST_P(HttpNetworkTransactionTest,
8865 MarkBrokenAlternateProtocolAndFallback) {
8866 session_deps_.use_alternate_protocols = true;
8868 HttpRequestInfo request;
8869 request.method = "GET";
8870 request.url = GURL("http://www.example.org/");
8871 request.load_flags = 0;
8873 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8874 StaticSocketDataProvider first_data;
8875 first_data.set_connect_data(mock_connect);
8876 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8878 MockRead data_reads[] = {
8879 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8880 MockRead("hello world"),
8881 MockRead(ASYNC, OK),
8883 StaticSocketDataProvider second_data(
8884 data_reads, arraysize(data_reads), NULL, 0);
8885 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8887 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8889 base::WeakPtr<HttpServerProperties> http_server_properties =
8890 session->http_server_properties();
8891 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
8892 // Port must be < 1024, or the header will be ignored (since initial port was
8893 // port 80 (another restricted port).
8894 AlternativeService alternative_service(
8895 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8896 666); /* port is ignored by MockConnect anyway */
8897 http_server_properties->SetAlternativeService(host_port_pair,
8898 alternative_service, 1.0);
8900 scoped_ptr<HttpTransaction> trans(
8901 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8902 TestCompletionCallback callback;
8904 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8905 EXPECT_EQ(ERR_IO_PENDING, rv);
8906 EXPECT_EQ(OK, callback.WaitForResult());
8908 const HttpResponseInfo* response = trans->GetResponseInfo();
8909 ASSERT_TRUE(response != NULL);
8910 ASSERT_TRUE(response->headers.get() != NULL);
8911 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8913 std::string response_data;
8914 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8915 EXPECT_EQ("hello world", response_data);
8917 alternative_service =
8918 http_server_properties->GetAlternativeService(host_port_pair);
8919 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL, alternative_service.protocol);
8920 EXPECT_TRUE(
8921 http_server_properties->IsAlternativeServiceBroken(alternative_service));
8924 TEST_P(HttpNetworkTransactionTest,
8925 AlternateProtocolPortRestrictedBlocked) {
8926 // Ensure that we're not allowed to redirect traffic via an alternate
8927 // protocol to an unrestricted (port >= 1024) when the original traffic was
8928 // on a restricted port (port < 1024). Ensure that we can redirect in all
8929 // other cases.
8930 session_deps_.use_alternate_protocols = true;
8932 HttpRequestInfo restricted_port_request;
8933 restricted_port_request.method = "GET";
8934 restricted_port_request.url = GURL("http://www.example.org:1023/");
8935 restricted_port_request.load_flags = 0;
8937 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8938 StaticSocketDataProvider first_data;
8939 first_data.set_connect_data(mock_connect);
8940 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8942 MockRead data_reads[] = {
8943 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8944 MockRead("hello world"),
8945 MockRead(ASYNC, OK),
8947 StaticSocketDataProvider second_data(
8948 data_reads, arraysize(data_reads), NULL, 0);
8949 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8951 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8953 base::WeakPtr<HttpServerProperties> http_server_properties =
8954 session->http_server_properties();
8955 const int kUnrestrictedAlternatePort = 1024;
8956 AlternativeService alternative_service(
8957 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8958 kUnrestrictedAlternatePort);
8959 http_server_properties->SetAlternativeService(
8960 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
8961 1.0);
8963 scoped_ptr<HttpTransaction> trans(
8964 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8965 TestCompletionCallback callback;
8967 int rv = trans->Start(
8968 &restricted_port_request,
8969 callback.callback(), BoundNetLog());
8970 EXPECT_EQ(ERR_IO_PENDING, rv);
8971 // Invalid change to unrestricted port should fail.
8972 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8975 TEST_P(HttpNetworkTransactionTest,
8976 AlternateProtocolPortRestrictedPermitted) {
8977 // Ensure that we're allowed to redirect traffic via an alternate
8978 // protocol to an unrestricted (port >= 1024) when the original traffic was
8979 // on a restricted port (port < 1024) if we set
8980 // enable_user_alternate_protocol_ports.
8982 session_deps_.use_alternate_protocols = true;
8983 session_deps_.enable_user_alternate_protocol_ports = true;
8985 HttpRequestInfo restricted_port_request;
8986 restricted_port_request.method = "GET";
8987 restricted_port_request.url = GURL("http://www.example.org:1023/");
8988 restricted_port_request.load_flags = 0;
8990 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8991 StaticSocketDataProvider first_data;
8992 first_data.set_connect_data(mock_connect);
8993 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8995 MockRead data_reads[] = {
8996 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8997 MockRead("hello world"),
8998 MockRead(ASYNC, OK),
9000 StaticSocketDataProvider second_data(
9001 data_reads, arraysize(data_reads), NULL, 0);
9002 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9004 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9006 base::WeakPtr<HttpServerProperties> http_server_properties =
9007 session->http_server_properties();
9008 const int kUnrestrictedAlternatePort = 1024;
9009 AlternativeService alternative_service(
9010 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9011 kUnrestrictedAlternatePort);
9012 http_server_properties->SetAlternativeService(
9013 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9014 1.0);
9016 scoped_ptr<HttpTransaction> trans(
9017 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9018 TestCompletionCallback callback;
9020 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
9021 &restricted_port_request,
9022 callback.callback(), BoundNetLog()));
9023 // Change to unrestricted port should succeed.
9024 EXPECT_EQ(OK, callback.WaitForResult());
9027 TEST_P(HttpNetworkTransactionTest,
9028 AlternateProtocolPortRestrictedAllowed) {
9029 // Ensure that we're not allowed to redirect traffic via an alternate
9030 // protocol to an unrestricted (port >= 1024) when the original traffic was
9031 // on a restricted port (port < 1024). Ensure that we can redirect in all
9032 // other cases.
9033 session_deps_.use_alternate_protocols = true;
9035 HttpRequestInfo restricted_port_request;
9036 restricted_port_request.method = "GET";
9037 restricted_port_request.url = GURL("http://www.example.org:1023/");
9038 restricted_port_request.load_flags = 0;
9040 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9041 StaticSocketDataProvider first_data;
9042 first_data.set_connect_data(mock_connect);
9043 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9045 MockRead data_reads[] = {
9046 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9047 MockRead("hello world"),
9048 MockRead(ASYNC, OK),
9050 StaticSocketDataProvider second_data(
9051 data_reads, arraysize(data_reads), NULL, 0);
9052 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9054 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9056 base::WeakPtr<HttpServerProperties> http_server_properties =
9057 session->http_server_properties();
9058 const int kRestrictedAlternatePort = 80;
9059 AlternativeService alternative_service(
9060 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9061 kRestrictedAlternatePort);
9062 http_server_properties->SetAlternativeService(
9063 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9064 1.0);
9066 scoped_ptr<HttpTransaction> trans(
9067 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9068 TestCompletionCallback callback;
9070 int rv = trans->Start(
9071 &restricted_port_request,
9072 callback.callback(), BoundNetLog());
9073 EXPECT_EQ(ERR_IO_PENDING, rv);
9074 // Valid change to restricted port should pass.
9075 EXPECT_EQ(OK, callback.WaitForResult());
9078 TEST_P(HttpNetworkTransactionTest,
9079 AlternateProtocolPortUnrestrictedAllowed1) {
9080 // Ensure that we're not allowed to redirect traffic via an alternate
9081 // protocol to an unrestricted (port >= 1024) when the original traffic was
9082 // on a restricted port (port < 1024). Ensure that we can redirect in all
9083 // other cases.
9084 session_deps_.use_alternate_protocols = true;
9086 HttpRequestInfo unrestricted_port_request;
9087 unrestricted_port_request.method = "GET";
9088 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9089 unrestricted_port_request.load_flags = 0;
9091 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9092 StaticSocketDataProvider first_data;
9093 first_data.set_connect_data(mock_connect);
9094 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9096 MockRead data_reads[] = {
9097 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9098 MockRead("hello world"),
9099 MockRead(ASYNC, OK),
9101 StaticSocketDataProvider second_data(
9102 data_reads, arraysize(data_reads), NULL, 0);
9103 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9105 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9107 base::WeakPtr<HttpServerProperties> http_server_properties =
9108 session->http_server_properties();
9109 const int kRestrictedAlternatePort = 80;
9110 AlternativeService alternative_service(
9111 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9112 kRestrictedAlternatePort);
9113 http_server_properties->SetAlternativeService(
9114 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9115 1.0);
9117 scoped_ptr<HttpTransaction> trans(
9118 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9119 TestCompletionCallback callback;
9121 int rv = trans->Start(
9122 &unrestricted_port_request, callback.callback(), BoundNetLog());
9123 EXPECT_EQ(ERR_IO_PENDING, rv);
9124 // Valid change to restricted port should pass.
9125 EXPECT_EQ(OK, callback.WaitForResult());
9128 TEST_P(HttpNetworkTransactionTest,
9129 AlternateProtocolPortUnrestrictedAllowed2) {
9130 // Ensure that we're not allowed to redirect traffic via an alternate
9131 // protocol to an unrestricted (port >= 1024) when the original traffic was
9132 // on a restricted port (port < 1024). Ensure that we can redirect in all
9133 // other cases.
9134 session_deps_.use_alternate_protocols = true;
9136 HttpRequestInfo unrestricted_port_request;
9137 unrestricted_port_request.method = "GET";
9138 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9139 unrestricted_port_request.load_flags = 0;
9141 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9142 StaticSocketDataProvider first_data;
9143 first_data.set_connect_data(mock_connect);
9144 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9146 MockRead data_reads[] = {
9147 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9148 MockRead("hello world"),
9149 MockRead(ASYNC, OK),
9151 StaticSocketDataProvider second_data(
9152 data_reads, arraysize(data_reads), NULL, 0);
9153 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9155 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9157 base::WeakPtr<HttpServerProperties> http_server_properties =
9158 session->http_server_properties();
9159 const int kUnrestrictedAlternatePort = 1024;
9160 AlternativeService alternative_service(
9161 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9162 kUnrestrictedAlternatePort);
9163 http_server_properties->SetAlternativeService(
9164 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9165 1.0);
9167 scoped_ptr<HttpTransaction> trans(
9168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9169 TestCompletionCallback callback;
9171 int rv = trans->Start(
9172 &unrestricted_port_request, callback.callback(), BoundNetLog());
9173 EXPECT_EQ(ERR_IO_PENDING, rv);
9174 // Valid change to an unrestricted port should pass.
9175 EXPECT_EQ(OK, callback.WaitForResult());
9178 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
9179 // Ensure that we're not allowed to redirect traffic via an alternate
9180 // protocol to an unsafe port, and that we resume the second
9181 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9182 session_deps_.use_alternate_protocols = true;
9184 HttpRequestInfo request;
9185 request.method = "GET";
9186 request.url = GURL("http://www.example.org/");
9187 request.load_flags = 0;
9189 // The alternate protocol request will error out before we attempt to connect,
9190 // so only the standard HTTP request will try to connect.
9191 MockRead data_reads[] = {
9192 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9193 MockRead("hello world"),
9194 MockRead(ASYNC, OK),
9196 StaticSocketDataProvider data(
9197 data_reads, arraysize(data_reads), NULL, 0);
9198 session_deps_.socket_factory->AddSocketDataProvider(&data);
9200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9202 base::WeakPtr<HttpServerProperties> http_server_properties =
9203 session->http_server_properties();
9204 const int kUnsafePort = 7;
9205 AlternativeService alternative_service(
9206 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9207 kUnsafePort);
9208 http_server_properties->SetAlternativeService(
9209 HostPortPair::FromURL(request.url), alternative_service, 1.0);
9211 scoped_ptr<HttpTransaction> trans(
9212 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9213 TestCompletionCallback callback;
9215 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9216 EXPECT_EQ(ERR_IO_PENDING, rv);
9217 // The HTTP request should succeed.
9218 EXPECT_EQ(OK, callback.WaitForResult());
9220 // Disable alternate protocol before the asserts.
9221 // HttpStreamFactory::set_use_alternate_protocols(false);
9223 const HttpResponseInfo* response = trans->GetResponseInfo();
9224 ASSERT_TRUE(response != NULL);
9225 ASSERT_TRUE(response->headers.get() != NULL);
9226 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9228 std::string response_data;
9229 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9230 EXPECT_EQ("hello world", response_data);
9233 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
9234 session_deps_.use_alternate_protocols = true;
9235 session_deps_.next_protos = SpdyNextProtos();
9237 HttpRequestInfo request;
9238 request.method = "GET";
9239 request.url = GURL("http://www.example.org/");
9240 request.load_flags = 0;
9242 std::string alternate_protocol_http_header =
9243 GetAlternateProtocolHttpHeader();
9245 MockRead data_reads[] = {
9246 MockRead("HTTP/1.1 200 OK\r\n"),
9247 MockRead(alternate_protocol_http_header.c_str()),
9248 MockRead("hello world"),
9249 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9250 MockRead(ASYNC, OK)
9253 StaticSocketDataProvider first_transaction(
9254 data_reads, arraysize(data_reads), NULL, 0);
9255 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9257 SSLSocketDataProvider ssl(ASYNC, OK);
9258 ssl.SetNextProto(GetParam());
9259 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9260 ASSERT_TRUE(ssl.cert.get());
9261 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9263 scoped_ptr<SpdyFrame> req(
9264 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9265 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9267 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9268 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9269 MockRead spdy_reads[] = {
9270 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9273 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9274 arraysize(spdy_writes));
9275 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9277 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9278 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9279 NULL, 0, NULL, 0);
9280 hanging_non_alternate_protocol_socket.set_connect_data(
9281 never_finishing_connect);
9282 session_deps_.socket_factory->AddSocketDataProvider(
9283 &hanging_non_alternate_protocol_socket);
9285 TestCompletionCallback callback;
9287 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9288 scoped_ptr<HttpTransaction> trans(
9289 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9291 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9292 EXPECT_EQ(ERR_IO_PENDING, rv);
9293 EXPECT_EQ(OK, callback.WaitForResult());
9295 const HttpResponseInfo* response = trans->GetResponseInfo();
9296 ASSERT_TRUE(response != NULL);
9297 ASSERT_TRUE(response->headers.get() != NULL);
9298 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9300 std::string response_data;
9301 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9302 EXPECT_EQ("hello world", response_data);
9304 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9306 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9307 EXPECT_EQ(ERR_IO_PENDING, rv);
9308 EXPECT_EQ(OK, callback.WaitForResult());
9310 response = trans->GetResponseInfo();
9311 ASSERT_TRUE(response != NULL);
9312 ASSERT_TRUE(response->headers.get() != NULL);
9313 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9314 EXPECT_TRUE(response->was_fetched_via_spdy);
9315 EXPECT_TRUE(response->was_npn_negotiated);
9317 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9318 EXPECT_EQ("hello!", response_data);
9321 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
9322 session_deps_.use_alternate_protocols = true;
9323 session_deps_.next_protos = SpdyNextProtos();
9325 HttpRequestInfo request;
9326 request.method = "GET";
9327 request.url = GURL("http://www.example.org/");
9328 request.load_flags = 0;
9330 std::string alternate_protocol_http_header =
9331 GetAlternateProtocolHttpHeader();
9333 MockRead data_reads[] = {
9334 MockRead("HTTP/1.1 200 OK\r\n"),
9335 MockRead(alternate_protocol_http_header.c_str()),
9336 MockRead("hello world"),
9337 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9338 MockRead(ASYNC, OK),
9341 StaticSocketDataProvider first_transaction(
9342 data_reads, arraysize(data_reads), NULL, 0);
9343 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9344 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9346 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9347 StaticSocketDataProvider hanging_socket(
9348 NULL, 0, NULL, 0);
9349 hanging_socket.set_connect_data(never_finishing_connect);
9350 // Socket 2 and 3 are the hanging Alternate-Protocol and
9351 // non-Alternate-Protocol jobs from the 2nd transaction.
9352 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9353 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9355 SSLSocketDataProvider ssl(ASYNC, OK);
9356 ssl.SetNextProto(GetParam());
9357 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9358 ASSERT_TRUE(ssl.cert.get());
9359 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9361 scoped_ptr<SpdyFrame> req1(
9362 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9363 scoped_ptr<SpdyFrame> req2(
9364 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9365 MockWrite spdy_writes[] = {
9366 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
9368 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9369 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
9370 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9371 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9372 MockRead spdy_reads[] = {
9373 CreateMockRead(*resp1, 2),
9374 CreateMockRead(*data1, 3),
9375 CreateMockRead(*resp2, 4),
9376 CreateMockRead(*data2, 5),
9377 MockRead(ASYNC, 0, 6),
9380 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9381 arraysize(spdy_writes));
9382 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9383 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9385 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9386 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9388 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9389 TestCompletionCallback callback1;
9390 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9392 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
9393 EXPECT_EQ(ERR_IO_PENDING, rv);
9394 EXPECT_EQ(OK, callback1.WaitForResult());
9396 const HttpResponseInfo* response = trans1.GetResponseInfo();
9397 ASSERT_TRUE(response != NULL);
9398 ASSERT_TRUE(response->headers.get() != NULL);
9399 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9401 std::string response_data;
9402 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9403 EXPECT_EQ("hello world", response_data);
9405 TestCompletionCallback callback2;
9406 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9407 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
9408 EXPECT_EQ(ERR_IO_PENDING, rv);
9410 TestCompletionCallback callback3;
9411 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
9412 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
9413 EXPECT_EQ(ERR_IO_PENDING, rv);
9415 EXPECT_EQ(OK, callback2.WaitForResult());
9416 EXPECT_EQ(OK, callback3.WaitForResult());
9418 response = trans2.GetResponseInfo();
9419 ASSERT_TRUE(response != NULL);
9420 ASSERT_TRUE(response->headers.get() != NULL);
9421 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9422 EXPECT_TRUE(response->was_fetched_via_spdy);
9423 EXPECT_TRUE(response->was_npn_negotiated);
9424 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9425 EXPECT_EQ("hello!", response_data);
9427 response = trans3.GetResponseInfo();
9428 ASSERT_TRUE(response != NULL);
9429 ASSERT_TRUE(response->headers.get() != NULL);
9430 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9431 EXPECT_TRUE(response->was_fetched_via_spdy);
9432 EXPECT_TRUE(response->was_npn_negotiated);
9433 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9434 EXPECT_EQ("hello!", response_data);
9437 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9438 session_deps_.use_alternate_protocols = true;
9439 session_deps_.next_protos = SpdyNextProtos();
9441 HttpRequestInfo request;
9442 request.method = "GET";
9443 request.url = GURL("http://www.example.org/");
9444 request.load_flags = 0;
9446 std::string alternate_protocol_http_header =
9447 GetAlternateProtocolHttpHeader();
9449 MockRead data_reads[] = {
9450 MockRead("HTTP/1.1 200 OK\r\n"),
9451 MockRead(alternate_protocol_http_header.c_str()),
9452 MockRead("hello world"),
9453 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9454 MockRead(ASYNC, OK),
9457 StaticSocketDataProvider first_transaction(
9458 data_reads, arraysize(data_reads), NULL, 0);
9459 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9461 SSLSocketDataProvider ssl(ASYNC, OK);
9462 ssl.SetNextProto(GetParam());
9463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9465 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9466 StaticSocketDataProvider hanging_alternate_protocol_socket(
9467 NULL, 0, NULL, 0);
9468 hanging_alternate_protocol_socket.set_connect_data(
9469 never_finishing_connect);
9470 session_deps_.socket_factory->AddSocketDataProvider(
9471 &hanging_alternate_protocol_socket);
9473 // 2nd request is just a copy of the first one, over HTTP again.
9474 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9476 TestCompletionCallback callback;
9478 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9479 scoped_ptr<HttpTransaction> trans(
9480 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9482 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9483 EXPECT_EQ(ERR_IO_PENDING, rv);
9484 EXPECT_EQ(OK, callback.WaitForResult());
9486 const HttpResponseInfo* response = trans->GetResponseInfo();
9487 ASSERT_TRUE(response != NULL);
9488 ASSERT_TRUE(response->headers.get() != NULL);
9489 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9491 std::string response_data;
9492 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9493 EXPECT_EQ("hello world", response_data);
9495 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9497 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9498 EXPECT_EQ(ERR_IO_PENDING, rv);
9499 EXPECT_EQ(OK, callback.WaitForResult());
9501 response = trans->GetResponseInfo();
9502 ASSERT_TRUE(response != NULL);
9503 ASSERT_TRUE(response->headers.get() != NULL);
9504 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9505 EXPECT_FALSE(response->was_fetched_via_spdy);
9506 EXPECT_FALSE(response->was_npn_negotiated);
9508 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9509 EXPECT_EQ("hello world", response_data);
9512 class CapturingProxyResolver : public ProxyResolver {
9513 public:
9514 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9515 ~CapturingProxyResolver() override {}
9517 int GetProxyForURL(const GURL& url,
9518 ProxyInfo* results,
9519 const CompletionCallback& callback,
9520 RequestHandle* request,
9521 const BoundNetLog& net_log) override {
9522 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9523 HostPortPair("myproxy", 80));
9524 results->UseProxyServer(proxy_server);
9525 resolved_.push_back(url);
9526 return OK;
9529 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
9531 LoadState GetLoadState(RequestHandle request) const override {
9532 NOTREACHED();
9533 return LOAD_STATE_IDLE;
9536 void CancelSetPacScript() override { NOTREACHED(); }
9538 int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9539 const CompletionCallback& /*callback*/) override {
9540 return OK;
9543 const std::vector<GURL>& resolved() const { return resolved_; }
9545 private:
9546 std::vector<GURL> resolved_;
9548 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9551 class CapturingProxyResolverFactory : public ProxyResolverFactory {
9552 public:
9553 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
9554 : ProxyResolverFactory(false), resolver_(resolver) {}
9556 int CreateProxyResolver(
9557 const scoped_refptr<ProxyResolverScriptData>& pac_script,
9558 scoped_ptr<ProxyResolver>* resolver,
9559 const net::CompletionCallback& callback,
9560 scoped_ptr<Request>* request) override {
9561 resolver->reset(new ForwardingProxyResolver(resolver_));
9562 return OK;
9565 private:
9566 ProxyResolver* resolver_;
9569 TEST_P(HttpNetworkTransactionTest,
9570 UseAlternateProtocolForTunneledNpnSpdy) {
9571 session_deps_.use_alternate_protocols = true;
9572 session_deps_.next_protos = SpdyNextProtos();
9574 ProxyConfig proxy_config;
9575 proxy_config.set_auto_detect(true);
9576 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9578 CapturingProxyResolver capturing_proxy_resolver;
9579 session_deps_.proxy_service.reset(new ProxyService(
9580 new ProxyConfigServiceFixed(proxy_config),
9581 make_scoped_ptr(
9582 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
9583 NULL));
9584 TestNetLog net_log;
9585 session_deps_.net_log = &net_log;
9587 HttpRequestInfo request;
9588 request.method = "GET";
9589 request.url = GURL("http://www.example.org/");
9590 request.load_flags = 0;
9592 std::string alternate_protocol_http_header =
9593 GetAlternateProtocolHttpHeader();
9595 MockRead data_reads[] = {
9596 MockRead("HTTP/1.1 200 OK\r\n"),
9597 MockRead(alternate_protocol_http_header.c_str()),
9598 MockRead("hello world"),
9599 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9600 MockRead(ASYNC, OK),
9603 StaticSocketDataProvider first_transaction(
9604 data_reads, arraysize(data_reads), NULL, 0);
9605 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9607 SSLSocketDataProvider ssl(ASYNC, OK);
9608 ssl.SetNextProto(GetParam());
9609 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9610 ASSERT_TRUE(ssl.cert.get());
9611 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9613 scoped_ptr<SpdyFrame> req(
9614 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9615 MockWrite spdy_writes[] = {
9616 MockWrite(ASYNC, 0,
9617 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9618 "Host: www.example.org\r\n"
9619 "Proxy-Connection: keep-alive\r\n\r\n"),
9620 CreateMockWrite(*req, 2),
9623 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9625 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9626 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9627 MockRead spdy_reads[] = {
9628 MockRead(ASYNC, 1, kCONNECTResponse),
9629 CreateMockRead(*resp.get(), 3),
9630 CreateMockRead(*data.get(), 4),
9631 MockRead(ASYNC, ERR_IO_PENDING, 5),
9634 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9635 arraysize(spdy_writes));
9636 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9638 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9639 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9640 NULL, 0, NULL, 0);
9641 hanging_non_alternate_protocol_socket.set_connect_data(
9642 never_finishing_connect);
9643 session_deps_.socket_factory->AddSocketDataProvider(
9644 &hanging_non_alternate_protocol_socket);
9646 TestCompletionCallback callback;
9648 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9649 scoped_ptr<HttpTransaction> trans(
9650 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9652 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9653 EXPECT_EQ(ERR_IO_PENDING, rv);
9654 EXPECT_EQ(OK, callback.WaitForResult());
9656 const HttpResponseInfo* response = trans->GetResponseInfo();
9657 ASSERT_TRUE(response != NULL);
9658 ASSERT_TRUE(response->headers.get() != NULL);
9659 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9660 EXPECT_FALSE(response->was_fetched_via_spdy);
9661 EXPECT_FALSE(response->was_npn_negotiated);
9663 std::string response_data;
9664 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9665 EXPECT_EQ("hello world", response_data);
9667 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9669 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9670 EXPECT_EQ(ERR_IO_PENDING, rv);
9671 EXPECT_EQ(OK, callback.WaitForResult());
9673 response = trans->GetResponseInfo();
9674 ASSERT_TRUE(response != NULL);
9675 ASSERT_TRUE(response->headers.get() != NULL);
9676 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9677 EXPECT_TRUE(response->was_fetched_via_spdy);
9678 EXPECT_TRUE(response->was_npn_negotiated);
9680 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9681 EXPECT_EQ("hello!", response_data);
9682 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
9683 EXPECT_EQ("http://www.example.org/",
9684 capturing_proxy_resolver.resolved()[0].spec());
9685 EXPECT_EQ("https://www.example.org/",
9686 capturing_proxy_resolver.resolved()[1].spec());
9688 LoadTimingInfo load_timing_info;
9689 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9690 TestLoadTimingNotReusedWithPac(load_timing_info,
9691 CONNECT_TIMING_HAS_SSL_TIMES);
9694 TEST_P(HttpNetworkTransactionTest,
9695 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9696 session_deps_.use_alternate_protocols = true;
9697 session_deps_.next_protos = SpdyNextProtos();
9699 HttpRequestInfo request;
9700 request.method = "GET";
9701 request.url = GURL("http://www.example.org/");
9702 request.load_flags = 0;
9704 std::string alternate_protocol_http_header =
9705 GetAlternateProtocolHttpHeader();
9707 MockRead data_reads[] = {
9708 MockRead("HTTP/1.1 200 OK\r\n"),
9709 MockRead(alternate_protocol_http_header.c_str()),
9710 MockRead("hello world"),
9711 MockRead(ASYNC, OK),
9714 StaticSocketDataProvider first_transaction(
9715 data_reads, arraysize(data_reads), NULL, 0);
9716 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9718 SSLSocketDataProvider ssl(ASYNC, OK);
9719 ssl.SetNextProto(GetParam());
9720 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9721 ASSERT_TRUE(ssl.cert.get());
9722 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9724 scoped_ptr<SpdyFrame> req(
9725 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9726 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9728 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9729 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9730 MockRead spdy_reads[] = {
9731 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9734 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9735 arraysize(spdy_writes));
9736 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9738 TestCompletionCallback callback;
9740 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9742 scoped_ptr<HttpTransaction> trans(
9743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9745 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9746 EXPECT_EQ(ERR_IO_PENDING, rv);
9747 EXPECT_EQ(OK, callback.WaitForResult());
9749 const HttpResponseInfo* response = trans->GetResponseInfo();
9750 ASSERT_TRUE(response != NULL);
9751 ASSERT_TRUE(response->headers.get() != NULL);
9752 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9754 std::string response_data;
9755 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9756 EXPECT_EQ("hello world", response_data);
9758 // Set up an initial SpdySession in the pool to reuse.
9759 HostPortPair host_port_pair("www.example.org", 443);
9760 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9761 PRIVACY_MODE_DISABLED);
9762 base::WeakPtr<SpdySession> spdy_session =
9763 CreateSecureSpdySession(session, key, BoundNetLog());
9765 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9767 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9768 EXPECT_EQ(ERR_IO_PENDING, rv);
9769 EXPECT_EQ(OK, callback.WaitForResult());
9771 response = trans->GetResponseInfo();
9772 ASSERT_TRUE(response != NULL);
9773 ASSERT_TRUE(response->headers.get() != NULL);
9774 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9775 EXPECT_TRUE(response->was_fetched_via_spdy);
9776 EXPECT_TRUE(response->was_npn_negotiated);
9778 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9779 EXPECT_EQ("hello!", response_data);
9782 // GenerateAuthToken is a mighty big test.
9783 // It tests all permutation of GenerateAuthToken behavior:
9784 // - Synchronous and Asynchronous completion.
9785 // - OK or error on completion.
9786 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9787 // - HTTP or HTTPS backend (to include proxy tunneling).
9788 // - Non-authenticating and authenticating backend.
9790 // In all, there are 44 reasonable permuations (for example, if there are
9791 // problems generating an auth token for an authenticating proxy, we don't
9792 // need to test all permutations of the backend server).
9794 // The test proceeds by going over each of the configuration cases, and
9795 // potentially running up to three rounds in each of the tests. The TestConfig
9796 // specifies both the configuration for the test as well as the expectations
9797 // for the results.
9798 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9799 static const char kServer[] = "http://www.example.com";
9800 static const char kSecureServer[] = "https://www.example.com";
9801 static const char kProxy[] = "myproxy:70";
9802 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9804 enum AuthTiming {
9805 AUTH_NONE,
9806 AUTH_SYNC,
9807 AUTH_ASYNC,
9810 const MockWrite kGet(
9811 "GET / HTTP/1.1\r\n"
9812 "Host: www.example.com\r\n"
9813 "Connection: keep-alive\r\n\r\n");
9814 const MockWrite kGetProxy(
9815 "GET http://www.example.com/ HTTP/1.1\r\n"
9816 "Host: www.example.com\r\n"
9817 "Proxy-Connection: keep-alive\r\n\r\n");
9818 const MockWrite kGetAuth(
9819 "GET / HTTP/1.1\r\n"
9820 "Host: www.example.com\r\n"
9821 "Connection: keep-alive\r\n"
9822 "Authorization: auth_token\r\n\r\n");
9823 const MockWrite kGetProxyAuth(
9824 "GET http://www.example.com/ HTTP/1.1\r\n"
9825 "Host: www.example.com\r\n"
9826 "Proxy-Connection: keep-alive\r\n"
9827 "Proxy-Authorization: auth_token\r\n\r\n");
9828 const MockWrite kGetAuthThroughProxy(
9829 "GET http://www.example.com/ HTTP/1.1\r\n"
9830 "Host: www.example.com\r\n"
9831 "Proxy-Connection: keep-alive\r\n"
9832 "Authorization: auth_token\r\n\r\n");
9833 const MockWrite kGetAuthWithProxyAuth(
9834 "GET http://www.example.com/ HTTP/1.1\r\n"
9835 "Host: www.example.com\r\n"
9836 "Proxy-Connection: keep-alive\r\n"
9837 "Proxy-Authorization: auth_token\r\n"
9838 "Authorization: auth_token\r\n\r\n");
9839 const MockWrite kConnect(
9840 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9841 "Host: www.example.com\r\n"
9842 "Proxy-Connection: keep-alive\r\n\r\n");
9843 const MockWrite kConnectProxyAuth(
9844 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9845 "Host: www.example.com\r\n"
9846 "Proxy-Connection: keep-alive\r\n"
9847 "Proxy-Authorization: auth_token\r\n\r\n");
9849 const MockRead kSuccess(
9850 "HTTP/1.1 200 OK\r\n"
9851 "Content-Type: text/html; charset=iso-8859-1\r\n"
9852 "Content-Length: 3\r\n\r\n"
9853 "Yes");
9854 const MockRead kFailure(
9855 "Should not be called.");
9856 const MockRead kServerChallenge(
9857 "HTTP/1.1 401 Unauthorized\r\n"
9858 "WWW-Authenticate: Mock realm=server\r\n"
9859 "Content-Type: text/html; charset=iso-8859-1\r\n"
9860 "Content-Length: 14\r\n\r\n"
9861 "Unauthorized\r\n");
9862 const MockRead kProxyChallenge(
9863 "HTTP/1.1 407 Unauthorized\r\n"
9864 "Proxy-Authenticate: Mock realm=proxy\r\n"
9865 "Proxy-Connection: close\r\n"
9866 "Content-Type: text/html; charset=iso-8859-1\r\n"
9867 "Content-Length: 14\r\n\r\n"
9868 "Unauthorized\r\n");
9869 const MockRead kProxyConnected(
9870 "HTTP/1.1 200 Connection Established\r\n\r\n");
9872 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9873 // no constructors, but the C++ compiler on Windows warns about
9874 // unspecified data in compound literals. So, moved to using constructors,
9875 // and TestRound's created with the default constructor should not be used.
9876 struct TestRound {
9877 TestRound()
9878 : expected_rv(ERR_UNEXPECTED),
9879 extra_write(NULL),
9880 extra_read(NULL) {
9882 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9883 int expected_rv_arg)
9884 : write(write_arg),
9885 read(read_arg),
9886 expected_rv(expected_rv_arg),
9887 extra_write(NULL),
9888 extra_read(NULL) {
9890 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9891 int expected_rv_arg, const MockWrite* extra_write_arg,
9892 const MockRead* extra_read_arg)
9893 : write(write_arg),
9894 read(read_arg),
9895 expected_rv(expected_rv_arg),
9896 extra_write(extra_write_arg),
9897 extra_read(extra_read_arg) {
9899 MockWrite write;
9900 MockRead read;
9901 int expected_rv;
9902 const MockWrite* extra_write;
9903 const MockRead* extra_read;
9906 static const int kNoSSL = 500;
9908 struct TestConfig {
9909 const char* const proxy_url;
9910 AuthTiming proxy_auth_timing;
9911 int proxy_auth_rv;
9912 const char* const server_url;
9913 AuthTiming server_auth_timing;
9914 int server_auth_rv;
9915 int num_auth_rounds;
9916 int first_ssl_round;
9917 TestRound rounds[3];
9918 } test_configs[] = {
9919 // Non-authenticating HTTP server with a direct connection.
9920 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9921 { TestRound(kGet, kSuccess, OK)}},
9922 // Authenticating HTTP server with a direct connection.
9923 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9924 { TestRound(kGet, kServerChallenge, OK),
9925 TestRound(kGetAuth, kSuccess, OK)}},
9926 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9927 { TestRound(kGet, kServerChallenge, OK),
9928 TestRound(kGetAuth, kFailure, kAuthErr)}},
9929 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9930 { TestRound(kGet, kServerChallenge, OK),
9931 TestRound(kGetAuth, kSuccess, OK)}},
9932 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9933 { TestRound(kGet, kServerChallenge, OK),
9934 TestRound(kGetAuth, kFailure, kAuthErr)}},
9935 // Non-authenticating HTTP server through a non-authenticating proxy.
9936 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9937 { TestRound(kGetProxy, kSuccess, OK)}},
9938 // Authenticating HTTP server through a non-authenticating proxy.
9939 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9940 { TestRound(kGetProxy, kServerChallenge, OK),
9941 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9942 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9943 { TestRound(kGetProxy, kServerChallenge, OK),
9944 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9945 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9946 { TestRound(kGetProxy, kServerChallenge, OK),
9947 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9948 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9949 { TestRound(kGetProxy, kServerChallenge, OK),
9950 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9951 // Non-authenticating HTTP server through an authenticating proxy.
9952 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9953 { TestRound(kGetProxy, kProxyChallenge, OK),
9954 TestRound(kGetProxyAuth, kSuccess, OK)}},
9955 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9956 { TestRound(kGetProxy, kProxyChallenge, OK),
9957 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9958 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9959 { TestRound(kGetProxy, kProxyChallenge, OK),
9960 TestRound(kGetProxyAuth, kSuccess, OK)}},
9961 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9962 { TestRound(kGetProxy, kProxyChallenge, OK),
9963 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9964 // Authenticating HTTP server through an authenticating proxy.
9965 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9966 { TestRound(kGetProxy, kProxyChallenge, OK),
9967 TestRound(kGetProxyAuth, kServerChallenge, OK),
9968 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9969 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9970 { TestRound(kGetProxy, kProxyChallenge, OK),
9971 TestRound(kGetProxyAuth, kServerChallenge, OK),
9972 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9973 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9974 { TestRound(kGetProxy, kProxyChallenge, OK),
9975 TestRound(kGetProxyAuth, kServerChallenge, OK),
9976 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9977 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9978 { TestRound(kGetProxy, kProxyChallenge, OK),
9979 TestRound(kGetProxyAuth, kServerChallenge, OK),
9980 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9981 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9982 { TestRound(kGetProxy, kProxyChallenge, OK),
9983 TestRound(kGetProxyAuth, kServerChallenge, OK),
9984 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9985 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9986 { TestRound(kGetProxy, kProxyChallenge, OK),
9987 TestRound(kGetProxyAuth, kServerChallenge, OK),
9988 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9989 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9990 { TestRound(kGetProxy, kProxyChallenge, OK),
9991 TestRound(kGetProxyAuth, kServerChallenge, OK),
9992 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9993 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9994 { TestRound(kGetProxy, kProxyChallenge, OK),
9995 TestRound(kGetProxyAuth, kServerChallenge, OK),
9996 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9997 // Non-authenticating HTTPS server with a direct connection.
9998 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9999 { TestRound(kGet, kSuccess, OK)}},
10000 // Authenticating HTTPS server with a direct connection.
10001 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10002 { TestRound(kGet, kServerChallenge, OK),
10003 TestRound(kGetAuth, kSuccess, OK)}},
10004 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10005 { TestRound(kGet, kServerChallenge, OK),
10006 TestRound(kGetAuth, kFailure, kAuthErr)}},
10007 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10008 { TestRound(kGet, kServerChallenge, OK),
10009 TestRound(kGetAuth, kSuccess, OK)}},
10010 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10011 { TestRound(kGet, kServerChallenge, OK),
10012 TestRound(kGetAuth, kFailure, kAuthErr)}},
10013 // Non-authenticating HTTPS server with a non-authenticating proxy.
10014 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10015 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
10016 // Authenticating HTTPS server through a non-authenticating proxy.
10017 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10018 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10019 TestRound(kGetAuth, kSuccess, OK)}},
10020 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10021 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10022 TestRound(kGetAuth, kFailure, kAuthErr)}},
10023 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10024 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10025 TestRound(kGetAuth, kSuccess, OK)}},
10026 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10027 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10028 TestRound(kGetAuth, kFailure, kAuthErr)}},
10029 // Non-Authenticating HTTPS server through an authenticating proxy.
10030 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10031 { TestRound(kConnect, kProxyChallenge, OK),
10032 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10033 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10034 { TestRound(kConnect, kProxyChallenge, OK),
10035 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10036 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10037 { TestRound(kConnect, kProxyChallenge, OK),
10038 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10039 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10040 { TestRound(kConnect, kProxyChallenge, OK),
10041 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10042 // Authenticating HTTPS server through an authenticating proxy.
10043 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10044 { TestRound(kConnect, kProxyChallenge, OK),
10045 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10046 &kGet, &kServerChallenge),
10047 TestRound(kGetAuth, kSuccess, OK)}},
10048 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10049 { TestRound(kConnect, kProxyChallenge, OK),
10050 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10051 &kGet, &kServerChallenge),
10052 TestRound(kGetAuth, kFailure, kAuthErr)}},
10053 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10054 { TestRound(kConnect, kProxyChallenge, OK),
10055 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10056 &kGet, &kServerChallenge),
10057 TestRound(kGetAuth, kSuccess, OK)}},
10058 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10059 { TestRound(kConnect, kProxyChallenge, OK),
10060 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10061 &kGet, &kServerChallenge),
10062 TestRound(kGetAuth, kFailure, kAuthErr)}},
10063 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10064 { TestRound(kConnect, kProxyChallenge, OK),
10065 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10066 &kGet, &kServerChallenge),
10067 TestRound(kGetAuth, kSuccess, OK)}},
10068 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10069 { TestRound(kConnect, kProxyChallenge, OK),
10070 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10071 &kGet, &kServerChallenge),
10072 TestRound(kGetAuth, kFailure, kAuthErr)}},
10073 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10074 { TestRound(kConnect, kProxyChallenge, OK),
10075 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10076 &kGet, &kServerChallenge),
10077 TestRound(kGetAuth, kSuccess, OK)}},
10078 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10079 { TestRound(kConnect, kProxyChallenge, OK),
10080 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10081 &kGet, &kServerChallenge),
10082 TestRound(kGetAuth, kFailure, kAuthErr)}},
10085 for (size_t i = 0; i < arraysize(test_configs); ++i) {
10086 HttpAuthHandlerMock::Factory* auth_factory(
10087 new HttpAuthHandlerMock::Factory());
10088 session_deps_.http_auth_handler_factory.reset(auth_factory);
10089 const TestConfig& test_config = test_configs[i];
10091 // Set up authentication handlers as necessary.
10092 if (test_config.proxy_auth_timing != AUTH_NONE) {
10093 for (int n = 0; n < 2; n++) {
10094 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10095 std::string auth_challenge = "Mock realm=proxy";
10096 GURL origin(test_config.proxy_url);
10097 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10098 auth_challenge.end());
10099 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
10100 origin, BoundNetLog());
10101 auth_handler->SetGenerateExpectation(
10102 test_config.proxy_auth_timing == AUTH_ASYNC,
10103 test_config.proxy_auth_rv);
10104 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10107 if (test_config.server_auth_timing != AUTH_NONE) {
10108 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10109 std::string auth_challenge = "Mock realm=server";
10110 GURL origin(test_config.server_url);
10111 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10112 auth_challenge.end());
10113 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10114 origin, BoundNetLog());
10115 auth_handler->SetGenerateExpectation(
10116 test_config.server_auth_timing == AUTH_ASYNC,
10117 test_config.server_auth_rv);
10118 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10120 if (test_config.proxy_url) {
10121 session_deps_.proxy_service.reset(
10122 ProxyService::CreateFixed(test_config.proxy_url));
10123 } else {
10124 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10127 HttpRequestInfo request;
10128 request.method = "GET";
10129 request.url = GURL(test_config.server_url);
10130 request.load_flags = 0;
10132 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10133 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10135 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
10137 std::vector<std::vector<MockRead>> mock_reads(1);
10138 std::vector<std::vector<MockWrite>> mock_writes(1);
10139 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10140 const TestRound& read_write_round = test_config.rounds[round];
10142 // Set up expected reads and writes.
10143 mock_reads.back().push_back(read_write_round.read);
10144 mock_writes.back().push_back(read_write_round.write);
10146 // kProxyChallenge uses Proxy-Connection: close which means that the
10147 // socket is closed and a new one will be created for the next request.
10148 if (read_write_round.read.data == kProxyChallenge.data &&
10149 read_write_round.write.data != kConnect.data) {
10150 mock_reads.push_back(std::vector<MockRead>());
10151 mock_writes.push_back(std::vector<MockWrite>());
10154 if (read_write_round.extra_read) {
10155 mock_reads.back().push_back(*read_write_round.extra_read);
10157 if (read_write_round.extra_write) {
10158 mock_writes.back().push_back(*read_write_round.extra_write);
10161 // Add an SSL sequence if necessary.
10162 if (round >= test_config.first_ssl_round)
10163 session_deps_.socket_factory->AddSSLSocketDataProvider(
10164 &ssl_socket_data_provider);
10167 ScopedVector<StaticSocketDataProvider> data_providers;
10168 for (size_t i = 0; i < mock_reads.size(); ++i) {
10169 data_providers.push_back(new StaticSocketDataProvider(
10170 vector_as_array(&mock_reads[i]), mock_reads[i].size(),
10171 vector_as_array(&mock_writes[i]), mock_writes[i].size()));
10172 session_deps_.socket_factory->AddSocketDataProvider(
10173 data_providers.back());
10176 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10177 const TestRound& read_write_round = test_config.rounds[round];
10178 // Start or restart the transaction.
10179 TestCompletionCallback callback;
10180 int rv;
10181 if (round == 0) {
10182 rv = trans.Start(&request, callback.callback(), BoundNetLog());
10183 } else {
10184 rv = trans.RestartWithAuth(
10185 AuthCredentials(kFoo, kBar), callback.callback());
10187 if (rv == ERR_IO_PENDING)
10188 rv = callback.WaitForResult();
10190 // Compare results with expected data.
10191 EXPECT_EQ(read_write_round.expected_rv, rv);
10192 const HttpResponseInfo* response = trans.GetResponseInfo();
10193 if (read_write_round.expected_rv != OK) {
10194 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
10195 continue;
10197 if (round + 1 < test_config.num_auth_rounds) {
10198 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10199 } else {
10200 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10206 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
10207 // Do multi-round authentication and make sure it works correctly.
10208 HttpAuthHandlerMock::Factory* auth_factory(
10209 new HttpAuthHandlerMock::Factory());
10210 session_deps_.http_auth_handler_factory.reset(auth_factory);
10211 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10212 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
10213 session_deps_.host_resolver->set_synchronous_mode(true);
10215 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10216 auth_handler->set_connection_based(true);
10217 std::string auth_challenge = "Mock realm=server";
10218 GURL origin("http://www.example.com");
10219 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10220 auth_challenge.end());
10221 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10222 origin, BoundNetLog());
10223 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10225 int rv = OK;
10226 const HttpResponseInfo* response = NULL;
10227 HttpRequestInfo request;
10228 request.method = "GET";
10229 request.url = origin;
10230 request.load_flags = 0;
10232 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10234 // Use a TCP Socket Pool with only one connection per group. This is used
10235 // to validate that the TCP socket is not released to the pool between
10236 // each round of multi-round authentication.
10237 HttpNetworkSessionPeer session_peer(session);
10238 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
10239 50, // Max sockets for pool
10240 1, // Max sockets per group
10241 session_deps_.host_resolver.get(),
10242 session_deps_.socket_factory.get(),
10243 session_deps_.net_log);
10244 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
10245 new MockClientSocketPoolManager);
10246 mock_pool_manager->SetTransportSocketPool(transport_pool);
10247 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
10249 scoped_ptr<HttpTransaction> trans(
10250 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10251 TestCompletionCallback callback;
10253 const MockWrite kGet(
10254 "GET / HTTP/1.1\r\n"
10255 "Host: www.example.com\r\n"
10256 "Connection: keep-alive\r\n\r\n");
10257 const MockWrite kGetAuth(
10258 "GET / HTTP/1.1\r\n"
10259 "Host: www.example.com\r\n"
10260 "Connection: keep-alive\r\n"
10261 "Authorization: auth_token\r\n\r\n");
10263 const MockRead kServerChallenge(
10264 "HTTP/1.1 401 Unauthorized\r\n"
10265 "WWW-Authenticate: Mock realm=server\r\n"
10266 "Content-Type: text/html; charset=iso-8859-1\r\n"
10267 "Content-Length: 14\r\n\r\n"
10268 "Unauthorized\r\n");
10269 const MockRead kSuccess(
10270 "HTTP/1.1 200 OK\r\n"
10271 "Content-Type: text/html; charset=iso-8859-1\r\n"
10272 "Content-Length: 3\r\n\r\n"
10273 "Yes");
10275 MockWrite writes[] = {
10276 // First round
10277 kGet,
10278 // Second round
10279 kGetAuth,
10280 // Third round
10281 kGetAuth,
10282 // Fourth round
10283 kGetAuth,
10284 // Competing request
10285 kGet,
10287 MockRead reads[] = {
10288 // First round
10289 kServerChallenge,
10290 // Second round
10291 kServerChallenge,
10292 // Third round
10293 kServerChallenge,
10294 // Fourth round
10295 kSuccess,
10296 // Competing response
10297 kSuccess,
10299 StaticSocketDataProvider data_provider(reads, arraysize(reads),
10300 writes, arraysize(writes));
10301 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10303 const char kSocketGroup[] = "www.example.com:80";
10305 // First round of authentication.
10306 auth_handler->SetGenerateExpectation(false, OK);
10307 rv = trans->Start(&request, callback.callback(), BoundNetLog());
10308 if (rv == ERR_IO_PENDING)
10309 rv = callback.WaitForResult();
10310 EXPECT_EQ(OK, rv);
10311 response = trans->GetResponseInfo();
10312 ASSERT_TRUE(response != NULL);
10313 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10314 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10316 // In between rounds, another request comes in for the same domain.
10317 // It should not be able to grab the TCP socket that trans has already
10318 // claimed.
10319 scoped_ptr<HttpTransaction> trans_compete(
10320 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10321 TestCompletionCallback callback_compete;
10322 rv = trans_compete->Start(
10323 &request, callback_compete.callback(), BoundNetLog());
10324 EXPECT_EQ(ERR_IO_PENDING, rv);
10325 // callback_compete.WaitForResult at this point would stall forever,
10326 // since the HttpNetworkTransaction does not release the request back to
10327 // the pool until after authentication completes.
10329 // Second round of authentication.
10330 auth_handler->SetGenerateExpectation(false, OK);
10331 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
10332 if (rv == ERR_IO_PENDING)
10333 rv = callback.WaitForResult();
10334 EXPECT_EQ(OK, rv);
10335 response = trans->GetResponseInfo();
10336 ASSERT_TRUE(response != NULL);
10337 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10338 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10340 // Third round of authentication.
10341 auth_handler->SetGenerateExpectation(false, OK);
10342 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10343 if (rv == ERR_IO_PENDING)
10344 rv = callback.WaitForResult();
10345 EXPECT_EQ(OK, rv);
10346 response = trans->GetResponseInfo();
10347 ASSERT_TRUE(response != NULL);
10348 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10349 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10351 // Fourth round of authentication, which completes successfully.
10352 auth_handler->SetGenerateExpectation(false, OK);
10353 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10354 if (rv == ERR_IO_PENDING)
10355 rv = callback.WaitForResult();
10356 EXPECT_EQ(OK, rv);
10357 response = trans->GetResponseInfo();
10358 ASSERT_TRUE(response != NULL);
10359 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10360 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10362 // Read the body since the fourth round was successful. This will also
10363 // release the socket back to the pool.
10364 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
10365 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10366 if (rv == ERR_IO_PENDING)
10367 rv = callback.WaitForResult();
10368 EXPECT_EQ(3, rv);
10369 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10370 EXPECT_EQ(0, rv);
10371 // There are still 0 idle sockets, since the trans_compete transaction
10372 // will be handed it immediately after trans releases it to the group.
10373 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10375 // The competing request can now finish. Wait for the headers and then
10376 // read the body.
10377 rv = callback_compete.WaitForResult();
10378 EXPECT_EQ(OK, rv);
10379 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10380 if (rv == ERR_IO_PENDING)
10381 rv = callback.WaitForResult();
10382 EXPECT_EQ(3, rv);
10383 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10384 EXPECT_EQ(0, rv);
10386 // Finally, the socket is released to the group.
10387 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10390 // This tests the case that a request is issued via http instead of spdy after
10391 // npn is negotiated.
10392 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
10393 session_deps_.use_alternate_protocols = true;
10394 NextProtoVector next_protos;
10395 next_protos.push_back(kProtoHTTP11);
10396 session_deps_.next_protos = next_protos;
10398 HttpRequestInfo request;
10399 request.method = "GET";
10400 request.url = GURL("https://www.example.org/");
10401 request.load_flags = 0;
10403 MockWrite data_writes[] = {
10404 MockWrite(
10405 "GET / HTTP/1.1\r\n"
10406 "Host: www.example.org\r\n"
10407 "Connection: keep-alive\r\n\r\n"),
10410 std::string alternate_protocol_http_header =
10411 GetAlternateProtocolHttpHeader();
10413 MockRead data_reads[] = {
10414 MockRead("HTTP/1.1 200 OK\r\n"),
10415 MockRead(alternate_protocol_http_header.c_str()),
10416 MockRead("hello world"),
10417 MockRead(SYNCHRONOUS, OK),
10420 SSLSocketDataProvider ssl(ASYNC, OK);
10421 ssl.SetNextProto(kProtoHTTP11);
10423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10425 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
10426 data_writes, arraysize(data_writes));
10427 session_deps_.socket_factory->AddSocketDataProvider(&data);
10429 TestCompletionCallback callback;
10431 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10432 scoped_ptr<HttpTransaction> trans(
10433 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10435 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10437 EXPECT_EQ(ERR_IO_PENDING, rv);
10438 EXPECT_EQ(OK, callback.WaitForResult());
10440 const HttpResponseInfo* response = trans->GetResponseInfo();
10441 ASSERT_TRUE(response != NULL);
10442 ASSERT_TRUE(response->headers.get() != NULL);
10443 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10445 std::string response_data;
10446 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10447 EXPECT_EQ("hello world", response_data);
10449 EXPECT_FALSE(response->was_fetched_via_spdy);
10450 EXPECT_TRUE(response->was_npn_negotiated);
10453 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
10454 // Simulate the SSL handshake completing with an NPN negotiation
10455 // followed by an immediate server closing of the socket.
10456 // Fix crash: http://crbug.com/46369
10457 session_deps_.use_alternate_protocols = true;
10458 session_deps_.next_protos = SpdyNextProtos();
10460 HttpRequestInfo request;
10461 request.method = "GET";
10462 request.url = GURL("https://www.example.org/");
10463 request.load_flags = 0;
10465 SSLSocketDataProvider ssl(ASYNC, OK);
10466 ssl.SetNextProto(GetParam());
10467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10469 scoped_ptr<SpdyFrame> req(
10470 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10471 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
10473 MockRead spdy_reads[] = {
10474 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10477 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10478 arraysize(spdy_writes));
10479 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10481 TestCompletionCallback callback;
10483 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10484 scoped_ptr<HttpTransaction> trans(
10485 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10487 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10488 EXPECT_EQ(ERR_IO_PENDING, rv);
10489 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10492 // A subclass of HttpAuthHandlerMock that records the request URL when
10493 // it gets it. This is needed since the auth handler may get destroyed
10494 // before we get a chance to query it.
10495 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10496 public:
10497 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10499 ~UrlRecordingHttpAuthHandlerMock() override {}
10501 protected:
10502 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10503 const HttpRequestInfo* request,
10504 const CompletionCallback& callback,
10505 std::string* auth_token) override {
10506 *url_ = request->url;
10507 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10508 credentials, request, callback, auth_token);
10511 private:
10512 GURL* url_;
10515 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10516 // This test ensures that the URL passed into the proxy is upgraded
10517 // to https when doing an Alternate Protocol upgrade.
10518 session_deps_.use_alternate_protocols = true;
10519 session_deps_.next_protos = SpdyNextProtos();
10521 session_deps_.proxy_service.reset(
10522 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10523 TestNetLog net_log;
10524 session_deps_.net_log = &net_log;
10525 GURL request_url;
10527 HttpAuthHandlerMock::Factory* auth_factory =
10528 new HttpAuthHandlerMock::Factory();
10529 UrlRecordingHttpAuthHandlerMock* auth_handler =
10530 new UrlRecordingHttpAuthHandlerMock(&request_url);
10531 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10532 auth_factory->set_do_init_from_challenge(true);
10533 session_deps_.http_auth_handler_factory.reset(auth_factory);
10536 HttpRequestInfo request;
10537 request.method = "GET";
10538 request.url = GURL("http://www.example.org");
10539 request.load_flags = 0;
10541 // First round goes unauthenticated through the proxy.
10542 MockWrite data_writes_1[] = {
10543 MockWrite(
10544 "GET http://www.example.org/ HTTP/1.1\r\n"
10545 "Host: www.example.org\r\n"
10546 "Proxy-Connection: keep-alive\r\n"
10547 "\r\n"),
10549 MockRead data_reads_1[] = {
10550 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10551 MockRead("HTTP/1.1 200 OK\r\n"),
10552 MockRead("Alternate-Protocol: 443:"),
10553 MockRead(GetAlternateProtocolFromParam()),
10554 MockRead("\r\n"),
10555 MockRead("Proxy-Connection: close\r\n"),
10556 MockRead("\r\n"),
10558 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10559 data_writes_1, arraysize(data_writes_1));
10561 // Second round tries to tunnel to www.example.org due to the
10562 // Alternate-Protocol announcement in the first round. It fails due
10563 // to a proxy authentication challenge.
10564 // After the failure, a tunnel is established to www.example.org using
10565 // Proxy-Authorization headers. There is then a SPDY request round.
10567 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10568 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10569 // does a Disconnect and Connect on the same socket, rather than trying
10570 // to obtain a new one.
10572 // NOTE: Originally, the proxy response to the second CONNECT request
10573 // simply returned another 407 so the unit test could skip the SSL connection
10574 // establishment and SPDY framing issues. Alas, the
10575 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10576 // complicated to set up expectations for than the SPDY session.
10578 scoped_ptr<SpdyFrame> req(
10579 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10580 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10581 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10583 MockWrite data_writes_2[] = {
10584 // First connection attempt without Proxy-Authorization.
10585 MockWrite(ASYNC, 0,
10586 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10587 "Host: www.example.org\r\n"
10588 "Proxy-Connection: keep-alive\r\n"
10589 "\r\n"),
10591 // Second connection attempt with Proxy-Authorization.
10592 MockWrite(ASYNC, 2,
10593 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10594 "Host: www.example.org\r\n"
10595 "Proxy-Connection: keep-alive\r\n"
10596 "Proxy-Authorization: auth_token\r\n"
10597 "\r\n"),
10599 // SPDY request
10600 CreateMockWrite(*req, 4),
10602 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10603 "Proxy-Authenticate: Mock\r\n"
10604 "Proxy-Connection: close\r\n"
10605 "\r\n");
10606 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10607 MockRead data_reads_2[] = {
10608 // First connection attempt fails
10609 MockRead(ASYNC, kRejectConnectResponse,
10610 arraysize(kRejectConnectResponse) - 1, 1),
10612 // Second connection attempt passes
10613 MockRead(ASYNC, kAcceptConnectResponse,
10614 arraysize(kAcceptConnectResponse) - 1, 3),
10616 // SPDY response
10617 CreateMockRead(*resp.get(), 5),
10618 CreateMockRead(*data.get(), 6),
10619 MockRead(ASYNC, 0, 0, 7),
10621 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
10622 data_writes_2, arraysize(data_writes_2));
10624 SSLSocketDataProvider ssl(ASYNC, OK);
10625 ssl.SetNextProto(GetParam());
10626 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10627 ASSERT_TRUE(ssl.cert.get());
10629 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10630 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10631 NULL, 0, NULL, 0);
10632 hanging_non_alternate_protocol_socket.set_connect_data(
10633 never_finishing_connect);
10635 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10636 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10638 session_deps_.socket_factory->AddSocketDataProvider(
10639 &hanging_non_alternate_protocol_socket);
10640 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10642 // First round should work and provide the Alternate-Protocol state.
10643 TestCompletionCallback callback_1;
10644 scoped_ptr<HttpTransaction> trans_1(
10645 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10646 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10647 EXPECT_EQ(ERR_IO_PENDING, rv);
10648 EXPECT_EQ(OK, callback_1.WaitForResult());
10650 // Second round should attempt a tunnel connect and get an auth challenge.
10651 TestCompletionCallback callback_2;
10652 scoped_ptr<HttpTransaction> trans_2(
10653 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10654 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10655 EXPECT_EQ(ERR_IO_PENDING, rv);
10656 EXPECT_EQ(OK, callback_2.WaitForResult());
10657 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10658 ASSERT_TRUE(response != NULL);
10659 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10661 // Restart with auth. Tunnel should work and response received.
10662 TestCompletionCallback callback_3;
10663 rv = trans_2->RestartWithAuth(
10664 AuthCredentials(kFoo, kBar), callback_3.callback());
10665 EXPECT_EQ(ERR_IO_PENDING, rv);
10666 EXPECT_EQ(OK, callback_3.WaitForResult());
10668 // After all that work, these two lines (or actually, just the scheme) are
10669 // what this test is all about. Make sure it happens correctly.
10670 EXPECT_EQ("https", request_url.scheme());
10671 EXPECT_EQ("www.example.org", request_url.host());
10673 LoadTimingInfo load_timing_info;
10674 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10675 TestLoadTimingNotReusedWithPac(load_timing_info,
10676 CONNECT_TIMING_HAS_SSL_TIMES);
10679 // Test that if we cancel the transaction as the connection is completing, that
10680 // everything tears down correctly.
10681 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10682 // Setup everything about the connection to complete synchronously, so that
10683 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10684 // for is the callback from the HttpStreamRequest.
10685 // Then cancel the transaction.
10686 // Verify that we don't crash.
10687 MockConnect mock_connect(SYNCHRONOUS, OK);
10688 MockRead data_reads[] = {
10689 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10690 MockRead(SYNCHRONOUS, "hello world"),
10691 MockRead(SYNCHRONOUS, OK),
10694 HttpRequestInfo request;
10695 request.method = "GET";
10696 request.url = GURL("http://www.example.org/");
10697 request.load_flags = 0;
10699 session_deps_.host_resolver->set_synchronous_mode(true);
10700 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10701 scoped_ptr<HttpTransaction> trans(
10702 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10704 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10705 data.set_connect_data(mock_connect);
10706 session_deps_.socket_factory->AddSocketDataProvider(&data);
10708 TestCompletionCallback callback;
10710 BoundTestNetLog log;
10711 int rv = trans->Start(&request, callback.callback(), log.bound());
10712 EXPECT_EQ(ERR_IO_PENDING, rv);
10713 trans.reset(); // Cancel the transaction here.
10715 base::MessageLoop::current()->RunUntilIdle();
10718 // Test that if a transaction is cancelled after receiving the headers, the
10719 // stream is drained properly and added back to the socket pool. The main
10720 // purpose of this test is to make sure that an HttpStreamParser can be read
10721 // from after the HttpNetworkTransaction and the objects it owns have been
10722 // deleted.
10723 // See http://crbug.com/368418
10724 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10725 MockRead data_reads[] = {
10726 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10727 MockRead(ASYNC, "Content-Length: 2\r\n"),
10728 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10729 MockRead(ASYNC, "1"),
10730 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10731 // HttpNetworkTransaction has been deleted.
10732 MockRead(ASYNC, "2"),
10733 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10735 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10736 session_deps_.socket_factory->AddSocketDataProvider(&data);
10738 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10741 HttpRequestInfo request;
10742 request.method = "GET";
10743 request.url = GURL("http://www.example.org/");
10744 request.load_flags = 0;
10746 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10747 TestCompletionCallback callback;
10749 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10750 EXPECT_EQ(ERR_IO_PENDING, rv);
10751 callback.WaitForResult();
10753 const HttpResponseInfo* response = trans.GetResponseInfo();
10754 ASSERT_TRUE(response != NULL);
10755 EXPECT_TRUE(response->headers.get() != NULL);
10756 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10758 // The transaction and HttpRequestInfo are deleted.
10761 // Let the HttpResponseBodyDrainer drain the socket.
10762 base::MessageLoop::current()->RunUntilIdle();
10764 // Socket should now be idle, waiting to be reused.
10765 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
10768 // Test a basic GET request through a proxy.
10769 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10770 session_deps_.proxy_service.reset(
10771 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10772 BoundTestNetLog log;
10773 session_deps_.net_log = log.bound().net_log();
10774 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10776 HttpRequestInfo request;
10777 request.method = "GET";
10778 request.url = GURL("http://www.example.org/");
10780 MockWrite data_writes1[] = {
10781 MockWrite(
10782 "GET http://www.example.org/ HTTP/1.1\r\n"
10783 "Host: www.example.org\r\n"
10784 "Proxy-Connection: keep-alive\r\n\r\n"),
10787 MockRead data_reads1[] = {
10788 MockRead("HTTP/1.1 200 OK\r\n"),
10789 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10790 MockRead("Content-Length: 100\r\n\r\n"),
10791 MockRead(SYNCHRONOUS, OK),
10794 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10795 data_writes1, arraysize(data_writes1));
10796 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10798 TestCompletionCallback callback1;
10800 scoped_ptr<HttpTransaction> trans(
10801 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10802 BeforeProxyHeadersSentHandler proxy_headers_handler;
10803 trans->SetBeforeProxyHeadersSentCallback(
10804 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
10805 base::Unretained(&proxy_headers_handler)));
10807 int rv = trans->Start(&request, callback1.callback(), log.bound());
10808 EXPECT_EQ(ERR_IO_PENDING, rv);
10810 rv = callback1.WaitForResult();
10811 EXPECT_EQ(OK, rv);
10813 const HttpResponseInfo* response = trans->GetResponseInfo();
10814 ASSERT_TRUE(response != NULL);
10816 EXPECT_TRUE(response->headers->IsKeepAlive());
10817 EXPECT_EQ(200, response->headers->response_code());
10818 EXPECT_EQ(100, response->headers->GetContentLength());
10819 EXPECT_TRUE(response->was_fetched_via_proxy);
10820 EXPECT_TRUE(
10821 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10822 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
10823 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
10824 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10826 LoadTimingInfo load_timing_info;
10827 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10828 TestLoadTimingNotReusedWithPac(load_timing_info,
10829 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10832 // Test a basic HTTPS GET request through a proxy.
10833 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10834 session_deps_.proxy_service.reset(
10835 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10836 BoundTestNetLog log;
10837 session_deps_.net_log = log.bound().net_log();
10838 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10840 HttpRequestInfo request;
10841 request.method = "GET";
10842 request.url = GURL("https://www.example.org/");
10844 // Since we have proxy, should try to establish tunnel.
10845 MockWrite data_writes1[] = {
10846 MockWrite(
10847 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10848 "Host: www.example.org\r\n"
10849 "Proxy-Connection: keep-alive\r\n\r\n"),
10851 MockWrite(
10852 "GET / HTTP/1.1\r\n"
10853 "Host: www.example.org\r\n"
10854 "Connection: keep-alive\r\n\r\n"),
10857 MockRead data_reads1[] = {
10858 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10860 MockRead("HTTP/1.1 200 OK\r\n"),
10861 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10862 MockRead("Content-Length: 100\r\n\r\n"),
10863 MockRead(SYNCHRONOUS, OK),
10866 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10867 data_writes1, arraysize(data_writes1));
10868 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10869 SSLSocketDataProvider ssl(ASYNC, OK);
10870 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10872 TestCompletionCallback callback1;
10874 scoped_ptr<HttpTransaction> trans(
10875 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10877 int rv = trans->Start(&request, callback1.callback(), log.bound());
10878 EXPECT_EQ(ERR_IO_PENDING, rv);
10880 rv = callback1.WaitForResult();
10881 EXPECT_EQ(OK, rv);
10882 TestNetLogEntry::List entries;
10883 log.GetEntries(&entries);
10884 size_t pos = ExpectLogContainsSomewhere(
10885 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10886 NetLog::PHASE_NONE);
10887 ExpectLogContainsSomewhere(
10888 entries, pos,
10889 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10890 NetLog::PHASE_NONE);
10892 const HttpResponseInfo* response = trans->GetResponseInfo();
10893 ASSERT_TRUE(response != NULL);
10895 EXPECT_TRUE(response->headers->IsKeepAlive());
10896 EXPECT_EQ(200, response->headers->response_code());
10897 EXPECT_EQ(100, response->headers->GetContentLength());
10898 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10899 EXPECT_TRUE(response->was_fetched_via_proxy);
10900 EXPECT_TRUE(
10901 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10903 LoadTimingInfo load_timing_info;
10904 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10905 TestLoadTimingNotReusedWithPac(load_timing_info,
10906 CONNECT_TIMING_HAS_SSL_TIMES);
10909 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10910 // while establishing the tunnel.
10911 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10912 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10913 BoundTestNetLog log;
10914 session_deps_.net_log = log.bound().net_log();
10915 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10917 HttpRequestInfo request;
10918 request.method = "GET";
10919 request.url = GURL("https://www.example.org/");
10921 // Since we have proxy, should try to establish tunnel.
10922 MockWrite data_writes1[] = {
10923 MockWrite(
10924 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10925 "Host: www.example.org\r\n"
10926 "Proxy-Connection: keep-alive\r\n\r\n"),
10928 MockWrite(
10929 "GET / HTTP/1.1\r\n"
10930 "Host: www.example.org\r\n"
10931 "Connection: keep-alive\r\n\r\n"),
10934 MockRead data_reads1[] = {
10935 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10936 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10937 MockRead(ASYNC, 0, 0), // EOF
10940 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10941 data_writes1, arraysize(data_writes1));
10942 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10943 SSLSocketDataProvider ssl(ASYNC, OK);
10944 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10946 TestCompletionCallback callback1;
10948 scoped_ptr<HttpTransaction> trans(
10949 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10951 int rv = trans->Start(&request, callback1.callback(), log.bound());
10952 EXPECT_EQ(ERR_IO_PENDING, rv);
10954 rv = callback1.WaitForResult();
10955 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10956 TestNetLogEntry::List entries;
10957 log.GetEntries(&entries);
10958 size_t pos = ExpectLogContainsSomewhere(
10959 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10960 NetLog::PHASE_NONE);
10961 ExpectLogContainsSomewhere(
10962 entries, pos,
10963 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10964 NetLog::PHASE_NONE);
10967 // Test for crbug.com/55424.
10968 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10969 scoped_ptr<SpdyFrame> req(
10970 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
10971 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
10973 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10974 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10975 MockRead spdy_reads[] = {
10976 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
10979 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10980 arraysize(spdy_writes));
10981 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10983 SSLSocketDataProvider ssl(ASYNC, OK);
10984 ssl.SetNextProto(GetParam());
10985 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10987 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10989 // Set up an initial SpdySession in the pool to reuse.
10990 HostPortPair host_port_pair("www.example.org", 443);
10991 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10992 PRIVACY_MODE_DISABLED);
10993 base::WeakPtr<SpdySession> spdy_session =
10994 CreateInsecureSpdySession(session, key, BoundNetLog());
10996 HttpRequestInfo request;
10997 request.method = "GET";
10998 request.url = GURL("https://www.example.org/");
10999 request.load_flags = 0;
11001 // This is the important line that marks this as a preconnect.
11002 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
11004 scoped_ptr<HttpTransaction> trans(
11005 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11007 TestCompletionCallback callback;
11008 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11009 EXPECT_EQ(ERR_IO_PENDING, rv);
11010 EXPECT_EQ(OK, callback.WaitForResult());
11013 // Given a net error, cause that error to be returned from the first Write()
11014 // call and verify that the HttpTransaction fails with that error.
11015 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11016 int error, IoMode mode) {
11017 HttpRequestInfo request_info;
11018 request_info.url = GURL("https://www.example.com/");
11019 request_info.method = "GET";
11020 request_info.load_flags = LOAD_NORMAL;
11022 SSLSocketDataProvider ssl_data(mode, OK);
11023 MockWrite data_writes[] = {
11024 MockWrite(mode, error),
11026 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
11027 session_deps_.socket_factory->AddSocketDataProvider(&data);
11028 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
11030 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11031 scoped_ptr<HttpTransaction> trans(
11032 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11034 TestCompletionCallback callback;
11035 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11036 if (rv == ERR_IO_PENDING)
11037 rv = callback.WaitForResult();
11038 ASSERT_EQ(error, rv);
11041 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
11042 // Just check a grab bag of cert errors.
11043 static const int kErrors[] = {
11044 ERR_CERT_COMMON_NAME_INVALID,
11045 ERR_CERT_AUTHORITY_INVALID,
11046 ERR_CERT_DATE_INVALID,
11048 for (size_t i = 0; i < arraysize(kErrors); i++) {
11049 CheckErrorIsPassedBack(kErrors[i], ASYNC);
11050 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
11054 // Ensure that a client certificate is removed from the SSL client auth
11055 // cache when:
11056 // 1) No proxy is involved.
11057 // 2) TLS False Start is disabled.
11058 // 3) The initial TLS handshake requests a client certificate.
11059 // 4) The client supplies an invalid/unacceptable certificate.
11060 TEST_P(HttpNetworkTransactionTest,
11061 ClientAuthCertCache_Direct_NoFalseStart) {
11062 HttpRequestInfo request_info;
11063 request_info.url = GURL("https://www.example.com/");
11064 request_info.method = "GET";
11065 request_info.load_flags = LOAD_NORMAL;
11067 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11068 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11070 // [ssl_]data1 contains the data for the first SSL handshake. When a
11071 // CertificateRequest is received for the first time, the handshake will
11072 // be aborted to allow the caller to provide a certificate.
11073 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11074 ssl_data1.cert_request_info = cert_request.get();
11075 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11076 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11077 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11079 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11080 // False Start is not being used, the result of the SSL handshake will be
11081 // returned as part of the SSLClientSocket::Connect() call. This test
11082 // matches the result of a server sending a handshake_failure alert,
11083 // rather than a Finished message, because it requires a client
11084 // certificate and none was supplied.
11085 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11086 ssl_data2.cert_request_info = cert_request.get();
11087 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11088 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11089 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11091 // [ssl_]data3 contains the data for the third SSL handshake. When a
11092 // connection to a server fails during an SSL handshake,
11093 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11094 // connection was attempted with TLSv1.2. This is transparent to the caller
11095 // of the HttpNetworkTransaction. Because this test failure is due to
11096 // requiring a client certificate, this fallback handshake should also
11097 // fail.
11098 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11099 ssl_data3.cert_request_info = cert_request.get();
11100 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11101 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11102 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11104 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11105 // connection to a server fails during an SSL handshake,
11106 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11107 // connection was attempted with TLSv1.1. This is transparent to the caller
11108 // of the HttpNetworkTransaction. Because this test failure is due to
11109 // requiring a client certificate, this fallback handshake should also
11110 // fail.
11111 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11112 ssl_data4.cert_request_info = cert_request.get();
11113 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11114 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
11115 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11117 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11118 scoped_ptr<HttpTransaction> trans(
11119 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11121 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11122 TestCompletionCallback callback;
11123 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11124 ASSERT_EQ(ERR_IO_PENDING, rv);
11126 // Complete the SSL handshake, which should abort due to requiring a
11127 // client certificate.
11128 rv = callback.WaitForResult();
11129 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11131 // Indicate that no certificate should be supplied. From the perspective
11132 // of SSLClientCertCache, NULL is just as meaningful as a real
11133 // certificate, so this is the same as supply a
11134 // legitimate-but-unacceptable certificate.
11135 rv = trans->RestartWithCertificate(NULL, callback.callback());
11136 ASSERT_EQ(ERR_IO_PENDING, rv);
11138 // Ensure the certificate was added to the client auth cache before
11139 // allowing the connection to continue restarting.
11140 scoped_refptr<X509Certificate> client_cert;
11141 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11142 HostPortPair("www.example.com", 443), &client_cert));
11143 ASSERT_EQ(NULL, client_cert.get());
11145 // Restart the handshake. This will consume ssl_data2, which fails, and
11146 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11147 // The result code is checked against what ssl_data4 should return.
11148 rv = callback.WaitForResult();
11149 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11151 // Ensure that the client certificate is removed from the cache on a
11152 // handshake failure.
11153 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11154 HostPortPair("www.example.com", 443), &client_cert));
11157 // Ensure that a client certificate is removed from the SSL client auth
11158 // cache when:
11159 // 1) No proxy is involved.
11160 // 2) TLS False Start is enabled.
11161 // 3) The initial TLS handshake requests a client certificate.
11162 // 4) The client supplies an invalid/unacceptable certificate.
11163 TEST_P(HttpNetworkTransactionTest,
11164 ClientAuthCertCache_Direct_FalseStart) {
11165 HttpRequestInfo request_info;
11166 request_info.url = GURL("https://www.example.com/");
11167 request_info.method = "GET";
11168 request_info.load_flags = LOAD_NORMAL;
11170 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11171 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11173 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11174 // return successfully after reading up to the peer's Certificate message.
11175 // This is to allow the caller to call SSLClientSocket::Write(), which can
11176 // enqueue application data to be sent in the same packet as the
11177 // ChangeCipherSpec and Finished messages.
11178 // The actual handshake will be finished when SSLClientSocket::Read() is
11179 // called, which expects to process the peer's ChangeCipherSpec and
11180 // Finished messages. If there was an error negotiating with the peer,
11181 // such as due to the peer requiring a client certificate when none was
11182 // supplied, the alert sent by the peer won't be processed until Read() is
11183 // called.
11185 // Like the non-False Start case, when a client certificate is requested by
11186 // the peer, the handshake is aborted during the Connect() call.
11187 // [ssl_]data1 represents the initial SSL handshake with the peer.
11188 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11189 ssl_data1.cert_request_info = cert_request.get();
11190 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11191 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11192 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11194 // When a client certificate is supplied, Connect() will not be aborted
11195 // when the peer requests the certificate. Instead, the handshake will
11196 // artificially succeed, allowing the caller to write the HTTP request to
11197 // the socket. The handshake messages are not processed until Read() is
11198 // called, which then detects that the handshake was aborted, due to the
11199 // peer sending a handshake_failure because it requires a client
11200 // certificate.
11201 SSLSocketDataProvider ssl_data2(ASYNC, OK);
11202 ssl_data2.cert_request_info = cert_request.get();
11203 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11204 MockRead data2_reads[] = {
11205 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
11207 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
11208 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11210 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11211 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11212 // TLSv1. It has the same behaviour as [ssl_]data2.
11213 SSLSocketDataProvider ssl_data3(ASYNC, OK);
11214 ssl_data3.cert_request_info = cert_request.get();
11215 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11216 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
11217 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11219 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11220 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11221 SSLSocketDataProvider ssl_data4(ASYNC, OK);
11222 ssl_data4.cert_request_info = cert_request.get();
11223 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11224 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
11225 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11227 // Need one more if TLSv1.2 is enabled.
11228 SSLSocketDataProvider ssl_data5(ASYNC, OK);
11229 ssl_data5.cert_request_info = cert_request.get();
11230 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11231 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
11232 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11234 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11235 scoped_ptr<HttpTransaction> trans(
11236 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11238 // Begin the initial SSL handshake.
11239 TestCompletionCallback callback;
11240 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11241 ASSERT_EQ(ERR_IO_PENDING, rv);
11243 // Complete the SSL handshake, which should abort due to requiring a
11244 // client certificate.
11245 rv = callback.WaitForResult();
11246 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11248 // Indicate that no certificate should be supplied. From the perspective
11249 // of SSLClientCertCache, NULL is just as meaningful as a real
11250 // certificate, so this is the same as supply a
11251 // legitimate-but-unacceptable certificate.
11252 rv = trans->RestartWithCertificate(NULL, callback.callback());
11253 ASSERT_EQ(ERR_IO_PENDING, rv);
11255 // Ensure the certificate was added to the client auth cache before
11256 // allowing the connection to continue restarting.
11257 scoped_refptr<X509Certificate> client_cert;
11258 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11259 HostPortPair("www.example.com", 443), &client_cert));
11260 ASSERT_EQ(NULL, client_cert.get());
11262 // Restart the handshake. This will consume ssl_data2, which fails, and
11263 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11264 // The result code is checked against what ssl_data4 should return.
11265 rv = callback.WaitForResult();
11266 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11268 // Ensure that the client certificate is removed from the cache on a
11269 // handshake failure.
11270 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11271 HostPortPair("www.example.com", 443), &client_cert));
11274 // Ensure that a client certificate is removed from the SSL client auth
11275 // cache when:
11276 // 1) An HTTPS proxy is involved.
11277 // 3) The HTTPS proxy requests a client certificate.
11278 // 4) The client supplies an invalid/unacceptable certificate for the
11279 // proxy.
11280 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11281 // then for connecting to an HTTP endpoint.
11282 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
11283 session_deps_.proxy_service.reset(
11284 ProxyService::CreateFixed("https://proxy:70"));
11285 BoundTestNetLog log;
11286 session_deps_.net_log = log.bound().net_log();
11288 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11289 cert_request->host_and_port = HostPortPair("proxy", 70);
11291 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11292 // [ssl_]data[1-3]. Rather than represending the endpoint
11293 // (www.example.com:443), they represent failures with the HTTPS proxy
11294 // (proxy:70).
11295 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11296 ssl_data1.cert_request_info = cert_request.get();
11297 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11298 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11299 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11301 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11302 ssl_data2.cert_request_info = cert_request.get();
11303 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11304 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11305 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11307 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11308 #if 0
11309 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11310 ssl_data3.cert_request_info = cert_request.get();
11311 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11312 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11313 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11314 #endif
11316 HttpRequestInfo requests[2];
11317 requests[0].url = GURL("https://www.example.com/");
11318 requests[0].method = "GET";
11319 requests[0].load_flags = LOAD_NORMAL;
11321 requests[1].url = GURL("http://www.example.com/");
11322 requests[1].method = "GET";
11323 requests[1].load_flags = LOAD_NORMAL;
11325 for (size_t i = 0; i < arraysize(requests); ++i) {
11326 session_deps_.socket_factory->ResetNextMockIndexes();
11327 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11328 scoped_ptr<HttpNetworkTransaction> trans(
11329 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11331 // Begin the SSL handshake with the proxy.
11332 TestCompletionCallback callback;
11333 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
11334 ASSERT_EQ(ERR_IO_PENDING, rv);
11336 // Complete the SSL handshake, which should abort due to requiring a
11337 // client certificate.
11338 rv = callback.WaitForResult();
11339 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11341 // Indicate that no certificate should be supplied. From the perspective
11342 // of SSLClientCertCache, NULL is just as meaningful as a real
11343 // certificate, so this is the same as supply a
11344 // legitimate-but-unacceptable certificate.
11345 rv = trans->RestartWithCertificate(NULL, callback.callback());
11346 ASSERT_EQ(ERR_IO_PENDING, rv);
11348 // Ensure the certificate was added to the client auth cache before
11349 // allowing the connection to continue restarting.
11350 scoped_refptr<X509Certificate> client_cert;
11351 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11352 HostPortPair("proxy", 70), &client_cert));
11353 ASSERT_EQ(NULL, client_cert.get());
11354 // Ensure the certificate was NOT cached for the endpoint. This only
11355 // applies to HTTPS requests, but is fine to check for HTTP requests.
11356 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11357 HostPortPair("www.example.com", 443), &client_cert));
11359 // Restart the handshake. This will consume ssl_data2, which fails, and
11360 // then consume ssl_data3, which should also fail. The result code is
11361 // checked against what ssl_data3 should return.
11362 rv = callback.WaitForResult();
11363 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
11365 // Now that the new handshake has failed, ensure that the client
11366 // certificate was removed from the client auth cache.
11367 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11368 HostPortPair("proxy", 70), &client_cert));
11369 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11370 HostPortPair("www.example.com", 443), &client_cert));
11374 // Unlike TEST/TEST_F, which are macros that expand to further macros,
11375 // TEST_P is a macro that expands directly to code that stringizes the
11376 // arguments. As a result, macros passed as parameters (such as prefix
11377 // or test_case_name) will not be expanded by the preprocessor. To
11378 // work around this, indirect the macro for TEST_P, so that the
11379 // pre-processor will expand macros such as MAYBE_test_name before
11380 // instantiating the test.
11381 #define WRAPPED_TEST_P(test_case_name, test_name) \
11382 TEST_P(test_case_name, test_name)
11384 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11385 #if defined(OS_WIN)
11386 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
11387 #else
11388 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
11389 #endif
11390 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
11391 session_deps_.use_alternate_protocols = true;
11392 session_deps_.next_protos = SpdyNextProtos();
11394 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11395 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11396 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11397 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11398 pool_peer.DisableDomainAuthenticationVerification();
11400 SSLSocketDataProvider ssl(ASYNC, OK);
11401 ssl.SetNextProto(GetParam());
11402 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11404 scoped_ptr<SpdyFrame> host1_req(
11405 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11406 scoped_ptr<SpdyFrame> host2_req(
11407 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11408 MockWrite spdy_writes[] = {
11409 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11411 scoped_ptr<SpdyFrame> host1_resp(
11412 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11413 scoped_ptr<SpdyFrame> host1_resp_body(
11414 spdy_util_.ConstructSpdyBodyFrame(1, true));
11415 scoped_ptr<SpdyFrame> host2_resp(
11416 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11417 scoped_ptr<SpdyFrame> host2_resp_body(
11418 spdy_util_.ConstructSpdyBodyFrame(3, true));
11419 MockRead spdy_reads[] = {
11420 CreateMockRead(*host1_resp, 1),
11421 CreateMockRead(*host1_resp_body, 2),
11422 CreateMockRead(*host2_resp, 4),
11423 CreateMockRead(*host2_resp_body, 5),
11424 MockRead(ASYNC, 0, 6),
11427 IPAddressNumber ip;
11428 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11429 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11430 MockConnect connect(ASYNC, OK, peer_addr);
11431 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11432 spdy_writes, arraysize(spdy_writes));
11433 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11435 TestCompletionCallback callback;
11436 HttpRequestInfo request1;
11437 request1.method = "GET";
11438 request1.url = GURL("https://www.example.org/");
11439 request1.load_flags = 0;
11440 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11442 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11443 EXPECT_EQ(ERR_IO_PENDING, rv);
11444 EXPECT_EQ(OK, callback.WaitForResult());
11446 const HttpResponseInfo* response = trans1.GetResponseInfo();
11447 ASSERT_TRUE(response != NULL);
11448 ASSERT_TRUE(response->headers.get() != NULL);
11449 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11451 std::string response_data;
11452 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11453 EXPECT_EQ("hello!", response_data);
11455 // Preload www.gmail.com into HostCache.
11456 HostPortPair host_port("www.gmail.com", 443);
11457 HostResolver::RequestInfo resolve_info(host_port);
11458 AddressList ignored;
11459 rv = session_deps_.host_resolver->Resolve(resolve_info,
11460 DEFAULT_PRIORITY,
11461 &ignored,
11462 callback.callback(),
11463 NULL,
11464 BoundNetLog());
11465 EXPECT_EQ(ERR_IO_PENDING, rv);
11466 rv = callback.WaitForResult();
11467 EXPECT_EQ(OK, rv);
11469 HttpRequestInfo request2;
11470 request2.method = "GET";
11471 request2.url = GURL("https://www.gmail.com/");
11472 request2.load_flags = 0;
11473 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11475 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11476 EXPECT_EQ(ERR_IO_PENDING, rv);
11477 EXPECT_EQ(OK, callback.WaitForResult());
11479 response = trans2.GetResponseInfo();
11480 ASSERT_TRUE(response != NULL);
11481 ASSERT_TRUE(response->headers.get() != NULL);
11482 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11483 EXPECT_TRUE(response->was_fetched_via_spdy);
11484 EXPECT_TRUE(response->was_npn_negotiated);
11485 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11486 EXPECT_EQ("hello!", response_data);
11488 #undef MAYBE_UseIPConnectionPooling
11490 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11491 session_deps_.use_alternate_protocols = true;
11492 session_deps_.next_protos = SpdyNextProtos();
11494 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11495 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11496 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11497 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11498 pool_peer.DisableDomainAuthenticationVerification();
11500 SSLSocketDataProvider ssl(ASYNC, OK);
11501 ssl.SetNextProto(GetParam());
11502 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11504 scoped_ptr<SpdyFrame> host1_req(
11505 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11506 scoped_ptr<SpdyFrame> host2_req(
11507 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11508 MockWrite spdy_writes[] = {
11509 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11511 scoped_ptr<SpdyFrame> host1_resp(
11512 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11513 scoped_ptr<SpdyFrame> host1_resp_body(
11514 spdy_util_.ConstructSpdyBodyFrame(1, true));
11515 scoped_ptr<SpdyFrame> host2_resp(
11516 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11517 scoped_ptr<SpdyFrame> host2_resp_body(
11518 spdy_util_.ConstructSpdyBodyFrame(3, true));
11519 MockRead spdy_reads[] = {
11520 CreateMockRead(*host1_resp, 1),
11521 CreateMockRead(*host1_resp_body, 2),
11522 CreateMockRead(*host2_resp, 4),
11523 CreateMockRead(*host2_resp_body, 5),
11524 MockRead(ASYNC, 0, 6),
11527 IPAddressNumber ip;
11528 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11529 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11530 MockConnect connect(ASYNC, OK, peer_addr);
11531 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11532 spdy_writes, arraysize(spdy_writes));
11533 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11535 TestCompletionCallback callback;
11536 HttpRequestInfo request1;
11537 request1.method = "GET";
11538 request1.url = GURL("https://www.example.org/");
11539 request1.load_flags = 0;
11540 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11542 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11543 EXPECT_EQ(ERR_IO_PENDING, rv);
11544 EXPECT_EQ(OK, callback.WaitForResult());
11546 const HttpResponseInfo* response = trans1.GetResponseInfo();
11547 ASSERT_TRUE(response != NULL);
11548 ASSERT_TRUE(response->headers.get() != NULL);
11549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11551 std::string response_data;
11552 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11553 EXPECT_EQ("hello!", response_data);
11555 HttpRequestInfo request2;
11556 request2.method = "GET";
11557 request2.url = GURL("https://www.gmail.com/");
11558 request2.load_flags = 0;
11559 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11561 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11562 EXPECT_EQ(ERR_IO_PENDING, rv);
11563 EXPECT_EQ(OK, callback.WaitForResult());
11565 response = trans2.GetResponseInfo();
11566 ASSERT_TRUE(response != NULL);
11567 ASSERT_TRUE(response->headers.get() != NULL);
11568 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11569 EXPECT_TRUE(response->was_fetched_via_spdy);
11570 EXPECT_TRUE(response->was_npn_negotiated);
11571 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11572 EXPECT_EQ("hello!", response_data);
11575 class OneTimeCachingHostResolver : public HostResolver {
11576 public:
11577 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11578 : host_port_(host_port) {}
11579 ~OneTimeCachingHostResolver() override {}
11581 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11583 // HostResolver methods:
11584 int Resolve(const RequestInfo& info,
11585 RequestPriority priority,
11586 AddressList* addresses,
11587 const CompletionCallback& callback,
11588 RequestHandle* out_req,
11589 const BoundNetLog& net_log) override {
11590 return host_resolver_.Resolve(
11591 info, priority, addresses, callback, out_req, net_log);
11594 int ResolveFromCache(const RequestInfo& info,
11595 AddressList* addresses,
11596 const BoundNetLog& net_log) override {
11597 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11598 if (rv == OK && info.host_port_pair().Equals(host_port_))
11599 host_resolver_.GetHostCache()->clear();
11600 return rv;
11603 void CancelRequest(RequestHandle req) override {
11604 host_resolver_.CancelRequest(req);
11607 MockCachingHostResolver* GetMockHostResolver() {
11608 return &host_resolver_;
11611 private:
11612 MockCachingHostResolver host_resolver_;
11613 const HostPortPair host_port_;
11616 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11617 #if defined(OS_WIN)
11618 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11619 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11620 #else
11621 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11622 UseIPConnectionPoolingWithHostCacheExpiration
11623 #endif
11624 WRAPPED_TEST_P(HttpNetworkTransactionTest,
11625 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
11626 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11627 // prefix doesn't work with parametrized tests).
11628 #if defined(OS_WIN)
11629 return;
11630 #else
11631 session_deps_.use_alternate_protocols = true;
11632 session_deps_.next_protos = SpdyNextProtos();
11634 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11635 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11636 HttpNetworkSession::Params params =
11637 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11638 params.host_resolver = &host_resolver;
11639 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11640 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11641 pool_peer.DisableDomainAuthenticationVerification();
11643 SSLSocketDataProvider ssl(ASYNC, OK);
11644 ssl.SetNextProto(GetParam());
11645 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11647 scoped_ptr<SpdyFrame> host1_req(
11648 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11649 scoped_ptr<SpdyFrame> host2_req(
11650 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11651 MockWrite spdy_writes[] = {
11652 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11654 scoped_ptr<SpdyFrame> host1_resp(
11655 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11656 scoped_ptr<SpdyFrame> host1_resp_body(
11657 spdy_util_.ConstructSpdyBodyFrame(1, true));
11658 scoped_ptr<SpdyFrame> host2_resp(
11659 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11660 scoped_ptr<SpdyFrame> host2_resp_body(
11661 spdy_util_.ConstructSpdyBodyFrame(3, true));
11662 MockRead spdy_reads[] = {
11663 CreateMockRead(*host1_resp, 1),
11664 CreateMockRead(*host1_resp_body, 2),
11665 CreateMockRead(*host2_resp, 4),
11666 CreateMockRead(*host2_resp_body, 5),
11667 MockRead(ASYNC, 0, 6),
11670 IPAddressNumber ip;
11671 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11672 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11673 MockConnect connect(ASYNC, OK, peer_addr);
11674 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11675 spdy_writes, arraysize(spdy_writes));
11676 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11678 TestCompletionCallback callback;
11679 HttpRequestInfo request1;
11680 request1.method = "GET";
11681 request1.url = GURL("https://www.example.org/");
11682 request1.load_flags = 0;
11683 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11685 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11686 EXPECT_EQ(ERR_IO_PENDING, rv);
11687 EXPECT_EQ(OK, callback.WaitForResult());
11689 const HttpResponseInfo* response = trans1.GetResponseInfo();
11690 ASSERT_TRUE(response != NULL);
11691 ASSERT_TRUE(response->headers.get() != NULL);
11692 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11694 std::string response_data;
11695 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11696 EXPECT_EQ("hello!", response_data);
11698 // Preload cache entries into HostCache.
11699 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11700 AddressList ignored;
11701 rv = host_resolver.Resolve(resolve_info,
11702 DEFAULT_PRIORITY,
11703 &ignored,
11704 callback.callback(),
11705 NULL,
11706 BoundNetLog());
11707 EXPECT_EQ(ERR_IO_PENDING, rv);
11708 rv = callback.WaitForResult();
11709 EXPECT_EQ(OK, rv);
11711 HttpRequestInfo request2;
11712 request2.method = "GET";
11713 request2.url = GURL("https://www.gmail.com/");
11714 request2.load_flags = 0;
11715 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11717 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11718 EXPECT_EQ(ERR_IO_PENDING, rv);
11719 EXPECT_EQ(OK, callback.WaitForResult());
11721 response = trans2.GetResponseInfo();
11722 ASSERT_TRUE(response != NULL);
11723 ASSERT_TRUE(response->headers.get() != NULL);
11724 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11725 EXPECT_TRUE(response->was_fetched_via_spdy);
11726 EXPECT_TRUE(response->was_npn_negotiated);
11727 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11728 EXPECT_EQ("hello!", response_data);
11729 #endif
11731 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11733 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11734 const std::string https_url = "https://www.example.org:8080/";
11735 const std::string http_url = "http://www.example.org:8080/";
11737 // SPDY GET for HTTPS URL
11738 scoped_ptr<SpdyFrame> req1(
11739 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11741 MockWrite writes1[] = {
11742 CreateMockWrite(*req1, 0),
11745 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11746 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11747 MockRead reads1[] = {
11748 CreateMockRead(*resp1, 1),
11749 CreateMockRead(*body1, 2),
11750 MockRead(ASYNC, ERR_IO_PENDING, 3)
11753 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
11754 arraysize(writes1));
11755 MockConnect connect_data1(ASYNC, OK);
11756 data1.set_connect_data(connect_data1);
11758 // HTTP GET for the HTTP URL
11759 MockWrite writes2[] = {
11760 MockWrite(ASYNC, 0,
11761 "GET / HTTP/1.1\r\n"
11762 "Host: www.example.org:8080\r\n"
11763 "Connection: keep-alive\r\n\r\n"),
11766 MockRead reads2[] = {
11767 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11768 MockRead(ASYNC, 2, "hello"),
11769 MockRead(ASYNC, OK, 3),
11772 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
11773 arraysize(writes2));
11775 SSLSocketDataProvider ssl(ASYNC, OK);
11776 ssl.SetNextProto(GetParam());
11777 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11778 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11779 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11781 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11783 // Start the first transaction to set up the SpdySession
11784 HttpRequestInfo request1;
11785 request1.method = "GET";
11786 request1.url = GURL(https_url);
11787 request1.load_flags = 0;
11788 HttpNetworkTransaction trans1(LOWEST, session.get());
11789 TestCompletionCallback callback1;
11790 EXPECT_EQ(ERR_IO_PENDING,
11791 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11792 base::MessageLoop::current()->RunUntilIdle();
11794 EXPECT_EQ(OK, callback1.WaitForResult());
11795 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11797 // Now, start the HTTP request
11798 HttpRequestInfo request2;
11799 request2.method = "GET";
11800 request2.url = GURL(http_url);
11801 request2.load_flags = 0;
11802 HttpNetworkTransaction trans2(MEDIUM, session.get());
11803 TestCompletionCallback callback2;
11804 EXPECT_EQ(ERR_IO_PENDING,
11805 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11806 base::MessageLoop::current()->RunUntilIdle();
11808 EXPECT_EQ(OK, callback2.WaitForResult());
11809 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11812 class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
11813 public:
11814 void Run(bool pooling, bool valid) {
11815 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
11816 443);
11817 HostPortPair alternative("www.example.org", 443);
11819 base::FilePath certs_dir = GetTestCertsDirectory();
11820 scoped_refptr<X509Certificate> cert(
11821 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
11822 ASSERT_TRUE(cert.get());
11823 bool common_name_fallback_used;
11824 EXPECT_EQ(valid,
11825 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
11826 EXPECT_TRUE(
11827 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
11828 SSLSocketDataProvider ssl(ASYNC, OK);
11829 ssl.SetNextProto(GetParam());
11830 ssl.cert = cert;
11831 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11833 // If pooling, then start a request to alternative first to create a
11834 // SpdySession.
11835 std::string url0 = "https://www.example.org:443";
11836 // Second request to origin, which has an alternative service, and could
11837 // open a connection to the alternative host or pool to the existing one.
11838 std::string url1("https://");
11839 url1.append(origin.host());
11840 url1.append(":443");
11842 scoped_ptr<SpdyFrame> req0;
11843 scoped_ptr<SpdyFrame> req1;
11844 scoped_ptr<SpdyFrame> resp0;
11845 scoped_ptr<SpdyFrame> body0;
11846 scoped_ptr<SpdyFrame> resp1;
11847 scoped_ptr<SpdyFrame> body1;
11848 std::vector<MockWrite> writes;
11849 std::vector<MockRead> reads;
11851 if (pooling) {
11852 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
11853 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
11855 writes.push_back(CreateMockWrite(*req0, 0));
11856 writes.push_back(CreateMockWrite(*req1, 3));
11858 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11859 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
11860 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11861 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
11863 reads.push_back(CreateMockRead(*resp0, 1));
11864 reads.push_back(CreateMockRead(*body0, 2));
11865 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
11866 reads.push_back(CreateMockRead(*resp1, 5));
11867 reads.push_back(CreateMockRead(*body1, 6));
11868 reads.push_back(MockRead(ASYNC, OK, 7));
11869 } else {
11870 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
11872 writes.push_back(CreateMockWrite(*req1, 0));
11874 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11875 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
11877 reads.push_back(CreateMockRead(*resp1, 1));
11878 reads.push_back(CreateMockRead(*body1, 2));
11879 reads.push_back(MockRead(ASYNC, OK, 3));
11882 SequencedSocketData data(vector_as_array(&reads), reads.size(),
11883 vector_as_array(&writes), writes.size());
11884 session_deps_.socket_factory->AddSocketDataProvider(&data);
11886 // Connection to the origin fails.
11887 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11888 StaticSocketDataProvider data_refused;
11889 data_refused.set_connect_data(mock_connect);
11890 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
11892 session_deps_.use_alternate_protocols = true;
11893 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11894 base::WeakPtr<HttpServerProperties> http_server_properties =
11895 session->http_server_properties();
11896 AlternativeService alternative_service(
11897 AlternateProtocolFromNextProto(GetParam()), alternative);
11898 http_server_properties->SetAlternativeService(origin, alternative_service,
11899 1.0);
11901 // First request to alternative.
11902 if (pooling) {
11903 scoped_ptr<HttpTransaction> trans0(
11904 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11905 HttpRequestInfo request0;
11906 request0.method = "GET";
11907 request0.url = GURL(url0);
11908 request0.load_flags = 0;
11909 TestCompletionCallback callback0;
11911 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
11912 EXPECT_EQ(ERR_IO_PENDING, rv);
11913 rv = callback0.WaitForResult();
11914 EXPECT_EQ(OK, rv);
11917 // Second request to origin.
11918 scoped_ptr<HttpTransaction> trans1(
11919 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11920 HttpRequestInfo request1;
11921 request1.method = "GET";
11922 request1.url = GURL(url1);
11923 request1.load_flags = 0;
11924 TestCompletionCallback callback1;
11926 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
11927 EXPECT_EQ(ERR_IO_PENDING, rv);
11928 base::MessageLoop::current()->RunUntilIdle();
11929 if (data.IsReadPaused()) {
11930 data.CompleteRead();
11932 rv = callback1.WaitForResult();
11933 if (valid) {
11934 EXPECT_EQ(OK, rv);
11935 } else {
11936 if (pooling) {
11937 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11938 } else {
11939 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
11945 INSTANTIATE_TEST_CASE_P(NextProto,
11946 AltSvcCertificateVerificationTest,
11947 testing::Values(kProtoSPDY31,
11948 kProtoSPDY4_14,
11949 kProtoSPDY4));
11951 // The alternative service host must exhibit a certificate that is valid for the
11952 // origin host. Test that this is enforced when pooling to an existing
11953 // connection.
11954 TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
11955 Run(true, true);
11958 TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
11959 Run(true, false);
11962 // The alternative service host must exhibit a certificate that is valid for the
11963 // origin host. Test that this is enforced when opening a new connection.
11964 TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
11965 Run(false, true);
11968 TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
11969 Run(false, false);
11972 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
11973 // with the alternative server. That connection should not be used.
11974 TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
11975 HostPortPair origin("origin.example.org", 443);
11976 HostPortPair alternative("alternative.example.org", 443);
11978 // Negotiate HTTP/1.1 with alternative.example.org.
11979 SSLSocketDataProvider ssl(ASYNC, OK);
11980 ssl.SetNextProto(kProtoHTTP11);
11981 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11983 // No data should be read from the alternative, because HTTP/1.1 is
11984 // negotiated.
11985 StaticSocketDataProvider data;
11986 session_deps_.socket_factory->AddSocketDataProvider(&data);
11988 // This test documents that an alternate Job should not be used if HTTP/1.1 is
11989 // negotiated. In order to test this, a failed connection to the origin is
11990 // mocked. This way the request relies on the alternate Job.
11991 StaticSocketDataProvider data_refused;
11992 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
11993 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
11995 // Set up alternative service for origin.
11996 session_deps_.use_alternate_protocols = true;
11997 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11998 base::WeakPtr<HttpServerProperties> http_server_properties =
11999 session->http_server_properties();
12000 AlternativeService alternative_service(
12001 AlternateProtocolFromNextProto(GetParam()), alternative);
12002 http_server_properties->SetAlternativeService(origin, alternative_service,
12003 1.0);
12005 scoped_ptr<HttpTransaction> trans(
12006 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12007 HttpRequestInfo request;
12008 request.method = "GET";
12009 request.url = GURL("https://origin.example.org:443");
12010 request.load_flags = 0;
12011 TestCompletionCallback callback;
12013 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12014 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12015 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12016 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
12019 // A request to a server with an alternative service fires two Jobs: one to the
12020 // origin, and an alternate one to the alternative server. If the former
12021 // succeeds, the request should succeed, even if the latter fails because
12022 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12023 TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
12024 HostPortPair origin("origin.example.org", 443);
12025 HostPortPair alternative("alternative.example.org", 443);
12027 // Negotiate HTTP/1.1 with alternative.
12028 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
12029 alternative_ssl.SetNextProto(kProtoHTTP11);
12030 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
12032 // No data should be read from the alternative, because HTTP/1.1 is
12033 // negotiated.
12034 StaticSocketDataProvider data;
12035 session_deps_.socket_factory->AddSocketDataProvider(&data);
12037 // Negotiate HTTP/1.1 with origin.
12038 SSLSocketDataProvider origin_ssl(ASYNC, OK);
12039 origin_ssl.SetNextProto(kProtoHTTP11);
12040 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
12042 MockWrite http_writes[] = {
12043 MockWrite(
12044 "GET / HTTP/1.1\r\n"
12045 "Host: origin.example.org\r\n"
12046 "Connection: keep-alive\r\n\r\n"),
12047 MockWrite(
12048 "GET /second HTTP/1.1\r\n"
12049 "Host: origin.example.org\r\n"
12050 "Connection: keep-alive\r\n\r\n"),
12053 MockRead http_reads[] = {
12054 MockRead("HTTP/1.1 200 OK\r\n"),
12055 MockRead("Content-Type: text/html\r\n"),
12056 MockRead("Content-Length: 6\r\n\r\n"),
12057 MockRead("foobar"),
12058 MockRead("HTTP/1.1 200 OK\r\n"),
12059 MockRead("Content-Type: text/html\r\n"),
12060 MockRead("Content-Length: 7\r\n\r\n"),
12061 MockRead("another"),
12063 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12064 http_writes, arraysize(http_writes));
12065 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12067 // Set up alternative service for origin.
12068 session_deps_.use_alternate_protocols = true;
12069 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12070 base::WeakPtr<HttpServerProperties> http_server_properties =
12071 session->http_server_properties();
12072 AlternativeService alternative_service(
12073 AlternateProtocolFromNextProto(GetParam()), alternative);
12074 http_server_properties->SetAlternativeService(origin, alternative_service,
12075 1.0);
12077 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
12078 HttpRequestInfo request1;
12079 request1.method = "GET";
12080 request1.url = GURL("https://origin.example.org:443");
12081 request1.load_flags = 0;
12082 TestCompletionCallback callback1;
12084 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
12085 rv = callback1.GetResult(rv);
12086 EXPECT_EQ(OK, rv);
12088 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
12089 ASSERT_TRUE(response1 != nullptr);
12090 ASSERT_TRUE(response1->headers.get() != nullptr);
12091 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12093 std::string response_data1;
12094 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
12095 EXPECT_EQ("foobar", response_data1);
12097 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12098 // for alternative service.
12099 EXPECT_TRUE(
12100 http_server_properties->IsAlternativeServiceBroken(alternative_service));
12102 // Since |alternative_service| is broken, a second transaction to origin
12103 // should not start an alternate Job. It should pool to existing connection
12104 // to origin.
12105 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
12106 HttpRequestInfo request2;
12107 request2.method = "GET";
12108 request2.url = GURL("https://origin.example.org:443/second");
12109 request2.load_flags = 0;
12110 TestCompletionCallback callback2;
12112 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
12113 rv = callback2.GetResult(rv);
12114 EXPECT_EQ(OK, rv);
12116 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
12117 ASSERT_TRUE(response2 != nullptr);
12118 ASSERT_TRUE(response2->headers.get() != nullptr);
12119 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
12121 std::string response_data2;
12122 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
12123 EXPECT_EQ("another", response_data2);
12126 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12127 // HTTP/1.1 socket open to the alternative server. That socket should not be
12128 // used.
12129 TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
12130 HostPortPair origin("origin.example.org", 443);
12131 HostPortPair alternative("alternative.example.org", 443);
12132 std::string origin_url = "https://origin.example.org:443";
12133 std::string alternative_url = "https://alternative.example.org:443";
12135 // Negotiate HTTP/1.1 with alternative.example.org.
12136 SSLSocketDataProvider ssl(ASYNC, OK);
12137 ssl.SetNextProto(kProtoHTTP11);
12138 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12140 // HTTP/1.1 data for |request1| and |request2|.
12141 MockWrite http_writes[] = {
12142 MockWrite(
12143 "GET / HTTP/1.1\r\n"
12144 "Host: alternative.example.org\r\n"
12145 "Connection: keep-alive\r\n\r\n"),
12146 MockWrite(
12147 "GET / HTTP/1.1\r\n"
12148 "Host: alternative.example.org\r\n"
12149 "Connection: keep-alive\r\n\r\n"),
12152 MockRead http_reads[] = {
12153 MockRead(
12154 "HTTP/1.1 200 OK\r\n"
12155 "Content-Type: text/html; charset=iso-8859-1\r\n"
12156 "Content-Length: 40\r\n\r\n"
12157 "first HTTP/1.1 response from alternative"),
12158 MockRead(
12159 "HTTP/1.1 200 OK\r\n"
12160 "Content-Type: text/html; charset=iso-8859-1\r\n"
12161 "Content-Length: 41\r\n\r\n"
12162 "second HTTP/1.1 response from alternative"),
12164 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12165 http_writes, arraysize(http_writes));
12166 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12168 // This test documents that an alternate Job should not pool to an already
12169 // existing HTTP/1.1 connection. In order to test this, a failed connection
12170 // to the origin is mocked. This way |request2| relies on the alternate Job.
12171 StaticSocketDataProvider data_refused;
12172 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12173 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12175 // Set up alternative service for origin.
12176 session_deps_.use_alternate_protocols = true;
12177 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12178 base::WeakPtr<HttpServerProperties> http_server_properties =
12179 session->http_server_properties();
12180 AlternativeService alternative_service(
12181 AlternateProtocolFromNextProto(GetParam()), alternative);
12182 http_server_properties->SetAlternativeService(origin, alternative_service,
12183 1.0);
12185 // First transaction to alternative to open an HTTP/1.1 socket.
12186 scoped_ptr<HttpTransaction> trans1(
12187 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12188 HttpRequestInfo request1;
12189 request1.method = "GET";
12190 request1.url = GURL(alternative_url);
12191 request1.load_flags = 0;
12192 TestCompletionCallback callback1;
12194 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12195 EXPECT_EQ(OK, callback1.GetResult(rv));
12196 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12197 ASSERT_TRUE(response1);
12198 ASSERT_TRUE(response1->headers.get());
12199 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12200 EXPECT_TRUE(response1->was_npn_negotiated);
12201 EXPECT_FALSE(response1->was_fetched_via_spdy);
12202 std::string response_data1;
12203 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
12204 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
12206 // Request for origin.example.org, which has an alternative service. This
12207 // will start two Jobs: the alternative looks for connections to pool to,
12208 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12209 // open other connections to alternative server. The Job to origin fails, so
12210 // this request fails.
12211 scoped_ptr<HttpTransaction> trans2(
12212 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12213 HttpRequestInfo request2;
12214 request2.method = "GET";
12215 request2.url = GURL(origin_url);
12216 request2.load_flags = 0;
12217 TestCompletionCallback callback2;
12219 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
12220 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
12222 // Another transaction to alternative. This is to test that the HTTP/1.1
12223 // socket is still open and in the pool.
12224 scoped_ptr<HttpTransaction> trans3(
12225 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12226 HttpRequestInfo request3;
12227 request3.method = "GET";
12228 request3.url = GURL(alternative_url);
12229 request3.load_flags = 0;
12230 TestCompletionCallback callback3;
12232 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
12233 EXPECT_EQ(OK, callback3.GetResult(rv));
12234 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
12235 ASSERT_TRUE(response3);
12236 ASSERT_TRUE(response3->headers.get());
12237 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
12238 EXPECT_TRUE(response3->was_npn_negotiated);
12239 EXPECT_FALSE(response3->was_fetched_via_spdy);
12240 std::string response_data3;
12241 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
12242 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
12245 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
12246 const std::string https_url = "https://www.example.org:8080/";
12247 const std::string http_url = "http://www.example.org:8080/";
12249 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12250 const HostPortPair host_port_pair("www.example.org", 8080);
12251 scoped_ptr<SpdyFrame> connect(
12252 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
12253 scoped_ptr<SpdyFrame> req1(
12254 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
12255 scoped_ptr<SpdyFrame> wrapped_req1(
12256 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
12258 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12259 SpdyHeaderBlock req2_block;
12260 req2_block[spdy_util_.GetMethodKey()] = "GET";
12261 req2_block[spdy_util_.GetPathKey()] = "/";
12262 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
12263 req2_block[spdy_util_.GetSchemeKey()] = "http";
12264 spdy_util_.MaybeAddVersionHeader(&req2_block);
12265 scoped_ptr<SpdyFrame> req2(
12266 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
12268 MockWrite writes1[] = {
12269 CreateMockWrite(*connect, 0),
12270 CreateMockWrite(*wrapped_req1, 2),
12271 CreateMockWrite(*req2, 5),
12274 scoped_ptr<SpdyFrame> conn_resp(
12275 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12276 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12277 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12278 scoped_ptr<SpdyFrame> wrapped_resp1(
12279 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
12280 scoped_ptr<SpdyFrame> wrapped_body1(
12281 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
12282 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12283 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
12284 MockRead reads1[] = {
12285 CreateMockRead(*conn_resp, 1),
12286 CreateMockRead(*wrapped_resp1, 3),
12287 CreateMockRead(*wrapped_body1, 4),
12288 CreateMockRead(*resp2, 6),
12289 CreateMockRead(*body2, 7),
12290 MockRead(ASYNC, ERR_IO_PENDING, 8)
12293 DeterministicSocketData data1(reads1, arraysize(reads1),
12294 writes1, arraysize(writes1));
12295 MockConnect connect_data1(ASYNC, OK);
12296 data1.set_connect_data(connect_data1);
12298 session_deps_.proxy_service.reset(
12299 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12300 TestNetLog log;
12301 session_deps_.net_log = &log;
12302 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12303 ssl1.SetNextProto(GetParam());
12304 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12305 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12306 ssl2.SetNextProto(GetParam());
12307 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12308 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
12310 scoped_refptr<HttpNetworkSession> session(
12311 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12313 // Start the first transaction to set up the SpdySession
12314 HttpRequestInfo request1;
12315 request1.method = "GET";
12316 request1.url = GURL(https_url);
12317 request1.load_flags = 0;
12318 HttpNetworkTransaction trans1(LOWEST, session.get());
12319 TestCompletionCallback callback1;
12320 EXPECT_EQ(ERR_IO_PENDING,
12321 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12322 base::MessageLoop::current()->RunUntilIdle();
12323 data1.RunFor(4);
12325 EXPECT_EQ(OK, callback1.WaitForResult());
12326 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12328 LoadTimingInfo load_timing_info1;
12329 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
12330 TestLoadTimingNotReusedWithPac(load_timing_info1,
12331 CONNECT_TIMING_HAS_SSL_TIMES);
12333 // Now, start the HTTP request
12334 HttpRequestInfo request2;
12335 request2.method = "GET";
12336 request2.url = GURL(http_url);
12337 request2.load_flags = 0;
12338 HttpNetworkTransaction trans2(MEDIUM, session.get());
12339 TestCompletionCallback callback2;
12340 EXPECT_EQ(ERR_IO_PENDING,
12341 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12342 base::MessageLoop::current()->RunUntilIdle();
12343 data1.RunFor(3);
12345 EXPECT_EQ(OK, callback2.WaitForResult());
12346 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12348 LoadTimingInfo load_timing_info2;
12349 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
12350 // The established SPDY sessions is considered reused by the HTTP request.
12351 TestLoadTimingReusedWithPac(load_timing_info2);
12352 // HTTP requests over a SPDY session should have a different connection
12353 // socket_log_id than requests over a tunnel.
12354 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
12357 // Test that in the case where we have a SPDY session to a SPDY proxy
12358 // that we do not pool other origins that resolve to the same IP when
12359 // the certificate does not match the new origin.
12360 // http://crbug.com/134690
12361 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
12362 const std::string url1 = "http://www.example.org/";
12363 const std::string url2 = "https://news.example.org/";
12364 const std::string ip_addr = "1.2.3.4";
12366 // SPDY GET for HTTP URL (through SPDY proxy)
12367 scoped_ptr<SpdyHeaderBlock> headers(
12368 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12369 scoped_ptr<SpdyFrame> req1(
12370 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
12372 MockWrite writes1[] = {
12373 CreateMockWrite(*req1, 0),
12376 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12377 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12378 MockRead reads1[] = {
12379 CreateMockRead(*resp1, 1),
12380 CreateMockRead(*body1, 2),
12381 MockRead(ASYNC, OK, 3) // EOF
12384 scoped_ptr<DeterministicSocketData> data1(
12385 new DeterministicSocketData(reads1, arraysize(reads1),
12386 writes1, arraysize(writes1)));
12387 IPAddressNumber ip;
12388 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
12389 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12390 MockConnect connect_data1(ASYNC, OK, peer_addr);
12391 data1->set_connect_data(connect_data1);
12393 // SPDY GET for HTTPS URL (direct)
12394 scoped_ptr<SpdyFrame> req2(
12395 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
12397 MockWrite writes2[] = {
12398 CreateMockWrite(*req2, 0),
12401 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12402 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12403 MockRead reads2[] = {
12404 CreateMockRead(*resp2, 1),
12405 CreateMockRead(*body2, 2),
12406 MockRead(ASYNC, OK, 3) // EOF
12409 scoped_ptr<DeterministicSocketData> data2(
12410 new DeterministicSocketData(reads2, arraysize(reads2),
12411 writes2, arraysize(writes2)));
12412 MockConnect connect_data2(ASYNC, OK);
12413 data2->set_connect_data(connect_data2);
12415 // Set up a proxy config that sends HTTP requests to a proxy, and
12416 // all others direct.
12417 ProxyConfig proxy_config;
12418 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
12419 session_deps_.proxy_service.reset(new ProxyService(
12420 new ProxyConfigServiceFixed(proxy_config), nullptr, NULL));
12422 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12423 ssl1.SetNextProto(GetParam());
12424 // Load a valid cert. Note, that this does not need to
12425 // be valid for proxy because the MockSSLClientSocket does
12426 // not actually verify it. But SpdySession will use this
12427 // to see if it is valid for the new origin
12428 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12429 ASSERT_TRUE(ssl1.cert.get());
12430 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12431 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12432 data1.get());
12434 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12435 ssl2.SetNextProto(GetParam());
12436 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12437 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12438 data2.get());
12440 session_deps_.host_resolver.reset(new MockCachingHostResolver());
12441 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
12442 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
12444 scoped_refptr<HttpNetworkSession> session(
12445 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12447 // Start the first transaction to set up the SpdySession
12448 HttpRequestInfo request1;
12449 request1.method = "GET";
12450 request1.url = GURL(url1);
12451 request1.load_flags = 0;
12452 HttpNetworkTransaction trans1(LOWEST, session.get());
12453 TestCompletionCallback callback1;
12454 ASSERT_EQ(ERR_IO_PENDING,
12455 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12456 data1->RunFor(3);
12458 ASSERT_TRUE(callback1.have_result());
12459 EXPECT_EQ(OK, callback1.WaitForResult());
12460 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12462 // Now, start the HTTP request
12463 HttpRequestInfo request2;
12464 request2.method = "GET";
12465 request2.url = GURL(url2);
12466 request2.load_flags = 0;
12467 HttpNetworkTransaction trans2(MEDIUM, session.get());
12468 TestCompletionCallback callback2;
12469 EXPECT_EQ(ERR_IO_PENDING,
12470 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12471 base::MessageLoop::current()->RunUntilIdle();
12472 data2->RunFor(3);
12474 ASSERT_TRUE(callback2.have_result());
12475 EXPECT_EQ(OK, callback2.WaitForResult());
12476 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12479 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12480 // error) in SPDY session, removes the socket from pool and closes the SPDY
12481 // session. Verify that new url's from the same HttpNetworkSession (and a new
12482 // SpdySession) do work. http://crbug.com/224701
12483 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
12484 const std::string https_url = "https://www.example.org/";
12486 MockRead reads1[] = {
12487 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
12490 scoped_ptr<DeterministicSocketData> data1(
12491 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
12492 data1->SetStop(1);
12494 scoped_ptr<SpdyFrame> req2(
12495 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
12496 MockWrite writes2[] = {
12497 CreateMockWrite(*req2, 0),
12500 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12501 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12502 MockRead reads2[] = {
12503 CreateMockRead(*resp2, 1),
12504 CreateMockRead(*body2, 2),
12505 MockRead(ASYNC, OK, 3) // EOF
12508 scoped_ptr<DeterministicSocketData> data2(
12509 new DeterministicSocketData(reads2, arraysize(reads2),
12510 writes2, arraysize(writes2)));
12512 SSLSocketDataProvider ssl1(ASYNC, OK);
12513 ssl1.SetNextProto(GetParam());
12514 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12515 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12516 data1.get());
12518 SSLSocketDataProvider ssl2(ASYNC, OK);
12519 ssl2.SetNextProto(GetParam());
12520 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12521 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12522 data2.get());
12524 scoped_refptr<HttpNetworkSession> session(
12525 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12527 // Start the first transaction to set up the SpdySession and verify that
12528 // connection was closed.
12529 HttpRequestInfo request1;
12530 request1.method = "GET";
12531 request1.url = GURL(https_url);
12532 request1.load_flags = 0;
12533 HttpNetworkTransaction trans1(MEDIUM, session.get());
12534 TestCompletionCallback callback1;
12535 EXPECT_EQ(ERR_IO_PENDING,
12536 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12537 base::MessageLoop::current()->RunUntilIdle();
12538 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
12540 // Now, start the second request and make sure it succeeds.
12541 HttpRequestInfo request2;
12542 request2.method = "GET";
12543 request2.url = GURL(https_url);
12544 request2.load_flags = 0;
12545 HttpNetworkTransaction trans2(MEDIUM, session.get());
12546 TestCompletionCallback callback2;
12547 EXPECT_EQ(ERR_IO_PENDING,
12548 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12549 base::MessageLoop::current()->RunUntilIdle();
12550 data2->RunFor(3);
12552 ASSERT_TRUE(callback2.have_result());
12553 EXPECT_EQ(OK, callback2.WaitForResult());
12554 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12557 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
12558 session_deps_.next_protos = SpdyNextProtos();
12559 ClientSocketPoolManager::set_max_sockets_per_group(
12560 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12561 ClientSocketPoolManager::set_max_sockets_per_pool(
12562 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12564 // Use two different hosts with different IPs so they don't get pooled.
12565 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
12566 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
12567 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12569 SSLSocketDataProvider ssl1(ASYNC, OK);
12570 ssl1.SetNextProto(GetParam());
12571 SSLSocketDataProvider ssl2(ASYNC, OK);
12572 ssl2.SetNextProto(GetParam());
12573 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12574 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12576 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
12577 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
12578 MockWrite spdy1_writes[] = {
12579 CreateMockWrite(*host1_req, 0),
12581 scoped_ptr<SpdyFrame> host1_resp(
12582 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12583 scoped_ptr<SpdyFrame> host1_resp_body(
12584 spdy_util_.ConstructSpdyBodyFrame(1, true));
12585 MockRead spdy1_reads[] = {
12586 CreateMockRead(*host1_resp, 1),
12587 CreateMockRead(*host1_resp_body, 2),
12588 MockRead(ASYNC, ERR_IO_PENDING, 3),
12591 scoped_ptr<SequencedSocketData> spdy1_data(
12592 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
12593 arraysize(spdy1_writes)));
12594 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
12596 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
12597 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
12598 MockWrite spdy2_writes[] = {
12599 CreateMockWrite(*host2_req, 0),
12601 scoped_ptr<SpdyFrame> host2_resp(
12602 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12603 scoped_ptr<SpdyFrame> host2_resp_body(
12604 spdy_util_.ConstructSpdyBodyFrame(1, true));
12605 MockRead spdy2_reads[] = {
12606 CreateMockRead(*host2_resp, 1),
12607 CreateMockRead(*host2_resp_body, 2),
12608 MockRead(ASYNC, ERR_IO_PENDING, 3),
12611 scoped_ptr<SequencedSocketData> spdy2_data(
12612 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
12613 arraysize(spdy2_writes)));
12614 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
12616 MockWrite http_write[] = {
12617 MockWrite("GET / HTTP/1.1\r\n"
12618 "Host: www.a.com\r\n"
12619 "Connection: keep-alive\r\n\r\n"),
12622 MockRead http_read[] = {
12623 MockRead("HTTP/1.1 200 OK\r\n"),
12624 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12625 MockRead("Content-Length: 6\r\n\r\n"),
12626 MockRead("hello!"),
12628 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
12629 http_write, arraysize(http_write));
12630 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12632 HostPortPair host_port_pair_a("www.a.com", 443);
12633 SpdySessionKey spdy_session_key_a(
12634 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12635 EXPECT_FALSE(
12636 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12638 TestCompletionCallback callback;
12639 HttpRequestInfo request1;
12640 request1.method = "GET";
12641 request1.url = GURL("https://www.a.com/");
12642 request1.load_flags = 0;
12643 scoped_ptr<HttpNetworkTransaction> trans(
12644 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12646 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
12647 EXPECT_EQ(ERR_IO_PENDING, rv);
12648 EXPECT_EQ(OK, callback.WaitForResult());
12650 const HttpResponseInfo* response = trans->GetResponseInfo();
12651 ASSERT_TRUE(response != NULL);
12652 ASSERT_TRUE(response->headers.get() != NULL);
12653 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12654 EXPECT_TRUE(response->was_fetched_via_spdy);
12655 EXPECT_TRUE(response->was_npn_negotiated);
12657 std::string response_data;
12658 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12659 EXPECT_EQ("hello!", response_data);
12660 trans.reset();
12661 EXPECT_TRUE(
12662 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12664 HostPortPair host_port_pair_b("www.b.com", 443);
12665 SpdySessionKey spdy_session_key_b(
12666 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12667 EXPECT_FALSE(
12668 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12669 HttpRequestInfo request2;
12670 request2.method = "GET";
12671 request2.url = GURL("https://www.b.com/");
12672 request2.load_flags = 0;
12673 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12675 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
12676 EXPECT_EQ(ERR_IO_PENDING, rv);
12677 EXPECT_EQ(OK, callback.WaitForResult());
12679 response = trans->GetResponseInfo();
12680 ASSERT_TRUE(response != NULL);
12681 ASSERT_TRUE(response->headers.get() != NULL);
12682 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12683 EXPECT_TRUE(response->was_fetched_via_spdy);
12684 EXPECT_TRUE(response->was_npn_negotiated);
12685 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12686 EXPECT_EQ("hello!", response_data);
12687 EXPECT_FALSE(
12688 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12689 EXPECT_TRUE(
12690 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12692 HostPortPair host_port_pair_a1("www.a.com", 80);
12693 SpdySessionKey spdy_session_key_a1(
12694 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12695 EXPECT_FALSE(
12696 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
12697 HttpRequestInfo request3;
12698 request3.method = "GET";
12699 request3.url = GURL("http://www.a.com/");
12700 request3.load_flags = 0;
12701 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12703 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
12704 EXPECT_EQ(ERR_IO_PENDING, rv);
12705 EXPECT_EQ(OK, callback.WaitForResult());
12707 response = trans->GetResponseInfo();
12708 ASSERT_TRUE(response != NULL);
12709 ASSERT_TRUE(response->headers.get() != NULL);
12710 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12711 EXPECT_FALSE(response->was_fetched_via_spdy);
12712 EXPECT_FALSE(response->was_npn_negotiated);
12713 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12714 EXPECT_EQ("hello!", response_data);
12715 EXPECT_FALSE(
12716 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12717 EXPECT_FALSE(
12718 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12721 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
12722 HttpRequestInfo request;
12723 request.method = "GET";
12724 request.url = GURL("http://www.example.org/");
12725 request.load_flags = 0;
12727 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12728 scoped_ptr<HttpTransaction> trans(
12729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12731 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
12732 StaticSocketDataProvider data;
12733 data.set_connect_data(mock_connect);
12734 session_deps_.socket_factory->AddSocketDataProvider(&data);
12736 TestCompletionCallback callback;
12738 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12739 EXPECT_EQ(ERR_IO_PENDING, rv);
12741 rv = callback.WaitForResult();
12742 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12744 // We don't care whether this succeeds or fails, but it shouldn't crash.
12745 HttpRequestHeaders request_headers;
12746 trans->GetFullRequestHeaders(&request_headers);
12748 ConnectionAttempts attempts;
12749 trans->GetConnectionAttempts(&attempts);
12750 ASSERT_EQ(1u, attempts.size());
12751 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12754 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
12755 HttpRequestInfo request;
12756 request.method = "GET";
12757 request.url = GURL("http://www.example.org/");
12758 request.load_flags = 0;
12760 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12761 scoped_ptr<HttpTransaction> trans(
12762 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12764 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12765 StaticSocketDataProvider data;
12766 data.set_connect_data(mock_connect);
12767 session_deps_.socket_factory->AddSocketDataProvider(&data);
12769 TestCompletionCallback callback;
12771 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12772 EXPECT_EQ(ERR_IO_PENDING, rv);
12774 rv = callback.WaitForResult();
12775 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12777 // We don't care whether this succeeds or fails, but it shouldn't crash.
12778 HttpRequestHeaders request_headers;
12779 trans->GetFullRequestHeaders(&request_headers);
12781 ConnectionAttempts attempts;
12782 trans->GetConnectionAttempts(&attempts);
12783 ASSERT_EQ(1u, attempts.size());
12784 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12787 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
12788 HttpRequestInfo request;
12789 request.method = "GET";
12790 request.url = GURL("http://www.example.org/");
12791 request.load_flags = 0;
12793 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12794 scoped_ptr<HttpTransaction> trans(
12795 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12797 MockWrite data_writes[] = {
12798 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12800 MockRead data_reads[] = {
12801 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12804 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12805 data_writes, arraysize(data_writes));
12806 session_deps_.socket_factory->AddSocketDataProvider(&data);
12808 TestCompletionCallback callback;
12810 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12811 EXPECT_EQ(ERR_IO_PENDING, rv);
12813 rv = callback.WaitForResult();
12814 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12816 HttpRequestHeaders request_headers;
12817 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12818 EXPECT_TRUE(request_headers.HasHeader("Host"));
12821 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
12822 HttpRequestInfo request;
12823 request.method = "GET";
12824 request.url = GURL("http://www.example.org/");
12825 request.load_flags = 0;
12827 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12828 scoped_ptr<HttpTransaction> trans(
12829 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12831 MockWrite data_writes[] = {
12832 MockWrite(ASYNC, ERR_CONNECTION_RESET),
12834 MockRead data_reads[] = {
12835 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12838 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12839 data_writes, arraysize(data_writes));
12840 session_deps_.socket_factory->AddSocketDataProvider(&data);
12842 TestCompletionCallback callback;
12844 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12845 EXPECT_EQ(ERR_IO_PENDING, rv);
12847 rv = callback.WaitForResult();
12848 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12850 HttpRequestHeaders request_headers;
12851 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12852 EXPECT_TRUE(request_headers.HasHeader("Host"));
12855 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
12856 HttpRequestInfo request;
12857 request.method = "GET";
12858 request.url = GURL("http://www.example.org/");
12859 request.load_flags = 0;
12861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12862 scoped_ptr<HttpTransaction> trans(
12863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12865 MockWrite data_writes[] = {
12866 MockWrite(
12867 "GET / HTTP/1.1\r\n"
12868 "Host: www.example.org\r\n"
12869 "Connection: keep-alive\r\n\r\n"),
12871 MockRead data_reads[] = {
12872 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
12875 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12876 data_writes, arraysize(data_writes));
12877 session_deps_.socket_factory->AddSocketDataProvider(&data);
12879 TestCompletionCallback callback;
12881 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12882 EXPECT_EQ(ERR_IO_PENDING, rv);
12884 rv = callback.WaitForResult();
12885 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12887 HttpRequestHeaders request_headers;
12888 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12889 EXPECT_TRUE(request_headers.HasHeader("Host"));
12892 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
12893 HttpRequestInfo request;
12894 request.method = "GET";
12895 request.url = GURL("http://www.example.org/");
12896 request.load_flags = 0;
12898 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12899 scoped_ptr<HttpTransaction> trans(
12900 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12902 MockWrite data_writes[] = {
12903 MockWrite(
12904 "GET / HTTP/1.1\r\n"
12905 "Host: www.example.org\r\n"
12906 "Connection: keep-alive\r\n\r\n"),
12908 MockRead data_reads[] = {
12909 MockRead(ASYNC, ERR_CONNECTION_RESET),
12912 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12913 data_writes, arraysize(data_writes));
12914 session_deps_.socket_factory->AddSocketDataProvider(&data);
12916 TestCompletionCallback callback;
12918 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12919 EXPECT_EQ(ERR_IO_PENDING, rv);
12921 rv = callback.WaitForResult();
12922 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12924 HttpRequestHeaders request_headers;
12925 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12926 EXPECT_TRUE(request_headers.HasHeader("Host"));
12929 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12930 HttpRequestInfo request;
12931 request.method = "GET";
12932 request.url = GURL("http://www.example.org/");
12933 request.load_flags = 0;
12934 request.extra_headers.SetHeader("X-Foo", "bar");
12936 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12937 scoped_ptr<HttpTransaction> trans(
12938 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12940 MockWrite data_writes[] = {
12941 MockWrite(
12942 "GET / HTTP/1.1\r\n"
12943 "Host: www.example.org\r\n"
12944 "Connection: keep-alive\r\n"
12945 "X-Foo: bar\r\n\r\n"),
12947 MockRead data_reads[] = {
12948 MockRead("HTTP/1.1 200 OK\r\n"
12949 "Content-Length: 5\r\n\r\n"
12950 "hello"),
12951 MockRead(ASYNC, ERR_UNEXPECTED),
12954 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12955 data_writes, arraysize(data_writes));
12956 session_deps_.socket_factory->AddSocketDataProvider(&data);
12958 TestCompletionCallback callback;
12960 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12961 EXPECT_EQ(ERR_IO_PENDING, rv);
12963 rv = callback.WaitForResult();
12964 EXPECT_EQ(OK, rv);
12966 HttpRequestHeaders request_headers;
12967 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12968 std::string foo;
12969 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12970 EXPECT_EQ("bar", foo);
12973 namespace {
12975 // Fake HttpStream that simply records calls to SetPriority().
12976 class FakeStream : public HttpStream,
12977 public base::SupportsWeakPtr<FakeStream> {
12978 public:
12979 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12980 ~FakeStream() override {}
12982 RequestPriority priority() const { return priority_; }
12984 int InitializeStream(const HttpRequestInfo* request_info,
12985 RequestPriority priority,
12986 const BoundNetLog& net_log,
12987 const CompletionCallback& callback) override {
12988 return ERR_IO_PENDING;
12991 int SendRequest(const HttpRequestHeaders& request_headers,
12992 HttpResponseInfo* response,
12993 const CompletionCallback& callback) override {
12994 ADD_FAILURE();
12995 return ERR_UNEXPECTED;
12998 int ReadResponseHeaders(const CompletionCallback& callback) override {
12999 ADD_FAILURE();
13000 return ERR_UNEXPECTED;
13003 int ReadResponseBody(IOBuffer* buf,
13004 int buf_len,
13005 const CompletionCallback& callback) override {
13006 ADD_FAILURE();
13007 return ERR_UNEXPECTED;
13010 void Close(bool not_reusable) override {}
13012 bool IsResponseBodyComplete() const override {
13013 ADD_FAILURE();
13014 return false;
13017 bool CanFindEndOfResponse() const override { return false; }
13019 bool IsConnectionReused() const override {
13020 ADD_FAILURE();
13021 return false;
13024 void SetConnectionReused() override { ADD_FAILURE(); }
13026 bool IsConnectionReusable() const override {
13027 ADD_FAILURE();
13028 return false;
13031 int64 GetTotalReceivedBytes() const override {
13032 ADD_FAILURE();
13033 return 0;
13036 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13037 ADD_FAILURE();
13038 return false;
13041 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
13043 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13044 ADD_FAILURE();
13047 bool IsSpdyHttpStream() const override {
13048 ADD_FAILURE();
13049 return false;
13052 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
13054 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13056 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
13058 HttpStream* RenewStreamForAuth() override { return NULL; }
13060 private:
13061 RequestPriority priority_;
13063 DISALLOW_COPY_AND_ASSIGN(FakeStream);
13066 // Fake HttpStreamRequest that simply records calls to SetPriority()
13067 // and vends FakeStreams with its current priority.
13068 class FakeStreamRequest : public HttpStreamRequest,
13069 public base::SupportsWeakPtr<FakeStreamRequest> {
13070 public:
13071 FakeStreamRequest(RequestPriority priority,
13072 HttpStreamRequest::Delegate* delegate)
13073 : priority_(priority),
13074 delegate_(delegate),
13075 websocket_stream_create_helper_(NULL) {}
13077 FakeStreamRequest(RequestPriority priority,
13078 HttpStreamRequest::Delegate* delegate,
13079 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
13080 : priority_(priority),
13081 delegate_(delegate),
13082 websocket_stream_create_helper_(create_helper) {}
13084 ~FakeStreamRequest() override {}
13086 RequestPriority priority() const { return priority_; }
13088 const WebSocketHandshakeStreamBase::CreateHelper*
13089 websocket_stream_create_helper() const {
13090 return websocket_stream_create_helper_;
13093 // Create a new FakeStream and pass it to the request's
13094 // delegate. Returns a weak pointer to the FakeStream.
13095 base::WeakPtr<FakeStream> FinishStreamRequest() {
13096 FakeStream* fake_stream = new FakeStream(priority_);
13097 // Do this before calling OnStreamReady() as OnStreamReady() may
13098 // immediately delete |fake_stream|.
13099 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
13100 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
13101 return weak_stream;
13104 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
13105 ADD_FAILURE();
13106 return ERR_UNEXPECTED;
13109 LoadState GetLoadState() const override {
13110 ADD_FAILURE();
13111 return LoadState();
13114 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13116 bool was_npn_negotiated() const override { return false; }
13118 NextProto protocol_negotiated() const override { return kProtoUnknown; }
13120 bool using_spdy() const override { return false; }
13122 const ConnectionAttempts& connection_attempts() const override {
13123 static ConnectionAttempts no_attempts;
13124 return no_attempts;
13127 private:
13128 RequestPriority priority_;
13129 HttpStreamRequest::Delegate* const delegate_;
13130 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
13132 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
13135 // Fake HttpStreamFactory that vends FakeStreamRequests.
13136 class FakeStreamFactory : public HttpStreamFactory {
13137 public:
13138 FakeStreamFactory() {}
13139 ~FakeStreamFactory() override {}
13141 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13142 // RequestStream() (which may be NULL if it was destroyed already).
13143 base::WeakPtr<FakeStreamRequest> last_stream_request() {
13144 return last_stream_request_;
13147 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
13148 RequestPriority priority,
13149 const SSLConfig& server_ssl_config,
13150 const SSLConfig& proxy_ssl_config,
13151 HttpStreamRequest::Delegate* delegate,
13152 const BoundNetLog& net_log) override {
13153 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
13154 last_stream_request_ = fake_request->AsWeakPtr();
13155 return fake_request;
13158 HttpStreamRequest* RequestWebSocketHandshakeStream(
13159 const HttpRequestInfo& info,
13160 RequestPriority priority,
13161 const SSLConfig& server_ssl_config,
13162 const SSLConfig& proxy_ssl_config,
13163 HttpStreamRequest::Delegate* delegate,
13164 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
13165 const BoundNetLog& net_log) override {
13166 FakeStreamRequest* fake_request =
13167 new FakeStreamRequest(priority, delegate, create_helper);
13168 last_stream_request_ = fake_request->AsWeakPtr();
13169 return fake_request;
13172 void PreconnectStreams(int num_streams,
13173 const HttpRequestInfo& info,
13174 RequestPriority priority,
13175 const SSLConfig& server_ssl_config,
13176 const SSLConfig& proxy_ssl_config) override {
13177 ADD_FAILURE();
13180 const HostMappingRules* GetHostMappingRules() const override {
13181 ADD_FAILURE();
13182 return NULL;
13185 private:
13186 base::WeakPtr<FakeStreamRequest> last_stream_request_;
13188 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
13191 // TODO(ricea): Maybe unify this with the one in
13192 // url_request_http_job_unittest.cc ?
13193 class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
13194 public:
13195 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
13196 bool using_proxy)
13197 : state_(connection.release(), using_proxy) {}
13199 // Fake implementation of HttpStreamBase methods.
13200 // This ends up being quite "real" because this object has to really send data
13201 // on the mock socket. It might be easier to use the real implementation, but
13202 // the fact that the WebSocket code is not compiled on iOS makes that
13203 // difficult.
13204 int InitializeStream(const HttpRequestInfo* request_info,
13205 RequestPriority priority,
13206 const BoundNetLog& net_log,
13207 const CompletionCallback& callback) override {
13208 state_.Initialize(request_info, priority, net_log, callback);
13209 return OK;
13212 int SendRequest(const HttpRequestHeaders& request_headers,
13213 HttpResponseInfo* response,
13214 const CompletionCallback& callback) override {
13215 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
13216 response, callback);
13219 int ReadResponseHeaders(const CompletionCallback& callback) override {
13220 return parser()->ReadResponseHeaders(callback);
13223 int ReadResponseBody(IOBuffer* buf,
13224 int buf_len,
13225 const CompletionCallback& callback) override {
13226 NOTREACHED();
13227 return ERR_IO_PENDING;
13230 void Close(bool not_reusable) override {
13231 if (parser())
13232 parser()->Close(true);
13235 bool IsResponseBodyComplete() const override {
13236 NOTREACHED();
13237 return false;
13240 bool CanFindEndOfResponse() const override {
13241 return parser()->CanFindEndOfResponse();
13244 bool IsConnectionReused() const override {
13245 NOTREACHED();
13246 return false;
13248 void SetConnectionReused() override { NOTREACHED(); }
13250 bool IsConnectionReusable() const override {
13251 NOTREACHED();
13252 return false;
13255 int64 GetTotalReceivedBytes() const override {
13256 NOTREACHED();
13257 return 0;
13260 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13261 NOTREACHED();
13262 return false;
13265 void GetSSLInfo(SSLInfo* ssl_info) override {}
13267 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13268 NOTREACHED();
13271 bool IsSpdyHttpStream() const override {
13272 NOTREACHED();
13273 return false;
13276 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
13278 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
13280 UploadProgress GetUploadProgress() const override {
13281 NOTREACHED();
13282 return UploadProgress();
13285 HttpStream* RenewStreamForAuth() override {
13286 NOTREACHED();
13287 return nullptr;
13290 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13291 scoped_ptr<WebSocketStream> Upgrade() override {
13292 NOTREACHED();
13293 return scoped_ptr<WebSocketStream>();
13296 private:
13297 HttpStreamParser* parser() const { return state_.parser(); }
13298 HttpBasicState state_;
13300 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
13303 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13304 // worth doing.
13305 class FakeWebSocketStreamCreateHelper :
13306 public WebSocketHandshakeStreamBase::CreateHelper {
13307 public:
13308 WebSocketHandshakeStreamBase* CreateBasicStream(
13309 scoped_ptr<ClientSocketHandle> connection,
13310 bool using_proxy) override {
13311 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
13312 using_proxy);
13315 WebSocketHandshakeStreamBase* CreateSpdyStream(
13316 const base::WeakPtr<SpdySession>& session,
13317 bool use_relative_url) override {
13318 NOTREACHED();
13319 return NULL;
13322 ~FakeWebSocketStreamCreateHelper() override {}
13324 virtual scoped_ptr<WebSocketStream> Upgrade() {
13325 NOTREACHED();
13326 return scoped_ptr<WebSocketStream>();
13330 } // namespace
13332 // Make sure that HttpNetworkTransaction passes on its priority to its
13333 // stream request on start.
13334 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
13335 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13336 HttpNetworkSessionPeer peer(session);
13337 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13338 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13340 HttpNetworkTransaction trans(LOW, session.get());
13342 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
13344 HttpRequestInfo request;
13345 TestCompletionCallback callback;
13346 EXPECT_EQ(ERR_IO_PENDING,
13347 trans.Start(&request, callback.callback(), BoundNetLog()));
13349 base::WeakPtr<FakeStreamRequest> fake_request =
13350 fake_factory->last_stream_request();
13351 ASSERT_TRUE(fake_request != NULL);
13352 EXPECT_EQ(LOW, fake_request->priority());
13355 // Make sure that HttpNetworkTransaction passes on its priority
13356 // updates to its stream request.
13357 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
13358 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13359 HttpNetworkSessionPeer peer(session);
13360 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13361 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13363 HttpNetworkTransaction trans(LOW, session.get());
13365 HttpRequestInfo request;
13366 TestCompletionCallback callback;
13367 EXPECT_EQ(ERR_IO_PENDING,
13368 trans.Start(&request, callback.callback(), BoundNetLog()));
13370 base::WeakPtr<FakeStreamRequest> fake_request =
13371 fake_factory->last_stream_request();
13372 ASSERT_TRUE(fake_request != NULL);
13373 EXPECT_EQ(LOW, fake_request->priority());
13375 trans.SetPriority(LOWEST);
13376 ASSERT_TRUE(fake_request != NULL);
13377 EXPECT_EQ(LOWEST, fake_request->priority());
13380 // Make sure that HttpNetworkTransaction passes on its priority
13381 // updates to its stream.
13382 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
13383 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13384 HttpNetworkSessionPeer peer(session);
13385 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13386 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13388 HttpNetworkTransaction trans(LOW, session.get());
13390 HttpRequestInfo request;
13391 TestCompletionCallback callback;
13392 EXPECT_EQ(ERR_IO_PENDING,
13393 trans.Start(&request, callback.callback(), BoundNetLog()));
13395 base::WeakPtr<FakeStreamRequest> fake_request =
13396 fake_factory->last_stream_request();
13397 ASSERT_TRUE(fake_request != NULL);
13398 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
13399 ASSERT_TRUE(fake_stream != NULL);
13400 EXPECT_EQ(LOW, fake_stream->priority());
13402 trans.SetPriority(LOWEST);
13403 EXPECT_EQ(LOWEST, fake_stream->priority());
13406 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
13407 // The same logic needs to be tested for both ws: and wss: schemes, but this
13408 // test is already parameterised on NextProto, so it uses a loop to verify
13409 // that the different schemes work.
13410 std::string test_cases[] = {"ws://www.example.org/",
13411 "wss://www.example.org/"};
13412 for (size_t i = 0; i < arraysize(test_cases); ++i) {
13413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13414 HttpNetworkSessionPeer peer(session);
13415 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13416 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13417 peer.SetHttpStreamFactoryForWebSocket(
13418 scoped_ptr<HttpStreamFactory>(fake_factory));
13420 HttpNetworkTransaction trans(LOW, session.get());
13421 trans.SetWebSocketHandshakeStreamCreateHelper(
13422 &websocket_stream_create_helper);
13424 HttpRequestInfo request;
13425 TestCompletionCallback callback;
13426 request.method = "GET";
13427 request.url = GURL(test_cases[i]);
13429 EXPECT_EQ(ERR_IO_PENDING,
13430 trans.Start(&request, callback.callback(), BoundNetLog()));
13432 base::WeakPtr<FakeStreamRequest> fake_request =
13433 fake_factory->last_stream_request();
13434 ASSERT_TRUE(fake_request != NULL);
13435 EXPECT_EQ(&websocket_stream_create_helper,
13436 fake_request->websocket_stream_create_helper());
13440 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13441 // if the transport socket pool is stalled on the global socket limit.
13442 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
13443 ClientSocketPoolManager::set_max_sockets_per_group(
13444 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13445 ClientSocketPoolManager::set_max_sockets_per_pool(
13446 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13448 // Set up SSL request.
13450 HttpRequestInfo ssl_request;
13451 ssl_request.method = "GET";
13452 ssl_request.url = GURL("https://www.example.org/");
13454 MockWrite ssl_writes[] = {
13455 MockWrite(
13456 "GET / HTTP/1.1\r\n"
13457 "Host: www.example.org\r\n"
13458 "Connection: keep-alive\r\n\r\n"),
13460 MockRead ssl_reads[] = {
13461 MockRead("HTTP/1.1 200 OK\r\n"),
13462 MockRead("Content-Length: 11\r\n\r\n"),
13463 MockRead("hello world"),
13464 MockRead(SYNCHRONOUS, OK),
13466 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
13467 ssl_writes, arraysize(ssl_writes));
13468 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13470 SSLSocketDataProvider ssl(ASYNC, OK);
13471 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13473 // Set up HTTP request.
13475 HttpRequestInfo http_request;
13476 http_request.method = "GET";
13477 http_request.url = GURL("http://www.example.org/");
13479 MockWrite http_writes[] = {
13480 MockWrite(
13481 "GET / HTTP/1.1\r\n"
13482 "Host: www.example.org\r\n"
13483 "Connection: keep-alive\r\n\r\n"),
13485 MockRead http_reads[] = {
13486 MockRead("HTTP/1.1 200 OK\r\n"),
13487 MockRead("Content-Length: 7\r\n\r\n"),
13488 MockRead("falafel"),
13489 MockRead(SYNCHRONOUS, OK),
13491 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13492 http_writes, arraysize(http_writes));
13493 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13495 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13497 // Start the SSL request.
13498 TestCompletionCallback ssl_callback;
13499 scoped_ptr<HttpTransaction> ssl_trans(
13500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13501 ASSERT_EQ(ERR_IO_PENDING,
13502 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
13503 BoundNetLog()));
13505 // Start the HTTP request. Pool should stall.
13506 TestCompletionCallback http_callback;
13507 scoped_ptr<HttpTransaction> http_trans(
13508 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13509 ASSERT_EQ(ERR_IO_PENDING,
13510 http_trans->Start(&http_request, http_callback.callback(),
13511 BoundNetLog()));
13512 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13514 // Wait for response from SSL request.
13515 ASSERT_EQ(OK, ssl_callback.WaitForResult());
13516 std::string response_data;
13517 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
13518 EXPECT_EQ("hello world", response_data);
13520 // The SSL socket should automatically be closed, so the HTTP request can
13521 // start.
13522 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13523 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
13525 // The HTTP request can now complete.
13526 ASSERT_EQ(OK, http_callback.WaitForResult());
13527 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13528 EXPECT_EQ("falafel", response_data);
13530 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13533 // Tests that when a SSL connection is established but there's no corresponding
13534 // request that needs it, the new socket is closed if the transport socket pool
13535 // is stalled on the global socket limit.
13536 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
13537 ClientSocketPoolManager::set_max_sockets_per_group(
13538 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13539 ClientSocketPoolManager::set_max_sockets_per_pool(
13540 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13542 // Set up an ssl request.
13544 HttpRequestInfo ssl_request;
13545 ssl_request.method = "GET";
13546 ssl_request.url = GURL("https://www.foopy.com/");
13548 // No data will be sent on the SSL socket.
13549 StaticSocketDataProvider ssl_data;
13550 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13552 SSLSocketDataProvider ssl(ASYNC, OK);
13553 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13555 // Set up HTTP request.
13557 HttpRequestInfo http_request;
13558 http_request.method = "GET";
13559 http_request.url = GURL("http://www.example.org/");
13561 MockWrite http_writes[] = {
13562 MockWrite(
13563 "GET / HTTP/1.1\r\n"
13564 "Host: www.example.org\r\n"
13565 "Connection: keep-alive\r\n\r\n"),
13567 MockRead http_reads[] = {
13568 MockRead("HTTP/1.1 200 OK\r\n"),
13569 MockRead("Content-Length: 7\r\n\r\n"),
13570 MockRead("falafel"),
13571 MockRead(SYNCHRONOUS, OK),
13573 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13574 http_writes, arraysize(http_writes));
13575 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13577 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13579 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13580 // cancelled when a normal transaction is cancelled.
13581 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
13582 SSLConfig ssl_config;
13583 session->ssl_config_service()->GetSSLConfig(&ssl_config);
13584 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
13585 ssl_config, ssl_config);
13586 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13588 // Start the HTTP request. Pool should stall.
13589 TestCompletionCallback http_callback;
13590 scoped_ptr<HttpTransaction> http_trans(
13591 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13592 ASSERT_EQ(ERR_IO_PENDING,
13593 http_trans->Start(&http_request, http_callback.callback(),
13594 BoundNetLog()));
13595 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13597 // The SSL connection will automatically be closed once the connection is
13598 // established, to let the HTTP request start.
13599 ASSERT_EQ(OK, http_callback.WaitForResult());
13600 std::string response_data;
13601 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13602 EXPECT_EQ("falafel", response_data);
13604 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13607 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
13608 ScopedVector<UploadElementReader> element_readers;
13609 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13610 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13612 HttpRequestInfo request;
13613 request.method = "POST";
13614 request.url = GURL("http://www.foo.com/");
13615 request.upload_data_stream = &upload_data_stream;
13616 request.load_flags = 0;
13618 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13619 scoped_ptr<HttpTransaction> trans(
13620 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13621 // Send headers successfully, but get an error while sending the body.
13622 MockWrite data_writes[] = {
13623 MockWrite("POST / HTTP/1.1\r\n"
13624 "Host: www.foo.com\r\n"
13625 "Connection: keep-alive\r\n"
13626 "Content-Length: 3\r\n\r\n"),
13627 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13630 MockRead data_reads[] = {
13631 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13632 MockRead("hello world"),
13633 MockRead(SYNCHRONOUS, OK),
13635 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13636 arraysize(data_writes));
13637 session_deps_.socket_factory->AddSocketDataProvider(&data);
13639 TestCompletionCallback callback;
13641 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13642 EXPECT_EQ(ERR_IO_PENDING, rv);
13644 rv = callback.WaitForResult();
13645 EXPECT_EQ(OK, rv);
13647 const HttpResponseInfo* response = trans->GetResponseInfo();
13648 ASSERT_TRUE(response != NULL);
13650 EXPECT_TRUE(response->headers.get() != NULL);
13651 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13653 std::string response_data;
13654 rv = ReadTransaction(trans.get(), &response_data);
13655 EXPECT_EQ(OK, rv);
13656 EXPECT_EQ("hello world", response_data);
13659 // This test makes sure the retry logic doesn't trigger when reading an error
13660 // response from a server that rejected a POST with a CONNECTION_RESET.
13661 TEST_P(HttpNetworkTransactionTest,
13662 PostReadsErrorResponseAfterResetOnReusedSocket) {
13663 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13664 MockWrite data_writes[] = {
13665 MockWrite("GET / HTTP/1.1\r\n"
13666 "Host: www.foo.com\r\n"
13667 "Connection: keep-alive\r\n\r\n"),
13668 MockWrite("POST / HTTP/1.1\r\n"
13669 "Host: www.foo.com\r\n"
13670 "Connection: keep-alive\r\n"
13671 "Content-Length: 3\r\n\r\n"),
13672 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13675 MockRead data_reads[] = {
13676 MockRead("HTTP/1.1 200 Peachy\r\n"
13677 "Content-Length: 14\r\n\r\n"),
13678 MockRead("first response"),
13679 MockRead("HTTP/1.1 400 Not OK\r\n"
13680 "Content-Length: 15\r\n\r\n"),
13681 MockRead("second response"),
13682 MockRead(SYNCHRONOUS, OK),
13684 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13685 arraysize(data_writes));
13686 session_deps_.socket_factory->AddSocketDataProvider(&data);
13688 TestCompletionCallback callback;
13689 HttpRequestInfo request1;
13690 request1.method = "GET";
13691 request1.url = GURL("http://www.foo.com/");
13692 request1.load_flags = 0;
13694 scoped_ptr<HttpTransaction> trans1(
13695 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13696 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
13697 EXPECT_EQ(ERR_IO_PENDING, rv);
13699 rv = callback.WaitForResult();
13700 EXPECT_EQ(OK, rv);
13702 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13703 ASSERT_TRUE(response1 != NULL);
13705 EXPECT_TRUE(response1->headers.get() != NULL);
13706 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
13708 std::string response_data1;
13709 rv = ReadTransaction(trans1.get(), &response_data1);
13710 EXPECT_EQ(OK, rv);
13711 EXPECT_EQ("first response", response_data1);
13712 // Delete the transaction to release the socket back into the socket pool.
13713 trans1.reset();
13715 ScopedVector<UploadElementReader> element_readers;
13716 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13717 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13719 HttpRequestInfo request2;
13720 request2.method = "POST";
13721 request2.url = GURL("http://www.foo.com/");
13722 request2.upload_data_stream = &upload_data_stream;
13723 request2.load_flags = 0;
13725 scoped_ptr<HttpTransaction> trans2(
13726 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13727 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
13728 EXPECT_EQ(ERR_IO_PENDING, rv);
13730 rv = callback.WaitForResult();
13731 EXPECT_EQ(OK, rv);
13733 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
13734 ASSERT_TRUE(response2 != NULL);
13736 EXPECT_TRUE(response2->headers.get() != NULL);
13737 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
13739 std::string response_data2;
13740 rv = ReadTransaction(trans2.get(), &response_data2);
13741 EXPECT_EQ(OK, rv);
13742 EXPECT_EQ("second response", response_data2);
13745 TEST_P(HttpNetworkTransactionTest,
13746 PostReadsErrorResponseAfterResetPartialBodySent) {
13747 ScopedVector<UploadElementReader> element_readers;
13748 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13749 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13751 HttpRequestInfo request;
13752 request.method = "POST";
13753 request.url = GURL("http://www.foo.com/");
13754 request.upload_data_stream = &upload_data_stream;
13755 request.load_flags = 0;
13757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13758 scoped_ptr<HttpTransaction> trans(
13759 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13760 // Send headers successfully, but get an error while sending the body.
13761 MockWrite data_writes[] = {
13762 MockWrite("POST / HTTP/1.1\r\n"
13763 "Host: www.foo.com\r\n"
13764 "Connection: keep-alive\r\n"
13765 "Content-Length: 3\r\n\r\n"
13766 "fo"),
13767 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13770 MockRead data_reads[] = {
13771 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13772 MockRead("hello world"),
13773 MockRead(SYNCHRONOUS, OK),
13775 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13776 arraysize(data_writes));
13777 session_deps_.socket_factory->AddSocketDataProvider(&data);
13779 TestCompletionCallback callback;
13781 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13782 EXPECT_EQ(ERR_IO_PENDING, rv);
13784 rv = callback.WaitForResult();
13785 EXPECT_EQ(OK, rv);
13787 const HttpResponseInfo* response = trans->GetResponseInfo();
13788 ASSERT_TRUE(response != NULL);
13790 EXPECT_TRUE(response->headers.get() != NULL);
13791 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13793 std::string response_data;
13794 rv = ReadTransaction(trans.get(), &response_data);
13795 EXPECT_EQ(OK, rv);
13796 EXPECT_EQ("hello world", response_data);
13799 // This tests the more common case than the previous test, where headers and
13800 // body are not merged into a single request.
13801 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
13802 ScopedVector<UploadElementReader> element_readers;
13803 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13804 ChunkedUploadDataStream upload_data_stream(0);
13806 HttpRequestInfo request;
13807 request.method = "POST";
13808 request.url = GURL("http://www.foo.com/");
13809 request.upload_data_stream = &upload_data_stream;
13810 request.load_flags = 0;
13812 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13813 scoped_ptr<HttpTransaction> trans(
13814 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13815 // Send headers successfully, but get an error while sending the body.
13816 MockWrite data_writes[] = {
13817 MockWrite("POST / HTTP/1.1\r\n"
13818 "Host: www.foo.com\r\n"
13819 "Connection: keep-alive\r\n"
13820 "Transfer-Encoding: chunked\r\n\r\n"),
13821 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13824 MockRead data_reads[] = {
13825 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13826 MockRead("hello world"),
13827 MockRead(SYNCHRONOUS, OK),
13829 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13830 arraysize(data_writes));
13831 session_deps_.socket_factory->AddSocketDataProvider(&data);
13833 TestCompletionCallback callback;
13835 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13836 EXPECT_EQ(ERR_IO_PENDING, rv);
13837 // Make sure the headers are sent before adding a chunk. This ensures that
13838 // they can't be merged with the body in a single send. Not currently
13839 // necessary since a chunked body is never merged with headers, but this makes
13840 // the test more future proof.
13841 base::RunLoop().RunUntilIdle();
13843 upload_data_stream.AppendData("last chunk", 10, true);
13845 rv = callback.WaitForResult();
13846 EXPECT_EQ(OK, rv);
13848 const HttpResponseInfo* response = trans->GetResponseInfo();
13849 ASSERT_TRUE(response != NULL);
13851 EXPECT_TRUE(response->headers.get() != NULL);
13852 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13854 std::string response_data;
13855 rv = ReadTransaction(trans.get(), &response_data);
13856 EXPECT_EQ(OK, rv);
13857 EXPECT_EQ("hello world", response_data);
13860 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
13861 ScopedVector<UploadElementReader> element_readers;
13862 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13863 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13865 HttpRequestInfo request;
13866 request.method = "POST";
13867 request.url = GURL("http://www.foo.com/");
13868 request.upload_data_stream = &upload_data_stream;
13869 request.load_flags = 0;
13871 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13872 scoped_ptr<HttpTransaction> trans(
13873 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13875 MockWrite data_writes[] = {
13876 MockWrite("POST / HTTP/1.1\r\n"
13877 "Host: www.foo.com\r\n"
13878 "Connection: keep-alive\r\n"
13879 "Content-Length: 3\r\n\r\n"),
13880 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13883 MockRead data_reads[] = {
13884 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13885 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13886 MockRead("hello world"),
13887 MockRead(SYNCHRONOUS, OK),
13889 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13890 arraysize(data_writes));
13891 session_deps_.socket_factory->AddSocketDataProvider(&data);
13893 TestCompletionCallback callback;
13895 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13896 EXPECT_EQ(ERR_IO_PENDING, rv);
13898 rv = callback.WaitForResult();
13899 EXPECT_EQ(OK, rv);
13901 const HttpResponseInfo* response = trans->GetResponseInfo();
13902 ASSERT_TRUE(response != NULL);
13904 EXPECT_TRUE(response->headers.get() != NULL);
13905 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13907 std::string response_data;
13908 rv = ReadTransaction(trans.get(), &response_data);
13909 EXPECT_EQ(OK, rv);
13910 EXPECT_EQ("hello world", response_data);
13913 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
13914 ScopedVector<UploadElementReader> element_readers;
13915 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13916 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13918 HttpRequestInfo request;
13919 request.method = "POST";
13920 request.url = GURL("http://www.foo.com/");
13921 request.upload_data_stream = &upload_data_stream;
13922 request.load_flags = 0;
13924 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13925 scoped_ptr<HttpTransaction> trans(
13926 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13927 // Send headers successfully, but get an error while sending the body.
13928 MockWrite data_writes[] = {
13929 MockWrite("POST / HTTP/1.1\r\n"
13930 "Host: www.foo.com\r\n"
13931 "Connection: keep-alive\r\n"
13932 "Content-Length: 3\r\n\r\n"),
13933 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13936 MockRead data_reads[] = {
13937 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13938 MockRead("hello world"),
13939 MockRead(SYNCHRONOUS, OK),
13941 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13942 arraysize(data_writes));
13943 session_deps_.socket_factory->AddSocketDataProvider(&data);
13945 TestCompletionCallback callback;
13947 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13948 EXPECT_EQ(ERR_IO_PENDING, rv);
13950 rv = callback.WaitForResult();
13951 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13954 TEST_P(HttpNetworkTransactionTest,
13955 PostIgnoresNonErrorResponseAfterResetAnd100) {
13956 ScopedVector<UploadElementReader> element_readers;
13957 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13958 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13960 HttpRequestInfo request;
13961 request.method = "POST";
13962 request.url = GURL("http://www.foo.com/");
13963 request.upload_data_stream = &upload_data_stream;
13964 request.load_flags = 0;
13966 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13967 scoped_ptr<HttpTransaction> trans(
13968 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13969 // Send headers successfully, but get an error while sending the body.
13970 MockWrite data_writes[] = {
13971 MockWrite("POST / HTTP/1.1\r\n"
13972 "Host: www.foo.com\r\n"
13973 "Connection: keep-alive\r\n"
13974 "Content-Length: 3\r\n\r\n"),
13975 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13978 MockRead data_reads[] = {
13979 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13980 MockRead("HTTP/1.0 302 Redirect\r\n"),
13981 MockRead("Location: http://somewhere-else.com/\r\n"),
13982 MockRead("Content-Length: 0\r\n\r\n"),
13983 MockRead(SYNCHRONOUS, OK),
13985 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13986 arraysize(data_writes));
13987 session_deps_.socket_factory->AddSocketDataProvider(&data);
13989 TestCompletionCallback callback;
13991 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13992 EXPECT_EQ(ERR_IO_PENDING, rv);
13994 rv = callback.WaitForResult();
13995 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13998 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
13999 ScopedVector<UploadElementReader> element_readers;
14000 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14001 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14003 HttpRequestInfo request;
14004 request.method = "POST";
14005 request.url = GURL("http://www.foo.com/");
14006 request.upload_data_stream = &upload_data_stream;
14007 request.load_flags = 0;
14009 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14010 scoped_ptr<HttpTransaction> trans(
14011 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14012 // Send headers successfully, but get an error while sending the body.
14013 MockWrite data_writes[] = {
14014 MockWrite("POST / HTTP/1.1\r\n"
14015 "Host: www.foo.com\r\n"
14016 "Connection: keep-alive\r\n"
14017 "Content-Length: 3\r\n\r\n"),
14018 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14021 MockRead data_reads[] = {
14022 MockRead("HTTP 0.9 rocks!"),
14023 MockRead(SYNCHRONOUS, OK),
14025 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14026 arraysize(data_writes));
14027 session_deps_.socket_factory->AddSocketDataProvider(&data);
14029 TestCompletionCallback callback;
14031 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14032 EXPECT_EQ(ERR_IO_PENDING, rv);
14034 rv = callback.WaitForResult();
14035 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14038 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
14039 ScopedVector<UploadElementReader> element_readers;
14040 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14041 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14043 HttpRequestInfo request;
14044 request.method = "POST";
14045 request.url = GURL("http://www.foo.com/");
14046 request.upload_data_stream = &upload_data_stream;
14047 request.load_flags = 0;
14049 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14050 scoped_ptr<HttpTransaction> trans(
14051 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14052 // Send headers successfully, but get an error while sending the body.
14053 MockWrite data_writes[] = {
14054 MockWrite("POST / HTTP/1.1\r\n"
14055 "Host: www.foo.com\r\n"
14056 "Connection: keep-alive\r\n"
14057 "Content-Length: 3\r\n\r\n"),
14058 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14061 MockRead data_reads[] = {
14062 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14063 MockRead(SYNCHRONOUS, OK),
14065 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14066 arraysize(data_writes));
14067 session_deps_.socket_factory->AddSocketDataProvider(&data);
14069 TestCompletionCallback callback;
14071 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14072 EXPECT_EQ(ERR_IO_PENDING, rv);
14074 rv = callback.WaitForResult();
14075 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14078 // Verify that proxy headers are not sent to the destination server when
14079 // establishing a tunnel for a secure WebSocket connection.
14080 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
14081 HttpRequestInfo request;
14082 request.method = "GET";
14083 request.url = GURL("wss://www.example.org/");
14084 AddWebSocketHeaders(&request.extra_headers);
14086 // Configure against proxy server "myproxy:70".
14087 session_deps_.proxy_service.reset(
14088 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14090 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14092 // Since a proxy is configured, try to establish a tunnel.
14093 MockWrite data_writes[] = {
14094 MockWrite(
14095 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14096 "Host: www.example.org\r\n"
14097 "Proxy-Connection: keep-alive\r\n\r\n"),
14099 // After calling trans->RestartWithAuth(), this is the request we should
14100 // be issuing -- the final header line contains the credentials.
14101 MockWrite(
14102 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14103 "Host: www.example.org\r\n"
14104 "Proxy-Connection: keep-alive\r\n"
14105 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14107 MockWrite(
14108 "GET / HTTP/1.1\r\n"
14109 "Host: www.example.org\r\n"
14110 "Connection: Upgrade\r\n"
14111 "Upgrade: websocket\r\n"
14112 "Origin: http://www.example.org\r\n"
14113 "Sec-WebSocket-Version: 13\r\n"
14114 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14117 // The proxy responds to the connect with a 407, using a persistent
14118 // connection.
14119 MockRead data_reads[] = {
14120 // No credentials.
14121 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14122 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14123 MockRead("Proxy-Connection: close\r\n\r\n"),
14125 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14127 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14128 MockRead("Upgrade: websocket\r\n"),
14129 MockRead("Connection: Upgrade\r\n"),
14130 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14133 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14134 arraysize(data_writes));
14135 session_deps_.socket_factory->AddSocketDataProvider(&data);
14136 SSLSocketDataProvider ssl(ASYNC, OK);
14137 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14139 scoped_ptr<HttpTransaction> trans(
14140 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14141 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14142 trans->SetWebSocketHandshakeStreamCreateHelper(
14143 &websocket_stream_create_helper);
14146 TestCompletionCallback callback;
14148 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14149 EXPECT_EQ(ERR_IO_PENDING, rv);
14151 rv = callback.WaitForResult();
14152 EXPECT_EQ(OK, rv);
14155 const HttpResponseInfo* response = trans->GetResponseInfo();
14156 ASSERT_TRUE(response);
14157 ASSERT_TRUE(response->headers.get());
14158 EXPECT_EQ(407, response->headers->response_code());
14161 TestCompletionCallback callback;
14163 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
14164 callback.callback());
14165 EXPECT_EQ(ERR_IO_PENDING, rv);
14167 rv = callback.WaitForResult();
14168 EXPECT_EQ(OK, rv);
14171 response = trans->GetResponseInfo();
14172 ASSERT_TRUE(response);
14173 ASSERT_TRUE(response->headers.get());
14175 EXPECT_EQ(101, response->headers->response_code());
14177 trans.reset();
14178 session->CloseAllConnections();
14181 // Verify that proxy headers are not sent to the destination server when
14182 // establishing a tunnel for an insecure WebSocket connection.
14183 // This requires the authentication info to be injected into the auth cache
14184 // due to crbug.com/395064
14185 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14186 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
14187 HttpRequestInfo request;
14188 request.method = "GET";
14189 request.url = GURL("ws://www.example.org/");
14190 AddWebSocketHeaders(&request.extra_headers);
14192 // Configure against proxy server "myproxy:70".
14193 session_deps_.proxy_service.reset(
14194 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14198 MockWrite data_writes[] = {
14199 // Try to establish a tunnel for the WebSocket connection, with
14200 // credentials. Because WebSockets have a separate set of socket pools,
14201 // they cannot and will not use the same TCP/IP connection as the
14202 // preflight HTTP request.
14203 MockWrite(
14204 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14205 "Host: www.example.org:80\r\n"
14206 "Proxy-Connection: keep-alive\r\n"
14207 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14209 MockWrite(
14210 "GET / HTTP/1.1\r\n"
14211 "Host: www.example.org\r\n"
14212 "Connection: Upgrade\r\n"
14213 "Upgrade: websocket\r\n"
14214 "Origin: http://www.example.org\r\n"
14215 "Sec-WebSocket-Version: 13\r\n"
14216 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14219 MockRead data_reads[] = {
14220 // HTTP CONNECT with credentials.
14221 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14223 // WebSocket connection established inside tunnel.
14224 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14225 MockRead("Upgrade: websocket\r\n"),
14226 MockRead("Connection: Upgrade\r\n"),
14227 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14230 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14231 arraysize(data_writes));
14232 session_deps_.socket_factory->AddSocketDataProvider(&data);
14234 session->http_auth_cache()->Add(
14235 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
14236 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
14238 scoped_ptr<HttpTransaction> trans(
14239 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14240 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14241 trans->SetWebSocketHandshakeStreamCreateHelper(
14242 &websocket_stream_create_helper);
14244 TestCompletionCallback callback;
14246 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14247 EXPECT_EQ(ERR_IO_PENDING, rv);
14249 rv = callback.WaitForResult();
14250 EXPECT_EQ(OK, rv);
14252 const HttpResponseInfo* response = trans->GetResponseInfo();
14253 ASSERT_TRUE(response);
14254 ASSERT_TRUE(response->headers.get());
14256 EXPECT_EQ(101, response->headers->response_code());
14258 trans.reset();
14259 session->CloseAllConnections();
14262 } // namespace net