Make Ctrl + T from apps focus the new tab's omnibox on Linux and ChromeOS.
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blob64fefa2ca407593bdd8e94c4ce1582c45894cbb2
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/captured_net_log_entry.h"
55 #include "net/log/net_log.h"
56 #include "net/log/net_log_unittest.h"
57 #include "net/log/test_net_log.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().GetCaptureMode().enabled());
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 CapturedNetLogEntry::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 OrderedSocketData 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);
1588 const HttpResponseInfo* response = trans->GetResponseInfo();
1589 EXPECT_TRUE(response == NULL);
1592 // What do various browsers do when the server closes a non-keepalive
1593 // connection without sending any response header or body?
1595 // IE7: error page
1596 // Safari 3.1.2 (Windows): error page
1597 // Firefox 3.0.1: blank page
1598 // Opera 9.52: after five attempts, blank page
1599 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1600 // Us: error page (EMPTY_RESPONSE)
1601 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1602 MockRead data_reads[] = {
1603 MockRead(SYNCHRONOUS, OK), // EOF
1604 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1605 MockRead("hello world"),
1606 MockRead(SYNCHRONOUS, OK),
1608 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1609 arraysize(data_reads));
1610 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1613 // Test that network access can be deferred and resumed.
1614 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1615 HttpRequestInfo request;
1616 request.method = "GET";
1617 request.url = GURL("http://www.example.org/");
1618 request.load_flags = 0;
1620 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1621 scoped_ptr<HttpTransaction> trans(
1622 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1624 // Defer on OnBeforeNetworkStart.
1625 BeforeNetworkStartHandler net_start_handler(true); // defer
1626 trans->SetBeforeNetworkStartCallback(
1627 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1628 base::Unretained(&net_start_handler)));
1630 MockRead data_reads[] = {
1631 MockRead("HTTP/1.0 200 OK\r\n"),
1632 MockRead("Content-Length: 5\r\n\r\n"),
1633 MockRead("hello"),
1634 MockRead(SYNCHRONOUS, 0),
1636 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1637 session_deps_.socket_factory->AddSocketDataProvider(&data);
1639 TestCompletionCallback callback;
1641 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1642 EXPECT_EQ(ERR_IO_PENDING, rv);
1643 base::MessageLoop::current()->RunUntilIdle();
1645 // Should have deferred for network start.
1646 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1647 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1648 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1650 trans->ResumeNetworkStart();
1651 rv = callback.WaitForResult();
1652 EXPECT_EQ(OK, rv);
1653 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1655 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1656 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1657 if (rv == ERR_IO_PENDING)
1658 rv = callback.WaitForResult();
1659 EXPECT_EQ(5, rv);
1660 trans.reset();
1663 // Test that network use can be deferred and canceled.
1664 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1665 HttpRequestInfo request;
1666 request.method = "GET";
1667 request.url = GURL("http://www.example.org/");
1668 request.load_flags = 0;
1670 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1671 scoped_ptr<HttpTransaction> trans(
1672 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1674 // Defer on OnBeforeNetworkStart.
1675 BeforeNetworkStartHandler net_start_handler(true); // defer
1676 trans->SetBeforeNetworkStartCallback(
1677 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1678 base::Unretained(&net_start_handler)));
1680 TestCompletionCallback callback;
1682 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1683 EXPECT_EQ(ERR_IO_PENDING, rv);
1684 base::MessageLoop::current()->RunUntilIdle();
1686 // Should have deferred for network start.
1687 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1688 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1689 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1692 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1693 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1694 // destructor in such situations.
1695 // See http://crbug.com/154712 and http://crbug.com/156609.
1696 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1697 HttpRequestInfo request;
1698 request.method = "GET";
1699 request.url = GURL("http://www.example.org/");
1700 request.load_flags = 0;
1702 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1703 scoped_ptr<HttpTransaction> trans(
1704 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1706 MockRead data_reads[] = {
1707 MockRead("HTTP/1.0 200 OK\r\n"),
1708 MockRead("Connection: keep-alive\r\n"),
1709 MockRead("Content-Length: 100\r\n\r\n"),
1710 MockRead("hello"),
1711 MockRead(SYNCHRONOUS, 0),
1713 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1714 session_deps_.socket_factory->AddSocketDataProvider(&data);
1716 TestCompletionCallback callback;
1718 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1719 EXPECT_EQ(ERR_IO_PENDING, rv);
1721 rv = callback.WaitForResult();
1722 EXPECT_EQ(OK, rv);
1724 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1725 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1726 if (rv == ERR_IO_PENDING)
1727 rv = callback.WaitForResult();
1728 EXPECT_EQ(5, rv);
1729 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1730 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1732 trans.reset();
1733 base::MessageLoop::current()->RunUntilIdle();
1734 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1737 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1738 HttpRequestInfo request;
1739 request.method = "GET";
1740 request.url = GURL("http://www.example.org/");
1741 request.load_flags = 0;
1743 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1744 scoped_ptr<HttpTransaction> trans(
1745 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1747 MockRead data_reads[] = {
1748 MockRead("HTTP/1.0 200 OK\r\n"),
1749 MockRead("Connection: keep-alive\r\n"),
1750 MockRead("Content-Length: 100\r\n\r\n"),
1751 MockRead(SYNCHRONOUS, 0),
1753 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1754 session_deps_.socket_factory->AddSocketDataProvider(&data);
1756 TestCompletionCallback callback;
1758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1759 EXPECT_EQ(ERR_IO_PENDING, rv);
1761 rv = callback.WaitForResult();
1762 EXPECT_EQ(OK, rv);
1764 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1765 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1766 if (rv == ERR_IO_PENDING)
1767 rv = callback.WaitForResult();
1768 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1770 trans.reset();
1771 base::MessageLoop::current()->RunUntilIdle();
1772 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1775 // Test that we correctly reuse a keep-alive connection after not explicitly
1776 // reading the body.
1777 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1778 HttpRequestInfo request;
1779 request.method = "GET";
1780 request.url = GURL("http://www.foo.com/");
1781 request.load_flags = 0;
1783 TestNetLog net_log;
1784 session_deps_.net_log = &net_log;
1785 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1787 // Note that because all these reads happen in the same
1788 // StaticSocketDataProvider, it shows that the same socket is being reused for
1789 // all transactions.
1790 MockRead data1_reads[] = {
1791 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1792 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1793 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1794 MockRead("HTTP/1.1 302 Found\r\n"
1795 "Content-Length: 0\r\n\r\n"),
1796 MockRead("HTTP/1.1 302 Found\r\n"
1797 "Content-Length: 5\r\n\r\n"
1798 "hello"),
1799 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1800 "Content-Length: 0\r\n\r\n"),
1801 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1802 "Content-Length: 5\r\n\r\n"
1803 "hello"),
1804 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1805 MockRead("hello"),
1807 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1808 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1810 MockRead data2_reads[] = {
1811 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1813 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1814 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1816 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1817 std::string response_lines[kNumUnreadBodies];
1819 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1820 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1821 TestCompletionCallback callback;
1823 scoped_ptr<HttpTransaction> trans(
1824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1826 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1827 EXPECT_EQ(ERR_IO_PENDING, rv);
1829 rv = callback.WaitForResult();
1830 EXPECT_EQ(OK, rv);
1832 LoadTimingInfo load_timing_info;
1833 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1834 if (i == 0) {
1835 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1836 first_socket_log_id = load_timing_info.socket_log_id;
1837 } else {
1838 TestLoadTimingReused(load_timing_info);
1839 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1842 const HttpResponseInfo* response = trans->GetResponseInfo();
1843 ASSERT_TRUE(response != NULL);
1845 ASSERT_TRUE(response->headers.get() != NULL);
1846 response_lines[i] = response->headers->GetStatusLine();
1848 // We intentionally don't read the response bodies.
1851 const char* const kStatusLines[] = {
1852 "HTTP/1.1 204 No Content",
1853 "HTTP/1.1 205 Reset Content",
1854 "HTTP/1.1 304 Not Modified",
1855 "HTTP/1.1 302 Found",
1856 "HTTP/1.1 302 Found",
1857 "HTTP/1.1 301 Moved Permanently",
1858 "HTTP/1.1 301 Moved Permanently",
1861 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1862 "forgot to update kStatusLines");
1864 for (int i = 0; i < kNumUnreadBodies; ++i)
1865 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1867 TestCompletionCallback callback;
1868 scoped_ptr<HttpTransaction> trans(
1869 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1870 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1871 EXPECT_EQ(ERR_IO_PENDING, rv);
1872 rv = callback.WaitForResult();
1873 EXPECT_EQ(OK, rv);
1874 const HttpResponseInfo* response = trans->GetResponseInfo();
1875 ASSERT_TRUE(response != NULL);
1876 ASSERT_TRUE(response->headers.get() != NULL);
1877 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1878 std::string response_data;
1879 rv = ReadTransaction(trans.get(), &response_data);
1880 EXPECT_EQ(OK, rv);
1881 EXPECT_EQ("hello", response_data);
1884 // Test the request-challenge-retry sequence for basic auth.
1885 // (basic auth is the easiest to mock, because it has no randomness).
1886 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1887 HttpRequestInfo request;
1888 request.method = "GET";
1889 request.url = GURL("http://www.example.org/");
1890 request.load_flags = 0;
1892 TestNetLog log;
1893 session_deps_.net_log = &log;
1894 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1895 scoped_ptr<HttpTransaction> trans(
1896 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1898 MockWrite data_writes1[] = {
1899 MockWrite(
1900 "GET / HTTP/1.1\r\n"
1901 "Host: www.example.org\r\n"
1902 "Connection: keep-alive\r\n\r\n"),
1905 MockRead data_reads1[] = {
1906 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1907 // Give a couple authenticate options (only the middle one is actually
1908 // supported).
1909 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1910 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1911 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1912 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1913 // Large content-length -- won't matter, as connection will be reset.
1914 MockRead("Content-Length: 10000\r\n\r\n"),
1915 MockRead(SYNCHRONOUS, ERR_FAILED),
1918 // After calling trans->RestartWithAuth(), this is the request we should
1919 // be issuing -- the final header line contains the credentials.
1920 MockWrite data_writes2[] = {
1921 MockWrite(
1922 "GET / HTTP/1.1\r\n"
1923 "Host: www.example.org\r\n"
1924 "Connection: keep-alive\r\n"
1925 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1928 // Lastly, the server responds with the actual content.
1929 MockRead data_reads2[] = {
1930 MockRead("HTTP/1.0 200 OK\r\n"),
1931 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1932 MockRead("Content-Length: 100\r\n\r\n"),
1933 MockRead(SYNCHRONOUS, OK),
1936 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1937 data_writes1, arraysize(data_writes1));
1938 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1939 data_writes2, arraysize(data_writes2));
1940 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1941 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1943 TestCompletionCallback callback1;
1945 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1946 EXPECT_EQ(ERR_IO_PENDING, rv);
1948 rv = callback1.WaitForResult();
1949 EXPECT_EQ(OK, rv);
1951 LoadTimingInfo load_timing_info1;
1952 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1953 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1955 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1956 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1958 const HttpResponseInfo* response = trans->GetResponseInfo();
1959 ASSERT_TRUE(response != NULL);
1960 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1962 TestCompletionCallback callback2;
1964 rv = trans->RestartWithAuth(
1965 AuthCredentials(kFoo, kBar), callback2.callback());
1966 EXPECT_EQ(ERR_IO_PENDING, rv);
1968 rv = callback2.WaitForResult();
1969 EXPECT_EQ(OK, rv);
1971 LoadTimingInfo load_timing_info2;
1972 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1973 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1974 // The load timing after restart should have a new socket ID, and times after
1975 // those of the first load timing.
1976 EXPECT_LE(load_timing_info1.receive_headers_end,
1977 load_timing_info2.connect_timing.connect_start);
1978 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1980 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1981 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1983 response = trans->GetResponseInfo();
1984 ASSERT_TRUE(response != NULL);
1985 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1986 EXPECT_EQ(100, response->headers->GetContentLength());
1989 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1990 HttpRequestInfo request;
1991 request.method = "GET";
1992 request.url = GURL("http://www.example.org/");
1993 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
1995 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1996 scoped_ptr<HttpTransaction> trans(
1997 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1999 MockWrite data_writes[] = {
2000 MockWrite(
2001 "GET / HTTP/1.1\r\n"
2002 "Host: www.example.org\r\n"
2003 "Connection: keep-alive\r\n\r\n"),
2006 MockRead data_reads[] = {
2007 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2008 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2009 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2010 // Large content-length -- won't matter, as connection will be reset.
2011 MockRead("Content-Length: 10000\r\n\r\n"),
2012 MockRead(SYNCHRONOUS, ERR_FAILED),
2015 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2016 data_writes, arraysize(data_writes));
2017 session_deps_.socket_factory->AddSocketDataProvider(&data);
2018 TestCompletionCallback callback;
2020 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2021 EXPECT_EQ(ERR_IO_PENDING, rv);
2023 rv = callback.WaitForResult();
2024 EXPECT_EQ(0, rv);
2026 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2027 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2029 const HttpResponseInfo* response = trans->GetResponseInfo();
2030 ASSERT_TRUE(response != NULL);
2031 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2034 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2035 // connection.
2036 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2037 HttpRequestInfo request;
2038 request.method = "GET";
2039 request.url = GURL("http://www.example.org/");
2040 request.load_flags = 0;
2042 TestNetLog log;
2043 session_deps_.net_log = &log;
2044 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2046 MockWrite data_writes1[] = {
2047 MockWrite(
2048 "GET / HTTP/1.1\r\n"
2049 "Host: www.example.org\r\n"
2050 "Connection: keep-alive\r\n\r\n"),
2052 // After calling trans->RestartWithAuth(), this is the request we should
2053 // be issuing -- the final header line contains the credentials.
2054 MockWrite(
2055 "GET / HTTP/1.1\r\n"
2056 "Host: www.example.org\r\n"
2057 "Connection: keep-alive\r\n"
2058 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2061 MockRead data_reads1[] = {
2062 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2063 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2064 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2065 MockRead("Content-Length: 14\r\n\r\n"),
2066 MockRead("Unauthorized\r\n"),
2068 // Lastly, the server responds with the actual content.
2069 MockRead("HTTP/1.1 200 OK\r\n"),
2070 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2071 MockRead("Content-Length: 5\r\n\r\n"),
2072 MockRead("Hello"),
2075 // If there is a regression where we disconnect a Keep-Alive
2076 // connection during an auth roundtrip, we'll end up reading this.
2077 MockRead data_reads2[] = {
2078 MockRead(SYNCHRONOUS, ERR_FAILED),
2081 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2082 data_writes1, arraysize(data_writes1));
2083 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2084 NULL, 0);
2085 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2086 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2088 TestCompletionCallback callback1;
2090 scoped_ptr<HttpTransaction> trans(
2091 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2092 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2093 EXPECT_EQ(ERR_IO_PENDING, rv);
2095 rv = callback1.WaitForResult();
2096 EXPECT_EQ(OK, rv);
2098 LoadTimingInfo load_timing_info1;
2099 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2100 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2102 const HttpResponseInfo* response = trans->GetResponseInfo();
2103 ASSERT_TRUE(response != NULL);
2104 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2106 TestCompletionCallback callback2;
2108 rv = trans->RestartWithAuth(
2109 AuthCredentials(kFoo, kBar), callback2.callback());
2110 EXPECT_EQ(ERR_IO_PENDING, rv);
2112 rv = callback2.WaitForResult();
2113 EXPECT_EQ(OK, rv);
2115 LoadTimingInfo load_timing_info2;
2116 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2117 TestLoadTimingReused(load_timing_info2);
2118 // The load timing after restart should have the same socket ID, and times
2119 // those of the first load timing.
2120 EXPECT_LE(load_timing_info1.receive_headers_end,
2121 load_timing_info2.send_start);
2122 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2124 response = trans->GetResponseInfo();
2125 ASSERT_TRUE(response != NULL);
2126 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2127 EXPECT_EQ(5, response->headers->GetContentLength());
2129 std::string response_data;
2130 rv = ReadTransaction(trans.get(), &response_data);
2131 EXPECT_EQ(OK, rv);
2132 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2133 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2136 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2137 // connection and with no response body to drain.
2138 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2139 HttpRequestInfo request;
2140 request.method = "GET";
2141 request.url = GURL("http://www.example.org/");
2142 request.load_flags = 0;
2144 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2146 MockWrite data_writes1[] = {
2147 MockWrite(
2148 "GET / HTTP/1.1\r\n"
2149 "Host: www.example.org\r\n"
2150 "Connection: keep-alive\r\n\r\n"),
2152 // After calling trans->RestartWithAuth(), this is the request we should
2153 // be issuing -- the final header line contains the credentials.
2154 MockWrite(
2155 "GET / HTTP/1.1\r\n"
2156 "Host: www.example.org\r\n"
2157 "Connection: keep-alive\r\n"
2158 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2161 MockRead data_reads1[] = {
2162 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2163 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2164 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2166 // Lastly, the server responds with the actual content.
2167 MockRead("HTTP/1.1 200 OK\r\n"),
2168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2169 MockRead("Content-Length: 5\r\n\r\n"),
2170 MockRead("hello"),
2173 // An incorrect reconnect would cause this to be read.
2174 MockRead data_reads2[] = {
2175 MockRead(SYNCHRONOUS, ERR_FAILED),
2178 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2179 data_writes1, arraysize(data_writes1));
2180 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2181 NULL, 0);
2182 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2183 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2185 TestCompletionCallback callback1;
2187 scoped_ptr<HttpTransaction> trans(
2188 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2189 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2190 EXPECT_EQ(ERR_IO_PENDING, rv);
2192 rv = callback1.WaitForResult();
2193 EXPECT_EQ(OK, rv);
2195 const HttpResponseInfo* response = trans->GetResponseInfo();
2196 ASSERT_TRUE(response != NULL);
2197 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2199 TestCompletionCallback callback2;
2201 rv = trans->RestartWithAuth(
2202 AuthCredentials(kFoo, kBar), callback2.callback());
2203 EXPECT_EQ(ERR_IO_PENDING, rv);
2205 rv = callback2.WaitForResult();
2206 EXPECT_EQ(OK, rv);
2208 response = trans->GetResponseInfo();
2209 ASSERT_TRUE(response != NULL);
2210 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2211 EXPECT_EQ(5, response->headers->GetContentLength());
2214 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2215 // connection and with a large response body to drain.
2216 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2217 HttpRequestInfo request;
2218 request.method = "GET";
2219 request.url = GURL("http://www.example.org/");
2220 request.load_flags = 0;
2222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2224 MockWrite data_writes1[] = {
2225 MockWrite(
2226 "GET / HTTP/1.1\r\n"
2227 "Host: www.example.org\r\n"
2228 "Connection: keep-alive\r\n\r\n"),
2230 // After calling trans->RestartWithAuth(), this is the request we should
2231 // be issuing -- the final header line contains the credentials.
2232 MockWrite(
2233 "GET / HTTP/1.1\r\n"
2234 "Host: www.example.org\r\n"
2235 "Connection: keep-alive\r\n"
2236 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2239 // Respond with 5 kb of response body.
2240 std::string large_body_string("Unauthorized");
2241 large_body_string.append(5 * 1024, ' ');
2242 large_body_string.append("\r\n");
2244 MockRead data_reads1[] = {
2245 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2246 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2247 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2248 // 5134 = 12 + 5 * 1024 + 2
2249 MockRead("Content-Length: 5134\r\n\r\n"),
2250 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2252 // Lastly, the server responds with the actual content.
2253 MockRead("HTTP/1.1 200 OK\r\n"),
2254 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2255 MockRead("Content-Length: 5\r\n\r\n"),
2256 MockRead("hello"),
2259 // An incorrect reconnect would cause this to be read.
2260 MockRead data_reads2[] = {
2261 MockRead(SYNCHRONOUS, ERR_FAILED),
2264 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2265 data_writes1, arraysize(data_writes1));
2266 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2267 NULL, 0);
2268 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2269 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2271 TestCompletionCallback callback1;
2273 scoped_ptr<HttpTransaction> trans(
2274 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2275 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2276 EXPECT_EQ(ERR_IO_PENDING, rv);
2278 rv = callback1.WaitForResult();
2279 EXPECT_EQ(OK, rv);
2281 const HttpResponseInfo* response = trans->GetResponseInfo();
2282 ASSERT_TRUE(response != NULL);
2283 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2285 TestCompletionCallback callback2;
2287 rv = trans->RestartWithAuth(
2288 AuthCredentials(kFoo, kBar), callback2.callback());
2289 EXPECT_EQ(ERR_IO_PENDING, rv);
2291 rv = callback2.WaitForResult();
2292 EXPECT_EQ(OK, rv);
2294 response = trans->GetResponseInfo();
2295 ASSERT_TRUE(response != NULL);
2296 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2297 EXPECT_EQ(5, response->headers->GetContentLength());
2300 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2301 // connection, but the server gets impatient and closes the connection.
2302 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2303 HttpRequestInfo request;
2304 request.method = "GET";
2305 request.url = GURL("http://www.example.org/");
2306 request.load_flags = 0;
2308 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2310 MockWrite data_writes1[] = {
2311 MockWrite(
2312 "GET / HTTP/1.1\r\n"
2313 "Host: www.example.org\r\n"
2314 "Connection: keep-alive\r\n\r\n"),
2315 // This simulates the seemingly successful write to a closed connection
2316 // if the bug is not fixed.
2317 MockWrite(
2318 "GET / HTTP/1.1\r\n"
2319 "Host: www.example.org\r\n"
2320 "Connection: keep-alive\r\n"
2321 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2324 MockRead data_reads1[] = {
2325 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2326 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2327 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2328 MockRead("Content-Length: 14\r\n\r\n"),
2329 // Tell MockTCPClientSocket to simulate the server closing the connection.
2330 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2331 MockRead("Unauthorized\r\n"),
2332 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2335 // After calling trans->RestartWithAuth(), this is the request we should
2336 // be issuing -- the final header line contains the credentials.
2337 MockWrite data_writes2[] = {
2338 MockWrite(
2339 "GET / HTTP/1.1\r\n"
2340 "Host: www.example.org\r\n"
2341 "Connection: keep-alive\r\n"
2342 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2345 // Lastly, the server responds with the actual content.
2346 MockRead data_reads2[] = {
2347 MockRead("HTTP/1.1 200 OK\r\n"),
2348 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2349 MockRead("Content-Length: 5\r\n\r\n"),
2350 MockRead("hello"),
2353 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2354 data_writes1, arraysize(data_writes1));
2355 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2356 data_writes2, arraysize(data_writes2));
2357 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2358 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2360 TestCompletionCallback callback1;
2362 scoped_ptr<HttpTransaction> trans(
2363 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2364 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2365 EXPECT_EQ(ERR_IO_PENDING, rv);
2367 rv = callback1.WaitForResult();
2368 EXPECT_EQ(OK, rv);
2370 const HttpResponseInfo* response = trans->GetResponseInfo();
2371 ASSERT_TRUE(response != NULL);
2372 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2374 TestCompletionCallback callback2;
2376 rv = trans->RestartWithAuth(
2377 AuthCredentials(kFoo, kBar), callback2.callback());
2378 EXPECT_EQ(ERR_IO_PENDING, rv);
2380 rv = callback2.WaitForResult();
2381 EXPECT_EQ(OK, rv);
2383 response = trans->GetResponseInfo();
2384 ASSERT_TRUE(response != NULL);
2385 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2386 EXPECT_EQ(5, response->headers->GetContentLength());
2389 // Test the request-challenge-retry sequence for basic auth, over a connection
2390 // that requires a restart when setting up an SSL tunnel.
2391 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2392 HttpRequestInfo request;
2393 request.method = "GET";
2394 request.url = GURL("https://www.example.org/");
2395 // when the no authentication data flag is set.
2396 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2398 // Configure against proxy server "myproxy:70".
2399 session_deps_.proxy_service.reset(
2400 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2401 BoundTestNetLog log;
2402 session_deps_.net_log = log.bound().net_log();
2403 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2405 // Since we have proxy, should try to establish tunnel.
2406 MockWrite data_writes1[] = {
2407 MockWrite(
2408 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2409 "Host: www.example.org\r\n"
2410 "Proxy-Connection: keep-alive\r\n\r\n"),
2412 // After calling trans->RestartWithAuth(), this is the request we should
2413 // be issuing -- the final header line contains the credentials.
2414 MockWrite(
2415 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2416 "Host: www.example.org\r\n"
2417 "Proxy-Connection: keep-alive\r\n"
2418 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2420 MockWrite(
2421 "GET / HTTP/1.1\r\n"
2422 "Host: www.example.org\r\n"
2423 "Connection: keep-alive\r\n\r\n"),
2426 // The proxy responds to the connect with a 407, using a persistent
2427 // connection.
2428 MockRead data_reads1[] = {
2429 // No credentials.
2430 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2431 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2433 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2435 MockRead("HTTP/1.1 200 OK\r\n"),
2436 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2437 MockRead("Content-Length: 5\r\n\r\n"),
2438 MockRead(SYNCHRONOUS, "hello"),
2441 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2442 data_writes1, arraysize(data_writes1));
2443 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2444 SSLSocketDataProvider ssl(ASYNC, OK);
2445 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2447 TestCompletionCallback callback1;
2449 scoped_ptr<HttpTransaction> trans(
2450 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2452 int rv = trans->Start(&request, callback1.callback(), log.bound());
2453 EXPECT_EQ(ERR_IO_PENDING, rv);
2455 rv = callback1.WaitForResult();
2456 EXPECT_EQ(OK, rv);
2457 CapturedNetLogEntry::List entries;
2458 log.GetEntries(&entries);
2459 size_t pos = ExpectLogContainsSomewhere(
2460 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2461 NetLog::PHASE_NONE);
2462 ExpectLogContainsSomewhere(
2463 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2464 NetLog::PHASE_NONE);
2466 const HttpResponseInfo* response = trans->GetResponseInfo();
2467 ASSERT_TRUE(response != NULL);
2468 EXPECT_FALSE(response->headers->IsKeepAlive());
2469 ASSERT_FALSE(response->headers.get() == NULL);
2470 EXPECT_EQ(407, response->headers->response_code());
2471 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2472 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2474 LoadTimingInfo load_timing_info;
2475 // CONNECT requests and responses are handled at the connect job level, so
2476 // the transaction does not yet have a connection.
2477 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2479 TestCompletionCallback callback2;
2481 rv =
2482 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2483 EXPECT_EQ(ERR_IO_PENDING, rv);
2485 rv = callback2.WaitForResult();
2486 EXPECT_EQ(OK, rv);
2488 response = trans->GetResponseInfo();
2489 ASSERT_TRUE(response != NULL);
2491 EXPECT_TRUE(response->headers->IsKeepAlive());
2492 EXPECT_EQ(200, response->headers->response_code());
2493 EXPECT_EQ(5, response->headers->GetContentLength());
2494 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2496 // The password prompt info should not be set.
2497 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2499 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2500 TestLoadTimingNotReusedWithPac(load_timing_info,
2501 CONNECT_TIMING_HAS_SSL_TIMES);
2503 trans.reset();
2504 session->CloseAllConnections();
2507 // Test the request-challenge-retry sequence for basic auth, over a connection
2508 // that requires a restart when setting up an SSL tunnel.
2509 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
2510 HttpRequestInfo request;
2511 request.method = "GET";
2512 request.url = GURL("https://www.example.org/");
2513 // when the no authentication data flag is set.
2514 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2516 // Configure against proxy server "myproxy:70".
2517 session_deps_.proxy_service.reset(
2518 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2519 BoundTestNetLog log;
2520 session_deps_.net_log = log.bound().net_log();
2521 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2523 // Since we have proxy, should try to establish tunnel.
2524 MockWrite data_writes1[] = {
2525 MockWrite(
2526 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2527 "Host: www.example.org\r\n"
2528 "Proxy-Connection: keep-alive\r\n\r\n"),
2530 // After calling trans->RestartWithAuth(), this is the request we should
2531 // be issuing -- the final header line contains the credentials.
2532 MockWrite(
2533 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2534 "Host: www.example.org\r\n"
2535 "Proxy-Connection: keep-alive\r\n"
2536 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2538 MockWrite(
2539 "GET / HTTP/1.1\r\n"
2540 "Host: www.example.org\r\n"
2541 "Connection: keep-alive\r\n\r\n"),
2544 // The proxy responds to the connect with a 407, using a persistent
2545 // connection.
2546 MockRead data_reads1[] = {
2547 // No credentials.
2548 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2549 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2550 MockRead("Proxy-Connection: close\r\n\r\n"),
2552 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2554 MockRead("HTTP/1.1 200 OK\r\n"),
2555 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2556 MockRead("Content-Length: 5\r\n\r\n"),
2557 MockRead(SYNCHRONOUS, "hello"),
2560 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2561 data_writes1, arraysize(data_writes1));
2562 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2563 SSLSocketDataProvider ssl(ASYNC, OK);
2564 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2566 TestCompletionCallback callback1;
2568 scoped_ptr<HttpTransaction> trans(
2569 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2571 int rv = trans->Start(&request, callback1.callback(), log.bound());
2572 EXPECT_EQ(ERR_IO_PENDING, rv);
2574 rv = callback1.WaitForResult();
2575 EXPECT_EQ(OK, rv);
2576 CapturedNetLogEntry::List entries;
2577 log.GetEntries(&entries);
2578 size_t pos = ExpectLogContainsSomewhere(
2579 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2580 NetLog::PHASE_NONE);
2581 ExpectLogContainsSomewhere(
2582 entries, pos,
2583 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2584 NetLog::PHASE_NONE);
2586 const HttpResponseInfo* response = trans->GetResponseInfo();
2587 ASSERT_TRUE(response != NULL);
2588 EXPECT_FALSE(response->headers->IsKeepAlive());
2589 ASSERT_FALSE(response->headers.get() == NULL);
2590 EXPECT_EQ(407, response->headers->response_code());
2591 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2592 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2594 LoadTimingInfo load_timing_info;
2595 // CONNECT requests and responses are handled at the connect job level, so
2596 // the transaction does not yet have a connection.
2597 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2599 TestCompletionCallback callback2;
2601 rv = trans->RestartWithAuth(
2602 AuthCredentials(kFoo, kBar), callback2.callback());
2603 EXPECT_EQ(ERR_IO_PENDING, rv);
2605 rv = callback2.WaitForResult();
2606 EXPECT_EQ(OK, rv);
2608 response = trans->GetResponseInfo();
2609 ASSERT_TRUE(response != NULL);
2611 EXPECT_TRUE(response->headers->IsKeepAlive());
2612 EXPECT_EQ(200, response->headers->response_code());
2613 EXPECT_EQ(5, response->headers->GetContentLength());
2614 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2616 // The password prompt info should not be set.
2617 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2619 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2620 TestLoadTimingNotReusedWithPac(load_timing_info,
2621 CONNECT_TIMING_HAS_SSL_TIMES);
2623 trans.reset();
2624 session->CloseAllConnections();
2627 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2628 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2629 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2630 HttpRequestInfo request;
2631 request.method = "GET";
2632 request.url = GURL("https://www.example.org/");
2633 // Ensure that proxy authentication is attempted even
2634 // when the no authentication data flag is set.
2635 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2637 // Configure against proxy server "myproxy:70".
2638 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2639 BoundTestNetLog log;
2640 session_deps_.net_log = log.bound().net_log();
2641 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2643 scoped_ptr<HttpTransaction> trans(
2644 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2646 // Since we have proxy, should try to establish tunnel.
2647 MockWrite data_writes1[] = {
2648 MockWrite(
2649 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2650 "Host: www.example.org\r\n"
2651 "Proxy-Connection: keep-alive\r\n\r\n"),
2653 // After calling trans->RestartWithAuth(), this is the request we should
2654 // be issuing -- the final header line contains the credentials.
2655 MockWrite(
2656 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2657 "Host: www.example.org\r\n"
2658 "Proxy-Connection: keep-alive\r\n"
2659 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2662 // The proxy responds to the connect with a 407, using a persistent
2663 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2664 MockRead data_reads1[] = {
2665 // No credentials.
2666 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2667 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2668 MockRead("Proxy-Connection: keep-alive\r\n"),
2669 MockRead("Content-Length: 10\r\n\r\n"),
2670 MockRead("0123456789"),
2672 // Wrong credentials (wrong password).
2673 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2674 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2675 MockRead("Proxy-Connection: keep-alive\r\n"),
2676 MockRead("Content-Length: 10\r\n\r\n"),
2677 // No response body because the test stops reading here.
2678 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2681 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2682 data_writes1, arraysize(data_writes1));
2683 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2685 TestCompletionCallback callback1;
2687 int rv = trans->Start(&request, callback1.callback(), log.bound());
2688 EXPECT_EQ(ERR_IO_PENDING, rv);
2690 rv = callback1.WaitForResult();
2691 EXPECT_EQ(OK, rv);
2692 CapturedNetLogEntry::List entries;
2693 log.GetEntries(&entries);
2694 size_t pos = ExpectLogContainsSomewhere(
2695 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2696 NetLog::PHASE_NONE);
2697 ExpectLogContainsSomewhere(
2698 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2699 NetLog::PHASE_NONE);
2701 const HttpResponseInfo* response = trans->GetResponseInfo();
2702 ASSERT_TRUE(response);
2703 ASSERT_TRUE(response->headers);
2704 EXPECT_TRUE(response->headers->IsKeepAlive());
2705 EXPECT_EQ(407, response->headers->response_code());
2706 EXPECT_EQ(10, response->headers->GetContentLength());
2707 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2708 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2710 TestCompletionCallback callback2;
2712 // Wrong password (should be "bar").
2713 rv =
2714 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2715 EXPECT_EQ(ERR_IO_PENDING, rv);
2717 rv = callback2.WaitForResult();
2718 EXPECT_EQ(OK, rv);
2720 response = trans->GetResponseInfo();
2721 ASSERT_TRUE(response);
2722 ASSERT_TRUE(response->headers);
2723 EXPECT_TRUE(response->headers->IsKeepAlive());
2724 EXPECT_EQ(407, response->headers->response_code());
2725 EXPECT_EQ(10, response->headers->GetContentLength());
2726 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2727 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2729 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2730 // out of scope.
2731 session->CloseAllConnections();
2734 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2735 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2736 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
2737 HttpRequestInfo request;
2738 request.method = "GET";
2739 request.url = GURL("https://www.example.org/");
2740 // Ensure that proxy authentication is attempted even
2741 // when the no authentication data flag is set.
2742 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2744 // Configure against proxy server "myproxy:70".
2745 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2746 BoundTestNetLog log;
2747 session_deps_.net_log = log.bound().net_log();
2748 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2750 scoped_ptr<HttpTransaction> trans(
2751 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2753 // Since we have proxy, should try to establish tunnel.
2754 MockWrite data_writes1[] = {
2755 MockWrite(
2756 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2757 "Host: www.example.org\r\n"
2758 "Proxy-Connection: keep-alive\r\n\r\n"),
2760 // After calling trans->RestartWithAuth(), this is the request we should
2761 // be issuing -- the final header line contains the credentials.
2762 MockWrite(
2763 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2764 "Host: www.example.org\r\n"
2765 "Proxy-Connection: keep-alive\r\n"
2766 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2769 // The proxy responds to the connect with a 407, using a persistent
2770 // connection.
2771 MockRead data_reads1[] = {
2772 // No credentials.
2773 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2774 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2775 MockRead("Content-Length: 10\r\n\r\n"),
2776 MockRead("0123456789"),
2778 // Wrong credentials (wrong password).
2779 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2780 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2781 MockRead("Content-Length: 10\r\n\r\n"),
2782 // No response body because the test stops reading here.
2783 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2786 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2787 data_writes1, arraysize(data_writes1));
2788 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2790 TestCompletionCallback callback1;
2792 int rv = trans->Start(&request, callback1.callback(), log.bound());
2793 EXPECT_EQ(ERR_IO_PENDING, rv);
2795 rv = callback1.WaitForResult();
2796 EXPECT_EQ(OK, rv);
2797 CapturedNetLogEntry::List entries;
2798 log.GetEntries(&entries);
2799 size_t pos = ExpectLogContainsSomewhere(
2800 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2801 NetLog::PHASE_NONE);
2802 ExpectLogContainsSomewhere(
2803 entries, pos,
2804 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2805 NetLog::PHASE_NONE);
2807 const HttpResponseInfo* response = trans->GetResponseInfo();
2808 ASSERT_TRUE(response);
2809 ASSERT_TRUE(response->headers);
2810 EXPECT_TRUE(response->headers->IsKeepAlive());
2811 EXPECT_EQ(407, response->headers->response_code());
2812 EXPECT_EQ(10, response->headers->GetContentLength());
2813 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2814 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2816 TestCompletionCallback callback2;
2818 // Wrong password (should be "bar").
2819 rv = trans->RestartWithAuth(
2820 AuthCredentials(kFoo, kBaz), callback2.callback());
2821 EXPECT_EQ(ERR_IO_PENDING, rv);
2823 rv = callback2.WaitForResult();
2824 EXPECT_EQ(OK, rv);
2826 response = trans->GetResponseInfo();
2827 ASSERT_TRUE(response);
2828 ASSERT_TRUE(response->headers);
2829 EXPECT_TRUE(response->headers->IsKeepAlive());
2830 EXPECT_EQ(407, response->headers->response_code());
2831 EXPECT_EQ(10, response->headers->GetContentLength());
2832 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2833 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2835 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2836 // out of scope.
2837 session->CloseAllConnections();
2840 // Test that we don't read the response body when we fail to establish a tunnel,
2841 // even if the user cancels the proxy's auth attempt.
2842 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2843 HttpRequestInfo request;
2844 request.method = "GET";
2845 request.url = GURL("https://www.example.org/");
2846 request.load_flags = 0;
2848 // Configure against proxy server "myproxy:70".
2849 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2851 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2853 scoped_ptr<HttpTransaction> trans(
2854 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2856 // Since we have proxy, should try to establish tunnel.
2857 MockWrite data_writes[] = {
2858 MockWrite(
2859 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2860 "Host: www.example.org\r\n"
2861 "Proxy-Connection: keep-alive\r\n\r\n"),
2864 // The proxy responds to the connect with a 407.
2865 MockRead data_reads[] = {
2866 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2867 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2868 MockRead("Content-Length: 10\r\n\r\n"),
2869 MockRead("0123456789"), // Should not be reached.
2870 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
2873 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2874 data_writes, arraysize(data_writes));
2875 session_deps_.socket_factory->AddSocketDataProvider(&data);
2877 TestCompletionCallback callback;
2879 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2880 EXPECT_EQ(ERR_IO_PENDING, rv);
2882 rv = callback.WaitForResult();
2883 EXPECT_EQ(OK, rv);
2885 const HttpResponseInfo* response = trans->GetResponseInfo();
2886 ASSERT_TRUE(response);
2887 ASSERT_TRUE(response->headers);
2888 EXPECT_TRUE(response->headers->IsKeepAlive());
2889 EXPECT_EQ(407, response->headers->response_code());
2890 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2892 std::string response_data;
2893 rv = ReadTransaction(trans.get(), &response_data);
2894 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2896 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2897 session->CloseAllConnections();
2900 // Test that we don't pass extraneous headers from the proxy's response to the
2901 // caller when the proxy responds to CONNECT with 407.
2902 TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
2903 HttpRequestInfo request;
2904 request.method = "GET";
2905 request.url = GURL("https://www.example.org/");
2906 request.load_flags = 0;
2908 // Configure against proxy server "myproxy:70".
2909 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2911 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2913 scoped_ptr<HttpTransaction> trans(
2914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2916 // Since we have proxy, should try to establish tunnel.
2917 MockWrite data_writes[] = {
2918 MockWrite(
2919 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2920 "Host: www.example.org\r\n"
2921 "Proxy-Connection: keep-alive\r\n\r\n"),
2924 // The proxy responds to the connect with a 407.
2925 MockRead data_reads[] = {
2926 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2927 MockRead("X-Foo: bar\r\n"),
2928 MockRead("Set-Cookie: foo=bar\r\n"),
2929 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2930 MockRead("Content-Length: 10\r\n\r\n"),
2931 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2934 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
2935 arraysize(data_writes));
2936 session_deps_.socket_factory->AddSocketDataProvider(&data);
2938 TestCompletionCallback callback;
2940 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2941 EXPECT_EQ(ERR_IO_PENDING, rv);
2943 rv = callback.WaitForResult();
2944 EXPECT_EQ(OK, rv);
2946 const HttpResponseInfo* response = trans->GetResponseInfo();
2947 ASSERT_TRUE(response);
2948 ASSERT_TRUE(response->headers);
2949 EXPECT_TRUE(response->headers->IsKeepAlive());
2950 EXPECT_EQ(407, response->headers->response_code());
2951 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2952 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
2953 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
2955 std::string response_data;
2956 rv = ReadTransaction(trans.get(), &response_data);
2957 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2959 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2960 session->CloseAllConnections();
2963 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2964 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2965 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2966 HttpRequestInfo request;
2967 request.method = "GET";
2968 request.url = GURL("http://www.example.org/");
2969 request.load_flags = 0;
2971 // We are using a DIRECT connection (i.e. no proxy) for this session.
2972 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2973 scoped_ptr<HttpTransaction> trans(
2974 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2976 MockWrite data_writes1[] = {
2977 MockWrite(
2978 "GET / HTTP/1.1\r\n"
2979 "Host: www.example.org\r\n"
2980 "Connection: keep-alive\r\n\r\n"),
2983 MockRead data_reads1[] = {
2984 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2985 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2986 // Large content-length -- won't matter, as connection will be reset.
2987 MockRead("Content-Length: 10000\r\n\r\n"),
2988 MockRead(SYNCHRONOUS, ERR_FAILED),
2991 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2992 data_writes1, arraysize(data_writes1));
2993 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2995 TestCompletionCallback callback;
2997 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2998 EXPECT_EQ(ERR_IO_PENDING, rv);
3000 rv = callback.WaitForResult();
3001 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3004 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3005 // through a non-authenticating proxy. The request should fail with
3006 // ERR_UNEXPECTED_PROXY_AUTH.
3007 // Note that it is impossible to detect if an HTTP server returns a 407 through
3008 // a non-authenticating proxy - there is nothing to indicate whether the
3009 // response came from the proxy or the server, so it is treated as if the proxy
3010 // issued the challenge.
3011 TEST_P(HttpNetworkTransactionTest,
3012 HttpsServerRequestsProxyAuthThroughProxy) {
3013 HttpRequestInfo request;
3014 request.method = "GET";
3015 request.url = GURL("https://www.example.org/");
3017 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3018 BoundTestNetLog log;
3019 session_deps_.net_log = log.bound().net_log();
3020 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3022 // Since we have proxy, should try to establish tunnel.
3023 MockWrite data_writes1[] = {
3024 MockWrite(
3025 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3026 "Host: www.example.org\r\n"
3027 "Proxy-Connection: keep-alive\r\n\r\n"),
3029 MockWrite(
3030 "GET / HTTP/1.1\r\n"
3031 "Host: www.example.org\r\n"
3032 "Connection: keep-alive\r\n\r\n"),
3035 MockRead data_reads1[] = {
3036 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3038 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3039 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3040 MockRead("\r\n"),
3041 MockRead(SYNCHRONOUS, OK),
3044 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3045 data_writes1, arraysize(data_writes1));
3046 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3047 SSLSocketDataProvider ssl(ASYNC, OK);
3048 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3050 TestCompletionCallback callback1;
3052 scoped_ptr<HttpTransaction> trans(
3053 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3055 int rv = trans->Start(&request, callback1.callback(), log.bound());
3056 EXPECT_EQ(ERR_IO_PENDING, rv);
3058 rv = callback1.WaitForResult();
3059 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3060 CapturedNetLogEntry::List entries;
3061 log.GetEntries(&entries);
3062 size_t pos = ExpectLogContainsSomewhere(
3063 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3064 NetLog::PHASE_NONE);
3065 ExpectLogContainsSomewhere(
3066 entries, pos,
3067 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3068 NetLog::PHASE_NONE);
3071 // Test the load timing for HTTPS requests with an HTTP proxy.
3072 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
3073 HttpRequestInfo request1;
3074 request1.method = "GET";
3075 request1.url = GURL("https://www.example.org/1");
3077 HttpRequestInfo request2;
3078 request2.method = "GET";
3079 request2.url = GURL("https://www.example.org/2");
3081 // Configure against proxy server "myproxy:70".
3082 session_deps_.proxy_service.reset(
3083 ProxyService::CreateFixed("PROXY myproxy:70"));
3084 BoundTestNetLog log;
3085 session_deps_.net_log = log.bound().net_log();
3086 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3088 // Since we have proxy, should try to establish tunnel.
3089 MockWrite data_writes1[] = {
3090 MockWrite(
3091 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3092 "Host: www.example.org\r\n"
3093 "Proxy-Connection: keep-alive\r\n\r\n"),
3095 MockWrite(
3096 "GET /1 HTTP/1.1\r\n"
3097 "Host: www.example.org\r\n"
3098 "Connection: keep-alive\r\n\r\n"),
3100 MockWrite(
3101 "GET /2 HTTP/1.1\r\n"
3102 "Host: www.example.org\r\n"
3103 "Connection: keep-alive\r\n\r\n"),
3106 // The proxy responds to the connect with a 407, using a persistent
3107 // connection.
3108 MockRead data_reads1[] = {
3109 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3111 MockRead("HTTP/1.1 200 OK\r\n"),
3112 MockRead("Content-Length: 1\r\n\r\n"),
3113 MockRead(SYNCHRONOUS, "1"),
3115 MockRead("HTTP/1.1 200 OK\r\n"),
3116 MockRead("Content-Length: 2\r\n\r\n"),
3117 MockRead(SYNCHRONOUS, "22"),
3120 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3121 data_writes1, arraysize(data_writes1));
3122 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3123 SSLSocketDataProvider ssl(ASYNC, OK);
3124 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3126 TestCompletionCallback callback1;
3127 scoped_ptr<HttpTransaction> trans1(
3128 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3130 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3131 EXPECT_EQ(ERR_IO_PENDING, rv);
3133 rv = callback1.WaitForResult();
3134 EXPECT_EQ(OK, rv);
3136 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3137 ASSERT_TRUE(response1 != NULL);
3138 ASSERT_TRUE(response1->headers.get() != NULL);
3139 EXPECT_EQ(1, response1->headers->GetContentLength());
3141 LoadTimingInfo load_timing_info1;
3142 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3143 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3145 trans1.reset();
3147 TestCompletionCallback callback2;
3148 scoped_ptr<HttpTransaction> trans2(
3149 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3151 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3152 EXPECT_EQ(ERR_IO_PENDING, rv);
3154 rv = callback2.WaitForResult();
3155 EXPECT_EQ(OK, rv);
3157 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3158 ASSERT_TRUE(response2 != NULL);
3159 ASSERT_TRUE(response2->headers.get() != NULL);
3160 EXPECT_EQ(2, response2->headers->GetContentLength());
3162 LoadTimingInfo load_timing_info2;
3163 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3164 TestLoadTimingReused(load_timing_info2);
3166 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3168 trans2.reset();
3169 session->CloseAllConnections();
3172 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3173 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
3174 HttpRequestInfo request1;
3175 request1.method = "GET";
3176 request1.url = GURL("https://www.example.org/1");
3178 HttpRequestInfo request2;
3179 request2.method = "GET";
3180 request2.url = GURL("https://www.example.org/2");
3182 // Configure against proxy server "myproxy:70".
3183 session_deps_.proxy_service.reset(
3184 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3185 BoundTestNetLog log;
3186 session_deps_.net_log = log.bound().net_log();
3187 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3189 // Since we have proxy, should try to establish tunnel.
3190 MockWrite data_writes1[] = {
3191 MockWrite(
3192 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3193 "Host: www.example.org\r\n"
3194 "Proxy-Connection: keep-alive\r\n\r\n"),
3196 MockWrite(
3197 "GET /1 HTTP/1.1\r\n"
3198 "Host: www.example.org\r\n"
3199 "Connection: keep-alive\r\n\r\n"),
3201 MockWrite(
3202 "GET /2 HTTP/1.1\r\n"
3203 "Host: www.example.org\r\n"
3204 "Connection: keep-alive\r\n\r\n"),
3207 // The proxy responds to the connect with a 407, using a persistent
3208 // connection.
3209 MockRead data_reads1[] = {
3210 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3212 MockRead("HTTP/1.1 200 OK\r\n"),
3213 MockRead("Content-Length: 1\r\n\r\n"),
3214 MockRead(SYNCHRONOUS, "1"),
3216 MockRead("HTTP/1.1 200 OK\r\n"),
3217 MockRead("Content-Length: 2\r\n\r\n"),
3218 MockRead(SYNCHRONOUS, "22"),
3221 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3222 data_writes1, arraysize(data_writes1));
3223 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3224 SSLSocketDataProvider ssl(ASYNC, OK);
3225 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3227 TestCompletionCallback callback1;
3228 scoped_ptr<HttpTransaction> trans1(
3229 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3231 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3232 EXPECT_EQ(ERR_IO_PENDING, rv);
3234 rv = callback1.WaitForResult();
3235 EXPECT_EQ(OK, rv);
3237 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3238 ASSERT_TRUE(response1 != NULL);
3239 ASSERT_TRUE(response1->headers.get() != NULL);
3240 EXPECT_EQ(1, response1->headers->GetContentLength());
3242 LoadTimingInfo load_timing_info1;
3243 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3244 TestLoadTimingNotReusedWithPac(load_timing_info1,
3245 CONNECT_TIMING_HAS_SSL_TIMES);
3247 trans1.reset();
3249 TestCompletionCallback callback2;
3250 scoped_ptr<HttpTransaction> trans2(
3251 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3253 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3254 EXPECT_EQ(ERR_IO_PENDING, rv);
3256 rv = callback2.WaitForResult();
3257 EXPECT_EQ(OK, rv);
3259 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3260 ASSERT_TRUE(response2 != NULL);
3261 ASSERT_TRUE(response2->headers.get() != NULL);
3262 EXPECT_EQ(2, response2->headers->GetContentLength());
3264 LoadTimingInfo load_timing_info2;
3265 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3266 TestLoadTimingReusedWithPac(load_timing_info2);
3268 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3270 trans2.reset();
3271 session->CloseAllConnections();
3274 // Test a simple get through an HTTPS Proxy.
3275 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
3276 HttpRequestInfo request;
3277 request.method = "GET";
3278 request.url = GURL("http://www.example.org/");
3280 // Configure against https proxy server "proxy:70".
3281 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3282 "https://proxy:70"));
3283 BoundTestNetLog log;
3284 session_deps_.net_log = log.bound().net_log();
3285 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3287 // Since we have proxy, should use full url
3288 MockWrite data_writes1[] = {
3289 MockWrite(
3290 "GET http://www.example.org/ HTTP/1.1\r\n"
3291 "Host: www.example.org\r\n"
3292 "Proxy-Connection: keep-alive\r\n\r\n"),
3295 MockRead data_reads1[] = {
3296 MockRead("HTTP/1.1 200 OK\r\n"),
3297 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3298 MockRead("Content-Length: 100\r\n\r\n"),
3299 MockRead(SYNCHRONOUS, OK),
3302 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3303 data_writes1, arraysize(data_writes1));
3304 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3305 SSLSocketDataProvider ssl(ASYNC, OK);
3306 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3308 TestCompletionCallback callback1;
3310 scoped_ptr<HttpTransaction> trans(
3311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3313 int rv = trans->Start(&request, callback1.callback(), log.bound());
3314 EXPECT_EQ(ERR_IO_PENDING, rv);
3316 rv = callback1.WaitForResult();
3317 EXPECT_EQ(OK, rv);
3319 LoadTimingInfo load_timing_info;
3320 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3321 TestLoadTimingNotReused(load_timing_info,
3322 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3324 const HttpResponseInfo* response = trans->GetResponseInfo();
3325 ASSERT_TRUE(response != NULL);
3327 EXPECT_TRUE(response->headers->IsKeepAlive());
3328 EXPECT_EQ(200, response->headers->response_code());
3329 EXPECT_EQ(100, response->headers->GetContentLength());
3330 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3332 // The password prompt info should not be set.
3333 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3336 // Test a SPDY get through an HTTPS Proxy.
3337 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3338 HttpRequestInfo request;
3339 request.method = "GET";
3340 request.url = GURL("http://www.example.org/");
3341 request.load_flags = 0;
3343 // Configure against https proxy server "proxy:70".
3344 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3345 "https://proxy:70"));
3346 BoundTestNetLog log;
3347 session_deps_.net_log = log.bound().net_log();
3348 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3350 // fetch http://www.example.org/ via SPDY
3351 scoped_ptr<SpdyFrame> req(
3352 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3353 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
3355 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3356 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3357 MockRead spdy_reads[] = {
3358 CreateMockRead(*resp),
3359 CreateMockRead(*data),
3360 MockRead(ASYNC, 0, 0),
3363 DelayedSocketData spdy_data(
3364 1, // wait for one write to finish before reading.
3365 spdy_reads, arraysize(spdy_reads),
3366 spdy_writes, arraysize(spdy_writes));
3367 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3369 SSLSocketDataProvider ssl(ASYNC, OK);
3370 ssl.SetNextProto(GetParam());
3371 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3373 TestCompletionCallback callback1;
3375 scoped_ptr<HttpTransaction> trans(
3376 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3378 int rv = trans->Start(&request, callback1.callback(), log.bound());
3379 EXPECT_EQ(ERR_IO_PENDING, rv);
3381 rv = callback1.WaitForResult();
3382 EXPECT_EQ(OK, rv);
3384 LoadTimingInfo load_timing_info;
3385 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3386 TestLoadTimingNotReused(load_timing_info,
3387 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3389 const HttpResponseInfo* response = trans->GetResponseInfo();
3390 ASSERT_TRUE(response != NULL);
3391 ASSERT_TRUE(response->headers.get() != NULL);
3392 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3394 std::string response_data;
3395 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3396 EXPECT_EQ(kUploadData, response_data);
3399 // Verifies that a session which races and wins against the owning transaction
3400 // (completing prior to host resolution), doesn't fail the transaction.
3401 // Regression test for crbug.com/334413.
3402 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3403 HttpRequestInfo request;
3404 request.method = "GET";
3405 request.url = GURL("http://www.example.org/");
3406 request.load_flags = 0;
3408 // Configure SPDY proxy server "proxy:70".
3409 session_deps_.proxy_service.reset(
3410 ProxyService::CreateFixed("https://proxy:70"));
3411 BoundTestNetLog log;
3412 session_deps_.net_log = log.bound().net_log();
3413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3415 // Fetch http://www.example.org/ through the SPDY proxy.
3416 scoped_ptr<SpdyFrame> req(
3417 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3418 MockWrite spdy_writes[] = {CreateMockWrite(*req)};
3420 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3421 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3422 MockRead spdy_reads[] = {
3423 CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0),
3426 DelayedSocketData spdy_data(
3427 1, // wait for one write to finish before reading.
3428 spdy_reads,
3429 arraysize(spdy_reads),
3430 spdy_writes,
3431 arraysize(spdy_writes));
3432 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3434 SSLSocketDataProvider ssl(ASYNC, OK);
3435 ssl.SetNextProto(GetParam());
3436 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3438 TestCompletionCallback callback1;
3440 scoped_ptr<HttpTransaction> trans(
3441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3443 // Stall the hostname resolution begun by the transaction.
3444 session_deps_.host_resolver->set_synchronous_mode(false);
3445 session_deps_.host_resolver->set_ondemand_mode(true);
3447 int rv = trans->Start(&request, callback1.callback(), log.bound());
3448 EXPECT_EQ(ERR_IO_PENDING, rv);
3450 // Race a session to the proxy, which completes first.
3451 session_deps_.host_resolver->set_ondemand_mode(false);
3452 SpdySessionKey key(
3453 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3454 base::WeakPtr<SpdySession> spdy_session =
3455 CreateSecureSpdySession(session, key, log.bound());
3457 // Unstall the resolution begun by the transaction.
3458 session_deps_.host_resolver->set_ondemand_mode(true);
3459 session_deps_.host_resolver->ResolveAllPending();
3461 EXPECT_FALSE(callback1.have_result());
3462 rv = callback1.WaitForResult();
3463 EXPECT_EQ(OK, rv);
3465 const HttpResponseInfo* response = trans->GetResponseInfo();
3466 ASSERT_TRUE(response != NULL);
3467 ASSERT_TRUE(response->headers.get() != NULL);
3468 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3470 std::string response_data;
3471 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3472 EXPECT_EQ(kUploadData, response_data);
3475 // Test a SPDY get through an HTTPS Proxy.
3476 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3477 HttpRequestInfo request;
3478 request.method = "GET";
3479 request.url = GURL("http://www.example.org/");
3480 request.load_flags = 0;
3482 // Configure against https proxy server "myproxy:70".
3483 session_deps_.proxy_service.reset(
3484 ProxyService::CreateFixed("https://myproxy:70"));
3485 BoundTestNetLog log;
3486 session_deps_.net_log = log.bound().net_log();
3487 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3489 // The first request will be a bare GET, the second request will be a
3490 // GET with a Proxy-Authorization header.
3491 scoped_ptr<SpdyFrame> req_get(
3492 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3493 const char* const kExtraAuthorizationHeaders[] = {
3494 "proxy-authorization", "Basic Zm9vOmJhcg=="
3496 scoped_ptr<SpdyFrame> req_get_authorization(
3497 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3498 arraysize(kExtraAuthorizationHeaders) / 2,
3499 false,
3501 LOWEST,
3502 false));
3503 MockWrite spdy_writes[] = {
3504 CreateMockWrite(*req_get, 1),
3505 CreateMockWrite(*req_get_authorization, 4),
3508 // The first response is a 407 proxy authentication challenge, and the second
3509 // response will be a 200 response since the second request includes a valid
3510 // Authorization header.
3511 const char* const kExtraAuthenticationHeaders[] = {
3512 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3514 scoped_ptr<SpdyFrame> resp_authentication(
3515 spdy_util_.ConstructSpdySynReplyError(
3516 "407 Proxy Authentication Required",
3517 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3518 1));
3519 scoped_ptr<SpdyFrame> body_authentication(
3520 spdy_util_.ConstructSpdyBodyFrame(1, true));
3521 scoped_ptr<SpdyFrame> resp_data(
3522 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3523 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3524 MockRead spdy_reads[] = {
3525 CreateMockRead(*resp_authentication, 2),
3526 CreateMockRead(*body_authentication, 3),
3527 CreateMockRead(*resp_data, 5),
3528 CreateMockRead(*body_data, 6),
3529 MockRead(ASYNC, 0, 7),
3532 OrderedSocketData data(
3533 spdy_reads, arraysize(spdy_reads),
3534 spdy_writes, arraysize(spdy_writes));
3535 session_deps_.socket_factory->AddSocketDataProvider(&data);
3537 SSLSocketDataProvider ssl(ASYNC, OK);
3538 ssl.SetNextProto(GetParam());
3539 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3541 TestCompletionCallback callback1;
3543 scoped_ptr<HttpTransaction> trans(
3544 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3546 int rv = trans->Start(&request, callback1.callback(), log.bound());
3547 EXPECT_EQ(ERR_IO_PENDING, rv);
3549 rv = callback1.WaitForResult();
3550 EXPECT_EQ(OK, rv);
3552 const HttpResponseInfo* const response = trans->GetResponseInfo();
3554 ASSERT_TRUE(response != NULL);
3555 ASSERT_TRUE(response->headers.get() != NULL);
3556 EXPECT_EQ(407, response->headers->response_code());
3557 EXPECT_TRUE(response->was_fetched_via_spdy);
3558 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3560 TestCompletionCallback callback2;
3562 rv = trans->RestartWithAuth(
3563 AuthCredentials(kFoo, kBar), callback2.callback());
3564 EXPECT_EQ(ERR_IO_PENDING, rv);
3566 rv = callback2.WaitForResult();
3567 EXPECT_EQ(OK, rv);
3569 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3571 ASSERT_TRUE(response_restart != NULL);
3572 ASSERT_TRUE(response_restart->headers.get() != NULL);
3573 EXPECT_EQ(200, response_restart->headers->response_code());
3574 // The password prompt info should not be set.
3575 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3578 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3579 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3580 HttpRequestInfo request;
3581 request.method = "GET";
3582 request.url = GURL("https://www.example.org/");
3583 request.load_flags = 0;
3585 // Configure against https proxy server "proxy:70".
3586 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3587 "https://proxy:70"));
3588 BoundTestNetLog log;
3589 session_deps_.net_log = log.bound().net_log();
3590 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3592 scoped_ptr<HttpTransaction> trans(
3593 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3595 // CONNECT to www.example.org:443 via SPDY
3596 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3597 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3598 // fetch https://www.example.org/ via HTTP
3600 const char get[] =
3601 "GET / HTTP/1.1\r\n"
3602 "Host: www.example.org\r\n"
3603 "Connection: keep-alive\r\n\r\n";
3604 scoped_ptr<SpdyFrame> wrapped_get(
3605 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3606 scoped_ptr<SpdyFrame> conn_resp(
3607 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3608 const char resp[] = "HTTP/1.1 200 OK\r\n"
3609 "Content-Length: 10\r\n\r\n";
3610 scoped_ptr<SpdyFrame> wrapped_get_resp(
3611 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3612 scoped_ptr<SpdyFrame> wrapped_body(
3613 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3614 scoped_ptr<SpdyFrame> window_update(
3615 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3617 MockWrite spdy_writes[] = {
3618 CreateMockWrite(*connect, 1),
3619 CreateMockWrite(*wrapped_get, 3),
3620 CreateMockWrite(*window_update, 5),
3623 MockRead spdy_reads[] = {
3624 CreateMockRead(*conn_resp, 2, ASYNC),
3625 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3626 CreateMockRead(*wrapped_body, 6, ASYNC),
3627 CreateMockRead(*wrapped_body, 7, ASYNC),
3628 MockRead(ASYNC, 0, 8),
3631 OrderedSocketData spdy_data(
3632 spdy_reads, arraysize(spdy_reads),
3633 spdy_writes, arraysize(spdy_writes));
3634 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3636 SSLSocketDataProvider ssl(ASYNC, OK);
3637 ssl.SetNextProto(GetParam());
3638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3639 SSLSocketDataProvider ssl2(ASYNC, OK);
3640 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3642 TestCompletionCallback callback1;
3644 int rv = trans->Start(&request, callback1.callback(), log.bound());
3645 EXPECT_EQ(ERR_IO_PENDING, rv);
3647 rv = callback1.WaitForResult();
3648 EXPECT_EQ(OK, rv);
3650 LoadTimingInfo load_timing_info;
3651 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3652 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3654 const HttpResponseInfo* response = trans->GetResponseInfo();
3655 ASSERT_TRUE(response != NULL);
3656 ASSERT_TRUE(response->headers.get() != NULL);
3657 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3659 std::string response_data;
3660 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3661 EXPECT_EQ("1234567890", response_data);
3664 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3665 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3666 HttpRequestInfo request;
3667 request.method = "GET";
3668 request.url = GURL("https://www.example.org/");
3669 request.load_flags = 0;
3671 // Configure against https proxy server "proxy:70".
3672 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3673 "https://proxy:70"));
3674 BoundTestNetLog log;
3675 session_deps_.net_log = log.bound().net_log();
3676 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3678 scoped_ptr<HttpTransaction> trans(
3679 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3681 // CONNECT to www.example.org:443 via SPDY
3682 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3683 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3684 // fetch https://www.example.org/ via SPDY
3685 const char kMyUrl[] = "https://www.example.org/";
3686 scoped_ptr<SpdyFrame> get(
3687 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3688 scoped_ptr<SpdyFrame> wrapped_get(
3689 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3690 scoped_ptr<SpdyFrame> conn_resp(
3691 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3692 scoped_ptr<SpdyFrame> get_resp(
3693 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3694 scoped_ptr<SpdyFrame> wrapped_get_resp(
3695 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3696 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3697 scoped_ptr<SpdyFrame> wrapped_body(
3698 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3699 scoped_ptr<SpdyFrame> window_update_get_resp(
3700 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3701 scoped_ptr<SpdyFrame> window_update_body(
3702 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3704 MockWrite spdy_writes[] = {
3705 CreateMockWrite(*connect, 1),
3706 CreateMockWrite(*wrapped_get, 3),
3707 CreateMockWrite(*window_update_get_resp, 5),
3708 CreateMockWrite(*window_update_body, 7),
3711 MockRead spdy_reads[] = {
3712 CreateMockRead(*conn_resp, 2, ASYNC),
3713 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3714 CreateMockRead(*wrapped_body, 6, ASYNC),
3715 MockRead(ASYNC, 0, 8),
3718 OrderedSocketData spdy_data(
3719 spdy_reads, arraysize(spdy_reads),
3720 spdy_writes, arraysize(spdy_writes));
3721 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3723 SSLSocketDataProvider ssl(ASYNC, OK);
3724 ssl.SetNextProto(GetParam());
3725 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3726 SSLSocketDataProvider ssl2(ASYNC, OK);
3727 ssl2.SetNextProto(GetParam());
3728 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3730 TestCompletionCallback callback1;
3732 int rv = trans->Start(&request, callback1.callback(), log.bound());
3733 EXPECT_EQ(ERR_IO_PENDING, rv);
3735 rv = callback1.WaitForResult();
3736 EXPECT_EQ(OK, rv);
3738 LoadTimingInfo load_timing_info;
3739 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3740 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3742 const HttpResponseInfo* response = trans->GetResponseInfo();
3743 ASSERT_TRUE(response != NULL);
3744 ASSERT_TRUE(response->headers.get() != NULL);
3745 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3747 std::string response_data;
3748 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3749 EXPECT_EQ(kUploadData, response_data);
3752 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3753 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3754 HttpRequestInfo request;
3755 request.method = "GET";
3756 request.url = GURL("https://www.example.org/");
3757 request.load_flags = 0;
3759 // Configure against https proxy server "proxy:70".
3760 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3761 "https://proxy:70"));
3762 BoundTestNetLog log;
3763 session_deps_.net_log = log.bound().net_log();
3764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3766 scoped_ptr<HttpTransaction> trans(
3767 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3769 // CONNECT to www.example.org:443 via SPDY
3770 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3771 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3772 scoped_ptr<SpdyFrame> get(
3773 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3775 MockWrite spdy_writes[] = {
3776 CreateMockWrite(*connect, 1),
3777 CreateMockWrite(*get, 3),
3780 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3781 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3782 MockRead spdy_reads[] = {
3783 CreateMockRead(*resp, 2, ASYNC),
3784 MockRead(ASYNC, 0, 4),
3787 OrderedSocketData spdy_data(
3788 spdy_reads, arraysize(spdy_reads),
3789 spdy_writes, arraysize(spdy_writes));
3790 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3792 SSLSocketDataProvider ssl(ASYNC, OK);
3793 ssl.SetNextProto(GetParam());
3794 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3795 SSLSocketDataProvider ssl2(ASYNC, OK);
3796 ssl2.SetNextProto(GetParam());
3797 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3799 TestCompletionCallback callback1;
3801 int rv = trans->Start(&request, callback1.callback(), log.bound());
3802 EXPECT_EQ(ERR_IO_PENDING, rv);
3804 rv = callback1.WaitForResult();
3805 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3807 // TODO(ttuttle): Anything else to check here?
3810 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3811 // HTTPS Proxy to different servers.
3812 TEST_P(HttpNetworkTransactionTest,
3813 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3814 // Configure against https proxy server "proxy:70".
3815 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3816 "https://proxy:70"));
3817 BoundTestNetLog log;
3818 session_deps_.net_log = log.bound().net_log();
3819 scoped_refptr<HttpNetworkSession> session(
3820 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3822 HttpRequestInfo request1;
3823 request1.method = "GET";
3824 request1.url = GURL("https://www.example.org/");
3825 request1.load_flags = 0;
3827 HttpRequestInfo request2;
3828 request2.method = "GET";
3829 request2.url = GURL("https://mail.example.org/");
3830 request2.load_flags = 0;
3832 // CONNECT to www.example.org:443 via SPDY.
3833 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3834 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3835 scoped_ptr<SpdyFrame> conn_resp1(
3836 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3838 // Fetch https://www.example.org/ via HTTP.
3839 const char get1[] =
3840 "GET / HTTP/1.1\r\n"
3841 "Host: www.example.org\r\n"
3842 "Connection: keep-alive\r\n\r\n";
3843 scoped_ptr<SpdyFrame> wrapped_get1(
3844 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3845 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3846 "Content-Length: 1\r\n\r\n";
3847 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3848 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3849 scoped_ptr<SpdyFrame> wrapped_body1(
3850 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3851 scoped_ptr<SpdyFrame> window_update(
3852 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3854 // CONNECT to mail.example.org:443 via SPDY.
3855 SpdyHeaderBlock connect2_block;
3856 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3857 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
3858 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
3859 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3860 scoped_ptr<SpdyFrame> connect2(
3861 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3863 scoped_ptr<SpdyFrame> conn_resp2(
3864 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3866 // Fetch https://mail.example.org/ via HTTP.
3867 const char get2[] =
3868 "GET / HTTP/1.1\r\n"
3869 "Host: mail.example.org\r\n"
3870 "Connection: keep-alive\r\n\r\n";
3871 scoped_ptr<SpdyFrame> wrapped_get2(
3872 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3873 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3874 "Content-Length: 2\r\n\r\n";
3875 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3876 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3877 scoped_ptr<SpdyFrame> wrapped_body2(
3878 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3880 MockWrite spdy_writes[] = {
3881 CreateMockWrite(*connect1, 0),
3882 CreateMockWrite(*wrapped_get1, 2),
3883 CreateMockWrite(*connect2, 5),
3884 CreateMockWrite(*wrapped_get2, 7),
3887 MockRead spdy_reads[] = {
3888 CreateMockRead(*conn_resp1, 1, ASYNC),
3889 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3890 CreateMockRead(*wrapped_body1, 4, ASYNC),
3891 CreateMockRead(*conn_resp2, 6, ASYNC),
3892 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3893 CreateMockRead(*wrapped_body2, 9, ASYNC),
3894 MockRead(ASYNC, 0, 10),
3897 DeterministicSocketData spdy_data(
3898 spdy_reads, arraysize(spdy_reads),
3899 spdy_writes, arraysize(spdy_writes));
3900 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3902 SSLSocketDataProvider ssl(ASYNC, OK);
3903 ssl.SetNextProto(GetParam());
3904 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3905 SSLSocketDataProvider ssl2(ASYNC, OK);
3906 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3907 SSLSocketDataProvider ssl3(ASYNC, OK);
3908 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3910 TestCompletionCallback callback;
3912 scoped_ptr<HttpTransaction> trans(
3913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3914 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3915 EXPECT_EQ(ERR_IO_PENDING, rv);
3916 // The first connect and request, each of their responses, and the body.
3917 spdy_data.RunFor(5);
3919 rv = callback.WaitForResult();
3920 EXPECT_EQ(OK, rv);
3922 LoadTimingInfo load_timing_info;
3923 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3924 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3926 const HttpResponseInfo* response = trans->GetResponseInfo();
3927 ASSERT_TRUE(response != NULL);
3928 ASSERT_TRUE(response->headers.get() != NULL);
3929 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3931 std::string response_data;
3932 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
3933 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3935 scoped_ptr<HttpTransaction> trans2(
3936 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3937 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3938 EXPECT_EQ(ERR_IO_PENDING, rv);
3940 // The second connect and request, each of their responses, and the body.
3941 spdy_data.RunFor(5);
3942 rv = callback.WaitForResult();
3943 EXPECT_EQ(OK, rv);
3945 LoadTimingInfo load_timing_info2;
3946 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3947 // Even though the SPDY connection is reused, a new tunnelled connection has
3948 // to be created, so the socket's load timing looks like a fresh connection.
3949 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3951 // The requests should have different IDs, since they each are using their own
3952 // separate stream.
3953 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3955 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3958 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3959 // HTTPS Proxy to the same server.
3960 TEST_P(HttpNetworkTransactionTest,
3961 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3962 // Configure against https proxy server "proxy:70".
3963 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3964 "https://proxy:70"));
3965 BoundTestNetLog log;
3966 session_deps_.net_log = log.bound().net_log();
3967 scoped_refptr<HttpNetworkSession> session(
3968 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3970 HttpRequestInfo request1;
3971 request1.method = "GET";
3972 request1.url = GURL("https://www.example.org/");
3973 request1.load_flags = 0;
3975 HttpRequestInfo request2;
3976 request2.method = "GET";
3977 request2.url = GURL("https://www.example.org/2");
3978 request2.load_flags = 0;
3980 // CONNECT to www.example.org:443 via SPDY.
3981 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3982 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3983 scoped_ptr<SpdyFrame> conn_resp1(
3984 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3986 // Fetch https://www.example.org/ via HTTP.
3987 const char get1[] =
3988 "GET / HTTP/1.1\r\n"
3989 "Host: www.example.org\r\n"
3990 "Connection: keep-alive\r\n\r\n";
3991 scoped_ptr<SpdyFrame> wrapped_get1(
3992 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3993 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3994 "Content-Length: 1\r\n\r\n";
3995 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3996 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3997 scoped_ptr<SpdyFrame> wrapped_body1(
3998 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3999 scoped_ptr<SpdyFrame> window_update(
4000 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
4002 // Fetch https://www.example.org/2 via HTTP.
4003 const char get2[] =
4004 "GET /2 HTTP/1.1\r\n"
4005 "Host: www.example.org\r\n"
4006 "Connection: keep-alive\r\n\r\n";
4007 scoped_ptr<SpdyFrame> wrapped_get2(
4008 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
4009 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4010 "Content-Length: 2\r\n\r\n";
4011 scoped_ptr<SpdyFrame> wrapped_get_resp2(
4012 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
4013 scoped_ptr<SpdyFrame> wrapped_body2(
4014 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
4016 MockWrite spdy_writes[] = {
4017 CreateMockWrite(*connect1, 0),
4018 CreateMockWrite(*wrapped_get1, 2),
4019 CreateMockWrite(*wrapped_get2, 5),
4022 MockRead spdy_reads[] = {
4023 CreateMockRead(*conn_resp1, 1, ASYNC),
4024 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4025 CreateMockRead(*wrapped_body1, 4, ASYNC),
4026 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4027 CreateMockRead(*wrapped_body2, 7, ASYNC),
4028 MockRead(ASYNC, 0, 8),
4031 DeterministicSocketData spdy_data(
4032 spdy_reads, arraysize(spdy_reads),
4033 spdy_writes, arraysize(spdy_writes));
4034 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
4036 SSLSocketDataProvider ssl(ASYNC, OK);
4037 ssl.SetNextProto(GetParam());
4038 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
4039 SSLSocketDataProvider ssl2(ASYNC, OK);
4040 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
4042 TestCompletionCallback callback;
4044 scoped_ptr<HttpTransaction> trans(
4045 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4046 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4047 EXPECT_EQ(ERR_IO_PENDING, rv);
4048 // The first connect and request, each of their responses, and the body.
4049 spdy_data.RunFor(5);
4051 rv = callback.WaitForResult();
4052 EXPECT_EQ(OK, rv);
4054 LoadTimingInfo load_timing_info;
4055 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4056 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4058 const HttpResponseInfo* response = trans->GetResponseInfo();
4059 ASSERT_TRUE(response != NULL);
4060 ASSERT_TRUE(response->headers.get() != NULL);
4061 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4063 std::string response_data;
4064 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4065 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
4066 trans.reset();
4068 scoped_ptr<HttpTransaction> trans2(
4069 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4070 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4071 EXPECT_EQ(ERR_IO_PENDING, rv);
4073 // The second request, response, and body. There should not be a second
4074 // connect.
4075 spdy_data.RunFor(3);
4076 rv = callback.WaitForResult();
4077 EXPECT_EQ(OK, rv);
4079 LoadTimingInfo load_timing_info2;
4080 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4081 TestLoadTimingReused(load_timing_info2);
4083 // The requests should have the same ID.
4084 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4086 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
4089 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4090 // Proxy to different servers.
4091 TEST_P(HttpNetworkTransactionTest,
4092 HttpsProxySpdyLoadTimingTwoHttpRequests) {
4093 // Configure against https proxy server "proxy:70".
4094 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
4095 "https://proxy:70"));
4096 BoundTestNetLog log;
4097 session_deps_.net_log = log.bound().net_log();
4098 scoped_refptr<HttpNetworkSession> session(
4099 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
4101 HttpRequestInfo request1;
4102 request1.method = "GET";
4103 request1.url = GURL("http://www.example.org/");
4104 request1.load_flags = 0;
4106 HttpRequestInfo request2;
4107 request2.method = "GET";
4108 request2.url = GURL("http://mail.example.org/");
4109 request2.load_flags = 0;
4111 // http://www.example.org/
4112 scoped_ptr<SpdyHeaderBlock> headers(
4113 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4114 scoped_ptr<SpdyFrame> get1(
4115 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4116 scoped_ptr<SpdyFrame> get_resp1(
4117 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4118 scoped_ptr<SpdyFrame> body1(
4119 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
4121 // http://mail.example.org/
4122 scoped_ptr<SpdyHeaderBlock> headers2(
4123 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4124 scoped_ptr<SpdyFrame> get2(
4125 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
4126 scoped_ptr<SpdyFrame> get_resp2(
4127 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4128 scoped_ptr<SpdyFrame> body2(
4129 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
4131 MockWrite spdy_writes[] = {
4132 CreateMockWrite(*get1, 0),
4133 CreateMockWrite(*get2, 3),
4136 MockRead spdy_reads[] = {
4137 CreateMockRead(*get_resp1, 1, ASYNC),
4138 CreateMockRead(*body1, 2, ASYNC),
4139 CreateMockRead(*get_resp2, 4, ASYNC),
4140 CreateMockRead(*body2, 5, ASYNC),
4141 MockRead(ASYNC, 0, 6),
4144 DeterministicSocketData spdy_data(
4145 spdy_reads, arraysize(spdy_reads),
4146 spdy_writes, arraysize(spdy_writes));
4147 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
4149 SSLSocketDataProvider ssl(ASYNC, OK);
4150 ssl.SetNextProto(GetParam());
4151 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
4153 TestCompletionCallback callback;
4155 scoped_ptr<HttpTransaction> trans(
4156 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4157 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4158 EXPECT_EQ(ERR_IO_PENDING, rv);
4159 spdy_data.RunFor(2);
4161 rv = callback.WaitForResult();
4162 EXPECT_EQ(OK, rv);
4164 LoadTimingInfo load_timing_info;
4165 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4166 TestLoadTimingNotReused(load_timing_info,
4167 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4169 const HttpResponseInfo* response = trans->GetResponseInfo();
4170 ASSERT_TRUE(response != NULL);
4171 ASSERT_TRUE(response->headers.get() != NULL);
4172 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4174 std::string response_data;
4175 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4176 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
4177 spdy_data.RunFor(1);
4178 EXPECT_EQ(1, callback.WaitForResult());
4179 // Delete the first request, so the second one can reuse the socket.
4180 trans.reset();
4182 scoped_ptr<HttpTransaction> trans2(
4183 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4184 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4185 EXPECT_EQ(ERR_IO_PENDING, rv);
4187 spdy_data.RunFor(2);
4188 rv = callback.WaitForResult();
4189 EXPECT_EQ(OK, rv);
4191 LoadTimingInfo load_timing_info2;
4192 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4193 TestLoadTimingReused(load_timing_info2);
4195 // The requests should have the same ID.
4196 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4198 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
4199 spdy_data.RunFor(1);
4200 EXPECT_EQ(2, callback.WaitForResult());
4203 // Test the challenge-response-retry sequence through an HTTPS Proxy
4204 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
4205 HttpRequestInfo request;
4206 request.method = "GET";
4207 request.url = GURL("http://www.example.org/");
4208 // when the no authentication data flag is set.
4209 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
4211 // Configure against https proxy server "myproxy:70".
4212 session_deps_.proxy_service.reset(
4213 ProxyService::CreateFixed("https://myproxy:70"));
4214 BoundTestNetLog log;
4215 session_deps_.net_log = log.bound().net_log();
4216 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4218 // Since we have proxy, should use full url
4219 MockWrite data_writes1[] = {
4220 MockWrite(
4221 "GET http://www.example.org/ HTTP/1.1\r\n"
4222 "Host: www.example.org\r\n"
4223 "Proxy-Connection: keep-alive\r\n\r\n"),
4225 // After calling trans->RestartWithAuth(), this is the request we should
4226 // be issuing -- the final header line contains the credentials.
4227 MockWrite(
4228 "GET http://www.example.org/ HTTP/1.1\r\n"
4229 "Host: www.example.org\r\n"
4230 "Proxy-Connection: keep-alive\r\n"
4231 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4234 // The proxy responds to the GET with a 407, using a persistent
4235 // connection.
4236 MockRead data_reads1[] = {
4237 // No credentials.
4238 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4239 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4240 MockRead("Proxy-Connection: keep-alive\r\n"),
4241 MockRead("Content-Length: 0\r\n\r\n"),
4243 MockRead("HTTP/1.1 200 OK\r\n"),
4244 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4245 MockRead("Content-Length: 100\r\n\r\n"),
4246 MockRead(SYNCHRONOUS, OK),
4249 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4250 data_writes1, arraysize(data_writes1));
4251 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4252 SSLSocketDataProvider ssl(ASYNC, OK);
4253 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4255 TestCompletionCallback callback1;
4257 scoped_ptr<HttpTransaction> trans(
4258 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4260 int rv = trans->Start(&request, callback1.callback(), log.bound());
4261 EXPECT_EQ(ERR_IO_PENDING, rv);
4263 rv = callback1.WaitForResult();
4264 EXPECT_EQ(OK, rv);
4266 LoadTimingInfo load_timing_info;
4267 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4268 TestLoadTimingNotReused(load_timing_info,
4269 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4271 const HttpResponseInfo* response = trans->GetResponseInfo();
4272 ASSERT_TRUE(response != NULL);
4273 ASSERT_FALSE(response->headers.get() == NULL);
4274 EXPECT_EQ(407, response->headers->response_code());
4275 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4276 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4278 TestCompletionCallback callback2;
4280 rv = trans->RestartWithAuth(
4281 AuthCredentials(kFoo, kBar), callback2.callback());
4282 EXPECT_EQ(ERR_IO_PENDING, rv);
4284 rv = callback2.WaitForResult();
4285 EXPECT_EQ(OK, rv);
4287 load_timing_info = LoadTimingInfo();
4288 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4289 // Retrying with HTTP AUTH is considered to be reusing a socket.
4290 TestLoadTimingReused(load_timing_info);
4292 response = trans->GetResponseInfo();
4293 ASSERT_TRUE(response != NULL);
4295 EXPECT_TRUE(response->headers->IsKeepAlive());
4296 EXPECT_EQ(200, response->headers->response_code());
4297 EXPECT_EQ(100, response->headers->GetContentLength());
4298 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4300 // The password prompt info should not be set.
4301 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4304 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4305 const MockRead& status, int expected_status) {
4306 HttpRequestInfo request;
4307 request.method = "GET";
4308 request.url = GURL("https://www.example.org/");
4309 request.load_flags = 0;
4311 // Configure against proxy server "myproxy:70".
4312 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4313 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4315 // Since we have proxy, should try to establish tunnel.
4316 MockWrite data_writes[] = {
4317 MockWrite(
4318 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4319 "Host: www.example.org\r\n"
4320 "Proxy-Connection: keep-alive\r\n\r\n"),
4323 MockRead data_reads[] = {
4324 status,
4325 MockRead("Content-Length: 10\r\n\r\n"),
4326 // No response body because the test stops reading here.
4327 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4330 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4331 data_writes, arraysize(data_writes));
4332 session_deps_.socket_factory->AddSocketDataProvider(&data);
4334 TestCompletionCallback callback;
4336 scoped_ptr<HttpTransaction> trans(
4337 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4339 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4340 EXPECT_EQ(ERR_IO_PENDING, rv);
4342 rv = callback.WaitForResult();
4343 EXPECT_EQ(expected_status, rv);
4346 void HttpNetworkTransactionTest::ConnectStatusHelper(
4347 const MockRead& status) {
4348 ConnectStatusHelperWithExpectedStatus(
4349 status, ERR_TUNNEL_CONNECTION_FAILED);
4352 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4353 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4356 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4357 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4360 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4361 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4364 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4365 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4368 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4369 ConnectStatusHelper(
4370 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4373 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4374 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4377 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4378 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4381 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4382 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4385 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4386 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4389 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4390 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4393 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4394 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4397 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4398 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4401 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4402 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4405 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4406 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4409 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4410 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4413 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4414 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4417 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4418 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4421 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4422 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4425 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4426 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4429 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4430 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4433 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4434 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4437 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4438 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4441 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4442 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4445 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4446 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4449 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4450 ConnectStatusHelperWithExpectedStatus(
4451 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4452 ERR_PROXY_AUTH_UNSUPPORTED);
4455 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4456 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4459 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4460 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4463 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4464 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4467 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4468 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4471 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4472 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4475 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4476 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4479 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4480 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4483 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4484 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4487 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4488 ConnectStatusHelper(
4489 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4492 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4493 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4496 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4497 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4500 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4501 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4504 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4505 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4508 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4509 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4512 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4513 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4516 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4517 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4520 // Test the flow when both the proxy server AND origin server require
4521 // authentication. Again, this uses basic auth for both since that is
4522 // the simplest to mock.
4523 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4524 HttpRequestInfo request;
4525 request.method = "GET";
4526 request.url = GURL("http://www.example.org/");
4527 request.load_flags = 0;
4529 // Configure against proxy server "myproxy:70".
4530 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4531 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4533 scoped_ptr<HttpTransaction> trans(
4534 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4536 MockWrite data_writes1[] = {
4537 MockWrite(
4538 "GET http://www.example.org/ HTTP/1.1\r\n"
4539 "Host: www.example.org\r\n"
4540 "Proxy-Connection: keep-alive\r\n\r\n"),
4543 MockRead data_reads1[] = {
4544 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4545 // Give a couple authenticate options (only the middle one is actually
4546 // supported).
4547 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4548 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4549 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4550 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4551 // Large content-length -- won't matter, as connection will be reset.
4552 MockRead("Content-Length: 10000\r\n\r\n"),
4553 MockRead(SYNCHRONOUS, ERR_FAILED),
4556 // After calling trans->RestartWithAuth() the first time, this is the
4557 // request we should be issuing -- the final header line contains the
4558 // proxy's credentials.
4559 MockWrite data_writes2[] = {
4560 MockWrite(
4561 "GET http://www.example.org/ HTTP/1.1\r\n"
4562 "Host: www.example.org\r\n"
4563 "Proxy-Connection: keep-alive\r\n"
4564 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4567 // Now the proxy server lets the request pass through to origin server.
4568 // The origin server responds with a 401.
4569 MockRead data_reads2[] = {
4570 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4571 // Note: We are using the same realm-name as the proxy server. This is
4572 // completely valid, as realms are unique across hosts.
4573 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4574 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4575 MockRead("Content-Length: 2000\r\n\r\n"),
4576 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4579 // After calling trans->RestartWithAuth() the second time, we should send
4580 // the credentials for both the proxy and origin server.
4581 MockWrite data_writes3[] = {
4582 MockWrite(
4583 "GET http://www.example.org/ HTTP/1.1\r\n"
4584 "Host: www.example.org\r\n"
4585 "Proxy-Connection: keep-alive\r\n"
4586 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4587 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4590 // Lastly we get the desired content.
4591 MockRead data_reads3[] = {
4592 MockRead("HTTP/1.0 200 OK\r\n"),
4593 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4594 MockRead("Content-Length: 100\r\n\r\n"),
4595 MockRead(SYNCHRONOUS, OK),
4598 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4599 data_writes1, arraysize(data_writes1));
4600 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4601 data_writes2, arraysize(data_writes2));
4602 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4603 data_writes3, arraysize(data_writes3));
4604 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4605 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4606 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4608 TestCompletionCallback callback1;
4610 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4611 EXPECT_EQ(ERR_IO_PENDING, rv);
4613 rv = callback1.WaitForResult();
4614 EXPECT_EQ(OK, rv);
4616 const HttpResponseInfo* response = trans->GetResponseInfo();
4617 ASSERT_TRUE(response != NULL);
4618 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4620 TestCompletionCallback callback2;
4622 rv = trans->RestartWithAuth(
4623 AuthCredentials(kFoo, kBar), callback2.callback());
4624 EXPECT_EQ(ERR_IO_PENDING, rv);
4626 rv = callback2.WaitForResult();
4627 EXPECT_EQ(OK, rv);
4629 response = trans->GetResponseInfo();
4630 ASSERT_TRUE(response != NULL);
4631 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4633 TestCompletionCallback callback3;
4635 rv = trans->RestartWithAuth(
4636 AuthCredentials(kFoo2, kBar2), callback3.callback());
4637 EXPECT_EQ(ERR_IO_PENDING, rv);
4639 rv = callback3.WaitForResult();
4640 EXPECT_EQ(OK, rv);
4642 response = trans->GetResponseInfo();
4643 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4644 EXPECT_EQ(100, response->headers->GetContentLength());
4647 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4648 // can't hook into its internals to cause it to generate predictable NTLM
4649 // authorization headers.
4650 #if defined(NTLM_PORTABLE)
4651 // The NTLM authentication unit tests were generated by capturing the HTTP
4652 // requests and responses using Fiddler 2 and inspecting the generated random
4653 // bytes in the debugger.
4655 // Enter the correct password and authenticate successfully.
4656 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4657 HttpRequestInfo request;
4658 request.method = "GET";
4659 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4661 // Ensure load is not disrupted by flags which suppress behaviour specific
4662 // to other auth schemes.
4663 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4665 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4666 MockGetHostName);
4667 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4669 MockWrite data_writes1[] = {
4670 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4671 "Host: 172.22.68.17\r\n"
4672 "Connection: keep-alive\r\n\r\n"),
4675 MockRead data_reads1[] = {
4676 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4677 // Negotiate and NTLM are often requested together. However, we only want
4678 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4679 // the header that requests Negotiate for this test.
4680 MockRead("WWW-Authenticate: NTLM\r\n"),
4681 MockRead("Connection: close\r\n"),
4682 MockRead("Content-Length: 42\r\n"),
4683 MockRead("Content-Type: text/html\r\n\r\n"),
4684 // Missing content -- won't matter, as connection will be reset.
4685 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4688 MockWrite data_writes2[] = {
4689 // After restarting with a null identity, this is the
4690 // request we should be issuing -- the final header line contains a Type
4691 // 1 message.
4692 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4693 "Host: 172.22.68.17\r\n"
4694 "Connection: keep-alive\r\n"
4695 "Authorization: NTLM "
4696 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4698 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4699 // (the credentials for the origin server). The second request continues
4700 // on the same connection.
4701 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4702 "Host: 172.22.68.17\r\n"
4703 "Connection: keep-alive\r\n"
4704 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4705 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4706 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4707 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4708 "ahlhx5I=\r\n\r\n"),
4711 MockRead data_reads2[] = {
4712 // The origin server responds with a Type 2 message.
4713 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4714 MockRead("WWW-Authenticate: NTLM "
4715 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4716 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4717 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4718 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4719 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4720 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4721 "BtAAAAAAA=\r\n"),
4722 MockRead("Content-Length: 42\r\n"),
4723 MockRead("Content-Type: text/html\r\n\r\n"),
4724 MockRead("You are not authorized to view this page\r\n"),
4726 // Lastly we get the desired content.
4727 MockRead("HTTP/1.1 200 OK\r\n"),
4728 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4729 MockRead("Content-Length: 13\r\n\r\n"),
4730 MockRead("Please Login\r\n"),
4731 MockRead(SYNCHRONOUS, OK),
4734 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4735 data_writes1, arraysize(data_writes1));
4736 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4737 data_writes2, arraysize(data_writes2));
4738 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4739 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4741 TestCompletionCallback callback1;
4743 scoped_ptr<HttpTransaction> trans(
4744 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4746 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4747 EXPECT_EQ(ERR_IO_PENDING, rv);
4749 rv = callback1.WaitForResult();
4750 EXPECT_EQ(OK, rv);
4752 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4754 const HttpResponseInfo* response = trans->GetResponseInfo();
4755 ASSERT_FALSE(response == NULL);
4756 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4758 TestCompletionCallback callback2;
4760 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4761 callback2.callback());
4762 EXPECT_EQ(ERR_IO_PENDING, rv);
4764 rv = callback2.WaitForResult();
4765 EXPECT_EQ(OK, rv);
4767 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4769 response = trans->GetResponseInfo();
4770 ASSERT_TRUE(response != NULL);
4771 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4773 TestCompletionCallback callback3;
4775 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4776 EXPECT_EQ(ERR_IO_PENDING, rv);
4778 rv = callback3.WaitForResult();
4779 EXPECT_EQ(OK, rv);
4781 response = trans->GetResponseInfo();
4782 ASSERT_TRUE(response != NULL);
4783 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4784 EXPECT_EQ(13, response->headers->GetContentLength());
4787 // Enter a wrong password, and then the correct one.
4788 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4789 HttpRequestInfo request;
4790 request.method = "GET";
4791 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4792 request.load_flags = 0;
4794 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4795 MockGetHostName);
4796 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4798 MockWrite data_writes1[] = {
4799 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4800 "Host: 172.22.68.17\r\n"
4801 "Connection: keep-alive\r\n\r\n"),
4804 MockRead data_reads1[] = {
4805 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4806 // Negotiate and NTLM are often requested together. However, we only want
4807 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4808 // the header that requests Negotiate for this test.
4809 MockRead("WWW-Authenticate: NTLM\r\n"),
4810 MockRead("Connection: close\r\n"),
4811 MockRead("Content-Length: 42\r\n"),
4812 MockRead("Content-Type: text/html\r\n\r\n"),
4813 // Missing content -- won't matter, as connection will be reset.
4814 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4817 MockWrite data_writes2[] = {
4818 // After restarting with a null identity, this is the
4819 // request we should be issuing -- the final header line contains a Type
4820 // 1 message.
4821 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4822 "Host: 172.22.68.17\r\n"
4823 "Connection: keep-alive\r\n"
4824 "Authorization: NTLM "
4825 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4827 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4828 // (the credentials for the origin server). The second request continues
4829 // on the same connection.
4830 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4831 "Host: 172.22.68.17\r\n"
4832 "Connection: keep-alive\r\n"
4833 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4834 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4835 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4836 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4837 "4Ww7b7E=\r\n\r\n"),
4840 MockRead data_reads2[] = {
4841 // The origin server responds with a Type 2 message.
4842 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4843 MockRead("WWW-Authenticate: NTLM "
4844 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4845 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4846 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4847 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4848 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4849 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4850 "BtAAAAAAA=\r\n"),
4851 MockRead("Content-Length: 42\r\n"),
4852 MockRead("Content-Type: text/html\r\n\r\n"),
4853 MockRead("You are not authorized to view this page\r\n"),
4855 // Wrong password.
4856 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4857 MockRead("WWW-Authenticate: NTLM\r\n"),
4858 MockRead("Connection: close\r\n"),
4859 MockRead("Content-Length: 42\r\n"),
4860 MockRead("Content-Type: text/html\r\n\r\n"),
4861 // Missing content -- won't matter, as connection will be reset.
4862 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4865 MockWrite data_writes3[] = {
4866 // After restarting with a null identity, this is the
4867 // request we should be issuing -- the final header line contains a Type
4868 // 1 message.
4869 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4870 "Host: 172.22.68.17\r\n"
4871 "Connection: keep-alive\r\n"
4872 "Authorization: NTLM "
4873 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4875 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4876 // (the credentials for the origin server). The second request continues
4877 // on the same connection.
4878 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4879 "Host: 172.22.68.17\r\n"
4880 "Connection: keep-alive\r\n"
4881 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4882 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4883 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4884 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4885 "+4MUm7c=\r\n\r\n"),
4888 MockRead data_reads3[] = {
4889 // The origin server responds with a Type 2 message.
4890 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4891 MockRead("WWW-Authenticate: NTLM "
4892 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4893 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4894 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4895 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4896 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4897 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4898 "BtAAAAAAA=\r\n"),
4899 MockRead("Content-Length: 42\r\n"),
4900 MockRead("Content-Type: text/html\r\n\r\n"),
4901 MockRead("You are not authorized to view this page\r\n"),
4903 // Lastly we get the desired content.
4904 MockRead("HTTP/1.1 200 OK\r\n"),
4905 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4906 MockRead("Content-Length: 13\r\n\r\n"),
4907 MockRead("Please Login\r\n"),
4908 MockRead(SYNCHRONOUS, OK),
4911 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4912 data_writes1, arraysize(data_writes1));
4913 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4914 data_writes2, arraysize(data_writes2));
4915 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4916 data_writes3, arraysize(data_writes3));
4917 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4918 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4919 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4921 TestCompletionCallback callback1;
4923 scoped_ptr<HttpTransaction> trans(
4924 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4926 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4927 EXPECT_EQ(ERR_IO_PENDING, rv);
4929 rv = callback1.WaitForResult();
4930 EXPECT_EQ(OK, rv);
4932 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4934 const HttpResponseInfo* response = trans->GetResponseInfo();
4935 ASSERT_TRUE(response != NULL);
4936 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4938 TestCompletionCallback callback2;
4940 // Enter the wrong password.
4941 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4942 callback2.callback());
4943 EXPECT_EQ(ERR_IO_PENDING, rv);
4945 rv = callback2.WaitForResult();
4946 EXPECT_EQ(OK, rv);
4948 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4949 TestCompletionCallback callback3;
4950 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4951 EXPECT_EQ(ERR_IO_PENDING, rv);
4952 rv = callback3.WaitForResult();
4953 EXPECT_EQ(OK, rv);
4954 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4956 response = trans->GetResponseInfo();
4957 ASSERT_FALSE(response == NULL);
4958 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4960 TestCompletionCallback callback4;
4962 // Now enter the right password.
4963 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4964 callback4.callback());
4965 EXPECT_EQ(ERR_IO_PENDING, rv);
4967 rv = callback4.WaitForResult();
4968 EXPECT_EQ(OK, rv);
4970 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4972 TestCompletionCallback callback5;
4974 // One more roundtrip
4975 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4976 EXPECT_EQ(ERR_IO_PENDING, rv);
4978 rv = callback5.WaitForResult();
4979 EXPECT_EQ(OK, rv);
4981 response = trans->GetResponseInfo();
4982 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4983 EXPECT_EQ(13, response->headers->GetContentLength());
4985 #endif // NTLM_PORTABLE
4987 // Test reading a server response which has only headers, and no body.
4988 // After some maximum number of bytes is consumed, the transaction should
4989 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4990 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4991 HttpRequestInfo request;
4992 request.method = "GET";
4993 request.url = GURL("http://www.example.org/");
4994 request.load_flags = 0;
4996 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4997 scoped_ptr<HttpTransaction> trans(
4998 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5000 // Respond with 300 kb of headers (we should fail after 256 kb).
5001 std::string large_headers_string;
5002 FillLargeHeadersString(&large_headers_string, 300 * 1024);
5004 MockRead data_reads[] = {
5005 MockRead("HTTP/1.0 200 OK\r\n"),
5006 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
5007 MockRead("\r\nBODY"),
5008 MockRead(SYNCHRONOUS, OK),
5010 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5011 session_deps_.socket_factory->AddSocketDataProvider(&data);
5013 TestCompletionCallback callback;
5015 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5016 EXPECT_EQ(ERR_IO_PENDING, rv);
5018 rv = callback.WaitForResult();
5019 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
5021 const HttpResponseInfo* response = trans->GetResponseInfo();
5022 EXPECT_TRUE(response == NULL);
5025 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5026 // establish tunnel.
5027 // http://code.google.com/p/chromium/issues/detail?id=3772
5028 TEST_P(HttpNetworkTransactionTest,
5029 DontRecycleTransportSocketForSSLTunnel) {
5030 HttpRequestInfo request;
5031 request.method = "GET";
5032 request.url = GURL("https://www.example.org/");
5033 request.load_flags = 0;
5035 // Configure against proxy server "myproxy:70".
5036 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5038 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5040 scoped_ptr<HttpTransaction> trans(
5041 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5043 // Since we have proxy, should try to establish tunnel.
5044 MockWrite data_writes1[] = {
5045 MockWrite(
5046 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5047 "Host: www.example.org\r\n"
5048 "Proxy-Connection: keep-alive\r\n\r\n"),
5051 // The proxy responds to the connect with a 404, using a persistent
5052 // connection. Usually a proxy would return 501 (not implemented),
5053 // or 200 (tunnel established).
5054 MockRead data_reads1[] = {
5055 MockRead("HTTP/1.1 404 Not Found\r\n"),
5056 MockRead("Content-Length: 10\r\n\r\n"),
5057 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
5060 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5061 data_writes1, arraysize(data_writes1));
5062 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5064 TestCompletionCallback callback1;
5066 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5067 EXPECT_EQ(ERR_IO_PENDING, rv);
5069 rv = callback1.WaitForResult();
5070 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5072 const HttpResponseInfo* response = trans->GetResponseInfo();
5073 EXPECT_TRUE(response == NULL);
5075 // Empty the current queue. This is necessary because idle sockets are
5076 // added to the connection pool asynchronously with a PostTask.
5077 base::MessageLoop::current()->RunUntilIdle();
5079 // We now check to make sure the TCPClientSocket was not added back to
5080 // the pool.
5081 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5082 trans.reset();
5083 base::MessageLoop::current()->RunUntilIdle();
5084 // Make sure that the socket didn't get recycled after calling the destructor.
5085 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5088 // Make sure that we recycle a socket after reading all of the response body.
5089 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
5090 HttpRequestInfo request;
5091 request.method = "GET";
5092 request.url = GURL("http://www.example.org/");
5093 request.load_flags = 0;
5095 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5097 scoped_ptr<HttpTransaction> trans(
5098 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5100 MockRead data_reads[] = {
5101 // A part of the response body is received with the response headers.
5102 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5103 // The rest of the response body is received in two parts.
5104 MockRead("lo"),
5105 MockRead(" world"),
5106 MockRead("junk"), // Should not be read!!
5107 MockRead(SYNCHRONOUS, OK),
5110 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5111 session_deps_.socket_factory->AddSocketDataProvider(&data);
5113 TestCompletionCallback callback;
5115 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5116 EXPECT_EQ(ERR_IO_PENDING, rv);
5118 rv = callback.WaitForResult();
5119 EXPECT_EQ(OK, rv);
5121 const HttpResponseInfo* response = trans->GetResponseInfo();
5122 ASSERT_TRUE(response != NULL);
5124 EXPECT_TRUE(response->headers.get() != NULL);
5125 std::string status_line = response->headers->GetStatusLine();
5126 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5128 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5130 std::string response_data;
5131 rv = ReadTransaction(trans.get(), &response_data);
5132 EXPECT_EQ(OK, rv);
5133 EXPECT_EQ("hello world", response_data);
5135 // Empty the current queue. This is necessary because idle sockets are
5136 // added to the connection pool asynchronously with a PostTask.
5137 base::MessageLoop::current()->RunUntilIdle();
5139 // We now check to make sure the socket was added back to the pool.
5140 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5143 // Make sure that we recycle a SSL socket after reading all of the response
5144 // body.
5145 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
5146 HttpRequestInfo request;
5147 request.method = "GET";
5148 request.url = GURL("https://www.example.org/");
5149 request.load_flags = 0;
5151 MockWrite data_writes[] = {
5152 MockWrite(
5153 "GET / HTTP/1.1\r\n"
5154 "Host: www.example.org\r\n"
5155 "Connection: keep-alive\r\n\r\n"),
5158 MockRead data_reads[] = {
5159 MockRead("HTTP/1.1 200 OK\r\n"),
5160 MockRead("Content-Length: 11\r\n\r\n"),
5161 MockRead("hello world"),
5162 MockRead(SYNCHRONOUS, OK),
5165 SSLSocketDataProvider ssl(ASYNC, OK);
5166 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5168 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5169 data_writes, arraysize(data_writes));
5170 session_deps_.socket_factory->AddSocketDataProvider(&data);
5172 TestCompletionCallback callback;
5174 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5175 scoped_ptr<HttpTransaction> trans(
5176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5180 EXPECT_EQ(ERR_IO_PENDING, rv);
5181 EXPECT_EQ(OK, callback.WaitForResult());
5183 const HttpResponseInfo* response = trans->GetResponseInfo();
5184 ASSERT_TRUE(response != NULL);
5185 ASSERT_TRUE(response->headers.get() != NULL);
5186 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5188 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5190 std::string response_data;
5191 rv = ReadTransaction(trans.get(), &response_data);
5192 EXPECT_EQ(OK, rv);
5193 EXPECT_EQ("hello world", response_data);
5195 // Empty the current queue. This is necessary because idle sockets are
5196 // added to the connection pool asynchronously with a PostTask.
5197 base::MessageLoop::current()->RunUntilIdle();
5199 // We now check to make sure the socket was added back to the pool.
5200 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5203 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5204 // from the pool and make sure that we recover okay.
5205 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
5206 HttpRequestInfo request;
5207 request.method = "GET";
5208 request.url = GURL("https://www.example.org/");
5209 request.load_flags = 0;
5211 MockWrite data_writes[] = {
5212 MockWrite(
5213 "GET / HTTP/1.1\r\n"
5214 "Host: www.example.org\r\n"
5215 "Connection: keep-alive\r\n\r\n"),
5216 MockWrite(
5217 "GET / HTTP/1.1\r\n"
5218 "Host: www.example.org\r\n"
5219 "Connection: keep-alive\r\n\r\n"),
5222 MockRead data_reads[] = {
5223 MockRead("HTTP/1.1 200 OK\r\n"),
5224 MockRead("Content-Length: 11\r\n\r\n"),
5225 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
5226 MockRead("hello world"),
5227 MockRead(ASYNC, 0, 0) // EOF
5230 SSLSocketDataProvider ssl(ASYNC, OK);
5231 SSLSocketDataProvider ssl2(ASYNC, OK);
5232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5233 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5235 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5236 data_writes, arraysize(data_writes));
5237 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5238 data_writes, arraysize(data_writes));
5239 session_deps_.socket_factory->AddSocketDataProvider(&data);
5240 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5242 TestCompletionCallback callback;
5244 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5245 scoped_ptr<HttpTransaction> trans(
5246 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5248 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5250 EXPECT_EQ(ERR_IO_PENDING, rv);
5251 EXPECT_EQ(OK, callback.WaitForResult());
5253 const HttpResponseInfo* response = trans->GetResponseInfo();
5254 ASSERT_TRUE(response != NULL);
5255 ASSERT_TRUE(response->headers.get() != NULL);
5256 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5258 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5260 std::string response_data;
5261 rv = ReadTransaction(trans.get(), &response_data);
5262 EXPECT_EQ(OK, rv);
5263 EXPECT_EQ("hello world", response_data);
5265 // Empty the current queue. This is necessary because idle sockets are
5266 // added to the connection pool asynchronously with a PostTask.
5267 base::MessageLoop::current()->RunUntilIdle();
5269 // We now check to make sure the socket was added back to the pool.
5270 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5272 // Now start the second transaction, which should reuse the previous socket.
5274 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5276 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5278 EXPECT_EQ(ERR_IO_PENDING, rv);
5279 EXPECT_EQ(OK, callback.WaitForResult());
5281 response = trans->GetResponseInfo();
5282 ASSERT_TRUE(response != NULL);
5283 ASSERT_TRUE(response->headers.get() != NULL);
5284 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5286 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5288 rv = ReadTransaction(trans.get(), &response_data);
5289 EXPECT_EQ(OK, rv);
5290 EXPECT_EQ("hello world", response_data);
5292 // Empty the current queue. This is necessary because idle sockets are
5293 // added to the connection pool asynchronously with a PostTask.
5294 base::MessageLoop::current()->RunUntilIdle();
5296 // We now check to make sure the socket was added back to the pool.
5297 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5300 // Make sure that we recycle a socket after a zero-length response.
5301 // http://crbug.com/9880
5302 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
5303 HttpRequestInfo request;
5304 request.method = "GET";
5305 request.url = GURL(
5306 "http://www.example.org/csi?v=3&s=web&action=&"
5307 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5308 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5309 "rt=prt.2642,ol.2649,xjs.2951");
5310 request.load_flags = 0;
5312 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5314 scoped_ptr<HttpTransaction> trans(
5315 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5317 MockRead data_reads[] = {
5318 MockRead("HTTP/1.1 204 No Content\r\n"
5319 "Content-Length: 0\r\n"
5320 "Content-Type: text/html\r\n\r\n"),
5321 MockRead("junk"), // Should not be read!!
5322 MockRead(SYNCHRONOUS, OK),
5325 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5326 session_deps_.socket_factory->AddSocketDataProvider(&data);
5328 TestCompletionCallback callback;
5330 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5331 EXPECT_EQ(ERR_IO_PENDING, rv);
5333 rv = callback.WaitForResult();
5334 EXPECT_EQ(OK, rv);
5336 const HttpResponseInfo* response = trans->GetResponseInfo();
5337 ASSERT_TRUE(response != NULL);
5339 EXPECT_TRUE(response->headers.get() != NULL);
5340 std::string status_line = response->headers->GetStatusLine();
5341 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5343 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5345 std::string response_data;
5346 rv = ReadTransaction(trans.get(), &response_data);
5347 EXPECT_EQ(OK, rv);
5348 EXPECT_EQ("", response_data);
5350 // Empty the current queue. This is necessary because idle sockets are
5351 // added to the connection pool asynchronously with a PostTask.
5352 base::MessageLoop::current()->RunUntilIdle();
5354 // We now check to make sure the socket was added back to the pool.
5355 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5358 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5359 ScopedVector<UploadElementReader> element_readers;
5360 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5361 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
5363 HttpRequestInfo request[2];
5364 // Transaction 1: a GET request that succeeds. The socket is recycled
5365 // after use.
5366 request[0].method = "GET";
5367 request[0].url = GURL("http://www.google.com/");
5368 request[0].load_flags = 0;
5369 // Transaction 2: a POST request. Reuses the socket kept alive from
5370 // transaction 1. The first attempts fails when writing the POST data.
5371 // This causes the transaction to retry with a new socket. The second
5372 // attempt succeeds.
5373 request[1].method = "POST";
5374 request[1].url = GURL("http://www.google.com/login.cgi");
5375 request[1].upload_data_stream = &upload_data_stream;
5376 request[1].load_flags = 0;
5378 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5380 // The first socket is used for transaction 1 and the first attempt of
5381 // transaction 2.
5383 // The response of transaction 1.
5384 MockRead data_reads1[] = {
5385 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5386 MockRead("hello world"),
5387 MockRead(SYNCHRONOUS, OK),
5389 // The mock write results of transaction 1 and the first attempt of
5390 // transaction 2.
5391 MockWrite data_writes1[] = {
5392 MockWrite(SYNCHRONOUS, 64), // GET
5393 MockWrite(SYNCHRONOUS, 93), // POST
5394 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5396 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5397 data_writes1, arraysize(data_writes1));
5399 // The second socket is used for the second attempt of transaction 2.
5401 // The response of transaction 2.
5402 MockRead data_reads2[] = {
5403 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5404 MockRead("welcome"),
5405 MockRead(SYNCHRONOUS, OK),
5407 // The mock write results of the second attempt of transaction 2.
5408 MockWrite data_writes2[] = {
5409 MockWrite(SYNCHRONOUS, 93), // POST
5410 MockWrite(SYNCHRONOUS, 3), // POST data
5412 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5413 data_writes2, arraysize(data_writes2));
5415 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5416 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5418 const char* const kExpectedResponseData[] = {
5419 "hello world", "welcome"
5422 for (int i = 0; i < 2; ++i) {
5423 scoped_ptr<HttpTransaction> trans(
5424 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5426 TestCompletionCallback callback;
5428 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5429 EXPECT_EQ(ERR_IO_PENDING, rv);
5431 rv = callback.WaitForResult();
5432 EXPECT_EQ(OK, rv);
5434 const HttpResponseInfo* response = trans->GetResponseInfo();
5435 ASSERT_TRUE(response != NULL);
5437 EXPECT_TRUE(response->headers.get() != NULL);
5438 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5440 std::string response_data;
5441 rv = ReadTransaction(trans.get(), &response_data);
5442 EXPECT_EQ(OK, rv);
5443 EXPECT_EQ(kExpectedResponseData[i], response_data);
5447 // Test the request-challenge-retry sequence for basic auth when there is
5448 // an identity in the URL. The request should be sent as normal, but when
5449 // it fails the identity from the URL is used to answer the challenge.
5450 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5451 HttpRequestInfo request;
5452 request.method = "GET";
5453 request.url = GURL("http://foo:b@r@www.example.org/");
5454 request.load_flags = LOAD_NORMAL;
5456 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5457 scoped_ptr<HttpTransaction> trans(
5458 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5460 // The password contains an escaped character -- for this test to pass it
5461 // will need to be unescaped by HttpNetworkTransaction.
5462 EXPECT_EQ("b%40r", request.url.password());
5464 MockWrite data_writes1[] = {
5465 MockWrite(
5466 "GET / HTTP/1.1\r\n"
5467 "Host: www.example.org\r\n"
5468 "Connection: keep-alive\r\n\r\n"),
5471 MockRead data_reads1[] = {
5472 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5473 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5474 MockRead("Content-Length: 10\r\n\r\n"),
5475 MockRead(SYNCHRONOUS, ERR_FAILED),
5478 // After the challenge above, the transaction will be restarted using the
5479 // identity from the url (foo, b@r) to answer the challenge.
5480 MockWrite data_writes2[] = {
5481 MockWrite(
5482 "GET / HTTP/1.1\r\n"
5483 "Host: www.example.org\r\n"
5484 "Connection: keep-alive\r\n"
5485 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5488 MockRead data_reads2[] = {
5489 MockRead("HTTP/1.0 200 OK\r\n"),
5490 MockRead("Content-Length: 100\r\n\r\n"),
5491 MockRead(SYNCHRONOUS, OK),
5494 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5495 data_writes1, arraysize(data_writes1));
5496 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5497 data_writes2, arraysize(data_writes2));
5498 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5499 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5501 TestCompletionCallback callback1;
5502 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5503 EXPECT_EQ(ERR_IO_PENDING, rv);
5504 rv = callback1.WaitForResult();
5505 EXPECT_EQ(OK, rv);
5506 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5508 TestCompletionCallback callback2;
5509 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5510 EXPECT_EQ(ERR_IO_PENDING, rv);
5511 rv = callback2.WaitForResult();
5512 EXPECT_EQ(OK, rv);
5513 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5515 const HttpResponseInfo* response = trans->GetResponseInfo();
5516 ASSERT_TRUE(response != NULL);
5518 // There is no challenge info, since the identity in URL worked.
5519 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5521 EXPECT_EQ(100, response->headers->GetContentLength());
5523 // Empty the current queue.
5524 base::MessageLoop::current()->RunUntilIdle();
5527 // Test the request-challenge-retry sequence for basic auth when there is an
5528 // incorrect identity in the URL. The identity from the URL should be used only
5529 // once.
5530 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5531 HttpRequestInfo request;
5532 request.method = "GET";
5533 // Note: the URL has a username:password in it. The password "baz" is
5534 // wrong (should be "bar").
5535 request.url = GURL("http://foo:baz@www.example.org/");
5537 request.load_flags = LOAD_NORMAL;
5539 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5540 scoped_ptr<HttpTransaction> trans(
5541 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5543 MockWrite data_writes1[] = {
5544 MockWrite(
5545 "GET / HTTP/1.1\r\n"
5546 "Host: www.example.org\r\n"
5547 "Connection: keep-alive\r\n\r\n"),
5550 MockRead data_reads1[] = {
5551 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5552 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5553 MockRead("Content-Length: 10\r\n\r\n"),
5554 MockRead(SYNCHRONOUS, ERR_FAILED),
5557 // After the challenge above, the transaction will be restarted using the
5558 // identity from the url (foo, baz) to answer the challenge.
5559 MockWrite data_writes2[] = {
5560 MockWrite(
5561 "GET / HTTP/1.1\r\n"
5562 "Host: www.example.org\r\n"
5563 "Connection: keep-alive\r\n"
5564 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5567 MockRead data_reads2[] = {
5568 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5569 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5570 MockRead("Content-Length: 10\r\n\r\n"),
5571 MockRead(SYNCHRONOUS, ERR_FAILED),
5574 // After the challenge above, the transaction will be restarted using the
5575 // identity supplied by the user (foo, bar) to answer the challenge.
5576 MockWrite data_writes3[] = {
5577 MockWrite(
5578 "GET / HTTP/1.1\r\n"
5579 "Host: www.example.org\r\n"
5580 "Connection: keep-alive\r\n"
5581 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5584 MockRead data_reads3[] = {
5585 MockRead("HTTP/1.0 200 OK\r\n"),
5586 MockRead("Content-Length: 100\r\n\r\n"),
5587 MockRead(SYNCHRONOUS, OK),
5590 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5591 data_writes1, arraysize(data_writes1));
5592 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5593 data_writes2, arraysize(data_writes2));
5594 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5595 data_writes3, arraysize(data_writes3));
5596 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5597 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5598 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5600 TestCompletionCallback callback1;
5602 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5603 EXPECT_EQ(ERR_IO_PENDING, rv);
5605 rv = callback1.WaitForResult();
5606 EXPECT_EQ(OK, rv);
5608 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5609 TestCompletionCallback callback2;
5610 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5611 EXPECT_EQ(ERR_IO_PENDING, rv);
5612 rv = callback2.WaitForResult();
5613 EXPECT_EQ(OK, rv);
5614 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5616 const HttpResponseInfo* response = trans->GetResponseInfo();
5617 ASSERT_TRUE(response != NULL);
5618 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5620 TestCompletionCallback callback3;
5621 rv = trans->RestartWithAuth(
5622 AuthCredentials(kFoo, kBar), callback3.callback());
5623 EXPECT_EQ(ERR_IO_PENDING, rv);
5624 rv = callback3.WaitForResult();
5625 EXPECT_EQ(OK, rv);
5626 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5628 response = trans->GetResponseInfo();
5629 ASSERT_TRUE(response != NULL);
5631 // There is no challenge info, since the identity worked.
5632 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5634 EXPECT_EQ(100, response->headers->GetContentLength());
5636 // Empty the current queue.
5637 base::MessageLoop::current()->RunUntilIdle();
5641 // Test the request-challenge-retry sequence for basic auth when there is a
5642 // correct identity in the URL, but its use is being suppressed. The identity
5643 // from the URL should never be used.
5644 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5645 HttpRequestInfo request;
5646 request.method = "GET";
5647 request.url = GURL("http://foo:bar@www.example.org/");
5648 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5651 scoped_ptr<HttpTransaction> trans(
5652 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5654 MockWrite data_writes1[] = {
5655 MockWrite(
5656 "GET / HTTP/1.1\r\n"
5657 "Host: www.example.org\r\n"
5658 "Connection: keep-alive\r\n\r\n"),
5661 MockRead data_reads1[] = {
5662 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5663 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5664 MockRead("Content-Length: 10\r\n\r\n"),
5665 MockRead(SYNCHRONOUS, ERR_FAILED),
5668 // After the challenge above, the transaction will be restarted using the
5669 // identity supplied by the user, not the one in the URL, to answer the
5670 // challenge.
5671 MockWrite data_writes3[] = {
5672 MockWrite(
5673 "GET / HTTP/1.1\r\n"
5674 "Host: www.example.org\r\n"
5675 "Connection: keep-alive\r\n"
5676 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5679 MockRead data_reads3[] = {
5680 MockRead("HTTP/1.0 200 OK\r\n"),
5681 MockRead("Content-Length: 100\r\n\r\n"),
5682 MockRead(SYNCHRONOUS, OK),
5685 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5686 data_writes1, arraysize(data_writes1));
5687 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5688 data_writes3, arraysize(data_writes3));
5689 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5690 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5692 TestCompletionCallback callback1;
5693 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5694 EXPECT_EQ(ERR_IO_PENDING, rv);
5695 rv = callback1.WaitForResult();
5696 EXPECT_EQ(OK, rv);
5697 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5699 const HttpResponseInfo* response = trans->GetResponseInfo();
5700 ASSERT_TRUE(response != NULL);
5701 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5703 TestCompletionCallback callback3;
5704 rv = trans->RestartWithAuth(
5705 AuthCredentials(kFoo, kBar), callback3.callback());
5706 EXPECT_EQ(ERR_IO_PENDING, rv);
5707 rv = callback3.WaitForResult();
5708 EXPECT_EQ(OK, rv);
5709 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5711 response = trans->GetResponseInfo();
5712 ASSERT_TRUE(response != NULL);
5714 // There is no challenge info, since the identity worked.
5715 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5716 EXPECT_EQ(100, response->headers->GetContentLength());
5718 // Empty the current queue.
5719 base::MessageLoop::current()->RunUntilIdle();
5722 // Test that previously tried username/passwords for a realm get re-used.
5723 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5724 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5726 // Transaction 1: authenticate (foo, bar) on MyRealm1
5728 HttpRequestInfo request;
5729 request.method = "GET";
5730 request.url = GURL("http://www.example.org/x/y/z");
5731 request.load_flags = 0;
5733 scoped_ptr<HttpTransaction> trans(
5734 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5736 MockWrite data_writes1[] = {
5737 MockWrite(
5738 "GET /x/y/z HTTP/1.1\r\n"
5739 "Host: www.example.org\r\n"
5740 "Connection: keep-alive\r\n\r\n"),
5743 MockRead data_reads1[] = {
5744 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5745 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5746 MockRead("Content-Length: 10000\r\n\r\n"),
5747 MockRead(SYNCHRONOUS, ERR_FAILED),
5750 // Resend with authorization (username=foo, password=bar)
5751 MockWrite data_writes2[] = {
5752 MockWrite(
5753 "GET /x/y/z HTTP/1.1\r\n"
5754 "Host: www.example.org\r\n"
5755 "Connection: keep-alive\r\n"
5756 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5759 // Sever accepts the authorization.
5760 MockRead data_reads2[] = {
5761 MockRead("HTTP/1.0 200 OK\r\n"),
5762 MockRead("Content-Length: 100\r\n\r\n"),
5763 MockRead(SYNCHRONOUS, OK),
5766 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5767 data_writes1, arraysize(data_writes1));
5768 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5769 data_writes2, arraysize(data_writes2));
5770 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5771 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5773 TestCompletionCallback callback1;
5775 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5776 EXPECT_EQ(ERR_IO_PENDING, rv);
5778 rv = callback1.WaitForResult();
5779 EXPECT_EQ(OK, rv);
5781 const HttpResponseInfo* response = trans->GetResponseInfo();
5782 ASSERT_TRUE(response != NULL);
5783 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5785 TestCompletionCallback callback2;
5787 rv = trans->RestartWithAuth(
5788 AuthCredentials(kFoo, kBar), callback2.callback());
5789 EXPECT_EQ(ERR_IO_PENDING, rv);
5791 rv = callback2.WaitForResult();
5792 EXPECT_EQ(OK, rv);
5794 response = trans->GetResponseInfo();
5795 ASSERT_TRUE(response != NULL);
5796 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5797 EXPECT_EQ(100, response->headers->GetContentLength());
5800 // ------------------------------------------------------------------------
5802 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5804 HttpRequestInfo request;
5805 request.method = "GET";
5806 // Note that Transaction 1 was at /x/y/z, so this is in the same
5807 // protection space as MyRealm1.
5808 request.url = GURL("http://www.example.org/x/y/a/b");
5809 request.load_flags = 0;
5811 scoped_ptr<HttpTransaction> trans(
5812 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5814 MockWrite data_writes1[] = {
5815 MockWrite(
5816 "GET /x/y/a/b HTTP/1.1\r\n"
5817 "Host: www.example.org\r\n"
5818 "Connection: keep-alive\r\n"
5819 // Send preemptive authorization for MyRealm1
5820 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5823 // The server didn't like the preemptive authorization, and
5824 // challenges us for a different realm (MyRealm2).
5825 MockRead data_reads1[] = {
5826 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5827 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5828 MockRead("Content-Length: 10000\r\n\r\n"),
5829 MockRead(SYNCHRONOUS, ERR_FAILED),
5832 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5833 MockWrite data_writes2[] = {
5834 MockWrite(
5835 "GET /x/y/a/b HTTP/1.1\r\n"
5836 "Host: www.example.org\r\n"
5837 "Connection: keep-alive\r\n"
5838 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5841 // Sever accepts the authorization.
5842 MockRead data_reads2[] = {
5843 MockRead("HTTP/1.0 200 OK\r\n"),
5844 MockRead("Content-Length: 100\r\n\r\n"),
5845 MockRead(SYNCHRONOUS, OK),
5848 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5849 data_writes1, arraysize(data_writes1));
5850 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5851 data_writes2, arraysize(data_writes2));
5852 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5853 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5855 TestCompletionCallback callback1;
5857 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5858 EXPECT_EQ(ERR_IO_PENDING, rv);
5860 rv = callback1.WaitForResult();
5861 EXPECT_EQ(OK, rv);
5863 const HttpResponseInfo* response = trans->GetResponseInfo();
5864 ASSERT_TRUE(response != NULL);
5865 ASSERT_TRUE(response->auth_challenge.get());
5866 EXPECT_FALSE(response->auth_challenge->is_proxy);
5867 EXPECT_EQ("www.example.org:80",
5868 response->auth_challenge->challenger.ToString());
5869 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5870 EXPECT_EQ("basic", response->auth_challenge->scheme);
5872 TestCompletionCallback callback2;
5874 rv = trans->RestartWithAuth(
5875 AuthCredentials(kFoo2, kBar2), callback2.callback());
5876 EXPECT_EQ(ERR_IO_PENDING, rv);
5878 rv = callback2.WaitForResult();
5879 EXPECT_EQ(OK, rv);
5881 response = trans->GetResponseInfo();
5882 ASSERT_TRUE(response != NULL);
5883 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5884 EXPECT_EQ(100, response->headers->GetContentLength());
5887 // ------------------------------------------------------------------------
5889 // Transaction 3: Resend a request in MyRealm's protection space --
5890 // succeed with preemptive authorization.
5892 HttpRequestInfo request;
5893 request.method = "GET";
5894 request.url = GURL("http://www.example.org/x/y/z2");
5895 request.load_flags = 0;
5897 scoped_ptr<HttpTransaction> trans(
5898 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5900 MockWrite data_writes1[] = {
5901 MockWrite(
5902 "GET /x/y/z2 HTTP/1.1\r\n"
5903 "Host: www.example.org\r\n"
5904 "Connection: keep-alive\r\n"
5905 // The authorization for MyRealm1 gets sent preemptively
5906 // (since the url is in the same protection space)
5907 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5910 // Sever accepts the preemptive authorization
5911 MockRead data_reads1[] = {
5912 MockRead("HTTP/1.0 200 OK\r\n"),
5913 MockRead("Content-Length: 100\r\n\r\n"),
5914 MockRead(SYNCHRONOUS, OK),
5917 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5918 data_writes1, arraysize(data_writes1));
5919 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5921 TestCompletionCallback callback1;
5923 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5924 EXPECT_EQ(ERR_IO_PENDING, rv);
5926 rv = callback1.WaitForResult();
5927 EXPECT_EQ(OK, rv);
5929 const HttpResponseInfo* response = trans->GetResponseInfo();
5930 ASSERT_TRUE(response != NULL);
5932 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5933 EXPECT_EQ(100, response->headers->GetContentLength());
5936 // ------------------------------------------------------------------------
5938 // Transaction 4: request another URL in MyRealm (however the
5939 // url is not known to belong to the protection space, so no pre-auth).
5941 HttpRequestInfo request;
5942 request.method = "GET";
5943 request.url = GURL("http://www.example.org/x/1");
5944 request.load_flags = 0;
5946 scoped_ptr<HttpTransaction> trans(
5947 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5949 MockWrite data_writes1[] = {
5950 MockWrite(
5951 "GET /x/1 HTTP/1.1\r\n"
5952 "Host: www.example.org\r\n"
5953 "Connection: keep-alive\r\n\r\n"),
5956 MockRead data_reads1[] = {
5957 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5958 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5959 MockRead("Content-Length: 10000\r\n\r\n"),
5960 MockRead(SYNCHRONOUS, ERR_FAILED),
5963 // Resend with authorization from MyRealm's cache.
5964 MockWrite data_writes2[] = {
5965 MockWrite(
5966 "GET /x/1 HTTP/1.1\r\n"
5967 "Host: www.example.org\r\n"
5968 "Connection: keep-alive\r\n"
5969 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5972 // Sever accepts the authorization.
5973 MockRead data_reads2[] = {
5974 MockRead("HTTP/1.0 200 OK\r\n"),
5975 MockRead("Content-Length: 100\r\n\r\n"),
5976 MockRead(SYNCHRONOUS, OK),
5979 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5980 data_writes1, arraysize(data_writes1));
5981 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5982 data_writes2, arraysize(data_writes2));
5983 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5984 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5986 TestCompletionCallback callback1;
5988 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5989 EXPECT_EQ(ERR_IO_PENDING, rv);
5991 rv = callback1.WaitForResult();
5992 EXPECT_EQ(OK, rv);
5994 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5995 TestCompletionCallback callback2;
5996 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5997 EXPECT_EQ(ERR_IO_PENDING, rv);
5998 rv = callback2.WaitForResult();
5999 EXPECT_EQ(OK, rv);
6000 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6002 const HttpResponseInfo* response = trans->GetResponseInfo();
6003 ASSERT_TRUE(response != NULL);
6004 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6005 EXPECT_EQ(100, response->headers->GetContentLength());
6008 // ------------------------------------------------------------------------
6010 // Transaction 5: request a URL in MyRealm, but the server rejects the
6011 // cached identity. Should invalidate and re-prompt.
6013 HttpRequestInfo request;
6014 request.method = "GET";
6015 request.url = GURL("http://www.example.org/p/q/t");
6016 request.load_flags = 0;
6018 scoped_ptr<HttpTransaction> trans(
6019 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6021 MockWrite data_writes1[] = {
6022 MockWrite(
6023 "GET /p/q/t HTTP/1.1\r\n"
6024 "Host: www.example.org\r\n"
6025 "Connection: keep-alive\r\n\r\n"),
6028 MockRead data_reads1[] = {
6029 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6030 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6031 MockRead("Content-Length: 10000\r\n\r\n"),
6032 MockRead(SYNCHRONOUS, ERR_FAILED),
6035 // Resend with authorization from cache for MyRealm.
6036 MockWrite data_writes2[] = {
6037 MockWrite(
6038 "GET /p/q/t HTTP/1.1\r\n"
6039 "Host: www.example.org\r\n"
6040 "Connection: keep-alive\r\n"
6041 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6044 // Sever rejects the authorization.
6045 MockRead data_reads2[] = {
6046 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6047 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6048 MockRead("Content-Length: 10000\r\n\r\n"),
6049 MockRead(SYNCHRONOUS, ERR_FAILED),
6052 // At this point we should prompt for new credentials for MyRealm.
6053 // Restart with username=foo3, password=foo4.
6054 MockWrite data_writes3[] = {
6055 MockWrite(
6056 "GET /p/q/t HTTP/1.1\r\n"
6057 "Host: www.example.org\r\n"
6058 "Connection: keep-alive\r\n"
6059 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6062 // Sever accepts the authorization.
6063 MockRead data_reads3[] = {
6064 MockRead("HTTP/1.0 200 OK\r\n"),
6065 MockRead("Content-Length: 100\r\n\r\n"),
6066 MockRead(SYNCHRONOUS, OK),
6069 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6070 data_writes1, arraysize(data_writes1));
6071 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6072 data_writes2, arraysize(data_writes2));
6073 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6074 data_writes3, arraysize(data_writes3));
6075 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6076 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6077 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6079 TestCompletionCallback callback1;
6081 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6082 EXPECT_EQ(ERR_IO_PENDING, rv);
6084 rv = callback1.WaitForResult();
6085 EXPECT_EQ(OK, rv);
6087 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6088 TestCompletionCallback callback2;
6089 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6090 EXPECT_EQ(ERR_IO_PENDING, rv);
6091 rv = callback2.WaitForResult();
6092 EXPECT_EQ(OK, rv);
6093 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6095 const HttpResponseInfo* response = trans->GetResponseInfo();
6096 ASSERT_TRUE(response != NULL);
6097 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6099 TestCompletionCallback callback3;
6101 rv = trans->RestartWithAuth(
6102 AuthCredentials(kFoo3, kBar3), callback3.callback());
6103 EXPECT_EQ(ERR_IO_PENDING, rv);
6105 rv = callback3.WaitForResult();
6106 EXPECT_EQ(OK, rv);
6108 response = trans->GetResponseInfo();
6109 ASSERT_TRUE(response != NULL);
6110 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6111 EXPECT_EQ(100, response->headers->GetContentLength());
6115 // Tests that nonce count increments when multiple auth attempts
6116 // are started with the same nonce.
6117 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
6118 HttpAuthHandlerDigest::Factory* digest_factory =
6119 new HttpAuthHandlerDigest::Factory();
6120 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6121 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6122 digest_factory->set_nonce_generator(nonce_generator);
6123 session_deps_.http_auth_handler_factory.reset(digest_factory);
6124 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6126 // Transaction 1: authenticate (foo, bar) on MyRealm1
6128 HttpRequestInfo request;
6129 request.method = "GET";
6130 request.url = GURL("http://www.example.org/x/y/z");
6131 request.load_flags = 0;
6133 scoped_ptr<HttpTransaction> trans(
6134 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6136 MockWrite data_writes1[] = {
6137 MockWrite(
6138 "GET /x/y/z HTTP/1.1\r\n"
6139 "Host: www.example.org\r\n"
6140 "Connection: keep-alive\r\n\r\n"),
6143 MockRead data_reads1[] = {
6144 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6145 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6146 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6147 MockRead(SYNCHRONOUS, OK),
6150 // Resend with authorization (username=foo, password=bar)
6151 MockWrite data_writes2[] = {
6152 MockWrite(
6153 "GET /x/y/z HTTP/1.1\r\n"
6154 "Host: www.example.org\r\n"
6155 "Connection: keep-alive\r\n"
6156 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6157 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6158 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6159 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6162 // Sever accepts the authorization.
6163 MockRead data_reads2[] = {
6164 MockRead("HTTP/1.0 200 OK\r\n"),
6165 MockRead(SYNCHRONOUS, OK),
6168 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6169 data_writes1, arraysize(data_writes1));
6170 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6171 data_writes2, arraysize(data_writes2));
6172 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6173 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6175 TestCompletionCallback callback1;
6177 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6178 EXPECT_EQ(ERR_IO_PENDING, rv);
6180 rv = callback1.WaitForResult();
6181 EXPECT_EQ(OK, rv);
6183 const HttpResponseInfo* response = trans->GetResponseInfo();
6184 ASSERT_TRUE(response != NULL);
6185 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
6187 TestCompletionCallback callback2;
6189 rv = trans->RestartWithAuth(
6190 AuthCredentials(kFoo, kBar), callback2.callback());
6191 EXPECT_EQ(ERR_IO_PENDING, rv);
6193 rv = callback2.WaitForResult();
6194 EXPECT_EQ(OK, rv);
6196 response = trans->GetResponseInfo();
6197 ASSERT_TRUE(response != NULL);
6198 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6201 // ------------------------------------------------------------------------
6203 // Transaction 2: Request another resource in digestive's protection space.
6204 // This will preemptively add an Authorization header which should have an
6205 // "nc" value of 2 (as compared to 1 in the first use.
6207 HttpRequestInfo request;
6208 request.method = "GET";
6209 // Note that Transaction 1 was at /x/y/z, so this is in the same
6210 // protection space as digest.
6211 request.url = GURL("http://www.example.org/x/y/a/b");
6212 request.load_flags = 0;
6214 scoped_ptr<HttpTransaction> trans(
6215 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6217 MockWrite data_writes1[] = {
6218 MockWrite(
6219 "GET /x/y/a/b HTTP/1.1\r\n"
6220 "Host: www.example.org\r\n"
6221 "Connection: keep-alive\r\n"
6222 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6223 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6224 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6225 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6228 // Sever accepts the authorization.
6229 MockRead data_reads1[] = {
6230 MockRead("HTTP/1.0 200 OK\r\n"),
6231 MockRead("Content-Length: 100\r\n\r\n"),
6232 MockRead(SYNCHRONOUS, OK),
6235 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6236 data_writes1, arraysize(data_writes1));
6237 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6239 TestCompletionCallback callback1;
6241 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6242 EXPECT_EQ(ERR_IO_PENDING, rv);
6244 rv = callback1.WaitForResult();
6245 EXPECT_EQ(OK, rv);
6247 const HttpResponseInfo* response = trans->GetResponseInfo();
6248 ASSERT_TRUE(response != NULL);
6249 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6253 // Test the ResetStateForRestart() private method.
6254 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
6255 // Create a transaction (the dependencies aren't important).
6256 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6257 scoped_ptr<HttpNetworkTransaction> trans(
6258 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6260 // Setup some state (which we expect ResetStateForRestart() will clear).
6261 trans->read_buf_ = new IOBuffer(15);
6262 trans->read_buf_len_ = 15;
6263 trans->request_headers_.SetHeader("Authorization", "NTLM");
6265 // Setup state in response_
6266 HttpResponseInfo* response = &trans->response_;
6267 response->auth_challenge = new AuthChallengeInfo();
6268 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
6269 response->response_time = base::Time::Now();
6270 response->was_cached = true; // (Wouldn't ever actually be true...)
6272 { // Setup state for response_.vary_data
6273 HttpRequestInfo request;
6274 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6275 std::replace(temp.begin(), temp.end(), '\n', '\0');
6276 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
6277 request.extra_headers.SetHeader("Foo", "1");
6278 request.extra_headers.SetHeader("bar", "23");
6279 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
6282 // Cause the above state to be reset.
6283 trans->ResetStateForRestart();
6285 // Verify that the state that needed to be reset, has been reset.
6286 EXPECT_TRUE(trans->read_buf_.get() == NULL);
6287 EXPECT_EQ(0, trans->read_buf_len_);
6288 EXPECT_TRUE(trans->request_headers_.IsEmpty());
6289 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6290 EXPECT_TRUE(response->headers.get() == NULL);
6291 EXPECT_FALSE(response->was_cached);
6292 EXPECT_EQ(0U, response->ssl_info.cert_status);
6293 EXPECT_FALSE(response->vary_data.is_valid());
6296 // Test HTTPS connections to a site with a bad certificate
6297 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
6298 HttpRequestInfo request;
6299 request.method = "GET";
6300 request.url = GURL("https://www.example.org/");
6301 request.load_flags = 0;
6303 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6304 scoped_ptr<HttpTransaction> trans(
6305 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6307 MockWrite data_writes[] = {
6308 MockWrite(
6309 "GET / HTTP/1.1\r\n"
6310 "Host: www.example.org\r\n"
6311 "Connection: keep-alive\r\n\r\n"),
6314 MockRead data_reads[] = {
6315 MockRead("HTTP/1.0 200 OK\r\n"),
6316 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6317 MockRead("Content-Length: 100\r\n\r\n"),
6318 MockRead(SYNCHRONOUS, OK),
6321 StaticSocketDataProvider ssl_bad_certificate;
6322 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6323 data_writes, arraysize(data_writes));
6324 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6325 SSLSocketDataProvider ssl(ASYNC, OK);
6327 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6328 session_deps_.socket_factory->AddSocketDataProvider(&data);
6329 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6332 TestCompletionCallback callback;
6334 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6335 EXPECT_EQ(ERR_IO_PENDING, rv);
6337 rv = callback.WaitForResult();
6338 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6340 rv = trans->RestartIgnoringLastError(callback.callback());
6341 EXPECT_EQ(ERR_IO_PENDING, rv);
6343 rv = callback.WaitForResult();
6344 EXPECT_EQ(OK, rv);
6346 const HttpResponseInfo* response = trans->GetResponseInfo();
6348 ASSERT_TRUE(response != NULL);
6349 EXPECT_EQ(100, response->headers->GetContentLength());
6352 // Test HTTPS connections to a site with a bad certificate, going through a
6353 // proxy
6354 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
6355 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6357 HttpRequestInfo request;
6358 request.method = "GET";
6359 request.url = GURL("https://www.example.org/");
6360 request.load_flags = 0;
6362 MockWrite proxy_writes[] = {
6363 MockWrite(
6364 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6365 "Host: www.example.org\r\n"
6366 "Proxy-Connection: keep-alive\r\n\r\n"),
6369 MockRead proxy_reads[] = {
6370 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6371 MockRead(SYNCHRONOUS, OK)
6374 MockWrite data_writes[] = {
6375 MockWrite(
6376 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6377 "Host: www.example.org\r\n"
6378 "Proxy-Connection: keep-alive\r\n\r\n"),
6379 MockWrite(
6380 "GET / HTTP/1.1\r\n"
6381 "Host: www.example.org\r\n"
6382 "Connection: keep-alive\r\n\r\n"),
6385 MockRead data_reads[] = {
6386 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6387 MockRead("HTTP/1.0 200 OK\r\n"),
6388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6389 MockRead("Content-Length: 100\r\n\r\n"),
6390 MockRead(SYNCHRONOUS, OK),
6393 StaticSocketDataProvider ssl_bad_certificate(
6394 proxy_reads, arraysize(proxy_reads),
6395 proxy_writes, arraysize(proxy_writes));
6396 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6397 data_writes, arraysize(data_writes));
6398 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6399 SSLSocketDataProvider ssl(ASYNC, OK);
6401 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6402 session_deps_.socket_factory->AddSocketDataProvider(&data);
6403 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6404 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6406 TestCompletionCallback callback;
6408 for (int i = 0; i < 2; i++) {
6409 session_deps_.socket_factory->ResetNextMockIndexes();
6411 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6412 scoped_ptr<HttpTransaction> trans(
6413 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6415 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6416 EXPECT_EQ(ERR_IO_PENDING, rv);
6418 rv = callback.WaitForResult();
6419 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6421 rv = trans->RestartIgnoringLastError(callback.callback());
6422 EXPECT_EQ(ERR_IO_PENDING, rv);
6424 rv = callback.WaitForResult();
6425 EXPECT_EQ(OK, rv);
6427 const HttpResponseInfo* response = trans->GetResponseInfo();
6429 ASSERT_TRUE(response != NULL);
6430 EXPECT_EQ(100, response->headers->GetContentLength());
6435 // Test HTTPS connections to a site, going through an HTTPS proxy
6436 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6437 session_deps_.proxy_service.reset(
6438 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6439 TestNetLog net_log;
6440 session_deps_.net_log = &net_log;
6442 HttpRequestInfo request;
6443 request.method = "GET";
6444 request.url = GURL("https://www.example.org/");
6445 request.load_flags = 0;
6447 MockWrite data_writes[] = {
6448 MockWrite(
6449 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6450 "Host: www.example.org\r\n"
6451 "Proxy-Connection: keep-alive\r\n\r\n"),
6452 MockWrite(
6453 "GET / HTTP/1.1\r\n"
6454 "Host: www.example.org\r\n"
6455 "Connection: keep-alive\r\n\r\n"),
6458 MockRead data_reads[] = {
6459 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6460 MockRead("HTTP/1.1 200 OK\r\n"),
6461 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6462 MockRead("Content-Length: 100\r\n\r\n"),
6463 MockRead(SYNCHRONOUS, OK),
6466 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6467 data_writes, arraysize(data_writes));
6468 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6469 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6471 session_deps_.socket_factory->AddSocketDataProvider(&data);
6472 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6473 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6475 TestCompletionCallback callback;
6477 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6478 scoped_ptr<HttpTransaction> trans(
6479 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6481 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6482 EXPECT_EQ(ERR_IO_PENDING, rv);
6484 rv = callback.WaitForResult();
6485 EXPECT_EQ(OK, rv);
6486 const HttpResponseInfo* response = trans->GetResponseInfo();
6488 ASSERT_TRUE(response != NULL);
6490 EXPECT_TRUE(response->headers->IsKeepAlive());
6491 EXPECT_EQ(200, response->headers->response_code());
6492 EXPECT_EQ(100, response->headers->GetContentLength());
6493 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6495 LoadTimingInfo load_timing_info;
6496 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6497 TestLoadTimingNotReusedWithPac(load_timing_info,
6498 CONNECT_TIMING_HAS_SSL_TIMES);
6501 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6502 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6503 session_deps_.proxy_service.reset(
6504 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6505 TestNetLog net_log;
6506 session_deps_.net_log = &net_log;
6508 HttpRequestInfo request;
6509 request.method = "GET";
6510 request.url = GURL("https://www.example.org/");
6511 request.load_flags = 0;
6513 MockWrite data_writes[] = {
6514 MockWrite(
6515 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6516 "Host: www.example.org\r\n"
6517 "Proxy-Connection: keep-alive\r\n\r\n"),
6520 MockRead data_reads[] = {
6521 MockRead("HTTP/1.1 302 Redirect\r\n"),
6522 MockRead("Location: http://login.example.com/\r\n"),
6523 MockRead("Content-Length: 0\r\n\r\n"),
6524 MockRead(SYNCHRONOUS, OK),
6527 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6528 data_writes, arraysize(data_writes));
6529 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6531 session_deps_.socket_factory->AddSocketDataProvider(&data);
6532 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6534 TestCompletionCallback callback;
6536 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6537 scoped_ptr<HttpTransaction> trans(
6538 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6540 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6541 EXPECT_EQ(ERR_IO_PENDING, rv);
6543 rv = callback.WaitForResult();
6544 EXPECT_EQ(OK, rv);
6545 const HttpResponseInfo* response = trans->GetResponseInfo();
6547 ASSERT_TRUE(response != NULL);
6549 EXPECT_EQ(302, response->headers->response_code());
6550 std::string url;
6551 EXPECT_TRUE(response->headers->IsRedirect(&url));
6552 EXPECT_EQ("http://login.example.com/", url);
6554 // In the case of redirects from proxies, HttpNetworkTransaction returns
6555 // timing for the proxy connection instead of the connection to the host,
6556 // and no send / receive times.
6557 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6558 LoadTimingInfo load_timing_info;
6559 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6561 EXPECT_FALSE(load_timing_info.socket_reused);
6562 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6564 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6565 EXPECT_LE(load_timing_info.proxy_resolve_start,
6566 load_timing_info.proxy_resolve_end);
6567 EXPECT_LE(load_timing_info.proxy_resolve_end,
6568 load_timing_info.connect_timing.connect_start);
6569 ExpectConnectTimingHasTimes(
6570 load_timing_info.connect_timing,
6571 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6573 EXPECT_TRUE(load_timing_info.send_start.is_null());
6574 EXPECT_TRUE(load_timing_info.send_end.is_null());
6575 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6578 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6579 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6580 session_deps_.proxy_service.reset(
6581 ProxyService::CreateFixed("https://proxy:70"));
6583 HttpRequestInfo request;
6584 request.method = "GET";
6585 request.url = GURL("https://www.example.org/");
6586 request.load_flags = 0;
6588 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6589 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6590 scoped_ptr<SpdyFrame> goaway(
6591 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6592 MockWrite data_writes[] = {
6593 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6594 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
6597 static const char* const kExtraHeaders[] = {
6598 "location",
6599 "http://login.example.com/",
6601 scoped_ptr<SpdyFrame> resp(
6602 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6603 arraysize(kExtraHeaders)/2, 1));
6604 MockRead data_reads[] = {
6605 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6606 MockRead(ASYNC, 0, 2), // EOF
6609 DelayedSocketData data(
6610 1, // wait for one write to finish before reading.
6611 data_reads, arraysize(data_reads),
6612 data_writes, arraysize(data_writes));
6613 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6614 proxy_ssl.SetNextProto(GetParam());
6616 session_deps_.socket_factory->AddSocketDataProvider(&data);
6617 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6619 TestCompletionCallback callback;
6621 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6622 scoped_ptr<HttpTransaction> trans(
6623 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6625 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6626 EXPECT_EQ(ERR_IO_PENDING, rv);
6628 rv = callback.WaitForResult();
6629 EXPECT_EQ(OK, rv);
6630 const HttpResponseInfo* response = trans->GetResponseInfo();
6632 ASSERT_TRUE(response != NULL);
6634 EXPECT_EQ(302, response->headers->response_code());
6635 std::string url;
6636 EXPECT_TRUE(response->headers->IsRedirect(&url));
6637 EXPECT_EQ("http://login.example.com/", url);
6640 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6641 TEST_P(HttpNetworkTransactionTest,
6642 ErrorResponseToHttpsConnectViaHttpsProxy) {
6643 session_deps_.proxy_service.reset(
6644 ProxyService::CreateFixed("https://proxy:70"));
6646 HttpRequestInfo request;
6647 request.method = "GET";
6648 request.url = GURL("https://www.example.org/");
6649 request.load_flags = 0;
6651 MockWrite data_writes[] = {
6652 MockWrite(
6653 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6654 "Host: www.example.org\r\n"
6655 "Proxy-Connection: keep-alive\r\n\r\n"),
6658 MockRead data_reads[] = {
6659 MockRead("HTTP/1.1 404 Not Found\r\n"),
6660 MockRead("Content-Length: 23\r\n\r\n"),
6661 MockRead("The host does not exist"),
6662 MockRead(SYNCHRONOUS, OK),
6665 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6666 data_writes, arraysize(data_writes));
6667 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6669 session_deps_.socket_factory->AddSocketDataProvider(&data);
6670 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6672 TestCompletionCallback callback;
6674 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6675 scoped_ptr<HttpTransaction> trans(
6676 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6678 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6679 EXPECT_EQ(ERR_IO_PENDING, rv);
6681 rv = callback.WaitForResult();
6682 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6684 // TODO(ttuttle): Anything else to check here?
6687 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6688 TEST_P(HttpNetworkTransactionTest,
6689 ErrorResponseToHttpsConnectViaSpdyProxy) {
6690 session_deps_.proxy_service.reset(
6691 ProxyService::CreateFixed("https://proxy:70"));
6693 HttpRequestInfo request;
6694 request.method = "GET";
6695 request.url = GURL("https://www.example.org/");
6696 request.load_flags = 0;
6698 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6699 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6700 scoped_ptr<SpdyFrame> rst(
6701 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6702 MockWrite data_writes[] = {
6703 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6704 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6707 static const char* const kExtraHeaders[] = {
6708 "location",
6709 "http://login.example.com/",
6711 scoped_ptr<SpdyFrame> resp(
6712 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6713 arraysize(kExtraHeaders)/2, 1));
6714 scoped_ptr<SpdyFrame> body(
6715 spdy_util_.ConstructSpdyBodyFrame(
6716 1, "The host does not exist", 23, true));
6717 MockRead data_reads[] = {
6718 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6719 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6720 MockRead(ASYNC, 0, 4), // EOF
6723 DelayedSocketData data(
6724 1, // wait for one write to finish before reading.
6725 data_reads, arraysize(data_reads),
6726 data_writes, arraysize(data_writes));
6727 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6728 proxy_ssl.SetNextProto(GetParam());
6730 session_deps_.socket_factory->AddSocketDataProvider(&data);
6731 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6733 TestCompletionCallback callback;
6735 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6736 scoped_ptr<HttpTransaction> trans(
6737 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6739 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6740 EXPECT_EQ(ERR_IO_PENDING, rv);
6742 rv = callback.WaitForResult();
6743 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6745 // TODO(ttuttle): Anything else to check here?
6748 // Test the request-challenge-retry sequence for basic auth, through
6749 // a SPDY proxy over a single SPDY session.
6750 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6751 HttpRequestInfo request;
6752 request.method = "GET";
6753 request.url = GURL("https://www.example.org/");
6754 // when the no authentication data flag is set.
6755 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
6757 // Configure against https proxy server "myproxy:70".
6758 session_deps_.proxy_service.reset(
6759 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6760 BoundTestNetLog log;
6761 session_deps_.net_log = log.bound().net_log();
6762 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6764 // Since we have proxy, should try to establish tunnel.
6765 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
6766 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6767 scoped_ptr<SpdyFrame> rst(
6768 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6770 // After calling trans->RestartWithAuth(), this is the request we should
6771 // be issuing -- the final header line contains the credentials.
6772 const char* const kAuthCredentials[] = {
6773 "proxy-authorization", "Basic Zm9vOmJhcg==",
6775 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6776 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
6777 HostPortPair("www.example.org", 443)));
6778 // fetch https://www.example.org/ via HTTP
6779 const char get[] =
6780 "GET / HTTP/1.1\r\n"
6781 "Host: www.example.org\r\n"
6782 "Connection: keep-alive\r\n\r\n";
6783 scoped_ptr<SpdyFrame> wrapped_get(
6784 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6786 MockWrite spdy_writes[] = {
6787 CreateMockWrite(*req, 1, ASYNC),
6788 CreateMockWrite(*rst, 4, ASYNC),
6789 CreateMockWrite(*connect2, 5),
6790 CreateMockWrite(*wrapped_get, 8),
6793 // The proxy responds to the connect with a 407, using a persistent
6794 // connection.
6795 const char kAuthStatus[] = "407";
6796 const char* const kAuthChallenge[] = {
6797 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6799 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6800 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6802 scoped_ptr<SpdyFrame> conn_resp(
6803 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6804 const char resp[] = "HTTP/1.1 200 OK\r\n"
6805 "Content-Length: 5\r\n\r\n";
6807 scoped_ptr<SpdyFrame> wrapped_get_resp(
6808 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6809 scoped_ptr<SpdyFrame> wrapped_body(
6810 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6811 MockRead spdy_reads[] = {
6812 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6813 CreateMockRead(*conn_resp, 6, ASYNC),
6814 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6815 CreateMockRead(*wrapped_body, 10, ASYNC),
6816 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6819 OrderedSocketData spdy_data(
6820 spdy_reads, arraysize(spdy_reads),
6821 spdy_writes, arraysize(spdy_writes));
6822 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6823 // Negotiate SPDY to the proxy
6824 SSLSocketDataProvider proxy(ASYNC, OK);
6825 proxy.SetNextProto(GetParam());
6826 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6827 // Vanilla SSL to the server
6828 SSLSocketDataProvider server(ASYNC, OK);
6829 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6831 TestCompletionCallback callback1;
6833 scoped_ptr<HttpTransaction> trans(
6834 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6836 int rv = trans->Start(&request, callback1.callback(), log.bound());
6837 EXPECT_EQ(ERR_IO_PENDING, rv);
6839 rv = callback1.WaitForResult();
6840 EXPECT_EQ(OK, rv);
6841 CapturedNetLogEntry::List entries;
6842 log.GetEntries(&entries);
6843 size_t pos = ExpectLogContainsSomewhere(
6844 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6845 NetLog::PHASE_NONE);
6846 ExpectLogContainsSomewhere(
6847 entries, pos,
6848 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6849 NetLog::PHASE_NONE);
6851 const HttpResponseInfo* response = trans->GetResponseInfo();
6852 ASSERT_TRUE(response != NULL);
6853 ASSERT_FALSE(response->headers.get() == NULL);
6854 EXPECT_EQ(407, response->headers->response_code());
6855 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6856 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6857 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6859 TestCompletionCallback callback2;
6861 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6862 callback2.callback());
6863 EXPECT_EQ(ERR_IO_PENDING, rv);
6865 rv = callback2.WaitForResult();
6866 EXPECT_EQ(OK, rv);
6868 response = trans->GetResponseInfo();
6869 ASSERT_TRUE(response != NULL);
6871 EXPECT_TRUE(response->headers->IsKeepAlive());
6872 EXPECT_EQ(200, response->headers->response_code());
6873 EXPECT_EQ(5, response->headers->GetContentLength());
6874 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6876 // The password prompt info should not be set.
6877 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6879 LoadTimingInfo load_timing_info;
6880 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6881 TestLoadTimingNotReusedWithPac(load_timing_info,
6882 CONNECT_TIMING_HAS_SSL_TIMES);
6884 trans.reset();
6885 session->CloseAllConnections();
6888 // Test that an explicitly trusted SPDY proxy can push a resource from an
6889 // origin that is different from that of its associated resource.
6890 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6891 HttpRequestInfo request;
6892 HttpRequestInfo push_request;
6894 request.method = "GET";
6895 request.url = GURL("http://www.example.org/");
6896 push_request.method = "GET";
6897 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6899 // Configure against https proxy server "myproxy:70".
6900 session_deps_.proxy_service.reset(
6901 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6902 BoundTestNetLog log;
6903 session_deps_.net_log = log.bound().net_log();
6905 // Enable cross-origin push.
6906 session_deps_.trusted_spdy_proxy = "myproxy:70";
6908 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6910 scoped_ptr<SpdyFrame> stream1_syn(
6911 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6913 MockWrite spdy_writes[] = {
6914 CreateMockWrite(*stream1_syn, 1, ASYNC),
6917 scoped_ptr<SpdyFrame>
6918 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6920 scoped_ptr<SpdyFrame>
6921 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6923 scoped_ptr<SpdyFrame>
6924 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6928 "http://www.another-origin.com/foo.dat"));
6929 const char kPushedData[] = "pushed";
6930 scoped_ptr<SpdyFrame> stream2_body(
6931 spdy_util_.ConstructSpdyBodyFrame(
6932 2, kPushedData, strlen(kPushedData), true));
6934 MockRead spdy_reads[] = {
6935 CreateMockRead(*stream1_reply, 2, ASYNC),
6936 CreateMockRead(*stream2_syn, 3, ASYNC),
6937 CreateMockRead(*stream1_body, 4, ASYNC),
6938 CreateMockRead(*stream2_body, 5, ASYNC),
6939 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6942 OrderedSocketData spdy_data(
6943 spdy_reads, arraysize(spdy_reads),
6944 spdy_writes, arraysize(spdy_writes));
6945 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6946 // Negotiate SPDY to the proxy
6947 SSLSocketDataProvider proxy(ASYNC, OK);
6948 proxy.SetNextProto(GetParam());
6949 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6951 scoped_ptr<HttpTransaction> trans(
6952 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6953 TestCompletionCallback callback;
6954 int rv = trans->Start(&request, callback.callback(), log.bound());
6955 EXPECT_EQ(ERR_IO_PENDING, rv);
6957 rv = callback.WaitForResult();
6958 EXPECT_EQ(OK, rv);
6959 const HttpResponseInfo* response = trans->GetResponseInfo();
6961 scoped_ptr<HttpTransaction> push_trans(
6962 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6963 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6964 EXPECT_EQ(ERR_IO_PENDING, rv);
6966 rv = callback.WaitForResult();
6967 EXPECT_EQ(OK, rv);
6968 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6970 ASSERT_TRUE(response != NULL);
6971 EXPECT_TRUE(response->headers->IsKeepAlive());
6973 EXPECT_EQ(200, response->headers->response_code());
6974 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6976 std::string response_data;
6977 rv = ReadTransaction(trans.get(), &response_data);
6978 EXPECT_EQ(OK, rv);
6979 EXPECT_EQ("hello!", response_data);
6981 LoadTimingInfo load_timing_info;
6982 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6983 TestLoadTimingNotReusedWithPac(load_timing_info,
6984 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6986 // Verify the pushed stream.
6987 EXPECT_TRUE(push_response->headers.get() != NULL);
6988 EXPECT_EQ(200, push_response->headers->response_code());
6990 rv = ReadTransaction(push_trans.get(), &response_data);
6991 EXPECT_EQ(OK, rv);
6992 EXPECT_EQ("pushed", response_data);
6994 LoadTimingInfo push_load_timing_info;
6995 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6996 TestLoadTimingReusedWithPac(push_load_timing_info);
6997 // The transactions should share a socket ID, despite being for different
6998 // origins.
6999 EXPECT_EQ(load_timing_info.socket_log_id,
7000 push_load_timing_info.socket_log_id);
7002 trans.reset();
7003 push_trans.reset();
7004 session->CloseAllConnections();
7007 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
7008 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
7009 HttpRequestInfo request;
7011 request.method = "GET";
7012 request.url = GURL("http://www.example.org/");
7014 // Configure against https proxy server "myproxy:70".
7015 session_deps_.proxy_service.reset(
7016 ProxyService::CreateFixed("https://myproxy:70"));
7017 BoundTestNetLog log;
7018 session_deps_.net_log = log.bound().net_log();
7020 // Enable cross-origin push.
7021 session_deps_.trusted_spdy_proxy = "myproxy:70";
7023 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7025 scoped_ptr<SpdyFrame> stream1_syn(
7026 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
7028 scoped_ptr<SpdyFrame> push_rst(
7029 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
7031 MockWrite spdy_writes[] = {
7032 CreateMockWrite(*stream1_syn, 1, ASYNC),
7033 CreateMockWrite(*push_rst, 4),
7036 scoped_ptr<SpdyFrame>
7037 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
7039 scoped_ptr<SpdyFrame>
7040 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
7042 scoped_ptr<SpdyFrame>
7043 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
7047 "https://www.another-origin.com/foo.dat"));
7049 MockRead spdy_reads[] = {
7050 CreateMockRead(*stream1_reply, 2, ASYNC),
7051 CreateMockRead(*stream2_syn, 3, ASYNC),
7052 CreateMockRead(*stream1_body, 5, ASYNC),
7053 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
7056 OrderedSocketData spdy_data(
7057 spdy_reads, arraysize(spdy_reads),
7058 spdy_writes, arraysize(spdy_writes));
7059 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7060 // Negotiate SPDY to the proxy
7061 SSLSocketDataProvider proxy(ASYNC, OK);
7062 proxy.SetNextProto(GetParam());
7063 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7065 scoped_ptr<HttpTransaction> trans(
7066 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7067 TestCompletionCallback callback;
7068 int rv = trans->Start(&request, callback.callback(), log.bound());
7069 EXPECT_EQ(ERR_IO_PENDING, rv);
7071 rv = callback.WaitForResult();
7072 EXPECT_EQ(OK, rv);
7073 const HttpResponseInfo* response = trans->GetResponseInfo();
7075 ASSERT_TRUE(response != NULL);
7076 EXPECT_TRUE(response->headers->IsKeepAlive());
7078 EXPECT_EQ(200, response->headers->response_code());
7079 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7081 std::string response_data;
7082 rv = ReadTransaction(trans.get(), &response_data);
7083 EXPECT_EQ(OK, rv);
7084 EXPECT_EQ("hello!", response_data);
7086 trans.reset();
7087 session->CloseAllConnections();
7090 // Test HTTPS connections to a site with a bad certificate, going through an
7091 // HTTPS proxy
7092 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
7093 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
7094 "https://proxy:70"));
7096 HttpRequestInfo request;
7097 request.method = "GET";
7098 request.url = GURL("https://www.example.org/");
7099 request.load_flags = 0;
7101 // Attempt to fetch the URL from a server with a bad cert
7102 MockWrite bad_cert_writes[] = {
7103 MockWrite(
7104 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7105 "Host: www.example.org\r\n"
7106 "Proxy-Connection: keep-alive\r\n\r\n"),
7109 MockRead bad_cert_reads[] = {
7110 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7111 MockRead(SYNCHRONOUS, OK)
7114 // Attempt to fetch the URL with a good cert
7115 MockWrite good_data_writes[] = {
7116 MockWrite(
7117 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7118 "Host: www.example.org\r\n"
7119 "Proxy-Connection: keep-alive\r\n\r\n"),
7120 MockWrite(
7121 "GET / HTTP/1.1\r\n"
7122 "Host: www.example.org\r\n"
7123 "Connection: keep-alive\r\n\r\n"),
7126 MockRead good_cert_reads[] = {
7127 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7128 MockRead("HTTP/1.0 200 OK\r\n"),
7129 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7130 MockRead("Content-Length: 100\r\n\r\n"),
7131 MockRead(SYNCHRONOUS, OK),
7134 StaticSocketDataProvider ssl_bad_certificate(
7135 bad_cert_reads, arraysize(bad_cert_reads),
7136 bad_cert_writes, arraysize(bad_cert_writes));
7137 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7138 good_data_writes, arraysize(good_data_writes));
7139 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7140 SSLSocketDataProvider ssl(ASYNC, OK);
7142 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7143 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7144 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7145 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7147 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7148 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7149 session_deps_.socket_factory->AddSocketDataProvider(&data);
7150 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7152 TestCompletionCallback callback;
7154 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7155 scoped_ptr<HttpTransaction> trans(
7156 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7158 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7159 EXPECT_EQ(ERR_IO_PENDING, rv);
7161 rv = callback.WaitForResult();
7162 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7164 rv = trans->RestartIgnoringLastError(callback.callback());
7165 EXPECT_EQ(ERR_IO_PENDING, rv);
7167 rv = callback.WaitForResult();
7168 EXPECT_EQ(OK, rv);
7170 const HttpResponseInfo* response = trans->GetResponseInfo();
7172 ASSERT_TRUE(response != NULL);
7173 EXPECT_EQ(100, response->headers->GetContentLength());
7176 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
7177 HttpRequestInfo request;
7178 request.method = "GET";
7179 request.url = GURL("http://www.example.org/");
7180 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7181 "Chromium Ultra Awesome X Edition");
7183 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7184 scoped_ptr<HttpTransaction> trans(
7185 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7187 MockWrite data_writes[] = {
7188 MockWrite(
7189 "GET / HTTP/1.1\r\n"
7190 "Host: www.example.org\r\n"
7191 "Connection: keep-alive\r\n"
7192 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7195 // Lastly, the server responds with the actual content.
7196 MockRead data_reads[] = {
7197 MockRead("HTTP/1.0 200 OK\r\n"),
7198 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7199 MockRead("Content-Length: 100\r\n\r\n"),
7200 MockRead(SYNCHRONOUS, OK),
7203 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7204 data_writes, arraysize(data_writes));
7205 session_deps_.socket_factory->AddSocketDataProvider(&data);
7207 TestCompletionCallback callback;
7209 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7210 EXPECT_EQ(ERR_IO_PENDING, rv);
7212 rv = callback.WaitForResult();
7213 EXPECT_EQ(OK, rv);
7216 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
7217 HttpRequestInfo request;
7218 request.method = "GET";
7219 request.url = GURL("https://www.example.org/");
7220 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7221 "Chromium Ultra Awesome X Edition");
7223 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7224 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7225 scoped_ptr<HttpTransaction> trans(
7226 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7228 MockWrite data_writes[] = {
7229 MockWrite(
7230 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7231 "Host: www.example.org\r\n"
7232 "Proxy-Connection: keep-alive\r\n"
7233 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7235 MockRead data_reads[] = {
7236 // Return an error, so the transaction stops here (this test isn't
7237 // interested in the rest).
7238 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7239 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7240 MockRead("Proxy-Connection: close\r\n\r\n"),
7243 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7244 data_writes, arraysize(data_writes));
7245 session_deps_.socket_factory->AddSocketDataProvider(&data);
7247 TestCompletionCallback callback;
7249 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7250 EXPECT_EQ(ERR_IO_PENDING, rv);
7252 rv = callback.WaitForResult();
7253 EXPECT_EQ(OK, rv);
7256 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
7257 HttpRequestInfo request;
7258 request.method = "GET";
7259 request.url = GURL("http://www.example.org/");
7260 request.load_flags = 0;
7261 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7262 "http://the.previous.site.com/");
7264 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7265 scoped_ptr<HttpTransaction> trans(
7266 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7268 MockWrite data_writes[] = {
7269 MockWrite(
7270 "GET / HTTP/1.1\r\n"
7271 "Host: www.example.org\r\n"
7272 "Connection: keep-alive\r\n"
7273 "Referer: http://the.previous.site.com/\r\n\r\n"),
7276 // Lastly, the server responds with the actual content.
7277 MockRead data_reads[] = {
7278 MockRead("HTTP/1.0 200 OK\r\n"),
7279 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7280 MockRead("Content-Length: 100\r\n\r\n"),
7281 MockRead(SYNCHRONOUS, OK),
7284 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7285 data_writes, arraysize(data_writes));
7286 session_deps_.socket_factory->AddSocketDataProvider(&data);
7288 TestCompletionCallback callback;
7290 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7291 EXPECT_EQ(ERR_IO_PENDING, rv);
7293 rv = callback.WaitForResult();
7294 EXPECT_EQ(OK, rv);
7297 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
7298 HttpRequestInfo request;
7299 request.method = "POST";
7300 request.url = GURL("http://www.example.org/");
7302 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7303 scoped_ptr<HttpTransaction> trans(
7304 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7306 MockWrite data_writes[] = {
7307 MockWrite(
7308 "POST / HTTP/1.1\r\n"
7309 "Host: www.example.org\r\n"
7310 "Connection: keep-alive\r\n"
7311 "Content-Length: 0\r\n\r\n"),
7314 // Lastly, the server responds with the actual content.
7315 MockRead data_reads[] = {
7316 MockRead("HTTP/1.0 200 OK\r\n"),
7317 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7318 MockRead("Content-Length: 100\r\n\r\n"),
7319 MockRead(SYNCHRONOUS, OK),
7322 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7323 data_writes, arraysize(data_writes));
7324 session_deps_.socket_factory->AddSocketDataProvider(&data);
7326 TestCompletionCallback callback;
7328 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7329 EXPECT_EQ(ERR_IO_PENDING, rv);
7331 rv = callback.WaitForResult();
7332 EXPECT_EQ(OK, rv);
7335 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
7336 HttpRequestInfo request;
7337 request.method = "PUT";
7338 request.url = GURL("http://www.example.org/");
7340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7341 scoped_ptr<HttpTransaction> trans(
7342 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7344 MockWrite data_writes[] = {
7345 MockWrite(
7346 "PUT / HTTP/1.1\r\n"
7347 "Host: www.example.org\r\n"
7348 "Connection: keep-alive\r\n"
7349 "Content-Length: 0\r\n\r\n"),
7352 // Lastly, the server responds with the actual content.
7353 MockRead data_reads[] = {
7354 MockRead("HTTP/1.0 200 OK\r\n"),
7355 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7356 MockRead("Content-Length: 100\r\n\r\n"),
7357 MockRead(SYNCHRONOUS, OK),
7360 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7361 data_writes, arraysize(data_writes));
7362 session_deps_.socket_factory->AddSocketDataProvider(&data);
7364 TestCompletionCallback callback;
7366 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7367 EXPECT_EQ(ERR_IO_PENDING, rv);
7369 rv = callback.WaitForResult();
7370 EXPECT_EQ(OK, rv);
7373 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
7374 HttpRequestInfo request;
7375 request.method = "HEAD";
7376 request.url = GURL("http://www.example.org/");
7378 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7379 scoped_ptr<HttpTransaction> trans(
7380 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7382 MockWrite data_writes[] = {
7383 MockWrite(
7384 "HEAD / HTTP/1.1\r\n"
7385 "Host: www.example.org\r\n"
7386 "Connection: keep-alive\r\n"
7387 "Content-Length: 0\r\n\r\n"),
7390 // Lastly, the server responds with the actual content.
7391 MockRead data_reads[] = {
7392 MockRead("HTTP/1.0 200 OK\r\n"),
7393 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7394 MockRead("Content-Length: 100\r\n\r\n"),
7395 MockRead(SYNCHRONOUS, OK),
7398 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7399 data_writes, arraysize(data_writes));
7400 session_deps_.socket_factory->AddSocketDataProvider(&data);
7402 TestCompletionCallback callback;
7404 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7405 EXPECT_EQ(ERR_IO_PENDING, rv);
7407 rv = callback.WaitForResult();
7408 EXPECT_EQ(OK, rv);
7411 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7412 HttpRequestInfo request;
7413 request.method = "GET";
7414 request.url = GURL("http://www.example.org/");
7415 request.load_flags = LOAD_BYPASS_CACHE;
7417 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7418 scoped_ptr<HttpTransaction> trans(
7419 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7421 MockWrite data_writes[] = {
7422 MockWrite(
7423 "GET / HTTP/1.1\r\n"
7424 "Host: www.example.org\r\n"
7425 "Connection: keep-alive\r\n"
7426 "Pragma: no-cache\r\n"
7427 "Cache-Control: no-cache\r\n\r\n"),
7430 // Lastly, the server responds with the actual content.
7431 MockRead data_reads[] = {
7432 MockRead("HTTP/1.0 200 OK\r\n"),
7433 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7434 MockRead("Content-Length: 100\r\n\r\n"),
7435 MockRead(SYNCHRONOUS, OK),
7438 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7439 data_writes, arraysize(data_writes));
7440 session_deps_.socket_factory->AddSocketDataProvider(&data);
7442 TestCompletionCallback callback;
7444 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7445 EXPECT_EQ(ERR_IO_PENDING, rv);
7447 rv = callback.WaitForResult();
7448 EXPECT_EQ(OK, rv);
7451 TEST_P(HttpNetworkTransactionTest,
7452 BuildRequest_CacheControlValidateCache) {
7453 HttpRequestInfo request;
7454 request.method = "GET";
7455 request.url = GURL("http://www.example.org/");
7456 request.load_flags = LOAD_VALIDATE_CACHE;
7458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7459 scoped_ptr<HttpTransaction> trans(
7460 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7462 MockWrite data_writes[] = {
7463 MockWrite(
7464 "GET / HTTP/1.1\r\n"
7465 "Host: www.example.org\r\n"
7466 "Connection: keep-alive\r\n"
7467 "Cache-Control: max-age=0\r\n\r\n"),
7470 // Lastly, the server responds with the actual content.
7471 MockRead data_reads[] = {
7472 MockRead("HTTP/1.0 200 OK\r\n"),
7473 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7474 MockRead("Content-Length: 100\r\n\r\n"),
7475 MockRead(SYNCHRONOUS, OK),
7478 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7479 data_writes, arraysize(data_writes));
7480 session_deps_.socket_factory->AddSocketDataProvider(&data);
7482 TestCompletionCallback callback;
7484 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7485 EXPECT_EQ(ERR_IO_PENDING, rv);
7487 rv = callback.WaitForResult();
7488 EXPECT_EQ(OK, rv);
7491 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7492 HttpRequestInfo request;
7493 request.method = "GET";
7494 request.url = GURL("http://www.example.org/");
7495 request.extra_headers.SetHeader("FooHeader", "Bar");
7497 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7498 scoped_ptr<HttpTransaction> trans(
7499 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7501 MockWrite data_writes[] = {
7502 MockWrite(
7503 "GET / HTTP/1.1\r\n"
7504 "Host: www.example.org\r\n"
7505 "Connection: keep-alive\r\n"
7506 "FooHeader: Bar\r\n\r\n"),
7509 // Lastly, the server responds with the actual content.
7510 MockRead data_reads[] = {
7511 MockRead("HTTP/1.0 200 OK\r\n"),
7512 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7513 MockRead("Content-Length: 100\r\n\r\n"),
7514 MockRead(SYNCHRONOUS, OK),
7517 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7518 data_writes, arraysize(data_writes));
7519 session_deps_.socket_factory->AddSocketDataProvider(&data);
7521 TestCompletionCallback callback;
7523 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7524 EXPECT_EQ(ERR_IO_PENDING, rv);
7526 rv = callback.WaitForResult();
7527 EXPECT_EQ(OK, rv);
7530 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7531 HttpRequestInfo request;
7532 request.method = "GET";
7533 request.url = GURL("http://www.example.org/");
7534 request.extra_headers.SetHeader("referer", "www.foo.com");
7535 request.extra_headers.SetHeader("hEllo", "Kitty");
7536 request.extra_headers.SetHeader("FoO", "bar");
7538 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7539 scoped_ptr<HttpTransaction> trans(
7540 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7542 MockWrite data_writes[] = {
7543 MockWrite(
7544 "GET / HTTP/1.1\r\n"
7545 "Host: www.example.org\r\n"
7546 "Connection: keep-alive\r\n"
7547 "referer: www.foo.com\r\n"
7548 "hEllo: Kitty\r\n"
7549 "FoO: bar\r\n\r\n"),
7552 // Lastly, the server responds with the actual content.
7553 MockRead data_reads[] = {
7554 MockRead("HTTP/1.0 200 OK\r\n"),
7555 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7556 MockRead("Content-Length: 100\r\n\r\n"),
7557 MockRead(SYNCHRONOUS, OK),
7560 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7561 data_writes, arraysize(data_writes));
7562 session_deps_.socket_factory->AddSocketDataProvider(&data);
7564 TestCompletionCallback callback;
7566 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7567 EXPECT_EQ(ERR_IO_PENDING, rv);
7569 rv = callback.WaitForResult();
7570 EXPECT_EQ(OK, rv);
7573 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7574 HttpRequestInfo request;
7575 request.method = "GET";
7576 request.url = GURL("http://www.example.org/");
7577 request.load_flags = 0;
7579 session_deps_.proxy_service.reset(
7580 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7581 TestNetLog net_log;
7582 session_deps_.net_log = &net_log;
7584 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7585 scoped_ptr<HttpTransaction> trans(
7586 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7588 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7589 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7591 MockWrite data_writes[] = {
7592 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7593 MockWrite(
7594 "GET / HTTP/1.1\r\n"
7595 "Host: www.example.org\r\n"
7596 "Connection: keep-alive\r\n\r\n")};
7598 MockRead data_reads[] = {
7599 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7600 MockRead("HTTP/1.0 200 OK\r\n"),
7601 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7602 MockRead("Payload"),
7603 MockRead(SYNCHRONOUS, OK)
7606 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7607 data_writes, arraysize(data_writes));
7608 session_deps_.socket_factory->AddSocketDataProvider(&data);
7610 TestCompletionCallback callback;
7612 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7613 EXPECT_EQ(ERR_IO_PENDING, rv);
7615 rv = callback.WaitForResult();
7616 EXPECT_EQ(OK, rv);
7618 const HttpResponseInfo* response = trans->GetResponseInfo();
7619 ASSERT_TRUE(response != NULL);
7621 LoadTimingInfo load_timing_info;
7622 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7623 TestLoadTimingNotReusedWithPac(load_timing_info,
7624 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7626 std::string response_text;
7627 rv = ReadTransaction(trans.get(), &response_text);
7628 EXPECT_EQ(OK, rv);
7629 EXPECT_EQ("Payload", response_text);
7632 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7633 HttpRequestInfo request;
7634 request.method = "GET";
7635 request.url = GURL("https://www.example.org/");
7636 request.load_flags = 0;
7638 session_deps_.proxy_service.reset(
7639 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7640 TestNetLog net_log;
7641 session_deps_.net_log = &net_log;
7643 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7644 scoped_ptr<HttpTransaction> trans(
7645 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7647 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7648 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7650 MockWrite data_writes[] = {
7651 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7652 arraysize(write_buffer)),
7653 MockWrite(
7654 "GET / HTTP/1.1\r\n"
7655 "Host: www.example.org\r\n"
7656 "Connection: keep-alive\r\n\r\n")};
7658 MockRead data_reads[] = {
7659 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7660 arraysize(read_buffer)),
7661 MockRead("HTTP/1.0 200 OK\r\n"),
7662 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7663 MockRead("Payload"),
7664 MockRead(SYNCHRONOUS, OK)
7667 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7668 data_writes, arraysize(data_writes));
7669 session_deps_.socket_factory->AddSocketDataProvider(&data);
7671 SSLSocketDataProvider ssl(ASYNC, OK);
7672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7674 TestCompletionCallback callback;
7676 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7677 EXPECT_EQ(ERR_IO_PENDING, rv);
7679 rv = callback.WaitForResult();
7680 EXPECT_EQ(OK, rv);
7682 LoadTimingInfo load_timing_info;
7683 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7684 TestLoadTimingNotReusedWithPac(load_timing_info,
7685 CONNECT_TIMING_HAS_SSL_TIMES);
7687 const HttpResponseInfo* response = trans->GetResponseInfo();
7688 ASSERT_TRUE(response != NULL);
7690 std::string response_text;
7691 rv = ReadTransaction(trans.get(), &response_text);
7692 EXPECT_EQ(OK, rv);
7693 EXPECT_EQ("Payload", response_text);
7696 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7697 HttpRequestInfo request;
7698 request.method = "GET";
7699 request.url = GURL("http://www.example.org/");
7700 request.load_flags = 0;
7702 session_deps_.proxy_service.reset(
7703 ProxyService::CreateFixed("socks4://myproxy:1080"));
7704 TestNetLog net_log;
7705 session_deps_.net_log = &net_log;
7707 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7708 scoped_ptr<HttpTransaction> trans(
7709 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7711 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7712 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7714 MockWrite data_writes[] = {
7715 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7716 MockWrite(
7717 "GET / HTTP/1.1\r\n"
7718 "Host: www.example.org\r\n"
7719 "Connection: keep-alive\r\n\r\n")};
7721 MockRead data_reads[] = {
7722 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7723 MockRead("HTTP/1.0 200 OK\r\n"),
7724 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7725 MockRead("Payload"),
7726 MockRead(SYNCHRONOUS, OK)
7729 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7730 data_writes, arraysize(data_writes));
7731 session_deps_.socket_factory->AddSocketDataProvider(&data);
7733 TestCompletionCallback callback;
7735 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7736 EXPECT_EQ(ERR_IO_PENDING, rv);
7738 rv = callback.WaitForResult();
7739 EXPECT_EQ(OK, rv);
7741 const HttpResponseInfo* response = trans->GetResponseInfo();
7742 ASSERT_TRUE(response != NULL);
7744 LoadTimingInfo load_timing_info;
7745 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7746 TestLoadTimingNotReused(load_timing_info,
7747 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7749 std::string response_text;
7750 rv = ReadTransaction(trans.get(), &response_text);
7751 EXPECT_EQ(OK, rv);
7752 EXPECT_EQ("Payload", response_text);
7755 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7756 HttpRequestInfo request;
7757 request.method = "GET";
7758 request.url = GURL("http://www.example.org/");
7759 request.load_flags = 0;
7761 session_deps_.proxy_service.reset(
7762 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7763 TestNetLog net_log;
7764 session_deps_.net_log = &net_log;
7766 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7767 scoped_ptr<HttpTransaction> trans(
7768 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7770 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7771 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7772 const char kSOCKS5OkRequest[] = {
7773 0x05, // Version
7774 0x01, // Command (CONNECT)
7775 0x00, // Reserved.
7776 0x03, // Address type (DOMAINNAME).
7777 0x0F, // Length of domain (15)
7778 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7779 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7781 const char kSOCKS5OkResponse[] =
7782 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7784 MockWrite data_writes[] = {
7785 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7786 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7787 MockWrite(
7788 "GET / HTTP/1.1\r\n"
7789 "Host: www.example.org\r\n"
7790 "Connection: keep-alive\r\n\r\n")};
7792 MockRead data_reads[] = {
7793 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7794 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7795 MockRead("HTTP/1.0 200 OK\r\n"),
7796 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7797 MockRead("Payload"),
7798 MockRead(SYNCHRONOUS, OK)
7801 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7802 data_writes, arraysize(data_writes));
7803 session_deps_.socket_factory->AddSocketDataProvider(&data);
7805 TestCompletionCallback callback;
7807 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7808 EXPECT_EQ(ERR_IO_PENDING, rv);
7810 rv = callback.WaitForResult();
7811 EXPECT_EQ(OK, rv);
7813 const HttpResponseInfo* response = trans->GetResponseInfo();
7814 ASSERT_TRUE(response != NULL);
7816 LoadTimingInfo load_timing_info;
7817 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7818 TestLoadTimingNotReusedWithPac(load_timing_info,
7819 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7821 std::string response_text;
7822 rv = ReadTransaction(trans.get(), &response_text);
7823 EXPECT_EQ(OK, rv);
7824 EXPECT_EQ("Payload", response_text);
7827 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7828 HttpRequestInfo request;
7829 request.method = "GET";
7830 request.url = GURL("https://www.example.org/");
7831 request.load_flags = 0;
7833 session_deps_.proxy_service.reset(
7834 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7835 TestNetLog net_log;
7836 session_deps_.net_log = &net_log;
7838 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7839 scoped_ptr<HttpTransaction> trans(
7840 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7842 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7843 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7844 const unsigned char kSOCKS5OkRequest[] = {
7845 0x05, // Version
7846 0x01, // Command (CONNECT)
7847 0x00, // Reserved.
7848 0x03, // Address type (DOMAINNAME).
7849 0x0F, // Length of domain (15)
7850 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7851 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7854 const char kSOCKS5OkResponse[] =
7855 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7857 MockWrite data_writes[] = {
7858 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7859 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7860 arraysize(kSOCKS5OkRequest)),
7861 MockWrite(
7862 "GET / HTTP/1.1\r\n"
7863 "Host: www.example.org\r\n"
7864 "Connection: keep-alive\r\n\r\n")};
7866 MockRead data_reads[] = {
7867 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7868 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7869 MockRead("HTTP/1.0 200 OK\r\n"),
7870 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7871 MockRead("Payload"),
7872 MockRead(SYNCHRONOUS, OK)
7875 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7876 data_writes, arraysize(data_writes));
7877 session_deps_.socket_factory->AddSocketDataProvider(&data);
7879 SSLSocketDataProvider ssl(ASYNC, OK);
7880 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7882 TestCompletionCallback callback;
7884 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7885 EXPECT_EQ(ERR_IO_PENDING, rv);
7887 rv = callback.WaitForResult();
7888 EXPECT_EQ(OK, rv);
7890 const HttpResponseInfo* response = trans->GetResponseInfo();
7891 ASSERT_TRUE(response != NULL);
7893 LoadTimingInfo load_timing_info;
7894 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7895 TestLoadTimingNotReusedWithPac(load_timing_info,
7896 CONNECT_TIMING_HAS_SSL_TIMES);
7898 std::string response_text;
7899 rv = ReadTransaction(trans.get(), &response_text);
7900 EXPECT_EQ(OK, rv);
7901 EXPECT_EQ("Payload", response_text);
7904 namespace {
7906 // Tests that for connection endpoints the group names are correctly set.
7908 struct GroupNameTest {
7909 std::string proxy_server;
7910 std::string url;
7911 std::string expected_group_name;
7912 bool ssl;
7915 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7916 NextProto next_proto,
7917 SpdySessionDependencies* session_deps_) {
7918 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7920 base::WeakPtr<HttpServerProperties> http_server_properties =
7921 session->http_server_properties();
7922 AlternativeService alternative_service(
7923 AlternateProtocolFromNextProto(next_proto), "", 443);
7924 http_server_properties->SetAlternativeService(
7925 HostPortPair("host.with.alternate", 80), alternative_service, 1.0);
7927 return session;
7930 int GroupNameTransactionHelper(
7931 const std::string& url,
7932 const scoped_refptr<HttpNetworkSession>& session) {
7933 HttpRequestInfo request;
7934 request.method = "GET";
7935 request.url = GURL(url);
7936 request.load_flags = 0;
7938 scoped_ptr<HttpTransaction> trans(
7939 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7941 TestCompletionCallback callback;
7943 // We do not complete this request, the dtor will clean the transaction up.
7944 return trans->Start(&request, callback.callback(), BoundNetLog());
7947 } // namespace
7949 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7950 const GroupNameTest tests[] = {
7952 "", // unused
7953 "http://www.example.org/direct",
7954 "www.example.org:80",
7955 false,
7958 "", // unused
7959 "http://[2001:1418:13:1::25]/direct",
7960 "[2001:1418:13:1::25]:80",
7961 false,
7964 // SSL Tests
7966 "", // unused
7967 "https://www.example.org/direct_ssl",
7968 "ssl/www.example.org:443",
7969 true,
7972 "", // unused
7973 "https://[2001:1418:13:1::25]/direct",
7974 "ssl/[2001:1418:13:1::25]:443",
7975 true,
7978 "", // unused
7979 "http://host.with.alternate/direct",
7980 "ssl/host.with.alternate:443",
7981 true,
7985 session_deps_.use_alternate_protocols = true;
7987 for (size_t i = 0; i < arraysize(tests); ++i) {
7988 session_deps_.proxy_service.reset(
7989 ProxyService::CreateFixed(tests[i].proxy_server));
7990 scoped_refptr<HttpNetworkSession> session(
7991 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7993 HttpNetworkSessionPeer peer(session);
7994 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7995 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7996 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7997 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7998 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7999 new MockClientSocketPoolManager);
8000 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8001 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
8002 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8004 EXPECT_EQ(ERR_IO_PENDING,
8005 GroupNameTransactionHelper(tests[i].url, session));
8006 if (tests[i].ssl)
8007 EXPECT_EQ(tests[i].expected_group_name,
8008 ssl_conn_pool->last_group_name_received());
8009 else
8010 EXPECT_EQ(tests[i].expected_group_name,
8011 transport_conn_pool->last_group_name_received());
8016 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
8017 const GroupNameTest tests[] = {
8019 "http_proxy",
8020 "http://www.example.org/http_proxy_normal",
8021 "www.example.org:80",
8022 false,
8025 // SSL Tests
8027 "http_proxy",
8028 "https://www.example.org/http_connect_ssl",
8029 "ssl/www.example.org:443",
8030 true,
8034 "http_proxy",
8035 "http://host.with.alternate/direct",
8036 "ssl/host.with.alternate:443",
8037 true,
8041 "http_proxy",
8042 "ftp://ftp.google.com/http_proxy_normal",
8043 "ftp/ftp.google.com:21",
8044 false,
8048 session_deps_.use_alternate_protocols = true;
8050 for (size_t i = 0; i < arraysize(tests); ++i) {
8051 session_deps_.proxy_service.reset(
8052 ProxyService::CreateFixed(tests[i].proxy_server));
8053 scoped_refptr<HttpNetworkSession> session(
8054 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8056 HttpNetworkSessionPeer peer(session);
8058 HostPortPair proxy_host("http_proxy", 80);
8059 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
8060 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
8061 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8062 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8064 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8065 new MockClientSocketPoolManager);
8066 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8067 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8068 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8070 EXPECT_EQ(ERR_IO_PENDING,
8071 GroupNameTransactionHelper(tests[i].url, session));
8072 if (tests[i].ssl)
8073 EXPECT_EQ(tests[i].expected_group_name,
8074 ssl_conn_pool->last_group_name_received());
8075 else
8076 EXPECT_EQ(tests[i].expected_group_name,
8077 http_proxy_pool->last_group_name_received());
8081 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
8082 const GroupNameTest tests[] = {
8084 "socks4://socks_proxy:1080",
8085 "http://www.example.org/socks4_direct",
8086 "socks4/www.example.org:80",
8087 false,
8090 "socks5://socks_proxy:1080",
8091 "http://www.example.org/socks5_direct",
8092 "socks5/www.example.org:80",
8093 false,
8096 // SSL Tests
8098 "socks4://socks_proxy:1080",
8099 "https://www.example.org/socks4_ssl",
8100 "socks4/ssl/www.example.org:443",
8101 true,
8104 "socks5://socks_proxy:1080",
8105 "https://www.example.org/socks5_ssl",
8106 "socks5/ssl/www.example.org:443",
8107 true,
8111 "socks4://socks_proxy:1080",
8112 "http://host.with.alternate/direct",
8113 "socks4/ssl/host.with.alternate:443",
8114 true,
8118 session_deps_.use_alternate_protocols = true;
8120 for (size_t i = 0; i < arraysize(tests); ++i) {
8121 session_deps_.proxy_service.reset(
8122 ProxyService::CreateFixed(tests[i].proxy_server));
8123 scoped_refptr<HttpNetworkSession> session(
8124 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8126 HttpNetworkSessionPeer peer(session);
8128 HostPortPair proxy_host("socks_proxy", 1080);
8129 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
8130 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
8131 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8132 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8134 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8135 new MockClientSocketPoolManager);
8136 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8137 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8138 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8140 scoped_ptr<HttpTransaction> trans(
8141 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8143 EXPECT_EQ(ERR_IO_PENDING,
8144 GroupNameTransactionHelper(tests[i].url, session));
8145 if (tests[i].ssl)
8146 EXPECT_EQ(tests[i].expected_group_name,
8147 ssl_conn_pool->last_group_name_received());
8148 else
8149 EXPECT_EQ(tests[i].expected_group_name,
8150 socks_conn_pool->last_group_name_received());
8154 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
8155 HttpRequestInfo request;
8156 request.method = "GET";
8157 request.url = GURL("http://www.example.org/");
8159 session_deps_.proxy_service.reset(
8160 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8162 // This simulates failure resolving all hostnames; that means we will fail
8163 // connecting to both proxies (myproxy:70 and foobar:80).
8164 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
8166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8167 scoped_ptr<HttpTransaction> trans(
8168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8170 TestCompletionCallback callback;
8172 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8173 EXPECT_EQ(ERR_IO_PENDING, rv);
8175 rv = callback.WaitForResult();
8176 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
8179 // Base test to make sure that when the load flags for a request specify to
8180 // bypass the cache, the DNS cache is not used.
8181 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8182 int load_flags) {
8183 // Issue a request, asking to bypass the cache(s).
8184 HttpRequestInfo request;
8185 request.method = "GET";
8186 request.load_flags = load_flags;
8187 request.url = GURL("http://www.example.org/");
8189 // Select a host resolver that does caching.
8190 session_deps_.host_resolver.reset(new MockCachingHostResolver);
8192 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8193 scoped_ptr<HttpTransaction> trans(
8194 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8196 // Warm up the host cache so it has an entry for "www.example.org".
8197 AddressList addrlist;
8198 TestCompletionCallback callback;
8199 int rv = session_deps_.host_resolver->Resolve(
8200 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8201 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8202 EXPECT_EQ(ERR_IO_PENDING, rv);
8203 rv = callback.WaitForResult();
8204 EXPECT_EQ(OK, rv);
8206 // Verify that it was added to host cache, by doing a subsequent async lookup
8207 // and confirming it completes synchronously.
8208 rv = session_deps_.host_resolver->Resolve(
8209 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8210 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8211 ASSERT_EQ(OK, rv);
8213 // Inject a failure the next time that "www.example.org" is resolved. This way
8214 // we can tell if the next lookup hit the cache, or the "network".
8215 // (cache --> success, "network" --> failure).
8216 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
8218 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8219 // first read -- this won't be reached as the host resolution will fail first.
8220 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
8221 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8222 session_deps_.socket_factory->AddSocketDataProvider(&data);
8224 // Run the request.
8225 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8226 ASSERT_EQ(ERR_IO_PENDING, rv);
8227 rv = callback.WaitForResult();
8229 // If we bypassed the cache, we would have gotten a failure while resolving
8230 // "www.example.org".
8231 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8234 // There are multiple load flags that should trigger the host cache bypass.
8235 // Test each in isolation:
8236 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
8237 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8240 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
8241 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8244 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
8245 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8248 // Make sure we can handle an error when writing the request.
8249 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
8250 HttpRequestInfo request;
8251 request.method = "GET";
8252 request.url = GURL("http://www.foo.com/");
8253 request.load_flags = 0;
8255 MockWrite write_failure[] = {
8256 MockWrite(ASYNC, ERR_CONNECTION_RESET),
8258 StaticSocketDataProvider data(NULL, 0,
8259 write_failure, arraysize(write_failure));
8260 session_deps_.socket_factory->AddSocketDataProvider(&data);
8261 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8263 TestCompletionCallback callback;
8265 scoped_ptr<HttpTransaction> trans(
8266 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8268 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8269 EXPECT_EQ(ERR_IO_PENDING, rv);
8271 rv = callback.WaitForResult();
8272 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
8275 // Check that a connection closed after the start of the headers finishes ok.
8276 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
8277 HttpRequestInfo request;
8278 request.method = "GET";
8279 request.url = GURL("http://www.foo.com/");
8280 request.load_flags = 0;
8282 MockRead data_reads[] = {
8283 MockRead("HTTP/1."),
8284 MockRead(SYNCHRONOUS, OK),
8287 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8288 session_deps_.socket_factory->AddSocketDataProvider(&data);
8289 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8291 TestCompletionCallback callback;
8293 scoped_ptr<HttpTransaction> trans(
8294 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8296 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8297 EXPECT_EQ(ERR_IO_PENDING, rv);
8299 rv = callback.WaitForResult();
8300 EXPECT_EQ(OK, rv);
8302 const HttpResponseInfo* response = trans->GetResponseInfo();
8303 ASSERT_TRUE(response != NULL);
8305 EXPECT_TRUE(response->headers.get() != NULL);
8306 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8308 std::string response_data;
8309 rv = ReadTransaction(trans.get(), &response_data);
8310 EXPECT_EQ(OK, rv);
8311 EXPECT_EQ("", response_data);
8314 // Make sure that a dropped connection while draining the body for auth
8315 // restart does the right thing.
8316 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
8317 HttpRequestInfo request;
8318 request.method = "GET";
8319 request.url = GURL("http://www.example.org/");
8320 request.load_flags = 0;
8322 MockWrite data_writes1[] = {
8323 MockWrite(
8324 "GET / HTTP/1.1\r\n"
8325 "Host: www.example.org\r\n"
8326 "Connection: keep-alive\r\n\r\n"),
8329 MockRead data_reads1[] = {
8330 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8331 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8332 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8333 MockRead("Content-Length: 14\r\n\r\n"),
8334 MockRead("Unauth"),
8335 MockRead(ASYNC, ERR_CONNECTION_RESET),
8338 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8339 data_writes1, arraysize(data_writes1));
8340 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8342 // After calling trans->RestartWithAuth(), this is the request we should
8343 // be issuing -- the final header line contains the credentials.
8344 MockWrite data_writes2[] = {
8345 MockWrite(
8346 "GET / HTTP/1.1\r\n"
8347 "Host: www.example.org\r\n"
8348 "Connection: keep-alive\r\n"
8349 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8352 // Lastly, the server responds with the actual content.
8353 MockRead data_reads2[] = {
8354 MockRead("HTTP/1.1 200 OK\r\n"),
8355 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8356 MockRead("Content-Length: 100\r\n\r\n"),
8357 MockRead(SYNCHRONOUS, OK),
8360 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8361 data_writes2, arraysize(data_writes2));
8362 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8363 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8365 TestCompletionCallback callback1;
8367 scoped_ptr<HttpTransaction> trans(
8368 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8370 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8371 EXPECT_EQ(ERR_IO_PENDING, rv);
8373 rv = callback1.WaitForResult();
8374 EXPECT_EQ(OK, rv);
8376 const HttpResponseInfo* response = trans->GetResponseInfo();
8377 ASSERT_TRUE(response != NULL);
8378 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8380 TestCompletionCallback callback2;
8382 rv = trans->RestartWithAuth(
8383 AuthCredentials(kFoo, kBar), callback2.callback());
8384 EXPECT_EQ(ERR_IO_PENDING, rv);
8386 rv = callback2.WaitForResult();
8387 EXPECT_EQ(OK, rv);
8389 response = trans->GetResponseInfo();
8390 ASSERT_TRUE(response != NULL);
8391 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8392 EXPECT_EQ(100, response->headers->GetContentLength());
8395 // Test HTTPS connections going through a proxy that sends extra data.
8396 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8397 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8399 HttpRequestInfo request;
8400 request.method = "GET";
8401 request.url = GURL("https://www.example.org/");
8402 request.load_flags = 0;
8404 MockRead proxy_reads[] = {
8405 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8406 MockRead(SYNCHRONOUS, OK)
8409 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8410 SSLSocketDataProvider ssl(ASYNC, OK);
8412 session_deps_.socket_factory->AddSocketDataProvider(&data);
8413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8415 TestCompletionCallback callback;
8417 session_deps_.socket_factory->ResetNextMockIndexes();
8419 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8420 scoped_ptr<HttpTransaction> trans(
8421 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8423 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8424 EXPECT_EQ(ERR_IO_PENDING, rv);
8426 rv = callback.WaitForResult();
8427 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8430 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8431 HttpRequestInfo request;
8432 request.method = "GET";
8433 request.url = GURL("http://www.example.org/");
8434 request.load_flags = 0;
8436 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8437 scoped_ptr<HttpTransaction> trans(
8438 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8440 MockRead data_reads[] = {
8441 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8442 MockRead(SYNCHRONOUS, OK),
8445 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8446 session_deps_.socket_factory->AddSocketDataProvider(&data);
8448 TestCompletionCallback callback;
8450 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8451 EXPECT_EQ(ERR_IO_PENDING, rv);
8453 EXPECT_EQ(OK, callback.WaitForResult());
8455 const HttpResponseInfo* response = trans->GetResponseInfo();
8456 ASSERT_TRUE(response != NULL);
8458 EXPECT_TRUE(response->headers.get() != NULL);
8459 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8461 std::string response_data;
8462 rv = ReadTransaction(trans.get(), &response_data);
8463 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8466 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8467 base::FilePath temp_file_path;
8468 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8469 const uint64 kFakeSize = 100000; // file is actually blank
8470 UploadFileElementReader::ScopedOverridingContentLengthForTests
8471 overriding_content_length(kFakeSize);
8473 ScopedVector<UploadElementReader> element_readers;
8474 element_readers.push_back(
8475 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8476 temp_file_path,
8478 kuint64max,
8479 base::Time()));
8480 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8482 HttpRequestInfo request;
8483 request.method = "POST";
8484 request.url = GURL("http://www.example.org/upload");
8485 request.upload_data_stream = &upload_data_stream;
8486 request.load_flags = 0;
8488 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8489 scoped_ptr<HttpTransaction> trans(
8490 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8492 MockRead data_reads[] = {
8493 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8494 MockRead("hello world"),
8495 MockRead(SYNCHRONOUS, OK),
8497 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8498 session_deps_.socket_factory->AddSocketDataProvider(&data);
8500 TestCompletionCallback callback;
8502 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8503 EXPECT_EQ(ERR_IO_PENDING, rv);
8505 rv = callback.WaitForResult();
8506 EXPECT_EQ(OK, rv);
8508 const HttpResponseInfo* response = trans->GetResponseInfo();
8509 ASSERT_TRUE(response != NULL);
8511 EXPECT_TRUE(response->headers.get() != NULL);
8512 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8514 std::string response_data;
8515 rv = ReadTransaction(trans.get(), &response_data);
8516 EXPECT_EQ(OK, rv);
8517 EXPECT_EQ("hello world", response_data);
8519 base::DeleteFile(temp_file_path, false);
8522 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8523 base::FilePath temp_file;
8524 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8525 std::string temp_file_content("Unreadable file.");
8526 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8527 temp_file_content.length()));
8528 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
8530 ScopedVector<UploadElementReader> element_readers;
8531 element_readers.push_back(
8532 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8533 temp_file,
8535 kuint64max,
8536 base::Time()));
8537 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8539 HttpRequestInfo request;
8540 request.method = "POST";
8541 request.url = GURL("http://www.example.org/upload");
8542 request.upload_data_stream = &upload_data_stream;
8543 request.load_flags = 0;
8545 // If we try to upload an unreadable file, the transaction should fail.
8546 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8547 scoped_ptr<HttpTransaction> trans(
8548 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8550 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8551 session_deps_.socket_factory->AddSocketDataProvider(&data);
8553 TestCompletionCallback callback;
8555 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8556 EXPECT_EQ(ERR_IO_PENDING, rv);
8558 rv = callback.WaitForResult();
8559 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8561 const HttpResponseInfo* response = trans->GetResponseInfo();
8562 EXPECT_FALSE(response);
8564 base::DeleteFile(temp_file, false);
8567 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8568 class FakeUploadElementReader : public UploadElementReader {
8569 public:
8570 FakeUploadElementReader() {}
8571 ~FakeUploadElementReader() override {}
8573 const CompletionCallback& callback() const { return callback_; }
8575 // UploadElementReader overrides:
8576 int Init(const CompletionCallback& callback) override {
8577 callback_ = callback;
8578 return ERR_IO_PENDING;
8580 uint64 GetContentLength() const override { return 0; }
8581 uint64 BytesRemaining() const override { return 0; }
8582 int Read(IOBuffer* buf,
8583 int buf_length,
8584 const CompletionCallback& callback) override {
8585 return ERR_FAILED;
8588 private:
8589 CompletionCallback callback_;
8592 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8593 ScopedVector<UploadElementReader> element_readers;
8594 element_readers.push_back(fake_reader);
8595 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8597 HttpRequestInfo request;
8598 request.method = "POST";
8599 request.url = GURL("http://www.example.org/upload");
8600 request.upload_data_stream = &upload_data_stream;
8601 request.load_flags = 0;
8603 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8604 scoped_ptr<HttpTransaction> trans(
8605 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8607 StaticSocketDataProvider data;
8608 session_deps_.socket_factory->AddSocketDataProvider(&data);
8610 TestCompletionCallback callback;
8611 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8612 EXPECT_EQ(ERR_IO_PENDING, rv);
8613 base::MessageLoop::current()->RunUntilIdle();
8615 // Transaction is pending on request body initialization.
8616 ASSERT_FALSE(fake_reader->callback().is_null());
8618 // Return Init()'s result after the transaction gets destroyed.
8619 trans.reset();
8620 fake_reader->callback().Run(OK); // Should not crash.
8623 // Tests that changes to Auth realms are treated like auth rejections.
8624 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8626 HttpRequestInfo request;
8627 request.method = "GET";
8628 request.url = GURL("http://www.example.org/");
8629 request.load_flags = 0;
8631 // First transaction will request a resource and receive a Basic challenge
8632 // with realm="first_realm".
8633 MockWrite data_writes1[] = {
8634 MockWrite(
8635 "GET / HTTP/1.1\r\n"
8636 "Host: www.example.org\r\n"
8637 "Connection: keep-alive\r\n"
8638 "\r\n"),
8640 MockRead data_reads1[] = {
8641 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8642 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8643 "\r\n"),
8646 // After calling trans->RestartWithAuth(), provide an Authentication header
8647 // for first_realm. The server will reject and provide a challenge with
8648 // second_realm.
8649 MockWrite data_writes2[] = {
8650 MockWrite(
8651 "GET / HTTP/1.1\r\n"
8652 "Host: www.example.org\r\n"
8653 "Connection: keep-alive\r\n"
8654 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8655 "\r\n"),
8657 MockRead data_reads2[] = {
8658 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8659 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8660 "\r\n"),
8663 // This again fails, and goes back to first_realm. Make sure that the
8664 // entry is removed from cache.
8665 MockWrite data_writes3[] = {
8666 MockWrite(
8667 "GET / HTTP/1.1\r\n"
8668 "Host: www.example.org\r\n"
8669 "Connection: keep-alive\r\n"
8670 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8671 "\r\n"),
8673 MockRead data_reads3[] = {
8674 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8675 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8676 "\r\n"),
8679 // Try one last time (with the correct password) and get the resource.
8680 MockWrite data_writes4[] = {
8681 MockWrite(
8682 "GET / HTTP/1.1\r\n"
8683 "Host: www.example.org\r\n"
8684 "Connection: keep-alive\r\n"
8685 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8686 "\r\n"),
8688 MockRead data_reads4[] = {
8689 MockRead("HTTP/1.1 200 OK\r\n"
8690 "Content-Type: text/html; charset=iso-8859-1\r\n"
8691 "Content-Length: 5\r\n"
8692 "\r\n"
8693 "hello"),
8696 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8697 data_writes1, arraysize(data_writes1));
8698 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8699 data_writes2, arraysize(data_writes2));
8700 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8701 data_writes3, arraysize(data_writes3));
8702 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8703 data_writes4, arraysize(data_writes4));
8704 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8705 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8706 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8707 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8709 TestCompletionCallback callback1;
8711 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8712 scoped_ptr<HttpTransaction> trans(
8713 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8715 // Issue the first request with Authorize headers. There should be a
8716 // password prompt for first_realm waiting to be filled in after the
8717 // transaction completes.
8718 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8719 EXPECT_EQ(ERR_IO_PENDING, rv);
8720 rv = callback1.WaitForResult();
8721 EXPECT_EQ(OK, rv);
8722 const HttpResponseInfo* response = trans->GetResponseInfo();
8723 ASSERT_TRUE(response != NULL);
8724 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8725 ASSERT_FALSE(challenge == NULL);
8726 EXPECT_FALSE(challenge->is_proxy);
8727 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8728 EXPECT_EQ("first_realm", challenge->realm);
8729 EXPECT_EQ("basic", challenge->scheme);
8731 // Issue the second request with an incorrect password. There should be a
8732 // password prompt for second_realm waiting to be filled in after the
8733 // transaction completes.
8734 TestCompletionCallback callback2;
8735 rv = trans->RestartWithAuth(
8736 AuthCredentials(kFirst, kBaz), callback2.callback());
8737 EXPECT_EQ(ERR_IO_PENDING, rv);
8738 rv = callback2.WaitForResult();
8739 EXPECT_EQ(OK, rv);
8740 response = trans->GetResponseInfo();
8741 ASSERT_TRUE(response != NULL);
8742 challenge = response->auth_challenge.get();
8743 ASSERT_FALSE(challenge == NULL);
8744 EXPECT_FALSE(challenge->is_proxy);
8745 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8746 EXPECT_EQ("second_realm", challenge->realm);
8747 EXPECT_EQ("basic", challenge->scheme);
8749 // Issue the third request with another incorrect password. There should be
8750 // a password prompt for first_realm waiting to be filled in. If the password
8751 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8752 // first_realm was not correctly removed.
8753 TestCompletionCallback callback3;
8754 rv = trans->RestartWithAuth(
8755 AuthCredentials(kSecond, kFou), callback3.callback());
8756 EXPECT_EQ(ERR_IO_PENDING, rv);
8757 rv = callback3.WaitForResult();
8758 EXPECT_EQ(OK, rv);
8759 response = trans->GetResponseInfo();
8760 ASSERT_TRUE(response != NULL);
8761 challenge = response->auth_challenge.get();
8762 ASSERT_FALSE(challenge == NULL);
8763 EXPECT_FALSE(challenge->is_proxy);
8764 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8765 EXPECT_EQ("first_realm", challenge->realm);
8766 EXPECT_EQ("basic", challenge->scheme);
8768 // Issue the fourth request with the correct password and username.
8769 TestCompletionCallback callback4;
8770 rv = trans->RestartWithAuth(
8771 AuthCredentials(kFirst, kBar), callback4.callback());
8772 EXPECT_EQ(ERR_IO_PENDING, rv);
8773 rv = callback4.WaitForResult();
8774 EXPECT_EQ(OK, rv);
8775 response = trans->GetResponseInfo();
8776 ASSERT_TRUE(response != NULL);
8777 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8780 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8781 session_deps_.next_protos = SpdyNextProtos();
8782 session_deps_.use_alternate_protocols = true;
8784 std::string alternate_protocol_http_header =
8785 GetAlternateProtocolHttpHeader();
8787 MockRead data_reads[] = {
8788 MockRead("HTTP/1.1 200 OK\r\n"),
8789 MockRead(alternate_protocol_http_header.c_str()),
8790 MockRead("hello world"),
8791 MockRead(SYNCHRONOUS, OK),
8794 HttpRequestInfo request;
8795 request.method = "GET";
8796 request.url = GURL("http://www.example.org/");
8797 request.load_flags = 0;
8799 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8801 session_deps_.socket_factory->AddSocketDataProvider(&data);
8803 TestCompletionCallback callback;
8805 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8806 scoped_ptr<HttpTransaction> trans(
8807 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8809 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8810 EXPECT_EQ(ERR_IO_PENDING, rv);
8812 HostPortPair http_host_port_pair("www.example.org", 80);
8813 HttpServerProperties& http_server_properties =
8814 *session->http_server_properties();
8815 AlternativeService alternative_service =
8816 http_server_properties.GetAlternativeService(http_host_port_pair);
8817 EXPECT_EQ(alternative_service.protocol, UNINITIALIZED_ALTERNATE_PROTOCOL);
8819 EXPECT_EQ(OK, callback.WaitForResult());
8821 const HttpResponseInfo* response = trans->GetResponseInfo();
8822 ASSERT_TRUE(response != NULL);
8823 ASSERT_TRUE(response->headers.get() != NULL);
8824 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8825 EXPECT_FALSE(response->was_fetched_via_spdy);
8826 EXPECT_FALSE(response->was_npn_negotiated);
8828 std::string response_data;
8829 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8830 EXPECT_EQ("hello world", response_data);
8832 alternative_service =
8833 http_server_properties.GetAlternativeService(http_host_port_pair);
8834 EXPECT_EQ(443, alternative_service.port);
8835 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8836 alternative_service.protocol);
8839 TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
8840 session_deps_.next_protos = SpdyNextProtos();
8841 session_deps_.use_alternate_protocols = true;
8843 MockRead data_reads[] = {
8844 MockRead("HTTP/1.1 200 OK\r\n"),
8845 MockRead("Alternate-Protocol: \r\n\r\n"),
8846 MockRead("hello world"),
8847 MockRead(SYNCHRONOUS, OK),
8850 HttpRequestInfo request;
8851 request.method = "GET";
8852 request.url = GURL("http://www.example.org/");
8853 request.load_flags = 0;
8855 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8857 session_deps_.socket_factory->AddSocketDataProvider(&data);
8859 TestCompletionCallback callback;
8861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8863 HostPortPair http_host_port_pair("www.example.org", 80);
8864 HttpServerProperties& http_server_properties =
8865 *session->http_server_properties();
8866 AlternativeService alternative_service(QUIC, "", 80);
8867 http_server_properties.SetAlternativeService(http_host_port_pair,
8868 alternative_service, 1.0);
8870 alternative_service =
8871 http_server_properties.GetAlternativeService(http_host_port_pair);
8872 EXPECT_EQ(alternative_service.protocol, QUIC);
8874 scoped_ptr<HttpTransaction> trans(
8875 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8877 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8878 EXPECT_EQ(ERR_IO_PENDING, rv);
8880 EXPECT_EQ(OK, callback.WaitForResult());
8882 const HttpResponseInfo* response = trans->GetResponseInfo();
8883 ASSERT_TRUE(response != NULL);
8884 ASSERT_TRUE(response->headers.get() != NULL);
8885 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8886 EXPECT_FALSE(response->was_fetched_via_spdy);
8887 EXPECT_FALSE(response->was_npn_negotiated);
8889 std::string response_data;
8890 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8891 EXPECT_EQ("hello world", response_data);
8893 alternative_service =
8894 http_server_properties.GetAlternativeService(http_host_port_pair);
8895 EXPECT_EQ(alternative_service.protocol, UNINITIALIZED_ALTERNATE_PROTOCOL);
8898 TEST_P(HttpNetworkTransactionTest,
8899 MarkBrokenAlternateProtocolAndFallback) {
8900 session_deps_.use_alternate_protocols = true;
8902 HttpRequestInfo request;
8903 request.method = "GET";
8904 request.url = GURL("http://www.example.org/");
8905 request.load_flags = 0;
8907 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8908 StaticSocketDataProvider first_data;
8909 first_data.set_connect_data(mock_connect);
8910 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8912 MockRead data_reads[] = {
8913 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8914 MockRead("hello world"),
8915 MockRead(ASYNC, OK),
8917 StaticSocketDataProvider second_data(
8918 data_reads, arraysize(data_reads), NULL, 0);
8919 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8921 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8923 base::WeakPtr<HttpServerProperties> http_server_properties =
8924 session->http_server_properties();
8925 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
8926 // Port must be < 1024, or the header will be ignored (since initial port was
8927 // port 80 (another restricted port).
8928 AlternativeService alternative_service(
8929 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8930 666); /* port is ignored by MockConnect anyway */
8931 http_server_properties->SetAlternativeService(host_port_pair,
8932 alternative_service, 1.0);
8934 scoped_ptr<HttpTransaction> trans(
8935 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8936 TestCompletionCallback callback;
8938 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8939 EXPECT_EQ(ERR_IO_PENDING, rv);
8940 EXPECT_EQ(OK, callback.WaitForResult());
8942 const HttpResponseInfo* response = trans->GetResponseInfo();
8943 ASSERT_TRUE(response != NULL);
8944 ASSERT_TRUE(response->headers.get() != NULL);
8945 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8947 std::string response_data;
8948 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8949 EXPECT_EQ("hello world", response_data);
8951 alternative_service =
8952 http_server_properties->GetAlternativeService(host_port_pair);
8953 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL, alternative_service.protocol);
8954 EXPECT_TRUE(
8955 http_server_properties->IsAlternativeServiceBroken(alternative_service));
8958 TEST_P(HttpNetworkTransactionTest,
8959 AlternateProtocolPortRestrictedBlocked) {
8960 // Ensure that we're not allowed to redirect traffic via an alternate
8961 // protocol to an unrestricted (port >= 1024) when the original traffic was
8962 // on a restricted port (port < 1024). Ensure that we can redirect in all
8963 // other cases.
8964 session_deps_.use_alternate_protocols = true;
8966 HttpRequestInfo restricted_port_request;
8967 restricted_port_request.method = "GET";
8968 restricted_port_request.url = GURL("http://www.example.org:1023/");
8969 restricted_port_request.load_flags = 0;
8971 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8972 StaticSocketDataProvider first_data;
8973 first_data.set_connect_data(mock_connect);
8974 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8976 MockRead data_reads[] = {
8977 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8978 MockRead("hello world"),
8979 MockRead(ASYNC, OK),
8981 StaticSocketDataProvider second_data(
8982 data_reads, arraysize(data_reads), NULL, 0);
8983 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8985 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8987 base::WeakPtr<HttpServerProperties> http_server_properties =
8988 session->http_server_properties();
8989 const int kUnrestrictedAlternatePort = 1024;
8990 AlternativeService alternative_service(
8991 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8992 kUnrestrictedAlternatePort);
8993 http_server_properties->SetAlternativeService(
8994 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
8995 1.0);
8997 scoped_ptr<HttpTransaction> trans(
8998 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8999 TestCompletionCallback callback;
9001 int rv = trans->Start(
9002 &restricted_port_request,
9003 callback.callback(), BoundNetLog());
9004 EXPECT_EQ(ERR_IO_PENDING, rv);
9005 // Invalid change to unrestricted port should fail.
9006 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
9009 TEST_P(HttpNetworkTransactionTest,
9010 AlternateProtocolPortRestrictedPermitted) {
9011 // Ensure that we're allowed to redirect traffic via an alternate
9012 // protocol to an unrestricted (port >= 1024) when the original traffic was
9013 // on a restricted port (port < 1024) if we set
9014 // enable_user_alternate_protocol_ports.
9016 session_deps_.use_alternate_protocols = true;
9017 session_deps_.enable_user_alternate_protocol_ports = true;
9019 HttpRequestInfo restricted_port_request;
9020 restricted_port_request.method = "GET";
9021 restricted_port_request.url = GURL("http://www.example.org:1023/");
9022 restricted_port_request.load_flags = 0;
9024 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9025 StaticSocketDataProvider first_data;
9026 first_data.set_connect_data(mock_connect);
9027 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9029 MockRead data_reads[] = {
9030 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9031 MockRead("hello world"),
9032 MockRead(ASYNC, OK),
9034 StaticSocketDataProvider second_data(
9035 data_reads, arraysize(data_reads), NULL, 0);
9036 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9038 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9040 base::WeakPtr<HttpServerProperties> http_server_properties =
9041 session->http_server_properties();
9042 const int kUnrestrictedAlternatePort = 1024;
9043 AlternativeService alternative_service(
9044 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9045 kUnrestrictedAlternatePort);
9046 http_server_properties->SetAlternativeService(
9047 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9048 1.0);
9050 scoped_ptr<HttpTransaction> trans(
9051 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9052 TestCompletionCallback callback;
9054 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
9055 &restricted_port_request,
9056 callback.callback(), BoundNetLog()));
9057 // Change to unrestricted port should succeed.
9058 EXPECT_EQ(OK, callback.WaitForResult());
9061 TEST_P(HttpNetworkTransactionTest,
9062 AlternateProtocolPortRestrictedAllowed) {
9063 // Ensure that we're not allowed to redirect traffic via an alternate
9064 // protocol to an unrestricted (port >= 1024) when the original traffic was
9065 // on a restricted port (port < 1024). Ensure that we can redirect in all
9066 // other cases.
9067 session_deps_.use_alternate_protocols = true;
9069 HttpRequestInfo restricted_port_request;
9070 restricted_port_request.method = "GET";
9071 restricted_port_request.url = GURL("http://www.example.org:1023/");
9072 restricted_port_request.load_flags = 0;
9074 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9075 StaticSocketDataProvider first_data;
9076 first_data.set_connect_data(mock_connect);
9077 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9079 MockRead data_reads[] = {
9080 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9081 MockRead("hello world"),
9082 MockRead(ASYNC, OK),
9084 StaticSocketDataProvider second_data(
9085 data_reads, arraysize(data_reads), NULL, 0);
9086 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9090 base::WeakPtr<HttpServerProperties> http_server_properties =
9091 session->http_server_properties();
9092 const int kRestrictedAlternatePort = 80;
9093 AlternativeService alternative_service(
9094 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9095 kRestrictedAlternatePort);
9096 http_server_properties->SetAlternativeService(
9097 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9098 1.0);
9100 scoped_ptr<HttpTransaction> trans(
9101 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9102 TestCompletionCallback callback;
9104 int rv = trans->Start(
9105 &restricted_port_request,
9106 callback.callback(), BoundNetLog());
9107 EXPECT_EQ(ERR_IO_PENDING, rv);
9108 // Valid change to restricted port should pass.
9109 EXPECT_EQ(OK, callback.WaitForResult());
9112 TEST_P(HttpNetworkTransactionTest,
9113 AlternateProtocolPortUnrestrictedAllowed1) {
9114 // Ensure that we're not allowed to redirect traffic via an alternate
9115 // protocol to an unrestricted (port >= 1024) when the original traffic was
9116 // on a restricted port (port < 1024). Ensure that we can redirect in all
9117 // other cases.
9118 session_deps_.use_alternate_protocols = true;
9120 HttpRequestInfo unrestricted_port_request;
9121 unrestricted_port_request.method = "GET";
9122 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9123 unrestricted_port_request.load_flags = 0;
9125 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9126 StaticSocketDataProvider first_data;
9127 first_data.set_connect_data(mock_connect);
9128 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9130 MockRead data_reads[] = {
9131 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9132 MockRead("hello world"),
9133 MockRead(ASYNC, OK),
9135 StaticSocketDataProvider second_data(
9136 data_reads, arraysize(data_reads), NULL, 0);
9137 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9139 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9141 base::WeakPtr<HttpServerProperties> http_server_properties =
9142 session->http_server_properties();
9143 const int kRestrictedAlternatePort = 80;
9144 AlternativeService alternative_service(
9145 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9146 kRestrictedAlternatePort);
9147 http_server_properties->SetAlternativeService(
9148 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9149 1.0);
9151 scoped_ptr<HttpTransaction> trans(
9152 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9153 TestCompletionCallback callback;
9155 int rv = trans->Start(
9156 &unrestricted_port_request, callback.callback(), BoundNetLog());
9157 EXPECT_EQ(ERR_IO_PENDING, rv);
9158 // Valid change to restricted port should pass.
9159 EXPECT_EQ(OK, callback.WaitForResult());
9162 TEST_P(HttpNetworkTransactionTest,
9163 AlternateProtocolPortUnrestrictedAllowed2) {
9164 // Ensure that we're not allowed to redirect traffic via an alternate
9165 // protocol to an unrestricted (port >= 1024) when the original traffic was
9166 // on a restricted port (port < 1024). Ensure that we can redirect in all
9167 // other cases.
9168 session_deps_.use_alternate_protocols = true;
9170 HttpRequestInfo unrestricted_port_request;
9171 unrestricted_port_request.method = "GET";
9172 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9173 unrestricted_port_request.load_flags = 0;
9175 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9176 StaticSocketDataProvider first_data;
9177 first_data.set_connect_data(mock_connect);
9178 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9180 MockRead data_reads[] = {
9181 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9182 MockRead("hello world"),
9183 MockRead(ASYNC, OK),
9185 StaticSocketDataProvider second_data(
9186 data_reads, arraysize(data_reads), NULL, 0);
9187 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9189 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9191 base::WeakPtr<HttpServerProperties> http_server_properties =
9192 session->http_server_properties();
9193 const int kUnrestrictedAlternatePort = 1024;
9194 AlternativeService alternative_service(
9195 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9196 kUnrestrictedAlternatePort);
9197 http_server_properties->SetAlternativeService(
9198 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9199 1.0);
9201 scoped_ptr<HttpTransaction> trans(
9202 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9203 TestCompletionCallback callback;
9205 int rv = trans->Start(
9206 &unrestricted_port_request, callback.callback(), BoundNetLog());
9207 EXPECT_EQ(ERR_IO_PENDING, rv);
9208 // Valid change to an unrestricted port should pass.
9209 EXPECT_EQ(OK, callback.WaitForResult());
9212 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
9213 // Ensure that we're not allowed to redirect traffic via an alternate
9214 // protocol to an unsafe port, and that we resume the second
9215 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9216 session_deps_.use_alternate_protocols = true;
9218 HttpRequestInfo request;
9219 request.method = "GET";
9220 request.url = GURL("http://www.example.org/");
9221 request.load_flags = 0;
9223 // The alternate protocol request will error out before we attempt to connect,
9224 // so only the standard HTTP request will try to connect.
9225 MockRead data_reads[] = {
9226 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9227 MockRead("hello world"),
9228 MockRead(ASYNC, OK),
9230 StaticSocketDataProvider data(
9231 data_reads, arraysize(data_reads), NULL, 0);
9232 session_deps_.socket_factory->AddSocketDataProvider(&data);
9234 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9236 base::WeakPtr<HttpServerProperties> http_server_properties =
9237 session->http_server_properties();
9238 const int kUnsafePort = 7;
9239 AlternativeService alternative_service(
9240 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9241 kUnsafePort);
9242 http_server_properties->SetAlternativeService(
9243 HostPortPair::FromURL(request.url), alternative_service, 1.0);
9245 scoped_ptr<HttpTransaction> trans(
9246 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9247 TestCompletionCallback callback;
9249 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9250 EXPECT_EQ(ERR_IO_PENDING, rv);
9251 // The HTTP request should succeed.
9252 EXPECT_EQ(OK, callback.WaitForResult());
9254 // Disable alternate protocol before the asserts.
9255 // HttpStreamFactory::set_use_alternate_protocols(false);
9257 const HttpResponseInfo* response = trans->GetResponseInfo();
9258 ASSERT_TRUE(response != NULL);
9259 ASSERT_TRUE(response->headers.get() != NULL);
9260 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9262 std::string response_data;
9263 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9264 EXPECT_EQ("hello world", response_data);
9267 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
9268 session_deps_.use_alternate_protocols = true;
9269 session_deps_.next_protos = SpdyNextProtos();
9271 HttpRequestInfo request;
9272 request.method = "GET";
9273 request.url = GURL("http://www.example.org/");
9274 request.load_flags = 0;
9276 std::string alternate_protocol_http_header =
9277 GetAlternateProtocolHttpHeader();
9279 MockRead data_reads[] = {
9280 MockRead("HTTP/1.1 200 OK\r\n"),
9281 MockRead(alternate_protocol_http_header.c_str()),
9282 MockRead("hello world"),
9283 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9284 MockRead(ASYNC, OK)
9287 StaticSocketDataProvider first_transaction(
9288 data_reads, arraysize(data_reads), NULL, 0);
9289 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9291 SSLSocketDataProvider ssl(ASYNC, OK);
9292 ssl.SetNextProto(GetParam());
9293 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9294 ASSERT_TRUE(ssl.cert.get());
9295 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9297 scoped_ptr<SpdyFrame> req(
9298 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9299 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9301 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9302 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9303 MockRead spdy_reads[] = {
9304 CreateMockRead(*resp),
9305 CreateMockRead(*data),
9306 MockRead(ASYNC, 0, 0),
9309 DelayedSocketData spdy_data(
9310 1, // wait for one write to finish before reading.
9311 spdy_reads, arraysize(spdy_reads),
9312 spdy_writes, arraysize(spdy_writes));
9313 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9315 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9316 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9317 NULL, 0, NULL, 0);
9318 hanging_non_alternate_protocol_socket.set_connect_data(
9319 never_finishing_connect);
9320 session_deps_.socket_factory->AddSocketDataProvider(
9321 &hanging_non_alternate_protocol_socket);
9323 TestCompletionCallback callback;
9325 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9326 scoped_ptr<HttpTransaction> trans(
9327 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9329 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9330 EXPECT_EQ(ERR_IO_PENDING, rv);
9331 EXPECT_EQ(OK, callback.WaitForResult());
9333 const HttpResponseInfo* response = trans->GetResponseInfo();
9334 ASSERT_TRUE(response != NULL);
9335 ASSERT_TRUE(response->headers.get() != NULL);
9336 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9338 std::string response_data;
9339 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9340 EXPECT_EQ("hello world", response_data);
9342 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9344 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9345 EXPECT_EQ(ERR_IO_PENDING, rv);
9346 EXPECT_EQ(OK, callback.WaitForResult());
9348 response = trans->GetResponseInfo();
9349 ASSERT_TRUE(response != NULL);
9350 ASSERT_TRUE(response->headers.get() != NULL);
9351 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9352 EXPECT_TRUE(response->was_fetched_via_spdy);
9353 EXPECT_TRUE(response->was_npn_negotiated);
9355 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9356 EXPECT_EQ("hello!", response_data);
9359 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
9360 session_deps_.use_alternate_protocols = true;
9361 session_deps_.next_protos = SpdyNextProtos();
9363 HttpRequestInfo request;
9364 request.method = "GET";
9365 request.url = GURL("http://www.example.org/");
9366 request.load_flags = 0;
9368 std::string alternate_protocol_http_header =
9369 GetAlternateProtocolHttpHeader();
9371 MockRead data_reads[] = {
9372 MockRead("HTTP/1.1 200 OK\r\n"),
9373 MockRead(alternate_protocol_http_header.c_str()),
9374 MockRead("hello world"),
9375 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9376 MockRead(ASYNC, OK),
9379 StaticSocketDataProvider first_transaction(
9380 data_reads, arraysize(data_reads), NULL, 0);
9381 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9382 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9384 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9385 StaticSocketDataProvider hanging_socket(
9386 NULL, 0, NULL, 0);
9387 hanging_socket.set_connect_data(never_finishing_connect);
9388 // Socket 2 and 3 are the hanging Alternate-Protocol and
9389 // non-Alternate-Protocol jobs from the 2nd transaction.
9390 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9391 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9393 SSLSocketDataProvider ssl(ASYNC, OK);
9394 ssl.SetNextProto(GetParam());
9395 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9396 ASSERT_TRUE(ssl.cert.get());
9397 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9399 scoped_ptr<SpdyFrame> req1(
9400 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9401 scoped_ptr<SpdyFrame> req2(
9402 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9403 MockWrite spdy_writes[] = {
9404 CreateMockWrite(*req1),
9405 CreateMockWrite(*req2),
9407 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9408 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
9409 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9410 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9411 MockRead spdy_reads[] = {
9412 CreateMockRead(*resp1),
9413 CreateMockRead(*data1),
9414 CreateMockRead(*resp2),
9415 CreateMockRead(*data2),
9416 MockRead(ASYNC, 0, 0),
9419 DelayedSocketData spdy_data(
9420 2, // wait for writes to finish before reading.
9421 spdy_reads, arraysize(spdy_reads),
9422 spdy_writes, arraysize(spdy_writes));
9423 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9424 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9426 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9427 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9429 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9430 TestCompletionCallback callback1;
9431 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9433 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
9434 EXPECT_EQ(ERR_IO_PENDING, rv);
9435 EXPECT_EQ(OK, callback1.WaitForResult());
9437 const HttpResponseInfo* response = trans1.GetResponseInfo();
9438 ASSERT_TRUE(response != NULL);
9439 ASSERT_TRUE(response->headers.get() != NULL);
9440 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9442 std::string response_data;
9443 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9444 EXPECT_EQ("hello world", response_data);
9446 TestCompletionCallback callback2;
9447 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9448 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
9449 EXPECT_EQ(ERR_IO_PENDING, rv);
9451 TestCompletionCallback callback3;
9452 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
9453 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
9454 EXPECT_EQ(ERR_IO_PENDING, rv);
9456 EXPECT_EQ(OK, callback2.WaitForResult());
9457 EXPECT_EQ(OK, callback3.WaitForResult());
9459 response = trans2.GetResponseInfo();
9460 ASSERT_TRUE(response != NULL);
9461 ASSERT_TRUE(response->headers.get() != NULL);
9462 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9463 EXPECT_TRUE(response->was_fetched_via_spdy);
9464 EXPECT_TRUE(response->was_npn_negotiated);
9465 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9466 EXPECT_EQ("hello!", response_data);
9468 response = trans3.GetResponseInfo();
9469 ASSERT_TRUE(response != NULL);
9470 ASSERT_TRUE(response->headers.get() != NULL);
9471 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9472 EXPECT_TRUE(response->was_fetched_via_spdy);
9473 EXPECT_TRUE(response->was_npn_negotiated);
9474 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9475 EXPECT_EQ("hello!", response_data);
9478 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9479 session_deps_.use_alternate_protocols = true;
9480 session_deps_.next_protos = SpdyNextProtos();
9482 HttpRequestInfo request;
9483 request.method = "GET";
9484 request.url = GURL("http://www.example.org/");
9485 request.load_flags = 0;
9487 std::string alternate_protocol_http_header =
9488 GetAlternateProtocolHttpHeader();
9490 MockRead data_reads[] = {
9491 MockRead("HTTP/1.1 200 OK\r\n"),
9492 MockRead(alternate_protocol_http_header.c_str()),
9493 MockRead("hello world"),
9494 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9495 MockRead(ASYNC, OK),
9498 StaticSocketDataProvider first_transaction(
9499 data_reads, arraysize(data_reads), NULL, 0);
9500 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9502 SSLSocketDataProvider ssl(ASYNC, OK);
9503 ssl.SetNextProto(GetParam());
9504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9506 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9507 StaticSocketDataProvider hanging_alternate_protocol_socket(
9508 NULL, 0, NULL, 0);
9509 hanging_alternate_protocol_socket.set_connect_data(
9510 never_finishing_connect);
9511 session_deps_.socket_factory->AddSocketDataProvider(
9512 &hanging_alternate_protocol_socket);
9514 // 2nd request is just a copy of the first one, over HTTP again.
9515 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9517 TestCompletionCallback callback;
9519 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9520 scoped_ptr<HttpTransaction> trans(
9521 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9523 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9524 EXPECT_EQ(ERR_IO_PENDING, rv);
9525 EXPECT_EQ(OK, callback.WaitForResult());
9527 const HttpResponseInfo* response = trans->GetResponseInfo();
9528 ASSERT_TRUE(response != NULL);
9529 ASSERT_TRUE(response->headers.get() != NULL);
9530 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9532 std::string response_data;
9533 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9534 EXPECT_EQ("hello world", response_data);
9536 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9538 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9539 EXPECT_EQ(ERR_IO_PENDING, rv);
9540 EXPECT_EQ(OK, callback.WaitForResult());
9542 response = trans->GetResponseInfo();
9543 ASSERT_TRUE(response != NULL);
9544 ASSERT_TRUE(response->headers.get() != NULL);
9545 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9546 EXPECT_FALSE(response->was_fetched_via_spdy);
9547 EXPECT_FALSE(response->was_npn_negotiated);
9549 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9550 EXPECT_EQ("hello world", response_data);
9553 class CapturingProxyResolver : public ProxyResolver {
9554 public:
9555 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9556 ~CapturingProxyResolver() override {}
9558 int GetProxyForURL(const GURL& url,
9559 ProxyInfo* results,
9560 const CompletionCallback& callback,
9561 RequestHandle* request,
9562 const BoundNetLog& net_log) override {
9563 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9564 HostPortPair("myproxy", 80));
9565 results->UseProxyServer(proxy_server);
9566 resolved_.push_back(url);
9567 return OK;
9570 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
9572 LoadState GetLoadState(RequestHandle request) const override {
9573 NOTREACHED();
9574 return LOAD_STATE_IDLE;
9577 void CancelSetPacScript() override { NOTREACHED(); }
9579 int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9580 const CompletionCallback& /*callback*/) override {
9581 return OK;
9584 const std::vector<GURL>& resolved() const { return resolved_; }
9586 private:
9587 std::vector<GURL> resolved_;
9589 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9592 class CapturingProxyResolverFactory : public ProxyResolverFactory {
9593 public:
9594 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
9595 : ProxyResolverFactory(false), resolver_(resolver) {}
9597 int CreateProxyResolver(
9598 const scoped_refptr<ProxyResolverScriptData>& pac_script,
9599 scoped_ptr<ProxyResolver>* resolver,
9600 const net::CompletionCallback& callback,
9601 scoped_ptr<Request>* request) override {
9602 resolver->reset(new ForwardingProxyResolver(resolver_));
9603 return OK;
9606 private:
9607 ProxyResolver* resolver_;
9610 TEST_P(HttpNetworkTransactionTest,
9611 UseAlternateProtocolForTunneledNpnSpdy) {
9612 session_deps_.use_alternate_protocols = true;
9613 session_deps_.next_protos = SpdyNextProtos();
9615 ProxyConfig proxy_config;
9616 proxy_config.set_auto_detect(true);
9617 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9619 CapturingProxyResolver capturing_proxy_resolver;
9620 session_deps_.proxy_service.reset(new ProxyService(
9621 new ProxyConfigServiceFixed(proxy_config),
9622 make_scoped_ptr(
9623 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
9624 NULL));
9625 TestNetLog net_log;
9626 session_deps_.net_log = &net_log;
9628 HttpRequestInfo request;
9629 request.method = "GET";
9630 request.url = GURL("http://www.example.org/");
9631 request.load_flags = 0;
9633 std::string alternate_protocol_http_header =
9634 GetAlternateProtocolHttpHeader();
9636 MockRead data_reads[] = {
9637 MockRead("HTTP/1.1 200 OK\r\n"),
9638 MockRead(alternate_protocol_http_header.c_str()),
9639 MockRead("hello world"),
9640 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9641 MockRead(ASYNC, OK),
9644 StaticSocketDataProvider first_transaction(
9645 data_reads, arraysize(data_reads), NULL, 0);
9646 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9648 SSLSocketDataProvider ssl(ASYNC, OK);
9649 ssl.SetNextProto(GetParam());
9650 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9651 ASSERT_TRUE(ssl.cert.get());
9652 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9654 scoped_ptr<SpdyFrame> req(
9655 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9656 MockWrite spdy_writes[] = {
9657 MockWrite(
9658 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9659 "Host: www.example.org\r\n"
9660 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9661 CreateMockWrite(*req), // 3
9664 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9666 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9667 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9668 MockRead spdy_reads[] = {
9669 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
9670 CreateMockRead(*resp.get(), 4), // 2, 4
9671 CreateMockRead(*data.get(), 4), // 5
9672 MockRead(ASYNC, 0, 0, 4), // 6
9675 OrderedSocketData spdy_data(
9676 spdy_reads, arraysize(spdy_reads),
9677 spdy_writes, arraysize(spdy_writes));
9678 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9680 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9681 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9682 NULL, 0, NULL, 0);
9683 hanging_non_alternate_protocol_socket.set_connect_data(
9684 never_finishing_connect);
9685 session_deps_.socket_factory->AddSocketDataProvider(
9686 &hanging_non_alternate_protocol_socket);
9688 TestCompletionCallback callback;
9690 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9691 scoped_ptr<HttpTransaction> trans(
9692 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9694 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9695 EXPECT_EQ(ERR_IO_PENDING, rv);
9696 EXPECT_EQ(OK, callback.WaitForResult());
9698 const HttpResponseInfo* response = trans->GetResponseInfo();
9699 ASSERT_TRUE(response != NULL);
9700 ASSERT_TRUE(response->headers.get() != NULL);
9701 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9702 EXPECT_FALSE(response->was_fetched_via_spdy);
9703 EXPECT_FALSE(response->was_npn_negotiated);
9705 std::string response_data;
9706 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9707 EXPECT_EQ("hello world", response_data);
9709 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9711 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9712 EXPECT_EQ(ERR_IO_PENDING, rv);
9713 EXPECT_EQ(OK, callback.WaitForResult());
9715 response = trans->GetResponseInfo();
9716 ASSERT_TRUE(response != NULL);
9717 ASSERT_TRUE(response->headers.get() != NULL);
9718 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9719 EXPECT_TRUE(response->was_fetched_via_spdy);
9720 EXPECT_TRUE(response->was_npn_negotiated);
9722 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9723 EXPECT_EQ("hello!", response_data);
9724 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
9725 EXPECT_EQ("http://www.example.org/",
9726 capturing_proxy_resolver.resolved()[0].spec());
9727 EXPECT_EQ("https://www.example.org/",
9728 capturing_proxy_resolver.resolved()[1].spec());
9730 LoadTimingInfo load_timing_info;
9731 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9732 TestLoadTimingNotReusedWithPac(load_timing_info,
9733 CONNECT_TIMING_HAS_SSL_TIMES);
9736 TEST_P(HttpNetworkTransactionTest,
9737 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9738 session_deps_.use_alternate_protocols = true;
9739 session_deps_.next_protos = SpdyNextProtos();
9741 HttpRequestInfo request;
9742 request.method = "GET";
9743 request.url = GURL("http://www.example.org/");
9744 request.load_flags = 0;
9746 std::string alternate_protocol_http_header =
9747 GetAlternateProtocolHttpHeader();
9749 MockRead data_reads[] = {
9750 MockRead("HTTP/1.1 200 OK\r\n"),
9751 MockRead(alternate_protocol_http_header.c_str()),
9752 MockRead("hello world"),
9753 MockRead(ASYNC, OK),
9756 StaticSocketDataProvider first_transaction(
9757 data_reads, arraysize(data_reads), NULL, 0);
9758 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9760 SSLSocketDataProvider ssl(ASYNC, OK);
9761 ssl.SetNextProto(GetParam());
9762 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9763 ASSERT_TRUE(ssl.cert.get());
9764 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9766 scoped_ptr<SpdyFrame> req(
9767 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9768 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9770 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9771 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9772 MockRead spdy_reads[] = {
9773 CreateMockRead(*resp),
9774 CreateMockRead(*data),
9775 MockRead(ASYNC, 0, 0),
9778 DelayedSocketData spdy_data(
9779 1, // wait for one write to finish before reading.
9780 spdy_reads, arraysize(spdy_reads),
9781 spdy_writes, arraysize(spdy_writes));
9782 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9784 TestCompletionCallback callback;
9786 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9788 scoped_ptr<HttpTransaction> trans(
9789 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9791 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9792 EXPECT_EQ(ERR_IO_PENDING, rv);
9793 EXPECT_EQ(OK, callback.WaitForResult());
9795 const HttpResponseInfo* response = trans->GetResponseInfo();
9796 ASSERT_TRUE(response != NULL);
9797 ASSERT_TRUE(response->headers.get() != NULL);
9798 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9800 std::string response_data;
9801 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9802 EXPECT_EQ("hello world", response_data);
9804 // Set up an initial SpdySession in the pool to reuse.
9805 HostPortPair host_port_pair("www.example.org", 443);
9806 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9807 PRIVACY_MODE_DISABLED);
9808 base::WeakPtr<SpdySession> spdy_session =
9809 CreateSecureSpdySession(session, key, BoundNetLog());
9811 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9813 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9814 EXPECT_EQ(ERR_IO_PENDING, rv);
9815 EXPECT_EQ(OK, callback.WaitForResult());
9817 response = trans->GetResponseInfo();
9818 ASSERT_TRUE(response != NULL);
9819 ASSERT_TRUE(response->headers.get() != NULL);
9820 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9821 EXPECT_TRUE(response->was_fetched_via_spdy);
9822 EXPECT_TRUE(response->was_npn_negotiated);
9824 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9825 EXPECT_EQ("hello!", response_data);
9828 // GenerateAuthToken is a mighty big test.
9829 // It tests all permutation of GenerateAuthToken behavior:
9830 // - Synchronous and Asynchronous completion.
9831 // - OK or error on completion.
9832 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9833 // - HTTP or HTTPS backend (to include proxy tunneling).
9834 // - Non-authenticating and authenticating backend.
9836 // In all, there are 44 reasonable permuations (for example, if there are
9837 // problems generating an auth token for an authenticating proxy, we don't
9838 // need to test all permutations of the backend server).
9840 // The test proceeds by going over each of the configuration cases, and
9841 // potentially running up to three rounds in each of the tests. The TestConfig
9842 // specifies both the configuration for the test as well as the expectations
9843 // for the results.
9844 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9845 static const char kServer[] = "http://www.example.com";
9846 static const char kSecureServer[] = "https://www.example.com";
9847 static const char kProxy[] = "myproxy:70";
9848 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9850 enum AuthTiming {
9851 AUTH_NONE,
9852 AUTH_SYNC,
9853 AUTH_ASYNC,
9856 const MockWrite kGet(
9857 "GET / HTTP/1.1\r\n"
9858 "Host: www.example.com\r\n"
9859 "Connection: keep-alive\r\n\r\n");
9860 const MockWrite kGetProxy(
9861 "GET http://www.example.com/ HTTP/1.1\r\n"
9862 "Host: www.example.com\r\n"
9863 "Proxy-Connection: keep-alive\r\n\r\n");
9864 const MockWrite kGetAuth(
9865 "GET / HTTP/1.1\r\n"
9866 "Host: www.example.com\r\n"
9867 "Connection: keep-alive\r\n"
9868 "Authorization: auth_token\r\n\r\n");
9869 const MockWrite kGetProxyAuth(
9870 "GET http://www.example.com/ HTTP/1.1\r\n"
9871 "Host: www.example.com\r\n"
9872 "Proxy-Connection: keep-alive\r\n"
9873 "Proxy-Authorization: auth_token\r\n\r\n");
9874 const MockWrite kGetAuthThroughProxy(
9875 "GET http://www.example.com/ HTTP/1.1\r\n"
9876 "Host: www.example.com\r\n"
9877 "Proxy-Connection: keep-alive\r\n"
9878 "Authorization: auth_token\r\n\r\n");
9879 const MockWrite kGetAuthWithProxyAuth(
9880 "GET http://www.example.com/ HTTP/1.1\r\n"
9881 "Host: www.example.com\r\n"
9882 "Proxy-Connection: keep-alive\r\n"
9883 "Proxy-Authorization: auth_token\r\n"
9884 "Authorization: auth_token\r\n\r\n");
9885 const MockWrite kConnect(
9886 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9887 "Host: www.example.com\r\n"
9888 "Proxy-Connection: keep-alive\r\n\r\n");
9889 const MockWrite kConnectProxyAuth(
9890 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9891 "Host: www.example.com\r\n"
9892 "Proxy-Connection: keep-alive\r\n"
9893 "Proxy-Authorization: auth_token\r\n\r\n");
9895 const MockRead kSuccess(
9896 "HTTP/1.1 200 OK\r\n"
9897 "Content-Type: text/html; charset=iso-8859-1\r\n"
9898 "Content-Length: 3\r\n\r\n"
9899 "Yes");
9900 const MockRead kFailure(
9901 "Should not be called.");
9902 const MockRead kServerChallenge(
9903 "HTTP/1.1 401 Unauthorized\r\n"
9904 "WWW-Authenticate: Mock realm=server\r\n"
9905 "Content-Type: text/html; charset=iso-8859-1\r\n"
9906 "Content-Length: 14\r\n\r\n"
9907 "Unauthorized\r\n");
9908 const MockRead kProxyChallenge(
9909 "HTTP/1.1 407 Unauthorized\r\n"
9910 "Proxy-Authenticate: Mock realm=proxy\r\n"
9911 "Proxy-Connection: close\r\n"
9912 "Content-Type: text/html; charset=iso-8859-1\r\n"
9913 "Content-Length: 14\r\n\r\n"
9914 "Unauthorized\r\n");
9915 const MockRead kProxyConnected(
9916 "HTTP/1.1 200 Connection Established\r\n\r\n");
9918 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9919 // no constructors, but the C++ compiler on Windows warns about
9920 // unspecified data in compound literals. So, moved to using constructors,
9921 // and TestRound's created with the default constructor should not be used.
9922 struct TestRound {
9923 TestRound()
9924 : expected_rv(ERR_UNEXPECTED),
9925 extra_write(NULL),
9926 extra_read(NULL) {
9928 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9929 int expected_rv_arg)
9930 : write(write_arg),
9931 read(read_arg),
9932 expected_rv(expected_rv_arg),
9933 extra_write(NULL),
9934 extra_read(NULL) {
9936 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9937 int expected_rv_arg, const MockWrite* extra_write_arg,
9938 const MockRead* extra_read_arg)
9939 : write(write_arg),
9940 read(read_arg),
9941 expected_rv(expected_rv_arg),
9942 extra_write(extra_write_arg),
9943 extra_read(extra_read_arg) {
9945 MockWrite write;
9946 MockRead read;
9947 int expected_rv;
9948 const MockWrite* extra_write;
9949 const MockRead* extra_read;
9952 static const int kNoSSL = 500;
9954 struct TestConfig {
9955 const char* const proxy_url;
9956 AuthTiming proxy_auth_timing;
9957 int proxy_auth_rv;
9958 const char* const server_url;
9959 AuthTiming server_auth_timing;
9960 int server_auth_rv;
9961 int num_auth_rounds;
9962 int first_ssl_round;
9963 TestRound rounds[3];
9964 } test_configs[] = {
9965 // Non-authenticating HTTP server with a direct connection.
9966 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9967 { TestRound(kGet, kSuccess, OK)}},
9968 // Authenticating HTTP server with a direct connection.
9969 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9970 { TestRound(kGet, kServerChallenge, OK),
9971 TestRound(kGetAuth, kSuccess, OK)}},
9972 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9973 { TestRound(kGet, kServerChallenge, OK),
9974 TestRound(kGetAuth, kFailure, kAuthErr)}},
9975 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9976 { TestRound(kGet, kServerChallenge, OK),
9977 TestRound(kGetAuth, kSuccess, OK)}},
9978 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9979 { TestRound(kGet, kServerChallenge, OK),
9980 TestRound(kGetAuth, kFailure, kAuthErr)}},
9981 // Non-authenticating HTTP server through a non-authenticating proxy.
9982 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9983 { TestRound(kGetProxy, kSuccess, OK)}},
9984 // Authenticating HTTP server through a non-authenticating proxy.
9985 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9986 { TestRound(kGetProxy, kServerChallenge, OK),
9987 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9988 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9989 { TestRound(kGetProxy, kServerChallenge, OK),
9990 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9991 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9992 { TestRound(kGetProxy, kServerChallenge, OK),
9993 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9994 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9995 { TestRound(kGetProxy, kServerChallenge, OK),
9996 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9997 // Non-authenticating HTTP server through an authenticating proxy.
9998 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9999 { TestRound(kGetProxy, kProxyChallenge, OK),
10000 TestRound(kGetProxyAuth, kSuccess, OK)}},
10001 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10002 { TestRound(kGetProxy, kProxyChallenge, OK),
10003 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10004 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10005 { TestRound(kGetProxy, kProxyChallenge, OK),
10006 TestRound(kGetProxyAuth, kSuccess, OK)}},
10007 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10008 { TestRound(kGetProxy, kProxyChallenge, OK),
10009 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10010 // Authenticating HTTP server through an authenticating proxy.
10011 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10012 { TestRound(kGetProxy, kProxyChallenge, OK),
10013 TestRound(kGetProxyAuth, kServerChallenge, OK),
10014 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10015 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10016 { TestRound(kGetProxy, kProxyChallenge, OK),
10017 TestRound(kGetProxyAuth, kServerChallenge, OK),
10018 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10019 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10020 { TestRound(kGetProxy, kProxyChallenge, OK),
10021 TestRound(kGetProxyAuth, kServerChallenge, OK),
10022 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10023 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10024 { TestRound(kGetProxy, kProxyChallenge, OK),
10025 TestRound(kGetProxyAuth, kServerChallenge, OK),
10026 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10027 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10028 { TestRound(kGetProxy, kProxyChallenge, OK),
10029 TestRound(kGetProxyAuth, kServerChallenge, OK),
10030 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10031 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10032 { TestRound(kGetProxy, kProxyChallenge, OK),
10033 TestRound(kGetProxyAuth, kServerChallenge, OK),
10034 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10035 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10036 { TestRound(kGetProxy, kProxyChallenge, OK),
10037 TestRound(kGetProxyAuth, kServerChallenge, OK),
10038 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10039 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10040 { TestRound(kGetProxy, kProxyChallenge, OK),
10041 TestRound(kGetProxyAuth, kServerChallenge, OK),
10042 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10043 // Non-authenticating HTTPS server with a direct connection.
10044 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10045 { TestRound(kGet, kSuccess, OK)}},
10046 // Authenticating HTTPS server with a direct connection.
10047 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10048 { TestRound(kGet, kServerChallenge, OK),
10049 TestRound(kGetAuth, kSuccess, OK)}},
10050 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10051 { TestRound(kGet, kServerChallenge, OK),
10052 TestRound(kGetAuth, kFailure, kAuthErr)}},
10053 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10054 { TestRound(kGet, kServerChallenge, OK),
10055 TestRound(kGetAuth, kSuccess, OK)}},
10056 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10057 { TestRound(kGet, kServerChallenge, OK),
10058 TestRound(kGetAuth, kFailure, kAuthErr)}},
10059 // Non-authenticating HTTPS server with a non-authenticating proxy.
10060 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10061 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
10062 // Authenticating HTTPS server through a non-authenticating proxy.
10063 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10064 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10065 TestRound(kGetAuth, kSuccess, OK)}},
10066 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10067 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10068 TestRound(kGetAuth, kFailure, kAuthErr)}},
10069 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10070 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10071 TestRound(kGetAuth, kSuccess, OK)}},
10072 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10073 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10074 TestRound(kGetAuth, kFailure, kAuthErr)}},
10075 // Non-Authenticating HTTPS server through an authenticating proxy.
10076 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10077 { TestRound(kConnect, kProxyChallenge, OK),
10078 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10079 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10080 { TestRound(kConnect, kProxyChallenge, OK),
10081 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10082 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10083 { TestRound(kConnect, kProxyChallenge, OK),
10084 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10085 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10086 { TestRound(kConnect, kProxyChallenge, OK),
10087 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10088 // Authenticating HTTPS server through an authenticating proxy.
10089 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10090 { TestRound(kConnect, kProxyChallenge, OK),
10091 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10092 &kGet, &kServerChallenge),
10093 TestRound(kGetAuth, kSuccess, OK)}},
10094 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10095 { TestRound(kConnect, kProxyChallenge, OK),
10096 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10097 &kGet, &kServerChallenge),
10098 TestRound(kGetAuth, kFailure, kAuthErr)}},
10099 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10100 { TestRound(kConnect, kProxyChallenge, OK),
10101 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10102 &kGet, &kServerChallenge),
10103 TestRound(kGetAuth, kSuccess, OK)}},
10104 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10105 { TestRound(kConnect, kProxyChallenge, OK),
10106 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10107 &kGet, &kServerChallenge),
10108 TestRound(kGetAuth, kFailure, kAuthErr)}},
10109 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10110 { TestRound(kConnect, kProxyChallenge, OK),
10111 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10112 &kGet, &kServerChallenge),
10113 TestRound(kGetAuth, kSuccess, OK)}},
10114 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10115 { TestRound(kConnect, kProxyChallenge, OK),
10116 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10117 &kGet, &kServerChallenge),
10118 TestRound(kGetAuth, kFailure, kAuthErr)}},
10119 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10120 { TestRound(kConnect, kProxyChallenge, OK),
10121 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10122 &kGet, &kServerChallenge),
10123 TestRound(kGetAuth, kSuccess, OK)}},
10124 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10125 { TestRound(kConnect, kProxyChallenge, OK),
10126 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10127 &kGet, &kServerChallenge),
10128 TestRound(kGetAuth, kFailure, kAuthErr)}},
10131 for (size_t i = 0; i < arraysize(test_configs); ++i) {
10132 HttpAuthHandlerMock::Factory* auth_factory(
10133 new HttpAuthHandlerMock::Factory());
10134 session_deps_.http_auth_handler_factory.reset(auth_factory);
10135 const TestConfig& test_config = test_configs[i];
10137 // Set up authentication handlers as necessary.
10138 if (test_config.proxy_auth_timing != AUTH_NONE) {
10139 for (int n = 0; n < 2; n++) {
10140 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10141 std::string auth_challenge = "Mock realm=proxy";
10142 GURL origin(test_config.proxy_url);
10143 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10144 auth_challenge.end());
10145 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
10146 origin, BoundNetLog());
10147 auth_handler->SetGenerateExpectation(
10148 test_config.proxy_auth_timing == AUTH_ASYNC,
10149 test_config.proxy_auth_rv);
10150 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10153 if (test_config.server_auth_timing != AUTH_NONE) {
10154 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10155 std::string auth_challenge = "Mock realm=server";
10156 GURL origin(test_config.server_url);
10157 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10158 auth_challenge.end());
10159 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10160 origin, BoundNetLog());
10161 auth_handler->SetGenerateExpectation(
10162 test_config.server_auth_timing == AUTH_ASYNC,
10163 test_config.server_auth_rv);
10164 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10166 if (test_config.proxy_url) {
10167 session_deps_.proxy_service.reset(
10168 ProxyService::CreateFixed(test_config.proxy_url));
10169 } else {
10170 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10173 HttpRequestInfo request;
10174 request.method = "GET";
10175 request.url = GURL(test_config.server_url);
10176 request.load_flags = 0;
10178 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10179 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10181 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10182 const TestRound& read_write_round = test_config.rounds[round];
10184 // Set up expected reads and writes.
10185 MockRead reads[2];
10186 reads[0] = read_write_round.read;
10187 size_t length_reads = 1;
10188 if (read_write_round.extra_read) {
10189 reads[1] = *read_write_round.extra_read;
10190 length_reads = 2;
10193 MockWrite writes[2];
10194 writes[0] = read_write_round.write;
10195 size_t length_writes = 1;
10196 if (read_write_round.extra_write) {
10197 writes[1] = *read_write_round.extra_write;
10198 length_writes = 2;
10200 StaticSocketDataProvider data_provider(
10201 reads, length_reads, writes, length_writes);
10202 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10204 // Add an SSL sequence if necessary.
10205 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
10206 if (round >= test_config.first_ssl_round)
10207 session_deps_.socket_factory->AddSSLSocketDataProvider(
10208 &ssl_socket_data_provider);
10210 // Start or restart the transaction.
10211 TestCompletionCallback callback;
10212 int rv;
10213 if (round == 0) {
10214 rv = trans.Start(&request, callback.callback(), BoundNetLog());
10215 } else {
10216 rv = trans.RestartWithAuth(
10217 AuthCredentials(kFoo, kBar), callback.callback());
10219 if (rv == ERR_IO_PENDING)
10220 rv = callback.WaitForResult();
10222 // Compare results with expected data.
10223 EXPECT_EQ(read_write_round.expected_rv, rv);
10224 const HttpResponseInfo* response = trans.GetResponseInfo();
10225 if (read_write_round.expected_rv == OK) {
10226 ASSERT_TRUE(response != NULL);
10227 } else {
10228 EXPECT_TRUE(response == NULL);
10229 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
10230 continue;
10232 if (round + 1 < test_config.num_auth_rounds) {
10233 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10234 } else {
10235 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10241 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
10242 // Do multi-round authentication and make sure it works correctly.
10243 HttpAuthHandlerMock::Factory* auth_factory(
10244 new HttpAuthHandlerMock::Factory());
10245 session_deps_.http_auth_handler_factory.reset(auth_factory);
10246 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10247 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
10248 session_deps_.host_resolver->set_synchronous_mode(true);
10250 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10251 auth_handler->set_connection_based(true);
10252 std::string auth_challenge = "Mock realm=server";
10253 GURL origin("http://www.example.com");
10254 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10255 auth_challenge.end());
10256 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10257 origin, BoundNetLog());
10258 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10260 int rv = OK;
10261 const HttpResponseInfo* response = NULL;
10262 HttpRequestInfo request;
10263 request.method = "GET";
10264 request.url = origin;
10265 request.load_flags = 0;
10267 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10269 // Use a TCP Socket Pool with only one connection per group. This is used
10270 // to validate that the TCP socket is not released to the pool between
10271 // each round of multi-round authentication.
10272 HttpNetworkSessionPeer session_peer(session);
10273 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
10274 50, // Max sockets for pool
10275 1, // Max sockets per group
10276 session_deps_.host_resolver.get(),
10277 session_deps_.socket_factory.get(),
10278 session_deps_.net_log);
10279 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
10280 new MockClientSocketPoolManager);
10281 mock_pool_manager->SetTransportSocketPool(transport_pool);
10282 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
10284 scoped_ptr<HttpTransaction> trans(
10285 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10286 TestCompletionCallback callback;
10288 const MockWrite kGet(
10289 "GET / HTTP/1.1\r\n"
10290 "Host: www.example.com\r\n"
10291 "Connection: keep-alive\r\n\r\n");
10292 const MockWrite kGetAuth(
10293 "GET / HTTP/1.1\r\n"
10294 "Host: www.example.com\r\n"
10295 "Connection: keep-alive\r\n"
10296 "Authorization: auth_token\r\n\r\n");
10298 const MockRead kServerChallenge(
10299 "HTTP/1.1 401 Unauthorized\r\n"
10300 "WWW-Authenticate: Mock realm=server\r\n"
10301 "Content-Type: text/html; charset=iso-8859-1\r\n"
10302 "Content-Length: 14\r\n\r\n"
10303 "Unauthorized\r\n");
10304 const MockRead kSuccess(
10305 "HTTP/1.1 200 OK\r\n"
10306 "Content-Type: text/html; charset=iso-8859-1\r\n"
10307 "Content-Length: 3\r\n\r\n"
10308 "Yes");
10310 MockWrite writes[] = {
10311 // First round
10312 kGet,
10313 // Second round
10314 kGetAuth,
10315 // Third round
10316 kGetAuth,
10317 // Fourth round
10318 kGetAuth,
10319 // Competing request
10320 kGet,
10322 MockRead reads[] = {
10323 // First round
10324 kServerChallenge,
10325 // Second round
10326 kServerChallenge,
10327 // Third round
10328 kServerChallenge,
10329 // Fourth round
10330 kSuccess,
10331 // Competing response
10332 kSuccess,
10334 StaticSocketDataProvider data_provider(reads, arraysize(reads),
10335 writes, arraysize(writes));
10336 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10338 const char kSocketGroup[] = "www.example.com:80";
10340 // First round of authentication.
10341 auth_handler->SetGenerateExpectation(false, OK);
10342 rv = trans->Start(&request, callback.callback(), BoundNetLog());
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_FALSE(response->auth_challenge.get() == NULL);
10349 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10351 // In between rounds, another request comes in for the same domain.
10352 // It should not be able to grab the TCP socket that trans has already
10353 // claimed.
10354 scoped_ptr<HttpTransaction> trans_compete(
10355 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10356 TestCompletionCallback callback_compete;
10357 rv = trans_compete->Start(
10358 &request, callback_compete.callback(), BoundNetLog());
10359 EXPECT_EQ(ERR_IO_PENDING, rv);
10360 // callback_compete.WaitForResult at this point would stall forever,
10361 // since the HttpNetworkTransaction does not release the request back to
10362 // the pool until after authentication completes.
10364 // Second round of authentication.
10365 auth_handler->SetGenerateExpectation(false, OK);
10366 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
10367 if (rv == ERR_IO_PENDING)
10368 rv = callback.WaitForResult();
10369 EXPECT_EQ(OK, rv);
10370 response = trans->GetResponseInfo();
10371 ASSERT_TRUE(response != NULL);
10372 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10373 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10375 // Third round of authentication.
10376 auth_handler->SetGenerateExpectation(false, OK);
10377 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10378 if (rv == ERR_IO_PENDING)
10379 rv = callback.WaitForResult();
10380 EXPECT_EQ(OK, rv);
10381 response = trans->GetResponseInfo();
10382 ASSERT_TRUE(response != NULL);
10383 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10384 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10386 // Fourth round of authentication, which completes successfully.
10387 auth_handler->SetGenerateExpectation(false, OK);
10388 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10389 if (rv == ERR_IO_PENDING)
10390 rv = callback.WaitForResult();
10391 EXPECT_EQ(OK, rv);
10392 response = trans->GetResponseInfo();
10393 ASSERT_TRUE(response != NULL);
10394 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10395 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10397 // Read the body since the fourth round was successful. This will also
10398 // release the socket back to the pool.
10399 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
10400 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10401 if (rv == ERR_IO_PENDING)
10402 rv = callback.WaitForResult();
10403 EXPECT_EQ(3, rv);
10404 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10405 EXPECT_EQ(0, rv);
10406 // There are still 0 idle sockets, since the trans_compete transaction
10407 // will be handed it immediately after trans releases it to the group.
10408 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10410 // The competing request can now finish. Wait for the headers and then
10411 // read the body.
10412 rv = callback_compete.WaitForResult();
10413 EXPECT_EQ(OK, rv);
10414 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10415 if (rv == ERR_IO_PENDING)
10416 rv = callback.WaitForResult();
10417 EXPECT_EQ(3, rv);
10418 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10419 EXPECT_EQ(0, rv);
10421 // Finally, the socket is released to the group.
10422 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10425 // This tests the case that a request is issued via http instead of spdy after
10426 // npn is negotiated.
10427 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
10428 session_deps_.use_alternate_protocols = true;
10429 NextProtoVector next_protos;
10430 next_protos.push_back(kProtoHTTP11);
10431 session_deps_.next_protos = next_protos;
10433 HttpRequestInfo request;
10434 request.method = "GET";
10435 request.url = GURL("https://www.example.org/");
10436 request.load_flags = 0;
10438 MockWrite data_writes[] = {
10439 MockWrite(
10440 "GET / HTTP/1.1\r\n"
10441 "Host: www.example.org\r\n"
10442 "Connection: keep-alive\r\n\r\n"),
10445 std::string alternate_protocol_http_header =
10446 GetAlternateProtocolHttpHeader();
10448 MockRead data_reads[] = {
10449 MockRead("HTTP/1.1 200 OK\r\n"),
10450 MockRead(alternate_protocol_http_header.c_str()),
10451 MockRead("hello world"),
10452 MockRead(SYNCHRONOUS, OK),
10455 SSLSocketDataProvider ssl(ASYNC, OK);
10456 ssl.SetNextProto(kProtoHTTP11);
10458 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10460 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
10461 data_writes, arraysize(data_writes));
10462 session_deps_.socket_factory->AddSocketDataProvider(&data);
10464 TestCompletionCallback callback;
10466 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10467 scoped_ptr<HttpTransaction> trans(
10468 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10470 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10472 EXPECT_EQ(ERR_IO_PENDING, rv);
10473 EXPECT_EQ(OK, callback.WaitForResult());
10475 const HttpResponseInfo* response = trans->GetResponseInfo();
10476 ASSERT_TRUE(response != NULL);
10477 ASSERT_TRUE(response->headers.get() != NULL);
10478 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10480 std::string response_data;
10481 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10482 EXPECT_EQ("hello world", response_data);
10484 EXPECT_FALSE(response->was_fetched_via_spdy);
10485 EXPECT_TRUE(response->was_npn_negotiated);
10488 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
10489 // Simulate the SSL handshake completing with an NPN negotiation
10490 // followed by an immediate server closing of the socket.
10491 // Fix crash: http://crbug.com/46369
10492 session_deps_.use_alternate_protocols = true;
10493 session_deps_.next_protos = SpdyNextProtos();
10495 HttpRequestInfo request;
10496 request.method = "GET";
10497 request.url = GURL("https://www.example.org/");
10498 request.load_flags = 0;
10500 SSLSocketDataProvider ssl(ASYNC, OK);
10501 ssl.SetNextProto(GetParam());
10502 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10504 scoped_ptr<SpdyFrame> req(
10505 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10506 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10508 MockRead spdy_reads[] = {
10509 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10512 DelayedSocketData spdy_data(
10513 0, // don't wait in this case, immediate hangup.
10514 spdy_reads, arraysize(spdy_reads),
10515 spdy_writes, arraysize(spdy_writes));
10516 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10518 TestCompletionCallback callback;
10520 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10521 scoped_ptr<HttpTransaction> trans(
10522 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10524 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10525 EXPECT_EQ(ERR_IO_PENDING, rv);
10526 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10529 // A subclass of HttpAuthHandlerMock that records the request URL when
10530 // it gets it. This is needed since the auth handler may get destroyed
10531 // before we get a chance to query it.
10532 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10533 public:
10534 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10536 ~UrlRecordingHttpAuthHandlerMock() override {}
10538 protected:
10539 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10540 const HttpRequestInfo* request,
10541 const CompletionCallback& callback,
10542 std::string* auth_token) override {
10543 *url_ = request->url;
10544 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10545 credentials, request, callback, auth_token);
10548 private:
10549 GURL* url_;
10552 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10553 // This test ensures that the URL passed into the proxy is upgraded
10554 // to https when doing an Alternate Protocol upgrade.
10555 session_deps_.use_alternate_protocols = true;
10556 session_deps_.next_protos = SpdyNextProtos();
10558 session_deps_.proxy_service.reset(
10559 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10560 TestNetLog net_log;
10561 session_deps_.net_log = &net_log;
10562 GURL request_url;
10564 HttpAuthHandlerMock::Factory* auth_factory =
10565 new HttpAuthHandlerMock::Factory();
10566 UrlRecordingHttpAuthHandlerMock* auth_handler =
10567 new UrlRecordingHttpAuthHandlerMock(&request_url);
10568 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10569 auth_factory->set_do_init_from_challenge(true);
10570 session_deps_.http_auth_handler_factory.reset(auth_factory);
10573 HttpRequestInfo request;
10574 request.method = "GET";
10575 request.url = GURL("http://www.example.org");
10576 request.load_flags = 0;
10578 // First round goes unauthenticated through the proxy.
10579 MockWrite data_writes_1[] = {
10580 MockWrite(
10581 "GET http://www.example.org/ HTTP/1.1\r\n"
10582 "Host: www.example.org\r\n"
10583 "Proxy-Connection: keep-alive\r\n"
10584 "\r\n"),
10586 MockRead data_reads_1[] = {
10587 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10588 MockRead("HTTP/1.1 200 OK\r\n"),
10589 MockRead("Alternate-Protocol: 443:"),
10590 MockRead(GetAlternateProtocolFromParam()),
10591 MockRead("\r\n"),
10592 MockRead("Proxy-Connection: close\r\n"),
10593 MockRead("\r\n"),
10595 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10596 data_writes_1, arraysize(data_writes_1));
10598 // Second round tries to tunnel to www.example.org due to the
10599 // Alternate-Protocol announcement in the first round. It fails due
10600 // to a proxy authentication challenge.
10601 // After the failure, a tunnel is established to www.example.org using
10602 // Proxy-Authorization headers. There is then a SPDY request round.
10604 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10605 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10606 // does a Disconnect and Connect on the same socket, rather than trying
10607 // to obtain a new one.
10609 // NOTE: Originally, the proxy response to the second CONNECT request
10610 // simply returned another 407 so the unit test could skip the SSL connection
10611 // establishment and SPDY framing issues. Alas, the
10612 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10613 // complicated to set up expectations for than the SPDY session.
10615 scoped_ptr<SpdyFrame> req(
10616 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10617 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10618 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10620 MockWrite data_writes_2[] = {
10621 // First connection attempt without Proxy-Authorization.
10622 MockWrite(
10623 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10624 "Host: www.example.org\r\n"
10625 "Proxy-Connection: keep-alive\r\n"
10626 "\r\n"),
10628 // Second connection attempt with Proxy-Authorization.
10629 MockWrite(
10630 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10631 "Host: www.example.org\r\n"
10632 "Proxy-Connection: keep-alive\r\n"
10633 "Proxy-Authorization: auth_token\r\n"
10634 "\r\n"),
10636 // SPDY request
10637 CreateMockWrite(*req),
10639 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10640 "Proxy-Authenticate: Mock\r\n"
10641 "Proxy-Connection: close\r\n"
10642 "\r\n");
10643 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10644 MockRead data_reads_2[] = {
10645 // First connection attempt fails
10646 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
10647 MockRead(ASYNC, kRejectConnectResponse,
10648 arraysize(kRejectConnectResponse) - 1, 1),
10650 // Second connection attempt passes
10651 MockRead(ASYNC, kAcceptConnectResponse,
10652 arraysize(kAcceptConnectResponse) -1, 4),
10654 // SPDY response
10655 CreateMockRead(*resp.get(), 6),
10656 CreateMockRead(*data.get(), 6),
10657 MockRead(ASYNC, 0, 0, 6),
10659 OrderedSocketData data_2(
10660 data_reads_2, arraysize(data_reads_2),
10661 data_writes_2, arraysize(data_writes_2));
10663 SSLSocketDataProvider ssl(ASYNC, OK);
10664 ssl.SetNextProto(GetParam());
10665 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10666 ASSERT_TRUE(ssl.cert.get());
10668 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10669 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10670 NULL, 0, NULL, 0);
10671 hanging_non_alternate_protocol_socket.set_connect_data(
10672 never_finishing_connect);
10674 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10675 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10676 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10677 session_deps_.socket_factory->AddSocketDataProvider(
10678 &hanging_non_alternate_protocol_socket);
10679 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10681 // First round should work and provide the Alternate-Protocol state.
10682 TestCompletionCallback callback_1;
10683 scoped_ptr<HttpTransaction> trans_1(
10684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10685 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10686 EXPECT_EQ(ERR_IO_PENDING, rv);
10687 EXPECT_EQ(OK, callback_1.WaitForResult());
10689 // Second round should attempt a tunnel connect and get an auth challenge.
10690 TestCompletionCallback callback_2;
10691 scoped_ptr<HttpTransaction> trans_2(
10692 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10693 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10694 EXPECT_EQ(ERR_IO_PENDING, rv);
10695 EXPECT_EQ(OK, callback_2.WaitForResult());
10696 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10697 ASSERT_TRUE(response != NULL);
10698 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10700 // Restart with auth. Tunnel should work and response received.
10701 TestCompletionCallback callback_3;
10702 rv = trans_2->RestartWithAuth(
10703 AuthCredentials(kFoo, kBar), callback_3.callback());
10704 EXPECT_EQ(ERR_IO_PENDING, rv);
10705 EXPECT_EQ(OK, callback_3.WaitForResult());
10707 // After all that work, these two lines (or actually, just the scheme) are
10708 // what this test is all about. Make sure it happens correctly.
10709 EXPECT_EQ("https", request_url.scheme());
10710 EXPECT_EQ("www.example.org", request_url.host());
10712 LoadTimingInfo load_timing_info;
10713 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10714 TestLoadTimingNotReusedWithPac(load_timing_info,
10715 CONNECT_TIMING_HAS_SSL_TIMES);
10718 // Test that if we cancel the transaction as the connection is completing, that
10719 // everything tears down correctly.
10720 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10721 // Setup everything about the connection to complete synchronously, so that
10722 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10723 // for is the callback from the HttpStreamRequest.
10724 // Then cancel the transaction.
10725 // Verify that we don't crash.
10726 MockConnect mock_connect(SYNCHRONOUS, OK);
10727 MockRead data_reads[] = {
10728 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10729 MockRead(SYNCHRONOUS, "hello world"),
10730 MockRead(SYNCHRONOUS, OK),
10733 HttpRequestInfo request;
10734 request.method = "GET";
10735 request.url = GURL("http://www.example.org/");
10736 request.load_flags = 0;
10738 session_deps_.host_resolver->set_synchronous_mode(true);
10739 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10740 scoped_ptr<HttpTransaction> trans(
10741 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10743 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10744 data.set_connect_data(mock_connect);
10745 session_deps_.socket_factory->AddSocketDataProvider(&data);
10747 TestCompletionCallback callback;
10749 BoundTestNetLog log;
10750 int rv = trans->Start(&request, callback.callback(), log.bound());
10751 EXPECT_EQ(ERR_IO_PENDING, rv);
10752 trans.reset(); // Cancel the transaction here.
10754 base::MessageLoop::current()->RunUntilIdle();
10757 // Test that if a transaction is cancelled after receiving the headers, the
10758 // stream is drained properly and added back to the socket pool. The main
10759 // purpose of this test is to make sure that an HttpStreamParser can be read
10760 // from after the HttpNetworkTransaction and the objects it owns have been
10761 // deleted.
10762 // See http://crbug.com/368418
10763 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10764 MockRead data_reads[] = {
10765 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10766 MockRead(ASYNC, "Content-Length: 2\r\n"),
10767 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10768 MockRead(ASYNC, "1"),
10769 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10770 // HttpNetworkTransaction has been deleted.
10771 MockRead(ASYNC, "2"),
10772 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10774 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10775 session_deps_.socket_factory->AddSocketDataProvider(&data);
10777 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10780 HttpRequestInfo request;
10781 request.method = "GET";
10782 request.url = GURL("http://www.example.org/");
10783 request.load_flags = 0;
10785 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10786 TestCompletionCallback callback;
10788 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10789 EXPECT_EQ(ERR_IO_PENDING, rv);
10790 callback.WaitForResult();
10792 const HttpResponseInfo* response = trans.GetResponseInfo();
10793 ASSERT_TRUE(response != NULL);
10794 EXPECT_TRUE(response->headers.get() != NULL);
10795 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10797 // The transaction and HttpRequestInfo are deleted.
10800 // Let the HttpResponseBodyDrainer drain the socket.
10801 base::MessageLoop::current()->RunUntilIdle();
10803 // Socket should now be idle, waiting to be reused.
10804 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
10807 // Test a basic GET request through a proxy.
10808 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10809 session_deps_.proxy_service.reset(
10810 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10811 BoundTestNetLog log;
10812 session_deps_.net_log = log.bound().net_log();
10813 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10815 HttpRequestInfo request;
10816 request.method = "GET";
10817 request.url = GURL("http://www.example.org/");
10819 MockWrite data_writes1[] = {
10820 MockWrite(
10821 "GET http://www.example.org/ HTTP/1.1\r\n"
10822 "Host: www.example.org\r\n"
10823 "Proxy-Connection: keep-alive\r\n\r\n"),
10826 MockRead data_reads1[] = {
10827 MockRead("HTTP/1.1 200 OK\r\n"),
10828 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10829 MockRead("Content-Length: 100\r\n\r\n"),
10830 MockRead(SYNCHRONOUS, OK),
10833 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10834 data_writes1, arraysize(data_writes1));
10835 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10837 TestCompletionCallback callback1;
10839 scoped_ptr<HttpTransaction> trans(
10840 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10841 BeforeProxyHeadersSentHandler proxy_headers_handler;
10842 trans->SetBeforeProxyHeadersSentCallback(
10843 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
10844 base::Unretained(&proxy_headers_handler)));
10846 int rv = trans->Start(&request, callback1.callback(), log.bound());
10847 EXPECT_EQ(ERR_IO_PENDING, rv);
10849 rv = callback1.WaitForResult();
10850 EXPECT_EQ(OK, rv);
10852 const HttpResponseInfo* response = trans->GetResponseInfo();
10853 ASSERT_TRUE(response != NULL);
10855 EXPECT_TRUE(response->headers->IsKeepAlive());
10856 EXPECT_EQ(200, response->headers->response_code());
10857 EXPECT_EQ(100, response->headers->GetContentLength());
10858 EXPECT_TRUE(response->was_fetched_via_proxy);
10859 EXPECT_TRUE(
10860 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10861 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
10862 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
10863 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10865 LoadTimingInfo load_timing_info;
10866 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10867 TestLoadTimingNotReusedWithPac(load_timing_info,
10868 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10871 // Test a basic HTTPS GET request through a proxy.
10872 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10873 session_deps_.proxy_service.reset(
10874 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10875 BoundTestNetLog log;
10876 session_deps_.net_log = log.bound().net_log();
10877 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10879 HttpRequestInfo request;
10880 request.method = "GET";
10881 request.url = GURL("https://www.example.org/");
10883 // Since we have proxy, should try to establish tunnel.
10884 MockWrite data_writes1[] = {
10885 MockWrite(
10886 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10887 "Host: www.example.org\r\n"
10888 "Proxy-Connection: keep-alive\r\n\r\n"),
10890 MockWrite(
10891 "GET / HTTP/1.1\r\n"
10892 "Host: www.example.org\r\n"
10893 "Connection: keep-alive\r\n\r\n"),
10896 MockRead data_reads1[] = {
10897 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10899 MockRead("HTTP/1.1 200 OK\r\n"),
10900 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10901 MockRead("Content-Length: 100\r\n\r\n"),
10902 MockRead(SYNCHRONOUS, OK),
10905 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10906 data_writes1, arraysize(data_writes1));
10907 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10908 SSLSocketDataProvider ssl(ASYNC, OK);
10909 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10911 TestCompletionCallback callback1;
10913 scoped_ptr<HttpTransaction> trans(
10914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10916 int rv = trans->Start(&request, callback1.callback(), log.bound());
10917 EXPECT_EQ(ERR_IO_PENDING, rv);
10919 rv = callback1.WaitForResult();
10920 EXPECT_EQ(OK, rv);
10921 CapturedNetLogEntry::List entries;
10922 log.GetEntries(&entries);
10923 size_t pos = ExpectLogContainsSomewhere(
10924 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10925 NetLog::PHASE_NONE);
10926 ExpectLogContainsSomewhere(
10927 entries, pos,
10928 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10929 NetLog::PHASE_NONE);
10931 const HttpResponseInfo* response = trans->GetResponseInfo();
10932 ASSERT_TRUE(response != NULL);
10934 EXPECT_TRUE(response->headers->IsKeepAlive());
10935 EXPECT_EQ(200, response->headers->response_code());
10936 EXPECT_EQ(100, response->headers->GetContentLength());
10937 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10938 EXPECT_TRUE(response->was_fetched_via_proxy);
10939 EXPECT_TRUE(
10940 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10942 LoadTimingInfo load_timing_info;
10943 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10944 TestLoadTimingNotReusedWithPac(load_timing_info,
10945 CONNECT_TIMING_HAS_SSL_TIMES);
10948 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10949 // while establishing the tunnel.
10950 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10951 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10952 BoundTestNetLog log;
10953 session_deps_.net_log = log.bound().net_log();
10954 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10956 HttpRequestInfo request;
10957 request.method = "GET";
10958 request.url = GURL("https://www.example.org/");
10960 // Since we have proxy, should try to establish tunnel.
10961 MockWrite data_writes1[] = {
10962 MockWrite(
10963 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10964 "Host: www.example.org\r\n"
10965 "Proxy-Connection: keep-alive\r\n\r\n"),
10967 MockWrite(
10968 "GET / HTTP/1.1\r\n"
10969 "Host: www.example.org\r\n"
10970 "Connection: keep-alive\r\n\r\n"),
10973 MockRead data_reads1[] = {
10974 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10975 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10976 MockRead(ASYNC, 0, 0), // EOF
10979 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10980 data_writes1, arraysize(data_writes1));
10981 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10982 SSLSocketDataProvider ssl(ASYNC, OK);
10983 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10985 TestCompletionCallback callback1;
10987 scoped_ptr<HttpTransaction> trans(
10988 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10990 int rv = trans->Start(&request, callback1.callback(), log.bound());
10991 EXPECT_EQ(ERR_IO_PENDING, rv);
10993 rv = callback1.WaitForResult();
10994 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10995 CapturedNetLogEntry::List entries;
10996 log.GetEntries(&entries);
10997 size_t pos = ExpectLogContainsSomewhere(
10998 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10999 NetLog::PHASE_NONE);
11000 ExpectLogContainsSomewhere(
11001 entries, pos,
11002 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11003 NetLog::PHASE_NONE);
11006 // Test for crbug.com/55424.
11007 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
11008 scoped_ptr<SpdyFrame> req(
11009 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11010 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
11012 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11013 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
11014 MockRead spdy_reads[] = {
11015 CreateMockRead(*resp),
11016 CreateMockRead(*data),
11017 MockRead(ASYNC, 0, 0),
11020 DelayedSocketData spdy_data(
11021 1, // wait for one write to finish before reading.
11022 spdy_reads, arraysize(spdy_reads),
11023 spdy_writes, arraysize(spdy_writes));
11024 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11026 SSLSocketDataProvider ssl(ASYNC, OK);
11027 ssl.SetNextProto(GetParam());
11028 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11030 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11032 // Set up an initial SpdySession in the pool to reuse.
11033 HostPortPair host_port_pair("www.example.org", 443);
11034 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
11035 PRIVACY_MODE_DISABLED);
11036 base::WeakPtr<SpdySession> spdy_session =
11037 CreateInsecureSpdySession(session, key, BoundNetLog());
11039 HttpRequestInfo request;
11040 request.method = "GET";
11041 request.url = GURL("https://www.example.org/");
11042 request.load_flags = 0;
11044 // This is the important line that marks this as a preconnect.
11045 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
11047 scoped_ptr<HttpTransaction> trans(
11048 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11050 TestCompletionCallback callback;
11051 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11052 EXPECT_EQ(ERR_IO_PENDING, rv);
11053 EXPECT_EQ(OK, callback.WaitForResult());
11056 // Given a net error, cause that error to be returned from the first Write()
11057 // call and verify that the HttpTransaction fails with that error.
11058 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11059 int error, IoMode mode) {
11060 HttpRequestInfo request_info;
11061 request_info.url = GURL("https://www.example.com/");
11062 request_info.method = "GET";
11063 request_info.load_flags = LOAD_NORMAL;
11065 SSLSocketDataProvider ssl_data(mode, OK);
11066 MockWrite data_writes[] = {
11067 MockWrite(mode, error),
11069 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
11070 session_deps_.socket_factory->AddSocketDataProvider(&data);
11071 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
11073 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11074 scoped_ptr<HttpTransaction> trans(
11075 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11077 TestCompletionCallback callback;
11078 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11079 if (rv == ERR_IO_PENDING)
11080 rv = callback.WaitForResult();
11081 ASSERT_EQ(error, rv);
11084 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
11085 // Just check a grab bag of cert errors.
11086 static const int kErrors[] = {
11087 ERR_CERT_COMMON_NAME_INVALID,
11088 ERR_CERT_AUTHORITY_INVALID,
11089 ERR_CERT_DATE_INVALID,
11091 for (size_t i = 0; i < arraysize(kErrors); i++) {
11092 CheckErrorIsPassedBack(kErrors[i], ASYNC);
11093 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
11097 // Ensure that a client certificate is removed from the SSL client auth
11098 // cache when:
11099 // 1) No proxy is involved.
11100 // 2) TLS False Start is disabled.
11101 // 3) The initial TLS handshake requests a client certificate.
11102 // 4) The client supplies an invalid/unacceptable certificate.
11103 TEST_P(HttpNetworkTransactionTest,
11104 ClientAuthCertCache_Direct_NoFalseStart) {
11105 HttpRequestInfo request_info;
11106 request_info.url = GURL("https://www.example.com/");
11107 request_info.method = "GET";
11108 request_info.load_flags = LOAD_NORMAL;
11110 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11111 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11113 // [ssl_]data1 contains the data for the first SSL handshake. When a
11114 // CertificateRequest is received for the first time, the handshake will
11115 // be aborted to allow the caller to provide a certificate.
11116 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11117 ssl_data1.cert_request_info = cert_request.get();
11118 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11119 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11120 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11122 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11123 // False Start is not being used, the result of the SSL handshake will be
11124 // returned as part of the SSLClientSocket::Connect() call. This test
11125 // matches the result of a server sending a handshake_failure alert,
11126 // rather than a Finished message, because it requires a client
11127 // certificate and none was supplied.
11128 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11129 ssl_data2.cert_request_info = cert_request.get();
11130 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11131 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11132 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11134 // [ssl_]data3 contains the data for the third SSL handshake. When a
11135 // connection to a server fails during an SSL handshake,
11136 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11137 // connection was attempted with TLSv1.1. This is transparent to the caller
11138 // of the HttpNetworkTransaction. Because this test failure is due to
11139 // requiring a client certificate, this fallback handshake should also
11140 // fail.
11141 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11142 ssl_data3.cert_request_info = cert_request.get();
11143 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11144 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11145 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11147 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11148 // connection to a server fails during an SSL handshake,
11149 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
11150 // connection was attempted with TLSv1. This is transparent to the caller
11151 // of the HttpNetworkTransaction. Because this test failure is due to
11152 // requiring a client certificate, this fallback handshake should also
11153 // fail.
11154 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11155 ssl_data4.cert_request_info = cert_request.get();
11156 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11157 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
11158 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11160 // Need one more if TLSv1.2 is enabled.
11161 SSLSocketDataProvider ssl_data5(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11162 ssl_data5.cert_request_info = cert_request.get();
11163 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11164 StaticSocketDataProvider data5(NULL, 0, NULL, 0);
11165 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11167 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11168 scoped_ptr<HttpTransaction> trans(
11169 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11171 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11172 TestCompletionCallback callback;
11173 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11174 ASSERT_EQ(ERR_IO_PENDING, rv);
11176 // Complete the SSL handshake, which should abort due to requiring a
11177 // client certificate.
11178 rv = callback.WaitForResult();
11179 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11181 // Indicate that no certificate should be supplied. From the perspective
11182 // of SSLClientCertCache, NULL is just as meaningful as a real
11183 // certificate, so this is the same as supply a
11184 // legitimate-but-unacceptable certificate.
11185 rv = trans->RestartWithCertificate(NULL, callback.callback());
11186 ASSERT_EQ(ERR_IO_PENDING, rv);
11188 // Ensure the certificate was added to the client auth cache before
11189 // allowing the connection to continue restarting.
11190 scoped_refptr<X509Certificate> client_cert;
11191 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11192 HostPortPair("www.example.com", 443), &client_cert));
11193 ASSERT_EQ(NULL, client_cert.get());
11195 // Restart the handshake. This will consume ssl_data2, which fails, and
11196 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11197 // The result code is checked against what ssl_data4 should return.
11198 rv = callback.WaitForResult();
11199 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11201 // Ensure that the client certificate is removed from the cache on a
11202 // handshake failure.
11203 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11204 HostPortPair("www.example.com", 443), &client_cert));
11207 // Ensure that a client certificate is removed from the SSL client auth
11208 // cache when:
11209 // 1) No proxy is involved.
11210 // 2) TLS False Start is enabled.
11211 // 3) The initial TLS handshake requests a client certificate.
11212 // 4) The client supplies an invalid/unacceptable certificate.
11213 TEST_P(HttpNetworkTransactionTest,
11214 ClientAuthCertCache_Direct_FalseStart) {
11215 HttpRequestInfo request_info;
11216 request_info.url = GURL("https://www.example.com/");
11217 request_info.method = "GET";
11218 request_info.load_flags = LOAD_NORMAL;
11220 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11221 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11223 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11224 // return successfully after reading up to the peer's Certificate message.
11225 // This is to allow the caller to call SSLClientSocket::Write(), which can
11226 // enqueue application data to be sent in the same packet as the
11227 // ChangeCipherSpec and Finished messages.
11228 // The actual handshake will be finished when SSLClientSocket::Read() is
11229 // called, which expects to process the peer's ChangeCipherSpec and
11230 // Finished messages. If there was an error negotiating with the peer,
11231 // such as due to the peer requiring a client certificate when none was
11232 // supplied, the alert sent by the peer won't be processed until Read() is
11233 // called.
11235 // Like the non-False Start case, when a client certificate is requested by
11236 // the peer, the handshake is aborted during the Connect() call.
11237 // [ssl_]data1 represents the initial SSL handshake with the peer.
11238 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11239 ssl_data1.cert_request_info = cert_request.get();
11240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11241 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11242 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11244 // When a client certificate is supplied, Connect() will not be aborted
11245 // when the peer requests the certificate. Instead, the handshake will
11246 // artificially succeed, allowing the caller to write the HTTP request to
11247 // the socket. The handshake messages are not processed until Read() is
11248 // called, which then detects that the handshake was aborted, due to the
11249 // peer sending a handshake_failure because it requires a client
11250 // certificate.
11251 SSLSocketDataProvider ssl_data2(ASYNC, OK);
11252 ssl_data2.cert_request_info = cert_request.get();
11253 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11254 MockRead data2_reads[] = {
11255 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
11257 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
11258 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11260 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11261 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11262 // TLSv1. It has the same behaviour as [ssl_]data2.
11263 SSLSocketDataProvider ssl_data3(ASYNC, OK);
11264 ssl_data3.cert_request_info = cert_request.get();
11265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11266 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
11267 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11269 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11270 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11271 SSLSocketDataProvider ssl_data4(ASYNC, OK);
11272 ssl_data4.cert_request_info = cert_request.get();
11273 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11274 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
11275 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11277 // Need one more if TLSv1.2 is enabled.
11278 SSLSocketDataProvider ssl_data5(ASYNC, OK);
11279 ssl_data5.cert_request_info = cert_request.get();
11280 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11281 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
11282 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11284 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11285 scoped_ptr<HttpTransaction> trans(
11286 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11288 // Begin the initial SSL handshake.
11289 TestCompletionCallback callback;
11290 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11291 ASSERT_EQ(ERR_IO_PENDING, rv);
11293 // Complete the SSL handshake, which should abort due to requiring a
11294 // client certificate.
11295 rv = callback.WaitForResult();
11296 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11298 // Indicate that no certificate should be supplied. From the perspective
11299 // of SSLClientCertCache, NULL is just as meaningful as a real
11300 // certificate, so this is the same as supply a
11301 // legitimate-but-unacceptable certificate.
11302 rv = trans->RestartWithCertificate(NULL, callback.callback());
11303 ASSERT_EQ(ERR_IO_PENDING, rv);
11305 // Ensure the certificate was added to the client auth cache before
11306 // allowing the connection to continue restarting.
11307 scoped_refptr<X509Certificate> client_cert;
11308 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11309 HostPortPair("www.example.com", 443), &client_cert));
11310 ASSERT_EQ(NULL, client_cert.get());
11312 // Restart the handshake. This will consume ssl_data2, which fails, and
11313 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11314 // The result code is checked against what ssl_data4 should return.
11315 rv = callback.WaitForResult();
11316 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11318 // Ensure that the client certificate is removed from the cache on a
11319 // handshake failure.
11320 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11321 HostPortPair("www.example.com", 443), &client_cert));
11324 // Ensure that a client certificate is removed from the SSL client auth
11325 // cache when:
11326 // 1) An HTTPS proxy is involved.
11327 // 3) The HTTPS proxy requests a client certificate.
11328 // 4) The client supplies an invalid/unacceptable certificate for the
11329 // proxy.
11330 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11331 // then for connecting to an HTTP endpoint.
11332 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
11333 session_deps_.proxy_service.reset(
11334 ProxyService::CreateFixed("https://proxy:70"));
11335 BoundTestNetLog log;
11336 session_deps_.net_log = log.bound().net_log();
11338 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11339 cert_request->host_and_port = HostPortPair("proxy", 70);
11341 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11342 // [ssl_]data[1-3]. Rather than represending the endpoint
11343 // (www.example.com:443), they represent failures with the HTTPS proxy
11344 // (proxy:70).
11345 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11346 ssl_data1.cert_request_info = cert_request.get();
11347 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11348 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11349 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11351 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11352 ssl_data2.cert_request_info = cert_request.get();
11353 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11354 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11355 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11357 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11358 #if 0
11359 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11360 ssl_data3.cert_request_info = cert_request.get();
11361 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11362 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11363 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11364 #endif
11366 HttpRequestInfo requests[2];
11367 requests[0].url = GURL("https://www.example.com/");
11368 requests[0].method = "GET";
11369 requests[0].load_flags = LOAD_NORMAL;
11371 requests[1].url = GURL("http://www.example.com/");
11372 requests[1].method = "GET";
11373 requests[1].load_flags = LOAD_NORMAL;
11375 for (size_t i = 0; i < arraysize(requests); ++i) {
11376 session_deps_.socket_factory->ResetNextMockIndexes();
11377 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11378 scoped_ptr<HttpNetworkTransaction> trans(
11379 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11381 // Begin the SSL handshake with the proxy.
11382 TestCompletionCallback callback;
11383 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
11384 ASSERT_EQ(ERR_IO_PENDING, rv);
11386 // Complete the SSL handshake, which should abort due to requiring a
11387 // client certificate.
11388 rv = callback.WaitForResult();
11389 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11391 // Indicate that no certificate should be supplied. From the perspective
11392 // of SSLClientCertCache, NULL is just as meaningful as a real
11393 // certificate, so this is the same as supply a
11394 // legitimate-but-unacceptable certificate.
11395 rv = trans->RestartWithCertificate(NULL, callback.callback());
11396 ASSERT_EQ(ERR_IO_PENDING, rv);
11398 // Ensure the certificate was added to the client auth cache before
11399 // allowing the connection to continue restarting.
11400 scoped_refptr<X509Certificate> client_cert;
11401 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11402 HostPortPair("proxy", 70), &client_cert));
11403 ASSERT_EQ(NULL, client_cert.get());
11404 // Ensure the certificate was NOT cached for the endpoint. This only
11405 // applies to HTTPS requests, but is fine to check for HTTP requests.
11406 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11407 HostPortPair("www.example.com", 443), &client_cert));
11409 // Restart the handshake. This will consume ssl_data2, which fails, and
11410 // then consume ssl_data3, which should also fail. The result code is
11411 // checked against what ssl_data3 should return.
11412 rv = callback.WaitForResult();
11413 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
11415 // Now that the new handshake has failed, ensure that the client
11416 // certificate was removed from the client auth cache.
11417 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11418 HostPortPair("proxy", 70), &client_cert));
11419 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11420 HostPortPair("www.example.com", 443), &client_cert));
11424 // Unlike TEST/TEST_F, which are macros that expand to further macros,
11425 // TEST_P is a macro that expands directly to code that stringizes the
11426 // arguments. As a result, macros passed as parameters (such as prefix
11427 // or test_case_name) will not be expanded by the preprocessor. To
11428 // work around this, indirect the macro for TEST_P, so that the
11429 // pre-processor will expand macros such as MAYBE_test_name before
11430 // instantiating the test.
11431 #define WRAPPED_TEST_P(test_case_name, test_name) \
11432 TEST_P(test_case_name, test_name)
11434 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11435 #if defined(OS_WIN)
11436 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
11437 #else
11438 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
11439 #endif
11440 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
11441 session_deps_.use_alternate_protocols = true;
11442 session_deps_.next_protos = SpdyNextProtos();
11444 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11445 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11446 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11447 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11448 pool_peer.DisableDomainAuthenticationVerification();
11450 SSLSocketDataProvider ssl(ASYNC, OK);
11451 ssl.SetNextProto(GetParam());
11452 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11454 scoped_ptr<SpdyFrame> host1_req(
11455 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11456 scoped_ptr<SpdyFrame> host2_req(
11457 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11458 MockWrite spdy_writes[] = {
11459 CreateMockWrite(*host1_req, 1),
11460 CreateMockWrite(*host2_req, 4),
11462 scoped_ptr<SpdyFrame> host1_resp(
11463 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11464 scoped_ptr<SpdyFrame> host1_resp_body(
11465 spdy_util_.ConstructSpdyBodyFrame(1, true));
11466 scoped_ptr<SpdyFrame> host2_resp(
11467 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11468 scoped_ptr<SpdyFrame> host2_resp_body(
11469 spdy_util_.ConstructSpdyBodyFrame(3, true));
11470 MockRead spdy_reads[] = {
11471 CreateMockRead(*host1_resp, 2),
11472 CreateMockRead(*host1_resp_body, 3),
11473 CreateMockRead(*host2_resp, 5),
11474 CreateMockRead(*host2_resp_body, 6),
11475 MockRead(ASYNC, 0, 7),
11478 IPAddressNumber ip;
11479 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11480 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11481 MockConnect connect(ASYNC, OK, peer_addr);
11482 OrderedSocketData spdy_data(
11483 connect,
11484 spdy_reads, arraysize(spdy_reads),
11485 spdy_writes, arraysize(spdy_writes));
11486 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11488 TestCompletionCallback callback;
11489 HttpRequestInfo request1;
11490 request1.method = "GET";
11491 request1.url = GURL("https://www.example.org/");
11492 request1.load_flags = 0;
11493 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11495 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11496 EXPECT_EQ(ERR_IO_PENDING, rv);
11497 EXPECT_EQ(OK, callback.WaitForResult());
11499 const HttpResponseInfo* response = trans1.GetResponseInfo();
11500 ASSERT_TRUE(response != NULL);
11501 ASSERT_TRUE(response->headers.get() != NULL);
11502 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11504 std::string response_data;
11505 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11506 EXPECT_EQ("hello!", response_data);
11508 // Preload www.gmail.com into HostCache.
11509 HostPortPair host_port("www.gmail.com", 443);
11510 HostResolver::RequestInfo resolve_info(host_port);
11511 AddressList ignored;
11512 rv = session_deps_.host_resolver->Resolve(resolve_info,
11513 DEFAULT_PRIORITY,
11514 &ignored,
11515 callback.callback(),
11516 NULL,
11517 BoundNetLog());
11518 EXPECT_EQ(ERR_IO_PENDING, rv);
11519 rv = callback.WaitForResult();
11520 EXPECT_EQ(OK, rv);
11522 HttpRequestInfo request2;
11523 request2.method = "GET";
11524 request2.url = GURL("https://www.gmail.com/");
11525 request2.load_flags = 0;
11526 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11528 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11529 EXPECT_EQ(ERR_IO_PENDING, rv);
11530 EXPECT_EQ(OK, callback.WaitForResult());
11532 response = trans2.GetResponseInfo();
11533 ASSERT_TRUE(response != NULL);
11534 ASSERT_TRUE(response->headers.get() != NULL);
11535 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11536 EXPECT_TRUE(response->was_fetched_via_spdy);
11537 EXPECT_TRUE(response->was_npn_negotiated);
11538 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11539 EXPECT_EQ("hello!", response_data);
11541 #undef MAYBE_UseIPConnectionPooling
11543 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11544 session_deps_.use_alternate_protocols = true;
11545 session_deps_.next_protos = SpdyNextProtos();
11547 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11548 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11549 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11550 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11551 pool_peer.DisableDomainAuthenticationVerification();
11553 SSLSocketDataProvider ssl(ASYNC, OK);
11554 ssl.SetNextProto(GetParam());
11555 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11557 scoped_ptr<SpdyFrame> host1_req(
11558 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11559 scoped_ptr<SpdyFrame> host2_req(
11560 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11561 MockWrite spdy_writes[] = {
11562 CreateMockWrite(*host1_req, 1),
11563 CreateMockWrite(*host2_req, 4),
11565 scoped_ptr<SpdyFrame> host1_resp(
11566 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11567 scoped_ptr<SpdyFrame> host1_resp_body(
11568 spdy_util_.ConstructSpdyBodyFrame(1, true));
11569 scoped_ptr<SpdyFrame> host2_resp(
11570 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11571 scoped_ptr<SpdyFrame> host2_resp_body(
11572 spdy_util_.ConstructSpdyBodyFrame(3, true));
11573 MockRead spdy_reads[] = {
11574 CreateMockRead(*host1_resp, 2),
11575 CreateMockRead(*host1_resp_body, 3),
11576 CreateMockRead(*host2_resp, 5),
11577 CreateMockRead(*host2_resp_body, 6),
11578 MockRead(ASYNC, 0, 7),
11581 IPAddressNumber ip;
11582 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11583 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11584 MockConnect connect(ASYNC, OK, peer_addr);
11585 OrderedSocketData spdy_data(
11586 connect,
11587 spdy_reads, arraysize(spdy_reads),
11588 spdy_writes, arraysize(spdy_writes));
11589 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11591 TestCompletionCallback callback;
11592 HttpRequestInfo request1;
11593 request1.method = "GET";
11594 request1.url = GURL("https://www.example.org/");
11595 request1.load_flags = 0;
11596 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11598 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11599 EXPECT_EQ(ERR_IO_PENDING, rv);
11600 EXPECT_EQ(OK, callback.WaitForResult());
11602 const HttpResponseInfo* response = trans1.GetResponseInfo();
11603 ASSERT_TRUE(response != NULL);
11604 ASSERT_TRUE(response->headers.get() != NULL);
11605 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11607 std::string response_data;
11608 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11609 EXPECT_EQ("hello!", response_data);
11611 HttpRequestInfo request2;
11612 request2.method = "GET";
11613 request2.url = GURL("https://www.gmail.com/");
11614 request2.load_flags = 0;
11615 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11617 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11618 EXPECT_EQ(ERR_IO_PENDING, rv);
11619 EXPECT_EQ(OK, callback.WaitForResult());
11621 response = trans2.GetResponseInfo();
11622 ASSERT_TRUE(response != NULL);
11623 ASSERT_TRUE(response->headers.get() != NULL);
11624 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11625 EXPECT_TRUE(response->was_fetched_via_spdy);
11626 EXPECT_TRUE(response->was_npn_negotiated);
11627 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11628 EXPECT_EQ("hello!", response_data);
11631 class OneTimeCachingHostResolver : public HostResolver {
11632 public:
11633 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11634 : host_port_(host_port) {}
11635 ~OneTimeCachingHostResolver() override {}
11637 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11639 // HostResolver methods:
11640 int Resolve(const RequestInfo& info,
11641 RequestPriority priority,
11642 AddressList* addresses,
11643 const CompletionCallback& callback,
11644 RequestHandle* out_req,
11645 const BoundNetLog& net_log) override {
11646 return host_resolver_.Resolve(
11647 info, priority, addresses, callback, out_req, net_log);
11650 int ResolveFromCache(const RequestInfo& info,
11651 AddressList* addresses,
11652 const BoundNetLog& net_log) override {
11653 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11654 if (rv == OK && info.host_port_pair().Equals(host_port_))
11655 host_resolver_.GetHostCache()->clear();
11656 return rv;
11659 void CancelRequest(RequestHandle req) override {
11660 host_resolver_.CancelRequest(req);
11663 MockCachingHostResolver* GetMockHostResolver() {
11664 return &host_resolver_;
11667 private:
11668 MockCachingHostResolver host_resolver_;
11669 const HostPortPair host_port_;
11672 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11673 #if defined(OS_WIN)
11674 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11675 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11676 #else
11677 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11678 UseIPConnectionPoolingWithHostCacheExpiration
11679 #endif
11680 WRAPPED_TEST_P(HttpNetworkTransactionTest,
11681 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
11682 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11683 // prefix doesn't work with parametrized tests).
11684 #if defined(OS_WIN)
11685 return;
11686 #else
11687 session_deps_.use_alternate_protocols = true;
11688 session_deps_.next_protos = SpdyNextProtos();
11690 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11691 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11692 HttpNetworkSession::Params params =
11693 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11694 params.host_resolver = &host_resolver;
11695 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11696 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11697 pool_peer.DisableDomainAuthenticationVerification();
11699 SSLSocketDataProvider ssl(ASYNC, OK);
11700 ssl.SetNextProto(GetParam());
11701 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11703 scoped_ptr<SpdyFrame> host1_req(
11704 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11705 scoped_ptr<SpdyFrame> host2_req(
11706 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11707 MockWrite spdy_writes[] = {
11708 CreateMockWrite(*host1_req, 1),
11709 CreateMockWrite(*host2_req, 4),
11711 scoped_ptr<SpdyFrame> host1_resp(
11712 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11713 scoped_ptr<SpdyFrame> host1_resp_body(
11714 spdy_util_.ConstructSpdyBodyFrame(1, true));
11715 scoped_ptr<SpdyFrame> host2_resp(
11716 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11717 scoped_ptr<SpdyFrame> host2_resp_body(
11718 spdy_util_.ConstructSpdyBodyFrame(3, true));
11719 MockRead spdy_reads[] = {
11720 CreateMockRead(*host1_resp, 2),
11721 CreateMockRead(*host1_resp_body, 3),
11722 CreateMockRead(*host2_resp, 5),
11723 CreateMockRead(*host2_resp_body, 6),
11724 MockRead(ASYNC, 0, 7),
11727 IPAddressNumber ip;
11728 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11729 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11730 MockConnect connect(ASYNC, OK, peer_addr);
11731 OrderedSocketData spdy_data(
11732 connect,
11733 spdy_reads, arraysize(spdy_reads),
11734 spdy_writes, arraysize(spdy_writes));
11735 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11737 TestCompletionCallback callback;
11738 HttpRequestInfo request1;
11739 request1.method = "GET";
11740 request1.url = GURL("https://www.example.org/");
11741 request1.load_flags = 0;
11742 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11744 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11745 EXPECT_EQ(ERR_IO_PENDING, rv);
11746 EXPECT_EQ(OK, callback.WaitForResult());
11748 const HttpResponseInfo* response = trans1.GetResponseInfo();
11749 ASSERT_TRUE(response != NULL);
11750 ASSERT_TRUE(response->headers.get() != NULL);
11751 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11753 std::string response_data;
11754 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11755 EXPECT_EQ("hello!", response_data);
11757 // Preload cache entries into HostCache.
11758 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11759 AddressList ignored;
11760 rv = host_resolver.Resolve(resolve_info,
11761 DEFAULT_PRIORITY,
11762 &ignored,
11763 callback.callback(),
11764 NULL,
11765 BoundNetLog());
11766 EXPECT_EQ(ERR_IO_PENDING, rv);
11767 rv = callback.WaitForResult();
11768 EXPECT_EQ(OK, rv);
11770 HttpRequestInfo request2;
11771 request2.method = "GET";
11772 request2.url = GURL("https://www.gmail.com/");
11773 request2.load_flags = 0;
11774 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11776 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11777 EXPECT_EQ(ERR_IO_PENDING, rv);
11778 EXPECT_EQ(OK, callback.WaitForResult());
11780 response = trans2.GetResponseInfo();
11781 ASSERT_TRUE(response != NULL);
11782 ASSERT_TRUE(response->headers.get() != NULL);
11783 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11784 EXPECT_TRUE(response->was_fetched_via_spdy);
11785 EXPECT_TRUE(response->was_npn_negotiated);
11786 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11787 EXPECT_EQ("hello!", response_data);
11788 #endif
11790 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11792 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11793 const std::string https_url = "https://www.example.org:8080/";
11794 const std::string http_url = "http://www.example.org:8080/";
11796 // SPDY GET for HTTPS URL
11797 scoped_ptr<SpdyFrame> req1(
11798 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11800 MockWrite writes1[] = {
11801 CreateMockWrite(*req1, 0),
11804 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11805 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11806 MockRead reads1[] = {
11807 CreateMockRead(*resp1, 1),
11808 CreateMockRead(*body1, 2),
11809 MockRead(ASYNC, ERR_IO_PENDING, 3)
11812 DelayedSocketData data1(
11813 1, reads1, arraysize(reads1),
11814 writes1, arraysize(writes1));
11815 MockConnect connect_data1(ASYNC, OK);
11816 data1.set_connect_data(connect_data1);
11818 // HTTP GET for the HTTP URL
11819 MockWrite writes2[] = {
11820 MockWrite(ASYNC, 4,
11821 "GET / HTTP/1.1\r\n"
11822 "Host: www.example.org:8080\r\n"
11823 "Connection: keep-alive\r\n\r\n"),
11826 MockRead reads2[] = {
11827 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11828 MockRead(ASYNC, 6, "hello"),
11829 MockRead(ASYNC, 7, OK),
11832 DelayedSocketData data2(
11833 1, reads2, arraysize(reads2),
11834 writes2, arraysize(writes2));
11836 SSLSocketDataProvider ssl(ASYNC, OK);
11837 ssl.SetNextProto(GetParam());
11838 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11839 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11840 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11842 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11844 // Start the first transaction to set up the SpdySession
11845 HttpRequestInfo request1;
11846 request1.method = "GET";
11847 request1.url = GURL(https_url);
11848 request1.load_flags = 0;
11849 HttpNetworkTransaction trans1(LOWEST, session.get());
11850 TestCompletionCallback callback1;
11851 EXPECT_EQ(ERR_IO_PENDING,
11852 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11853 base::MessageLoop::current()->RunUntilIdle();
11855 EXPECT_EQ(OK, callback1.WaitForResult());
11856 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11858 // Now, start the HTTP request
11859 HttpRequestInfo request2;
11860 request2.method = "GET";
11861 request2.url = GURL(http_url);
11862 request2.load_flags = 0;
11863 HttpNetworkTransaction trans2(MEDIUM, session.get());
11864 TestCompletionCallback callback2;
11865 EXPECT_EQ(ERR_IO_PENDING,
11866 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11867 base::MessageLoop::current()->RunUntilIdle();
11869 EXPECT_EQ(OK, callback2.WaitForResult());
11870 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11873 class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
11874 public:
11875 void Run(bool pooling, bool valid) {
11876 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
11877 443);
11878 HostPortPair alternative("www.example.org", 443);
11880 base::FilePath certs_dir = GetTestCertsDirectory();
11881 scoped_refptr<X509Certificate> cert(
11882 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
11883 ASSERT_TRUE(cert.get());
11884 bool common_name_fallback_used;
11885 EXPECT_EQ(valid,
11886 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
11887 EXPECT_TRUE(
11888 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
11889 SSLSocketDataProvider ssl(ASYNC, OK);
11890 ssl.SetNextProto(GetParam());
11891 ssl.cert = cert;
11892 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11894 // If pooling, then start a request to alternative first to create a
11895 // SpdySession.
11896 std::string url0 = "https://www.example.org:443";
11897 // Second request to origin, which has an alternative service, and could
11898 // open a connection to the alternative host or pool to the existing one.
11899 std::string url1("https://");
11900 url1.append(origin.host());
11901 url1.append(":443");
11903 scoped_ptr<SpdyFrame> req0;
11904 scoped_ptr<SpdyFrame> req1;
11905 scoped_ptr<SpdyFrame> resp0;
11906 scoped_ptr<SpdyFrame> body0;
11907 scoped_ptr<SpdyFrame> resp1;
11908 scoped_ptr<SpdyFrame> body1;
11909 std::vector<MockWrite> writes;
11910 std::vector<MockRead> reads;
11912 if (pooling) {
11913 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
11914 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
11916 writes.push_back(CreateMockWrite(*req0, 0));
11917 writes.push_back(CreateMockWrite(*req1, 3));
11919 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11920 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
11921 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11922 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
11924 reads.push_back(CreateMockRead(*resp0, 1));
11925 reads.push_back(CreateMockRead(*body0, 2));
11926 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
11927 reads.push_back(CreateMockRead(*resp1, 5));
11928 reads.push_back(CreateMockRead(*body1, 6));
11929 reads.push_back(MockRead(ASYNC, OK, 7));
11930 } else {
11931 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
11933 writes.push_back(CreateMockWrite(*req1, 0));
11935 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11936 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
11938 reads.push_back(CreateMockRead(*resp1, 1));
11939 reads.push_back(CreateMockRead(*body1, 2));
11940 reads.push_back(MockRead(ASYNC, OK, 3));
11943 OrderedSocketData data(vector_as_array(&reads), reads.size(),
11944 vector_as_array(&writes), writes.size());
11945 session_deps_.socket_factory->AddSocketDataProvider(&data);
11947 // Connection to the origin fails.
11948 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11949 StaticSocketDataProvider data_refused;
11950 data_refused.set_connect_data(mock_connect);
11951 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
11953 session_deps_.use_alternate_protocols = true;
11954 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11955 base::WeakPtr<HttpServerProperties> http_server_properties =
11956 session->http_server_properties();
11957 AlternativeService alternative_service(
11958 AlternateProtocolFromNextProto(GetParam()), alternative);
11959 http_server_properties->SetAlternativeService(origin, alternative_service,
11960 1.0);
11962 // First request to alternative.
11963 if (pooling) {
11964 scoped_ptr<HttpTransaction> trans0(
11965 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11966 HttpRequestInfo request0;
11967 request0.method = "GET";
11968 request0.url = GURL(url0);
11969 request0.load_flags = 0;
11970 TestCompletionCallback callback0;
11972 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
11973 EXPECT_EQ(ERR_IO_PENDING, rv);
11974 rv = callback0.WaitForResult();
11975 EXPECT_EQ(OK, rv);
11978 // Second request to origin.
11979 scoped_ptr<HttpTransaction> trans1(
11980 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11981 HttpRequestInfo request1;
11982 request1.method = "GET";
11983 request1.url = GURL(url1);
11984 request1.load_flags = 0;
11985 TestCompletionCallback callback1;
11987 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
11988 EXPECT_EQ(ERR_IO_PENDING, rv);
11989 rv = callback1.WaitForResult();
11990 if (valid) {
11991 EXPECT_EQ(OK, rv);
11992 } else {
11993 if (pooling) {
11994 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11995 } else {
11996 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
12002 INSTANTIATE_TEST_CASE_P(NextProto,
12003 AltSvcCertificateVerificationTest,
12004 testing::Values(kProtoSPDY31,
12005 kProtoSPDY4_14,
12006 kProtoSPDY4));
12008 // The alternative service host must exhibit a certificate that is valid for the
12009 // origin host. Test that this is enforced when pooling to an existing
12010 // connection.
12011 TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
12012 Run(true, true);
12015 TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
12016 Run(true, false);
12019 // The alternative service host must exhibit a certificate that is valid for the
12020 // origin host. Test that this is enforced when opening a new connection.
12021 TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
12022 Run(false, true);
12025 TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
12026 Run(false, false);
12029 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
12030 const std::string https_url = "https://www.example.org:8080/";
12031 const std::string http_url = "http://www.example.org:8080/";
12033 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12034 const HostPortPair host_port_pair("www.example.org", 8080);
12035 scoped_ptr<SpdyFrame> connect(
12036 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
12037 scoped_ptr<SpdyFrame> req1(
12038 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
12039 scoped_ptr<SpdyFrame> wrapped_req1(
12040 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
12042 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12043 SpdyHeaderBlock req2_block;
12044 req2_block[spdy_util_.GetMethodKey()] = "GET";
12045 req2_block[spdy_util_.GetPathKey()] = "/";
12046 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
12047 req2_block[spdy_util_.GetSchemeKey()] = "http";
12048 spdy_util_.MaybeAddVersionHeader(&req2_block);
12049 scoped_ptr<SpdyFrame> req2(
12050 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
12052 MockWrite writes1[] = {
12053 CreateMockWrite(*connect, 0),
12054 CreateMockWrite(*wrapped_req1, 2),
12055 CreateMockWrite(*req2, 5),
12058 scoped_ptr<SpdyFrame> conn_resp(
12059 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12060 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12061 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12062 scoped_ptr<SpdyFrame> wrapped_resp1(
12063 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
12064 scoped_ptr<SpdyFrame> wrapped_body1(
12065 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
12066 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12067 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
12068 MockRead reads1[] = {
12069 CreateMockRead(*conn_resp, 1),
12070 CreateMockRead(*wrapped_resp1, 3),
12071 CreateMockRead(*wrapped_body1, 4),
12072 CreateMockRead(*resp2, 6),
12073 CreateMockRead(*body2, 7),
12074 MockRead(ASYNC, ERR_IO_PENDING, 8)
12077 DeterministicSocketData data1(reads1, arraysize(reads1),
12078 writes1, arraysize(writes1));
12079 MockConnect connect_data1(ASYNC, OK);
12080 data1.set_connect_data(connect_data1);
12082 session_deps_.proxy_service.reset(
12083 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12084 TestNetLog log;
12085 session_deps_.net_log = &log;
12086 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12087 ssl1.SetNextProto(GetParam());
12088 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12089 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12090 ssl2.SetNextProto(GetParam());
12091 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12092 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
12094 scoped_refptr<HttpNetworkSession> session(
12095 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12097 // Start the first transaction to set up the SpdySession
12098 HttpRequestInfo request1;
12099 request1.method = "GET";
12100 request1.url = GURL(https_url);
12101 request1.load_flags = 0;
12102 HttpNetworkTransaction trans1(LOWEST, session.get());
12103 TestCompletionCallback callback1;
12104 EXPECT_EQ(ERR_IO_PENDING,
12105 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12106 base::MessageLoop::current()->RunUntilIdle();
12107 data1.RunFor(4);
12109 EXPECT_EQ(OK, callback1.WaitForResult());
12110 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12112 LoadTimingInfo load_timing_info1;
12113 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
12114 TestLoadTimingNotReusedWithPac(load_timing_info1,
12115 CONNECT_TIMING_HAS_SSL_TIMES);
12117 // Now, start the HTTP request
12118 HttpRequestInfo request2;
12119 request2.method = "GET";
12120 request2.url = GURL(http_url);
12121 request2.load_flags = 0;
12122 HttpNetworkTransaction trans2(MEDIUM, session.get());
12123 TestCompletionCallback callback2;
12124 EXPECT_EQ(ERR_IO_PENDING,
12125 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12126 base::MessageLoop::current()->RunUntilIdle();
12127 data1.RunFor(3);
12129 EXPECT_EQ(OK, callback2.WaitForResult());
12130 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12132 LoadTimingInfo load_timing_info2;
12133 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
12134 // The established SPDY sessions is considered reused by the HTTP request.
12135 TestLoadTimingReusedWithPac(load_timing_info2);
12136 // HTTP requests over a SPDY session should have a different connection
12137 // socket_log_id than requests over a tunnel.
12138 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
12141 // Test that in the case where we have a SPDY session to a SPDY proxy
12142 // that we do not pool other origins that resolve to the same IP when
12143 // the certificate does not match the new origin.
12144 // http://crbug.com/134690
12145 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
12146 const std::string url1 = "http://www.example.org/";
12147 const std::string url2 = "https://news.example.org/";
12148 const std::string ip_addr = "1.2.3.4";
12150 // SPDY GET for HTTP URL (through SPDY proxy)
12151 scoped_ptr<SpdyHeaderBlock> headers(
12152 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12153 scoped_ptr<SpdyFrame> req1(
12154 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
12156 MockWrite writes1[] = {
12157 CreateMockWrite(*req1, 0),
12160 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12161 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12162 MockRead reads1[] = {
12163 CreateMockRead(*resp1, 1),
12164 CreateMockRead(*body1, 2),
12165 MockRead(ASYNC, OK, 3) // EOF
12168 scoped_ptr<DeterministicSocketData> data1(
12169 new DeterministicSocketData(reads1, arraysize(reads1),
12170 writes1, arraysize(writes1)));
12171 IPAddressNumber ip;
12172 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
12173 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12174 MockConnect connect_data1(ASYNC, OK, peer_addr);
12175 data1->set_connect_data(connect_data1);
12177 // SPDY GET for HTTPS URL (direct)
12178 scoped_ptr<SpdyFrame> req2(
12179 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
12181 MockWrite writes2[] = {
12182 CreateMockWrite(*req2, 0),
12185 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12186 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12187 MockRead reads2[] = {
12188 CreateMockRead(*resp2, 1),
12189 CreateMockRead(*body2, 2),
12190 MockRead(ASYNC, OK, 3) // EOF
12193 scoped_ptr<DeterministicSocketData> data2(
12194 new DeterministicSocketData(reads2, arraysize(reads2),
12195 writes2, arraysize(writes2)));
12196 MockConnect connect_data2(ASYNC, OK);
12197 data2->set_connect_data(connect_data2);
12199 // Set up a proxy config that sends HTTP requests to a proxy, and
12200 // all others direct.
12201 ProxyConfig proxy_config;
12202 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
12203 session_deps_.proxy_service.reset(new ProxyService(
12204 new ProxyConfigServiceFixed(proxy_config), nullptr, NULL));
12206 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12207 ssl1.SetNextProto(GetParam());
12208 // Load a valid cert. Note, that this does not need to
12209 // be valid for proxy because the MockSSLClientSocket does
12210 // not actually verify it. But SpdySession will use this
12211 // to see if it is valid for the new origin
12212 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12213 ASSERT_TRUE(ssl1.cert.get());
12214 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12215 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12216 data1.get());
12218 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12219 ssl2.SetNextProto(GetParam());
12220 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12221 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12222 data2.get());
12224 session_deps_.host_resolver.reset(new MockCachingHostResolver());
12225 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
12226 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
12228 scoped_refptr<HttpNetworkSession> session(
12229 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12231 // Start the first transaction to set up the SpdySession
12232 HttpRequestInfo request1;
12233 request1.method = "GET";
12234 request1.url = GURL(url1);
12235 request1.load_flags = 0;
12236 HttpNetworkTransaction trans1(LOWEST, session.get());
12237 TestCompletionCallback callback1;
12238 ASSERT_EQ(ERR_IO_PENDING,
12239 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12240 data1->RunFor(3);
12242 ASSERT_TRUE(callback1.have_result());
12243 EXPECT_EQ(OK, callback1.WaitForResult());
12244 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12246 // Now, start the HTTP request
12247 HttpRequestInfo request2;
12248 request2.method = "GET";
12249 request2.url = GURL(url2);
12250 request2.load_flags = 0;
12251 HttpNetworkTransaction trans2(MEDIUM, session.get());
12252 TestCompletionCallback callback2;
12253 EXPECT_EQ(ERR_IO_PENDING,
12254 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12255 base::MessageLoop::current()->RunUntilIdle();
12256 data2->RunFor(3);
12258 ASSERT_TRUE(callback2.have_result());
12259 EXPECT_EQ(OK, callback2.WaitForResult());
12260 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12263 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12264 // error) in SPDY session, removes the socket from pool and closes the SPDY
12265 // session. Verify that new url's from the same HttpNetworkSession (and a new
12266 // SpdySession) do work. http://crbug.com/224701
12267 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
12268 const std::string https_url = "https://www.example.org/";
12270 MockRead reads1[] = {
12271 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
12274 scoped_ptr<DeterministicSocketData> data1(
12275 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
12276 data1->SetStop(1);
12278 scoped_ptr<SpdyFrame> req2(
12279 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
12280 MockWrite writes2[] = {
12281 CreateMockWrite(*req2, 0),
12284 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12285 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12286 MockRead reads2[] = {
12287 CreateMockRead(*resp2, 1),
12288 CreateMockRead(*body2, 2),
12289 MockRead(ASYNC, OK, 3) // EOF
12292 scoped_ptr<DeterministicSocketData> data2(
12293 new DeterministicSocketData(reads2, arraysize(reads2),
12294 writes2, arraysize(writes2)));
12296 SSLSocketDataProvider ssl1(ASYNC, OK);
12297 ssl1.SetNextProto(GetParam());
12298 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12299 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12300 data1.get());
12302 SSLSocketDataProvider ssl2(ASYNC, OK);
12303 ssl2.SetNextProto(GetParam());
12304 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12305 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12306 data2.get());
12308 scoped_refptr<HttpNetworkSession> session(
12309 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12311 // Start the first transaction to set up the SpdySession and verify that
12312 // connection was closed.
12313 HttpRequestInfo request1;
12314 request1.method = "GET";
12315 request1.url = GURL(https_url);
12316 request1.load_flags = 0;
12317 HttpNetworkTransaction trans1(MEDIUM, session.get());
12318 TestCompletionCallback callback1;
12319 EXPECT_EQ(ERR_IO_PENDING,
12320 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12321 base::MessageLoop::current()->RunUntilIdle();
12322 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
12324 // Now, start the second request and make sure it succeeds.
12325 HttpRequestInfo request2;
12326 request2.method = "GET";
12327 request2.url = GURL(https_url);
12328 request2.load_flags = 0;
12329 HttpNetworkTransaction trans2(MEDIUM, session.get());
12330 TestCompletionCallback callback2;
12331 EXPECT_EQ(ERR_IO_PENDING,
12332 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12333 base::MessageLoop::current()->RunUntilIdle();
12334 data2->RunFor(3);
12336 ASSERT_TRUE(callback2.have_result());
12337 EXPECT_EQ(OK, callback2.WaitForResult());
12338 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12341 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
12342 session_deps_.next_protos = SpdyNextProtos();
12343 ClientSocketPoolManager::set_max_sockets_per_group(
12344 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12345 ClientSocketPoolManager::set_max_sockets_per_pool(
12346 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12348 // Use two different hosts with different IPs so they don't get pooled.
12349 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
12350 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
12351 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12353 SSLSocketDataProvider ssl1(ASYNC, OK);
12354 ssl1.SetNextProto(GetParam());
12355 SSLSocketDataProvider ssl2(ASYNC, OK);
12356 ssl2.SetNextProto(GetParam());
12357 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12360 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
12361 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
12362 MockWrite spdy1_writes[] = {
12363 CreateMockWrite(*host1_req, 1),
12365 scoped_ptr<SpdyFrame> host1_resp(
12366 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12367 scoped_ptr<SpdyFrame> host1_resp_body(
12368 spdy_util_.ConstructSpdyBodyFrame(1, true));
12369 MockRead spdy1_reads[] = {
12370 CreateMockRead(*host1_resp, 2),
12371 CreateMockRead(*host1_resp_body, 3),
12372 MockRead(ASYNC, ERR_IO_PENDING, 4),
12375 scoped_ptr<OrderedSocketData> spdy1_data(
12376 new OrderedSocketData(
12377 spdy1_reads, arraysize(spdy1_reads),
12378 spdy1_writes, arraysize(spdy1_writes)));
12379 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
12381 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
12382 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
12383 MockWrite spdy2_writes[] = {
12384 CreateMockWrite(*host2_req, 1),
12386 scoped_ptr<SpdyFrame> host2_resp(
12387 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12388 scoped_ptr<SpdyFrame> host2_resp_body(
12389 spdy_util_.ConstructSpdyBodyFrame(1, true));
12390 MockRead spdy2_reads[] = {
12391 CreateMockRead(*host2_resp, 2),
12392 CreateMockRead(*host2_resp_body, 3),
12393 MockRead(ASYNC, ERR_IO_PENDING, 4),
12396 scoped_ptr<OrderedSocketData> spdy2_data(
12397 new OrderedSocketData(
12398 spdy2_reads, arraysize(spdy2_reads),
12399 spdy2_writes, arraysize(spdy2_writes)));
12400 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
12402 MockWrite http_write[] = {
12403 MockWrite("GET / HTTP/1.1\r\n"
12404 "Host: www.a.com\r\n"
12405 "Connection: keep-alive\r\n\r\n"),
12408 MockRead http_read[] = {
12409 MockRead("HTTP/1.1 200 OK\r\n"),
12410 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12411 MockRead("Content-Length: 6\r\n\r\n"),
12412 MockRead("hello!"),
12414 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
12415 http_write, arraysize(http_write));
12416 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12418 HostPortPair host_port_pair_a("www.a.com", 443);
12419 SpdySessionKey spdy_session_key_a(
12420 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12421 EXPECT_FALSE(
12422 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12424 TestCompletionCallback callback;
12425 HttpRequestInfo request1;
12426 request1.method = "GET";
12427 request1.url = GURL("https://www.a.com/");
12428 request1.load_flags = 0;
12429 scoped_ptr<HttpNetworkTransaction> trans(
12430 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12432 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
12433 EXPECT_EQ(ERR_IO_PENDING, rv);
12434 EXPECT_EQ(OK, callback.WaitForResult());
12436 const HttpResponseInfo* response = trans->GetResponseInfo();
12437 ASSERT_TRUE(response != NULL);
12438 ASSERT_TRUE(response->headers.get() != NULL);
12439 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12440 EXPECT_TRUE(response->was_fetched_via_spdy);
12441 EXPECT_TRUE(response->was_npn_negotiated);
12443 std::string response_data;
12444 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12445 EXPECT_EQ("hello!", response_data);
12446 trans.reset();
12447 EXPECT_TRUE(
12448 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12450 HostPortPair host_port_pair_b("www.b.com", 443);
12451 SpdySessionKey spdy_session_key_b(
12452 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12453 EXPECT_FALSE(
12454 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12455 HttpRequestInfo request2;
12456 request2.method = "GET";
12457 request2.url = GURL("https://www.b.com/");
12458 request2.load_flags = 0;
12459 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12461 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
12462 EXPECT_EQ(ERR_IO_PENDING, rv);
12463 EXPECT_EQ(OK, callback.WaitForResult());
12465 response = trans->GetResponseInfo();
12466 ASSERT_TRUE(response != NULL);
12467 ASSERT_TRUE(response->headers.get() != NULL);
12468 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12469 EXPECT_TRUE(response->was_fetched_via_spdy);
12470 EXPECT_TRUE(response->was_npn_negotiated);
12471 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12472 EXPECT_EQ("hello!", response_data);
12473 EXPECT_FALSE(
12474 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12475 EXPECT_TRUE(
12476 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12478 HostPortPair host_port_pair_a1("www.a.com", 80);
12479 SpdySessionKey spdy_session_key_a1(
12480 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12481 EXPECT_FALSE(
12482 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
12483 HttpRequestInfo request3;
12484 request3.method = "GET";
12485 request3.url = GURL("http://www.a.com/");
12486 request3.load_flags = 0;
12487 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12489 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
12490 EXPECT_EQ(ERR_IO_PENDING, rv);
12491 EXPECT_EQ(OK, callback.WaitForResult());
12493 response = trans->GetResponseInfo();
12494 ASSERT_TRUE(response != NULL);
12495 ASSERT_TRUE(response->headers.get() != NULL);
12496 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12497 EXPECT_FALSE(response->was_fetched_via_spdy);
12498 EXPECT_FALSE(response->was_npn_negotiated);
12499 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12500 EXPECT_EQ("hello!", response_data);
12501 EXPECT_FALSE(
12502 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12503 EXPECT_FALSE(
12504 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12507 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
12508 HttpRequestInfo request;
12509 request.method = "GET";
12510 request.url = GURL("http://www.example.org/");
12511 request.load_flags = 0;
12513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12514 scoped_ptr<HttpTransaction> trans(
12515 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12517 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
12518 StaticSocketDataProvider data;
12519 data.set_connect_data(mock_connect);
12520 session_deps_.socket_factory->AddSocketDataProvider(&data);
12522 TestCompletionCallback callback;
12524 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12525 EXPECT_EQ(ERR_IO_PENDING, rv);
12527 rv = callback.WaitForResult();
12528 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12530 EXPECT_EQ(NULL, trans->GetResponseInfo());
12532 // We don't care whether this succeeds or fails, but it shouldn't crash.
12533 HttpRequestHeaders request_headers;
12534 trans->GetFullRequestHeaders(&request_headers);
12536 ConnectionAttempts attempts;
12537 trans->GetConnectionAttempts(&attempts);
12538 ASSERT_EQ(1u, attempts.size());
12539 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12542 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
12543 HttpRequestInfo request;
12544 request.method = "GET";
12545 request.url = GURL("http://www.example.org/");
12546 request.load_flags = 0;
12548 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12549 scoped_ptr<HttpTransaction> trans(
12550 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12552 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12553 StaticSocketDataProvider data;
12554 data.set_connect_data(mock_connect);
12555 session_deps_.socket_factory->AddSocketDataProvider(&data);
12557 TestCompletionCallback callback;
12559 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12560 EXPECT_EQ(ERR_IO_PENDING, rv);
12562 rv = callback.WaitForResult();
12563 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12565 EXPECT_EQ(NULL, trans->GetResponseInfo());
12567 // We don't care whether this succeeds or fails, but it shouldn't crash.
12568 HttpRequestHeaders request_headers;
12569 trans->GetFullRequestHeaders(&request_headers);
12571 ConnectionAttempts attempts;
12572 trans->GetConnectionAttempts(&attempts);
12573 ASSERT_EQ(1u, attempts.size());
12574 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12577 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
12578 HttpRequestInfo request;
12579 request.method = "GET";
12580 request.url = GURL("http://www.example.org/");
12581 request.load_flags = 0;
12583 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12584 scoped_ptr<HttpTransaction> trans(
12585 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12587 MockWrite data_writes[] = {
12588 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12590 MockRead data_reads[] = {
12591 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12594 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12595 data_writes, arraysize(data_writes));
12596 session_deps_.socket_factory->AddSocketDataProvider(&data);
12598 TestCompletionCallback callback;
12600 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12601 EXPECT_EQ(ERR_IO_PENDING, rv);
12603 rv = callback.WaitForResult();
12604 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12606 EXPECT_EQ(NULL, trans->GetResponseInfo());
12608 HttpRequestHeaders request_headers;
12609 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12610 EXPECT_TRUE(request_headers.HasHeader("Host"));
12613 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
12614 HttpRequestInfo request;
12615 request.method = "GET";
12616 request.url = GURL("http://www.example.org/");
12617 request.load_flags = 0;
12619 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12620 scoped_ptr<HttpTransaction> trans(
12621 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12623 MockWrite data_writes[] = {
12624 MockWrite(ASYNC, ERR_CONNECTION_RESET),
12626 MockRead data_reads[] = {
12627 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12630 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12631 data_writes, arraysize(data_writes));
12632 session_deps_.socket_factory->AddSocketDataProvider(&data);
12634 TestCompletionCallback callback;
12636 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12637 EXPECT_EQ(ERR_IO_PENDING, rv);
12639 rv = callback.WaitForResult();
12640 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12642 EXPECT_EQ(NULL, trans->GetResponseInfo());
12644 HttpRequestHeaders request_headers;
12645 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12646 EXPECT_TRUE(request_headers.HasHeader("Host"));
12649 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
12650 HttpRequestInfo request;
12651 request.method = "GET";
12652 request.url = GURL("http://www.example.org/");
12653 request.load_flags = 0;
12655 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12656 scoped_ptr<HttpTransaction> trans(
12657 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12659 MockWrite data_writes[] = {
12660 MockWrite(
12661 "GET / HTTP/1.1\r\n"
12662 "Host: www.example.org\r\n"
12663 "Connection: keep-alive\r\n\r\n"),
12665 MockRead data_reads[] = {
12666 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
12669 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12670 data_writes, arraysize(data_writes));
12671 session_deps_.socket_factory->AddSocketDataProvider(&data);
12673 TestCompletionCallback callback;
12675 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12676 EXPECT_EQ(ERR_IO_PENDING, rv);
12678 rv = callback.WaitForResult();
12679 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12681 EXPECT_EQ(NULL, trans->GetResponseInfo());
12683 HttpRequestHeaders request_headers;
12684 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12685 EXPECT_TRUE(request_headers.HasHeader("Host"));
12688 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
12689 HttpRequestInfo request;
12690 request.method = "GET";
12691 request.url = GURL("http://www.example.org/");
12692 request.load_flags = 0;
12694 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12695 scoped_ptr<HttpTransaction> trans(
12696 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12698 MockWrite data_writes[] = {
12699 MockWrite(
12700 "GET / HTTP/1.1\r\n"
12701 "Host: www.example.org\r\n"
12702 "Connection: keep-alive\r\n\r\n"),
12704 MockRead data_reads[] = {
12705 MockRead(ASYNC, ERR_CONNECTION_RESET),
12708 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12709 data_writes, arraysize(data_writes));
12710 session_deps_.socket_factory->AddSocketDataProvider(&data);
12712 TestCompletionCallback callback;
12714 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12715 EXPECT_EQ(ERR_IO_PENDING, rv);
12717 rv = callback.WaitForResult();
12718 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12720 EXPECT_EQ(NULL, trans->GetResponseInfo());
12722 HttpRequestHeaders request_headers;
12723 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12724 EXPECT_TRUE(request_headers.HasHeader("Host"));
12727 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12728 HttpRequestInfo request;
12729 request.method = "GET";
12730 request.url = GURL("http://www.example.org/");
12731 request.load_flags = 0;
12732 request.extra_headers.SetHeader("X-Foo", "bar");
12734 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12735 scoped_ptr<HttpTransaction> trans(
12736 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12738 MockWrite data_writes[] = {
12739 MockWrite(
12740 "GET / HTTP/1.1\r\n"
12741 "Host: www.example.org\r\n"
12742 "Connection: keep-alive\r\n"
12743 "X-Foo: bar\r\n\r\n"),
12745 MockRead data_reads[] = {
12746 MockRead("HTTP/1.1 200 OK\r\n"
12747 "Content-Length: 5\r\n\r\n"
12748 "hello"),
12749 MockRead(ASYNC, ERR_UNEXPECTED),
12752 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12753 data_writes, arraysize(data_writes));
12754 session_deps_.socket_factory->AddSocketDataProvider(&data);
12756 TestCompletionCallback callback;
12758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12759 EXPECT_EQ(ERR_IO_PENDING, rv);
12761 rv = callback.WaitForResult();
12762 EXPECT_EQ(OK, rv);
12764 HttpRequestHeaders request_headers;
12765 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12766 std::string foo;
12767 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12768 EXPECT_EQ("bar", foo);
12771 namespace {
12773 // Fake HttpStream that simply records calls to SetPriority().
12774 class FakeStream : public HttpStream,
12775 public base::SupportsWeakPtr<FakeStream> {
12776 public:
12777 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12778 ~FakeStream() override {}
12780 RequestPriority priority() const { return priority_; }
12782 int InitializeStream(const HttpRequestInfo* request_info,
12783 RequestPriority priority,
12784 const BoundNetLog& net_log,
12785 const CompletionCallback& callback) override {
12786 return ERR_IO_PENDING;
12789 int SendRequest(const HttpRequestHeaders& request_headers,
12790 HttpResponseInfo* response,
12791 const CompletionCallback& callback) override {
12792 ADD_FAILURE();
12793 return ERR_UNEXPECTED;
12796 int ReadResponseHeaders(const CompletionCallback& callback) override {
12797 ADD_FAILURE();
12798 return ERR_UNEXPECTED;
12801 int ReadResponseBody(IOBuffer* buf,
12802 int buf_len,
12803 const CompletionCallback& callback) override {
12804 ADD_FAILURE();
12805 return ERR_UNEXPECTED;
12808 void Close(bool not_reusable) override {}
12810 bool IsResponseBodyComplete() const override {
12811 ADD_FAILURE();
12812 return false;
12815 bool CanFindEndOfResponse() const override { return false; }
12817 bool IsConnectionReused() const override {
12818 ADD_FAILURE();
12819 return false;
12822 void SetConnectionReused() override { ADD_FAILURE(); }
12824 bool IsConnectionReusable() const override {
12825 ADD_FAILURE();
12826 return false;
12829 int64 GetTotalReceivedBytes() const override {
12830 ADD_FAILURE();
12831 return 0;
12834 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
12835 ADD_FAILURE();
12836 return false;
12839 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
12841 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
12842 ADD_FAILURE();
12845 bool IsSpdyHttpStream() const override {
12846 ADD_FAILURE();
12847 return false;
12850 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
12852 void SetPriority(RequestPriority priority) override { priority_ = priority; }
12854 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
12856 HttpStream* RenewStreamForAuth() override { return NULL; }
12858 private:
12859 RequestPriority priority_;
12861 DISALLOW_COPY_AND_ASSIGN(FakeStream);
12864 // Fake HttpStreamRequest that simply records calls to SetPriority()
12865 // and vends FakeStreams with its current priority.
12866 class FakeStreamRequest : public HttpStreamRequest,
12867 public base::SupportsWeakPtr<FakeStreamRequest> {
12868 public:
12869 FakeStreamRequest(RequestPriority priority,
12870 HttpStreamRequest::Delegate* delegate)
12871 : priority_(priority),
12872 delegate_(delegate),
12873 websocket_stream_create_helper_(NULL) {}
12875 FakeStreamRequest(RequestPriority priority,
12876 HttpStreamRequest::Delegate* delegate,
12877 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
12878 : priority_(priority),
12879 delegate_(delegate),
12880 websocket_stream_create_helper_(create_helper) {}
12882 ~FakeStreamRequest() override {}
12884 RequestPriority priority() const { return priority_; }
12886 const WebSocketHandshakeStreamBase::CreateHelper*
12887 websocket_stream_create_helper() const {
12888 return websocket_stream_create_helper_;
12891 // Create a new FakeStream and pass it to the request's
12892 // delegate. Returns a weak pointer to the FakeStream.
12893 base::WeakPtr<FakeStream> FinishStreamRequest() {
12894 FakeStream* fake_stream = new FakeStream(priority_);
12895 // Do this before calling OnStreamReady() as OnStreamReady() may
12896 // immediately delete |fake_stream|.
12897 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
12898 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
12899 return weak_stream;
12902 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
12903 ADD_FAILURE();
12904 return ERR_UNEXPECTED;
12907 LoadState GetLoadState() const override {
12908 ADD_FAILURE();
12909 return LoadState();
12912 void SetPriority(RequestPriority priority) override { priority_ = priority; }
12914 bool was_npn_negotiated() const override { return false; }
12916 NextProto protocol_negotiated() const override { return kProtoUnknown; }
12918 bool using_spdy() const override { return false; }
12920 const ConnectionAttempts& connection_attempts() const override {
12921 static ConnectionAttempts no_attempts;
12922 return no_attempts;
12925 private:
12926 RequestPriority priority_;
12927 HttpStreamRequest::Delegate* const delegate_;
12928 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
12930 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12933 // Fake HttpStreamFactory that vends FakeStreamRequests.
12934 class FakeStreamFactory : public HttpStreamFactory {
12935 public:
12936 FakeStreamFactory() {}
12937 ~FakeStreamFactory() override {}
12939 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12940 // RequestStream() (which may be NULL if it was destroyed already).
12941 base::WeakPtr<FakeStreamRequest> last_stream_request() {
12942 return last_stream_request_;
12945 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
12946 RequestPriority priority,
12947 const SSLConfig& server_ssl_config,
12948 const SSLConfig& proxy_ssl_config,
12949 HttpStreamRequest::Delegate* delegate,
12950 const BoundNetLog& net_log) override {
12951 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12952 last_stream_request_ = fake_request->AsWeakPtr();
12953 return fake_request;
12956 HttpStreamRequest* RequestWebSocketHandshakeStream(
12957 const HttpRequestInfo& info,
12958 RequestPriority priority,
12959 const SSLConfig& server_ssl_config,
12960 const SSLConfig& proxy_ssl_config,
12961 HttpStreamRequest::Delegate* delegate,
12962 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
12963 const BoundNetLog& net_log) override {
12964 FakeStreamRequest* fake_request =
12965 new FakeStreamRequest(priority, delegate, create_helper);
12966 last_stream_request_ = fake_request->AsWeakPtr();
12967 return fake_request;
12970 void PreconnectStreams(int num_streams,
12971 const HttpRequestInfo& info,
12972 RequestPriority priority,
12973 const SSLConfig& server_ssl_config,
12974 const SSLConfig& proxy_ssl_config) override {
12975 ADD_FAILURE();
12978 const HostMappingRules* GetHostMappingRules() const override {
12979 ADD_FAILURE();
12980 return NULL;
12983 private:
12984 base::WeakPtr<FakeStreamRequest> last_stream_request_;
12986 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12989 // TODO(ricea): Maybe unify this with the one in
12990 // url_request_http_job_unittest.cc ?
12991 class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
12992 public:
12993 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
12994 bool using_proxy)
12995 : state_(connection.release(), using_proxy) {}
12997 // Fake implementation of HttpStreamBase methods.
12998 // This ends up being quite "real" because this object has to really send data
12999 // on the mock socket. It might be easier to use the real implementation, but
13000 // the fact that the WebSocket code is not compiled on iOS makes that
13001 // difficult.
13002 int InitializeStream(const HttpRequestInfo* request_info,
13003 RequestPriority priority,
13004 const BoundNetLog& net_log,
13005 const CompletionCallback& callback) override {
13006 state_.Initialize(request_info, priority, net_log, callback);
13007 return OK;
13010 int SendRequest(const HttpRequestHeaders& request_headers,
13011 HttpResponseInfo* response,
13012 const CompletionCallback& callback) override {
13013 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
13014 response, callback);
13017 int ReadResponseHeaders(const CompletionCallback& callback) override {
13018 return parser()->ReadResponseHeaders(callback);
13021 int ReadResponseBody(IOBuffer* buf,
13022 int buf_len,
13023 const CompletionCallback& callback) override {
13024 NOTREACHED();
13025 return ERR_IO_PENDING;
13028 void Close(bool not_reusable) override {
13029 if (parser())
13030 parser()->Close(true);
13033 bool IsResponseBodyComplete() const override {
13034 NOTREACHED();
13035 return false;
13038 bool CanFindEndOfResponse() const override {
13039 return parser()->CanFindEndOfResponse();
13042 bool IsConnectionReused() const override {
13043 NOTREACHED();
13044 return false;
13046 void SetConnectionReused() override { NOTREACHED(); }
13048 bool IsConnectionReusable() const override {
13049 NOTREACHED();
13050 return false;
13053 int64 GetTotalReceivedBytes() const override {
13054 NOTREACHED();
13055 return 0;
13058 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13059 NOTREACHED();
13060 return false;
13063 void GetSSLInfo(SSLInfo* ssl_info) override {}
13065 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13066 NOTREACHED();
13069 bool IsSpdyHttpStream() const override {
13070 NOTREACHED();
13071 return false;
13074 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
13076 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
13078 UploadProgress GetUploadProgress() const override {
13079 NOTREACHED();
13080 return UploadProgress();
13083 HttpStream* RenewStreamForAuth() override {
13084 NOTREACHED();
13085 return nullptr;
13088 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13089 scoped_ptr<WebSocketStream> Upgrade() override {
13090 NOTREACHED();
13091 return scoped_ptr<WebSocketStream>();
13094 private:
13095 HttpStreamParser* parser() const { return state_.parser(); }
13096 HttpBasicState state_;
13098 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
13101 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13102 // worth doing.
13103 class FakeWebSocketStreamCreateHelper :
13104 public WebSocketHandshakeStreamBase::CreateHelper {
13105 public:
13106 WebSocketHandshakeStreamBase* CreateBasicStream(
13107 scoped_ptr<ClientSocketHandle> connection,
13108 bool using_proxy) override {
13109 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
13110 using_proxy);
13113 WebSocketHandshakeStreamBase* CreateSpdyStream(
13114 const base::WeakPtr<SpdySession>& session,
13115 bool use_relative_url) override {
13116 NOTREACHED();
13117 return NULL;
13120 ~FakeWebSocketStreamCreateHelper() override {}
13122 virtual scoped_ptr<WebSocketStream> Upgrade() {
13123 NOTREACHED();
13124 return scoped_ptr<WebSocketStream>();
13128 } // namespace
13130 // Make sure that HttpNetworkTransaction passes on its priority to its
13131 // stream request on start.
13132 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
13133 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13134 HttpNetworkSessionPeer peer(session);
13135 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13136 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13138 HttpNetworkTransaction trans(LOW, session.get());
13140 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
13142 HttpRequestInfo request;
13143 TestCompletionCallback callback;
13144 EXPECT_EQ(ERR_IO_PENDING,
13145 trans.Start(&request, callback.callback(), BoundNetLog()));
13147 base::WeakPtr<FakeStreamRequest> fake_request =
13148 fake_factory->last_stream_request();
13149 ASSERT_TRUE(fake_request != NULL);
13150 EXPECT_EQ(LOW, fake_request->priority());
13153 // Make sure that HttpNetworkTransaction passes on its priority
13154 // updates to its stream request.
13155 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
13156 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13157 HttpNetworkSessionPeer peer(session);
13158 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13159 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13161 HttpNetworkTransaction trans(LOW, session.get());
13163 HttpRequestInfo request;
13164 TestCompletionCallback callback;
13165 EXPECT_EQ(ERR_IO_PENDING,
13166 trans.Start(&request, callback.callback(), BoundNetLog()));
13168 base::WeakPtr<FakeStreamRequest> fake_request =
13169 fake_factory->last_stream_request();
13170 ASSERT_TRUE(fake_request != NULL);
13171 EXPECT_EQ(LOW, fake_request->priority());
13173 trans.SetPriority(LOWEST);
13174 ASSERT_TRUE(fake_request != NULL);
13175 EXPECT_EQ(LOWEST, fake_request->priority());
13178 // Make sure that HttpNetworkTransaction passes on its priority
13179 // updates to its stream.
13180 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
13181 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13182 HttpNetworkSessionPeer peer(session);
13183 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13184 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13186 HttpNetworkTransaction trans(LOW, session.get());
13188 HttpRequestInfo request;
13189 TestCompletionCallback callback;
13190 EXPECT_EQ(ERR_IO_PENDING,
13191 trans.Start(&request, callback.callback(), BoundNetLog()));
13193 base::WeakPtr<FakeStreamRequest> fake_request =
13194 fake_factory->last_stream_request();
13195 ASSERT_TRUE(fake_request != NULL);
13196 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
13197 ASSERT_TRUE(fake_stream != NULL);
13198 EXPECT_EQ(LOW, fake_stream->priority());
13200 trans.SetPriority(LOWEST);
13201 EXPECT_EQ(LOWEST, fake_stream->priority());
13204 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
13205 // The same logic needs to be tested for both ws: and wss: schemes, but this
13206 // test is already parameterised on NextProto, so it uses a loop to verify
13207 // that the different schemes work.
13208 std::string test_cases[] = {"ws://www.example.org/",
13209 "wss://www.example.org/"};
13210 for (size_t i = 0; i < arraysize(test_cases); ++i) {
13211 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13212 HttpNetworkSessionPeer peer(session);
13213 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13214 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13215 peer.SetHttpStreamFactoryForWebSocket(
13216 scoped_ptr<HttpStreamFactory>(fake_factory));
13218 HttpNetworkTransaction trans(LOW, session.get());
13219 trans.SetWebSocketHandshakeStreamCreateHelper(
13220 &websocket_stream_create_helper);
13222 HttpRequestInfo request;
13223 TestCompletionCallback callback;
13224 request.method = "GET";
13225 request.url = GURL(test_cases[i]);
13227 EXPECT_EQ(ERR_IO_PENDING,
13228 trans.Start(&request, callback.callback(), BoundNetLog()));
13230 base::WeakPtr<FakeStreamRequest> fake_request =
13231 fake_factory->last_stream_request();
13232 ASSERT_TRUE(fake_request != NULL);
13233 EXPECT_EQ(&websocket_stream_create_helper,
13234 fake_request->websocket_stream_create_helper());
13238 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13239 // if the transport socket pool is stalled on the global socket limit.
13240 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
13241 ClientSocketPoolManager::set_max_sockets_per_group(
13242 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13243 ClientSocketPoolManager::set_max_sockets_per_pool(
13244 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13246 // Set up SSL request.
13248 HttpRequestInfo ssl_request;
13249 ssl_request.method = "GET";
13250 ssl_request.url = GURL("https://www.example.org/");
13252 MockWrite ssl_writes[] = {
13253 MockWrite(
13254 "GET / HTTP/1.1\r\n"
13255 "Host: www.example.org\r\n"
13256 "Connection: keep-alive\r\n\r\n"),
13258 MockRead ssl_reads[] = {
13259 MockRead("HTTP/1.1 200 OK\r\n"),
13260 MockRead("Content-Length: 11\r\n\r\n"),
13261 MockRead("hello world"),
13262 MockRead(SYNCHRONOUS, OK),
13264 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
13265 ssl_writes, arraysize(ssl_writes));
13266 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13268 SSLSocketDataProvider ssl(ASYNC, OK);
13269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13271 // Set up HTTP request.
13273 HttpRequestInfo http_request;
13274 http_request.method = "GET";
13275 http_request.url = GURL("http://www.example.org/");
13277 MockWrite http_writes[] = {
13278 MockWrite(
13279 "GET / HTTP/1.1\r\n"
13280 "Host: www.example.org\r\n"
13281 "Connection: keep-alive\r\n\r\n"),
13283 MockRead http_reads[] = {
13284 MockRead("HTTP/1.1 200 OK\r\n"),
13285 MockRead("Content-Length: 7\r\n\r\n"),
13286 MockRead("falafel"),
13287 MockRead(SYNCHRONOUS, OK),
13289 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13290 http_writes, arraysize(http_writes));
13291 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13293 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13295 // Start the SSL request.
13296 TestCompletionCallback ssl_callback;
13297 scoped_ptr<HttpTransaction> ssl_trans(
13298 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13299 ASSERT_EQ(ERR_IO_PENDING,
13300 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
13301 BoundNetLog()));
13303 // Start the HTTP request. Pool should stall.
13304 TestCompletionCallback http_callback;
13305 scoped_ptr<HttpTransaction> http_trans(
13306 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13307 ASSERT_EQ(ERR_IO_PENDING,
13308 http_trans->Start(&http_request, http_callback.callback(),
13309 BoundNetLog()));
13310 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13312 // Wait for response from SSL request.
13313 ASSERT_EQ(OK, ssl_callback.WaitForResult());
13314 std::string response_data;
13315 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
13316 EXPECT_EQ("hello world", response_data);
13318 // The SSL socket should automatically be closed, so the HTTP request can
13319 // start.
13320 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13321 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
13323 // The HTTP request can now complete.
13324 ASSERT_EQ(OK, http_callback.WaitForResult());
13325 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13326 EXPECT_EQ("falafel", response_data);
13328 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13331 // Tests that when a SSL connection is established but there's no corresponding
13332 // request that needs it, the new socket is closed if the transport socket pool
13333 // is stalled on the global socket limit.
13334 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
13335 ClientSocketPoolManager::set_max_sockets_per_group(
13336 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13337 ClientSocketPoolManager::set_max_sockets_per_pool(
13338 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13340 // Set up an ssl request.
13342 HttpRequestInfo ssl_request;
13343 ssl_request.method = "GET";
13344 ssl_request.url = GURL("https://www.foopy.com/");
13346 // No data will be sent on the SSL socket.
13347 StaticSocketDataProvider ssl_data;
13348 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13350 SSLSocketDataProvider ssl(ASYNC, OK);
13351 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13353 // Set up HTTP request.
13355 HttpRequestInfo http_request;
13356 http_request.method = "GET";
13357 http_request.url = GURL("http://www.example.org/");
13359 MockWrite http_writes[] = {
13360 MockWrite(
13361 "GET / HTTP/1.1\r\n"
13362 "Host: www.example.org\r\n"
13363 "Connection: keep-alive\r\n\r\n"),
13365 MockRead http_reads[] = {
13366 MockRead("HTTP/1.1 200 OK\r\n"),
13367 MockRead("Content-Length: 7\r\n\r\n"),
13368 MockRead("falafel"),
13369 MockRead(SYNCHRONOUS, OK),
13371 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13372 http_writes, arraysize(http_writes));
13373 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13377 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13378 // cancelled when a normal transaction is cancelled.
13379 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
13380 SSLConfig ssl_config;
13381 session->ssl_config_service()->GetSSLConfig(&ssl_config);
13382 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
13383 ssl_config, ssl_config);
13384 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13386 // Start the HTTP request. Pool should stall.
13387 TestCompletionCallback http_callback;
13388 scoped_ptr<HttpTransaction> http_trans(
13389 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13390 ASSERT_EQ(ERR_IO_PENDING,
13391 http_trans->Start(&http_request, http_callback.callback(),
13392 BoundNetLog()));
13393 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13395 // The SSL connection will automatically be closed once the connection is
13396 // established, to let the HTTP request start.
13397 ASSERT_EQ(OK, http_callback.WaitForResult());
13398 std::string response_data;
13399 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13400 EXPECT_EQ("falafel", response_data);
13402 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13405 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
13406 ScopedVector<UploadElementReader> element_readers;
13407 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13408 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13410 HttpRequestInfo request;
13411 request.method = "POST";
13412 request.url = GURL("http://www.foo.com/");
13413 request.upload_data_stream = &upload_data_stream;
13414 request.load_flags = 0;
13416 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13417 scoped_ptr<HttpTransaction> trans(
13418 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13419 // Send headers successfully, but get an error while sending the body.
13420 MockWrite data_writes[] = {
13421 MockWrite("POST / HTTP/1.1\r\n"
13422 "Host: www.foo.com\r\n"
13423 "Connection: keep-alive\r\n"
13424 "Content-Length: 3\r\n\r\n"),
13425 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13428 MockRead data_reads[] = {
13429 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13430 MockRead("hello world"),
13431 MockRead(SYNCHRONOUS, OK),
13433 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13434 arraysize(data_writes));
13435 session_deps_.socket_factory->AddSocketDataProvider(&data);
13437 TestCompletionCallback callback;
13439 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13440 EXPECT_EQ(ERR_IO_PENDING, rv);
13442 rv = callback.WaitForResult();
13443 EXPECT_EQ(OK, rv);
13445 const HttpResponseInfo* response = trans->GetResponseInfo();
13446 ASSERT_TRUE(response != NULL);
13448 EXPECT_TRUE(response->headers.get() != NULL);
13449 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13451 std::string response_data;
13452 rv = ReadTransaction(trans.get(), &response_data);
13453 EXPECT_EQ(OK, rv);
13454 EXPECT_EQ("hello world", response_data);
13457 // This test makes sure the retry logic doesn't trigger when reading an error
13458 // response from a server that rejected a POST with a CONNECTION_RESET.
13459 TEST_P(HttpNetworkTransactionTest,
13460 PostReadsErrorResponseAfterResetOnReusedSocket) {
13461 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13462 MockWrite data_writes[] = {
13463 MockWrite("GET / HTTP/1.1\r\n"
13464 "Host: www.foo.com\r\n"
13465 "Connection: keep-alive\r\n\r\n"),
13466 MockWrite("POST / HTTP/1.1\r\n"
13467 "Host: www.foo.com\r\n"
13468 "Connection: keep-alive\r\n"
13469 "Content-Length: 3\r\n\r\n"),
13470 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13473 MockRead data_reads[] = {
13474 MockRead("HTTP/1.1 200 Peachy\r\n"
13475 "Content-Length: 14\r\n\r\n"),
13476 MockRead("first response"),
13477 MockRead("HTTP/1.1 400 Not OK\r\n"
13478 "Content-Length: 15\r\n\r\n"),
13479 MockRead("second response"),
13480 MockRead(SYNCHRONOUS, OK),
13482 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13483 arraysize(data_writes));
13484 session_deps_.socket_factory->AddSocketDataProvider(&data);
13486 TestCompletionCallback callback;
13487 HttpRequestInfo request1;
13488 request1.method = "GET";
13489 request1.url = GURL("http://www.foo.com/");
13490 request1.load_flags = 0;
13492 scoped_ptr<HttpTransaction> trans1(
13493 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13494 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
13495 EXPECT_EQ(ERR_IO_PENDING, rv);
13497 rv = callback.WaitForResult();
13498 EXPECT_EQ(OK, rv);
13500 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13501 ASSERT_TRUE(response1 != NULL);
13503 EXPECT_TRUE(response1->headers.get() != NULL);
13504 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
13506 std::string response_data1;
13507 rv = ReadTransaction(trans1.get(), &response_data1);
13508 EXPECT_EQ(OK, rv);
13509 EXPECT_EQ("first response", response_data1);
13510 // Delete the transaction to release the socket back into the socket pool.
13511 trans1.reset();
13513 ScopedVector<UploadElementReader> element_readers;
13514 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13515 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13517 HttpRequestInfo request2;
13518 request2.method = "POST";
13519 request2.url = GURL("http://www.foo.com/");
13520 request2.upload_data_stream = &upload_data_stream;
13521 request2.load_flags = 0;
13523 scoped_ptr<HttpTransaction> trans2(
13524 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13525 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
13526 EXPECT_EQ(ERR_IO_PENDING, rv);
13528 rv = callback.WaitForResult();
13529 EXPECT_EQ(OK, rv);
13531 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
13532 ASSERT_TRUE(response2 != NULL);
13534 EXPECT_TRUE(response2->headers.get() != NULL);
13535 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
13537 std::string response_data2;
13538 rv = ReadTransaction(trans2.get(), &response_data2);
13539 EXPECT_EQ(OK, rv);
13540 EXPECT_EQ("second response", response_data2);
13543 TEST_P(HttpNetworkTransactionTest,
13544 PostReadsErrorResponseAfterResetPartialBodySent) {
13545 ScopedVector<UploadElementReader> element_readers;
13546 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13547 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13549 HttpRequestInfo request;
13550 request.method = "POST";
13551 request.url = GURL("http://www.foo.com/");
13552 request.upload_data_stream = &upload_data_stream;
13553 request.load_flags = 0;
13555 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13556 scoped_ptr<HttpTransaction> trans(
13557 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13558 // Send headers successfully, but get an error while sending the body.
13559 MockWrite data_writes[] = {
13560 MockWrite("POST / HTTP/1.1\r\n"
13561 "Host: www.foo.com\r\n"
13562 "Connection: keep-alive\r\n"
13563 "Content-Length: 3\r\n\r\n"
13564 "fo"),
13565 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13568 MockRead data_reads[] = {
13569 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13570 MockRead("hello world"),
13571 MockRead(SYNCHRONOUS, OK),
13573 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13574 arraysize(data_writes));
13575 session_deps_.socket_factory->AddSocketDataProvider(&data);
13577 TestCompletionCallback callback;
13579 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13580 EXPECT_EQ(ERR_IO_PENDING, rv);
13582 rv = callback.WaitForResult();
13583 EXPECT_EQ(OK, rv);
13585 const HttpResponseInfo* response = trans->GetResponseInfo();
13586 ASSERT_TRUE(response != NULL);
13588 EXPECT_TRUE(response->headers.get() != NULL);
13589 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13591 std::string response_data;
13592 rv = ReadTransaction(trans.get(), &response_data);
13593 EXPECT_EQ(OK, rv);
13594 EXPECT_EQ("hello world", response_data);
13597 // This tests the more common case than the previous test, where headers and
13598 // body are not merged into a single request.
13599 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
13600 ScopedVector<UploadElementReader> element_readers;
13601 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13602 ChunkedUploadDataStream upload_data_stream(0);
13604 HttpRequestInfo request;
13605 request.method = "POST";
13606 request.url = GURL("http://www.foo.com/");
13607 request.upload_data_stream = &upload_data_stream;
13608 request.load_flags = 0;
13610 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13611 scoped_ptr<HttpTransaction> trans(
13612 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13613 // Send headers successfully, but get an error while sending the body.
13614 MockWrite data_writes[] = {
13615 MockWrite("POST / HTTP/1.1\r\n"
13616 "Host: www.foo.com\r\n"
13617 "Connection: keep-alive\r\n"
13618 "Transfer-Encoding: chunked\r\n\r\n"),
13619 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13622 MockRead data_reads[] = {
13623 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13624 MockRead("hello world"),
13625 MockRead(SYNCHRONOUS, OK),
13627 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13628 arraysize(data_writes));
13629 session_deps_.socket_factory->AddSocketDataProvider(&data);
13631 TestCompletionCallback callback;
13633 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13634 EXPECT_EQ(ERR_IO_PENDING, rv);
13635 // Make sure the headers are sent before adding a chunk. This ensures that
13636 // they can't be merged with the body in a single send. Not currently
13637 // necessary since a chunked body is never merged with headers, but this makes
13638 // the test more future proof.
13639 base::RunLoop().RunUntilIdle();
13641 upload_data_stream.AppendData("last chunk", 10, true);
13643 rv = callback.WaitForResult();
13644 EXPECT_EQ(OK, rv);
13646 const HttpResponseInfo* response = trans->GetResponseInfo();
13647 ASSERT_TRUE(response != NULL);
13649 EXPECT_TRUE(response->headers.get() != NULL);
13650 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13652 std::string response_data;
13653 rv = ReadTransaction(trans.get(), &response_data);
13654 EXPECT_EQ(OK, rv);
13655 EXPECT_EQ("hello world", response_data);
13658 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
13659 ScopedVector<UploadElementReader> element_readers;
13660 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13661 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13663 HttpRequestInfo request;
13664 request.method = "POST";
13665 request.url = GURL("http://www.foo.com/");
13666 request.upload_data_stream = &upload_data_stream;
13667 request.load_flags = 0;
13669 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13670 scoped_ptr<HttpTransaction> trans(
13671 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13673 MockWrite data_writes[] = {
13674 MockWrite("POST / HTTP/1.1\r\n"
13675 "Host: www.foo.com\r\n"
13676 "Connection: keep-alive\r\n"
13677 "Content-Length: 3\r\n\r\n"),
13678 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13681 MockRead data_reads[] = {
13682 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13683 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13684 MockRead("hello world"),
13685 MockRead(SYNCHRONOUS, OK),
13687 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13688 arraysize(data_writes));
13689 session_deps_.socket_factory->AddSocketDataProvider(&data);
13691 TestCompletionCallback callback;
13693 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13694 EXPECT_EQ(ERR_IO_PENDING, rv);
13696 rv = callback.WaitForResult();
13697 EXPECT_EQ(OK, rv);
13699 const HttpResponseInfo* response = trans->GetResponseInfo();
13700 ASSERT_TRUE(response != NULL);
13702 EXPECT_TRUE(response->headers.get() != NULL);
13703 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13705 std::string response_data;
13706 rv = ReadTransaction(trans.get(), &response_data);
13707 EXPECT_EQ(OK, rv);
13708 EXPECT_EQ("hello world", response_data);
13711 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
13712 ScopedVector<UploadElementReader> element_readers;
13713 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13714 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13716 HttpRequestInfo request;
13717 request.method = "POST";
13718 request.url = GURL("http://www.foo.com/");
13719 request.upload_data_stream = &upload_data_stream;
13720 request.load_flags = 0;
13722 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13723 scoped_ptr<HttpTransaction> trans(
13724 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13725 // Send headers successfully, but get an error while sending the body.
13726 MockWrite data_writes[] = {
13727 MockWrite("POST / HTTP/1.1\r\n"
13728 "Host: www.foo.com\r\n"
13729 "Connection: keep-alive\r\n"
13730 "Content-Length: 3\r\n\r\n"),
13731 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13734 MockRead data_reads[] = {
13735 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13736 MockRead("hello world"),
13737 MockRead(SYNCHRONOUS, OK),
13739 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13740 arraysize(data_writes));
13741 session_deps_.socket_factory->AddSocketDataProvider(&data);
13743 TestCompletionCallback callback;
13745 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13746 EXPECT_EQ(ERR_IO_PENDING, rv);
13748 rv = callback.WaitForResult();
13749 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13751 const HttpResponseInfo* response = trans->GetResponseInfo();
13752 EXPECT_TRUE(response == NULL);
13755 TEST_P(HttpNetworkTransactionTest,
13756 PostIgnoresNonErrorResponseAfterResetAnd100) {
13757 ScopedVector<UploadElementReader> element_readers;
13758 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13759 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13761 HttpRequestInfo request;
13762 request.method = "POST";
13763 request.url = GURL("http://www.foo.com/");
13764 request.upload_data_stream = &upload_data_stream;
13765 request.load_flags = 0;
13767 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13768 scoped_ptr<HttpTransaction> trans(
13769 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13770 // Send headers successfully, but get an error while sending the body.
13771 MockWrite data_writes[] = {
13772 MockWrite("POST / HTTP/1.1\r\n"
13773 "Host: www.foo.com\r\n"
13774 "Connection: keep-alive\r\n"
13775 "Content-Length: 3\r\n\r\n"),
13776 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13779 MockRead data_reads[] = {
13780 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13781 MockRead("HTTP/1.0 302 Redirect\r\n"),
13782 MockRead("Location: http://somewhere-else.com/\r\n"),
13783 MockRead("Content-Length: 0\r\n\r\n"),
13784 MockRead(SYNCHRONOUS, OK),
13786 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13787 arraysize(data_writes));
13788 session_deps_.socket_factory->AddSocketDataProvider(&data);
13790 TestCompletionCallback callback;
13792 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13793 EXPECT_EQ(ERR_IO_PENDING, rv);
13795 rv = callback.WaitForResult();
13796 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13798 const HttpResponseInfo* response = trans->GetResponseInfo();
13799 EXPECT_TRUE(response == NULL);
13802 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
13803 ScopedVector<UploadElementReader> element_readers;
13804 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13805 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13807 HttpRequestInfo request;
13808 request.method = "POST";
13809 request.url = GURL("http://www.foo.com/");
13810 request.upload_data_stream = &upload_data_stream;
13811 request.load_flags = 0;
13813 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13814 scoped_ptr<HttpTransaction> trans(
13815 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13816 // Send headers successfully, but get an error while sending the body.
13817 MockWrite data_writes[] = {
13818 MockWrite("POST / HTTP/1.1\r\n"
13819 "Host: www.foo.com\r\n"
13820 "Connection: keep-alive\r\n"
13821 "Content-Length: 3\r\n\r\n"),
13822 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13825 MockRead data_reads[] = {
13826 MockRead("HTTP 0.9 rocks!"),
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);
13838 rv = callback.WaitForResult();
13839 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13841 const HttpResponseInfo* response = trans->GetResponseInfo();
13842 EXPECT_TRUE(response == NULL);
13845 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
13846 ScopedVector<UploadElementReader> element_readers;
13847 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13848 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13850 HttpRequestInfo request;
13851 request.method = "POST";
13852 request.url = GURL("http://www.foo.com/");
13853 request.upload_data_stream = &upload_data_stream;
13854 request.load_flags = 0;
13856 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13857 scoped_ptr<HttpTransaction> trans(
13858 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13859 // Send headers successfully, but get an error while sending the body.
13860 MockWrite data_writes[] = {
13861 MockWrite("POST / HTTP/1.1\r\n"
13862 "Host: www.foo.com\r\n"
13863 "Connection: keep-alive\r\n"
13864 "Content-Length: 3\r\n\r\n"),
13865 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13868 MockRead data_reads[] = {
13869 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13870 MockRead(SYNCHRONOUS, OK),
13872 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13873 arraysize(data_writes));
13874 session_deps_.socket_factory->AddSocketDataProvider(&data);
13876 TestCompletionCallback callback;
13878 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13879 EXPECT_EQ(ERR_IO_PENDING, rv);
13881 rv = callback.WaitForResult();
13882 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13884 const HttpResponseInfo* response = trans->GetResponseInfo();
13885 EXPECT_TRUE(response == NULL);
13888 // Verify that proxy headers are not sent to the destination server when
13889 // establishing a tunnel for a secure WebSocket connection.
13890 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
13891 HttpRequestInfo request;
13892 request.method = "GET";
13893 request.url = GURL("wss://www.example.org/");
13894 AddWebSocketHeaders(&request.extra_headers);
13896 // Configure against proxy server "myproxy:70".
13897 session_deps_.proxy_service.reset(
13898 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13900 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13902 // Since a proxy is configured, try to establish a tunnel.
13903 MockWrite data_writes[] = {
13904 MockWrite(
13905 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13906 "Host: www.example.org\r\n"
13907 "Proxy-Connection: keep-alive\r\n\r\n"),
13909 // After calling trans->RestartWithAuth(), this is the request we should
13910 // be issuing -- the final header line contains the credentials.
13911 MockWrite(
13912 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13913 "Host: www.example.org\r\n"
13914 "Proxy-Connection: keep-alive\r\n"
13915 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13917 MockWrite(
13918 "GET / HTTP/1.1\r\n"
13919 "Host: www.example.org\r\n"
13920 "Connection: Upgrade\r\n"
13921 "Upgrade: websocket\r\n"
13922 "Origin: http://www.example.org\r\n"
13923 "Sec-WebSocket-Version: 13\r\n"
13924 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13927 // The proxy responds to the connect with a 407, using a persistent
13928 // connection.
13929 MockRead data_reads[] = {
13930 // No credentials.
13931 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
13932 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13933 MockRead("Proxy-Connection: close\r\n\r\n"),
13935 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13937 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13938 MockRead("Upgrade: websocket\r\n"),
13939 MockRead("Connection: Upgrade\r\n"),
13940 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13943 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13944 arraysize(data_writes));
13945 session_deps_.socket_factory->AddSocketDataProvider(&data);
13946 SSLSocketDataProvider ssl(ASYNC, OK);
13947 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13949 scoped_ptr<HttpTransaction> trans(
13950 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13951 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13952 trans->SetWebSocketHandshakeStreamCreateHelper(
13953 &websocket_stream_create_helper);
13956 TestCompletionCallback callback;
13958 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13959 EXPECT_EQ(ERR_IO_PENDING, rv);
13961 rv = callback.WaitForResult();
13962 EXPECT_EQ(OK, rv);
13965 const HttpResponseInfo* response = trans->GetResponseInfo();
13966 ASSERT_TRUE(response);
13967 ASSERT_TRUE(response->headers.get());
13968 EXPECT_EQ(407, response->headers->response_code());
13971 TestCompletionCallback callback;
13973 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
13974 callback.callback());
13975 EXPECT_EQ(ERR_IO_PENDING, rv);
13977 rv = callback.WaitForResult();
13978 EXPECT_EQ(OK, rv);
13981 response = trans->GetResponseInfo();
13982 ASSERT_TRUE(response);
13983 ASSERT_TRUE(response->headers.get());
13985 EXPECT_EQ(101, response->headers->response_code());
13987 trans.reset();
13988 session->CloseAllConnections();
13991 // Verify that proxy headers are not sent to the destination server when
13992 // establishing a tunnel for an insecure WebSocket connection.
13993 // This requires the authentication info to be injected into the auth cache
13994 // due to crbug.com/395064
13995 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
13996 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
13997 HttpRequestInfo request;
13998 request.method = "GET";
13999 request.url = GURL("ws://www.example.org/");
14000 AddWebSocketHeaders(&request.extra_headers);
14002 // Configure against proxy server "myproxy:70".
14003 session_deps_.proxy_service.reset(
14004 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14006 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14008 MockWrite data_writes[] = {
14009 // Try to establish a tunnel for the WebSocket connection, with
14010 // credentials. Because WebSockets have a separate set of socket pools,
14011 // they cannot and will not use the same TCP/IP connection as the
14012 // preflight HTTP request.
14013 MockWrite(
14014 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14015 "Host: www.example.org:80\r\n"
14016 "Proxy-Connection: keep-alive\r\n"
14017 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14019 MockWrite(
14020 "GET / HTTP/1.1\r\n"
14021 "Host: www.example.org\r\n"
14022 "Connection: Upgrade\r\n"
14023 "Upgrade: websocket\r\n"
14024 "Origin: http://www.example.org\r\n"
14025 "Sec-WebSocket-Version: 13\r\n"
14026 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14029 MockRead data_reads[] = {
14030 // HTTP CONNECT with credentials.
14031 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14033 // WebSocket connection established inside tunnel.
14034 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14035 MockRead("Upgrade: websocket\r\n"),
14036 MockRead("Connection: Upgrade\r\n"),
14037 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14040 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14041 arraysize(data_writes));
14042 session_deps_.socket_factory->AddSocketDataProvider(&data);
14044 session->http_auth_cache()->Add(
14045 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
14046 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
14048 scoped_ptr<HttpTransaction> trans(
14049 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14050 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14051 trans->SetWebSocketHandshakeStreamCreateHelper(
14052 &websocket_stream_create_helper);
14054 TestCompletionCallback callback;
14056 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14057 EXPECT_EQ(ERR_IO_PENDING, rv);
14059 rv = callback.WaitForResult();
14060 EXPECT_EQ(OK, rv);
14062 const HttpResponseInfo* response = trans->GetResponseInfo();
14063 ASSERT_TRUE(response);
14064 ASSERT_TRUE(response->headers.get());
14066 EXPECT_EQ(101, response->headers->response_code());
14068 trans.reset();
14069 session->CloseAllConnections();
14072 } // namespace net