Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blob8fbc13d750e41fec8ebd139c8876d3c4af33545b
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 "base/thread_task_runner_handle.h"
26 #include "net/base/auth.h"
27 #include "net/base/chunked_upload_data_stream.h"
28 #include "net/base/completion_callback.h"
29 #include "net/base/elements_upload_data_stream.h"
30 #include "net/base/load_timing_info.h"
31 #include "net/base/load_timing_info_test_util.h"
32 #include "net/base/net_errors.h"
33 #include "net/base/request_priority.h"
34 #include "net/base/test_completion_callback.h"
35 #include "net/base/test_data_directory.h"
36 #include "net/base/upload_bytes_element_reader.h"
37 #include "net/base/upload_file_element_reader.h"
38 #include "net/cert/mock_cert_verifier.h"
39 #include "net/dns/host_cache.h"
40 #include "net/dns/mock_host_resolver.h"
41 #include "net/http/http_auth_challenge_tokenizer.h"
42 #include "net/http/http_auth_handler_digest.h"
43 #include "net/http/http_auth_handler_mock.h"
44 #include "net/http/http_auth_handler_ntlm.h"
45 #include "net/http/http_basic_state.h"
46 #include "net/http/http_basic_stream.h"
47 #include "net/http/http_network_session.h"
48 #include "net/http/http_network_session_peer.h"
49 #include "net/http/http_request_headers.h"
50 #include "net/http/http_server_properties_impl.h"
51 #include "net/http/http_stream.h"
52 #include "net/http/http_stream_factory.h"
53 #include "net/http/http_stream_parser.h"
54 #include "net/http/http_transaction_test_util.h"
55 #include "net/log/net_log.h"
56 #include "net/log/test_net_log.h"
57 #include "net/log/test_net_log_entry.h"
58 #include "net/log/test_net_log_util.h"
59 #include "net/proxy/mock_proxy_resolver.h"
60 #include "net/proxy/proxy_config_service_fixed.h"
61 #include "net/proxy/proxy_info.h"
62 #include "net/proxy/proxy_resolver.h"
63 #include "net/proxy/proxy_service.h"
64 #include "net/socket/client_socket_factory.h"
65 #include "net/socket/client_socket_pool_manager.h"
66 #include "net/socket/connection_attempts.h"
67 #include "net/socket/mock_client_socket_pool_manager.h"
68 #include "net/socket/next_proto.h"
69 #include "net/socket/socket_test_util.h"
70 #include "net/socket/ssl_client_socket.h"
71 #include "net/spdy/spdy_framer.h"
72 #include "net/spdy/spdy_session.h"
73 #include "net/spdy/spdy_session_pool.h"
74 #include "net/spdy/spdy_test_util_common.h"
75 #include "net/ssl/ssl_cert_request_info.h"
76 #include "net/ssl/ssl_config_service.h"
77 #include "net/ssl/ssl_config_service_defaults.h"
78 #include "net/ssl/ssl_info.h"
79 #include "net/test/cert_test_util.h"
80 #include "net/websockets/websocket_handshake_stream_base.h"
81 #include "testing/gtest/include/gtest/gtest.h"
82 #include "testing/platform_test.h"
83 #include "url/gurl.h"
85 using base::ASCIIToUTF16;
87 //-----------------------------------------------------------------------------
89 namespace net {
91 namespace {
93 const base::string16 kBar(ASCIIToUTF16("bar"));
94 const base::string16 kBar2(ASCIIToUTF16("bar2"));
95 const base::string16 kBar3(ASCIIToUTF16("bar3"));
96 const base::string16 kBaz(ASCIIToUTF16("baz"));
97 const base::string16 kFirst(ASCIIToUTF16("first"));
98 const base::string16 kFoo(ASCIIToUTF16("foo"));
99 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
100 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
101 const base::string16 kFou(ASCIIToUTF16("fou"));
102 const base::string16 kSecond(ASCIIToUTF16("second"));
103 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
104 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
106 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
107 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
108 ->IdleSocketCount();
111 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
112 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
113 ->IdleSocketCount();
116 bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
117 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
118 ->IsStalled();
121 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
122 // a JSONified list of headers as a single string. Uses single quotes instead
123 // of double quotes for easier comparison. Returns false on failure.
124 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
125 if (!params)
126 return false;
127 base::ListValue* header_list;
128 if (!params->GetList("headers", &header_list))
129 return false;
130 std::string double_quote_headers;
131 base::JSONWriter::Write(*header_list, &double_quote_headers);
132 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
133 return true;
136 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
137 // used.
138 void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
139 EXPECT_TRUE(load_timing_info.socket_reused);
140 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
142 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
143 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
145 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
146 EXPECT_FALSE(load_timing_info.send_start.is_null());
148 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
150 // Set at a higher level.
151 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
152 EXPECT_TRUE(load_timing_info.request_start.is_null());
153 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
156 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
157 // used.
158 void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
159 int connect_timing_flags) {
160 EXPECT_FALSE(load_timing_info.socket_reused);
161 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
163 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
164 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
166 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
167 connect_timing_flags);
168 EXPECT_LE(load_timing_info.connect_timing.connect_end,
169 load_timing_info.send_start);
171 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
173 // Set at a higher level.
174 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
175 EXPECT_TRUE(load_timing_info.request_start.is_null());
176 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
179 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
180 // used.
181 void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
182 EXPECT_TRUE(load_timing_info.socket_reused);
183 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
185 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
187 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
188 EXPECT_LE(load_timing_info.proxy_resolve_start,
189 load_timing_info.proxy_resolve_end);
190 EXPECT_LE(load_timing_info.proxy_resolve_end,
191 load_timing_info.send_start);
192 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
194 // Set at a higher level.
195 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
196 EXPECT_TRUE(load_timing_info.request_start.is_null());
197 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
200 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
201 // used.
202 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
203 int connect_timing_flags) {
204 EXPECT_FALSE(load_timing_info.socket_reused);
205 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
207 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
208 EXPECT_LE(load_timing_info.proxy_resolve_start,
209 load_timing_info.proxy_resolve_end);
210 EXPECT_LE(load_timing_info.proxy_resolve_end,
211 load_timing_info.connect_timing.connect_start);
212 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
213 connect_timing_flags);
214 EXPECT_LE(load_timing_info.connect_timing.connect_end,
215 load_timing_info.send_start);
217 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
219 // Set at a higher level.
220 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
221 EXPECT_TRUE(load_timing_info.request_start.is_null());
222 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
225 void AddWebSocketHeaders(HttpRequestHeaders* headers) {
226 headers->SetHeader("Connection", "Upgrade");
227 headers->SetHeader("Upgrade", "websocket");
228 headers->SetHeader("Origin", "http://www.example.org");
229 headers->SetHeader("Sec-WebSocket-Version", "13");
230 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
233 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
234 return SpdySessionDependencies::SpdyCreateSession(session_deps);
237 } // namespace
239 class HttpNetworkTransactionTest
240 : public PlatformTest,
241 public ::testing::WithParamInterface<NextProto> {
242 public:
243 virtual ~HttpNetworkTransactionTest() {
244 // Important to restore the per-pool limit first, since the pool limit must
245 // always be greater than group limit, and the tests reduce both limits.
246 ClientSocketPoolManager::set_max_sockets_per_pool(
247 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
248 ClientSocketPoolManager::set_max_sockets_per_group(
249 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
252 protected:
253 HttpNetworkTransactionTest()
254 : spdy_util_(GetParam()),
255 session_deps_(GetParam()),
256 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
257 HttpNetworkSession::NORMAL_SOCKET_POOL)),
258 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
259 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
262 struct SimpleGetHelperResult {
263 int rv;
264 std::string status_line;
265 std::string response_data;
266 int64 totalReceivedBytes;
267 LoadTimingInfo load_timing_info;
268 ConnectionAttempts connection_attempts;
271 void SetUp() override {
272 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
273 base::MessageLoop::current()->RunUntilIdle();
276 void TearDown() override {
277 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
278 base::MessageLoop::current()->RunUntilIdle();
279 // Empty the current queue.
280 base::MessageLoop::current()->RunUntilIdle();
281 PlatformTest::TearDown();
282 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
283 base::MessageLoop::current()->RunUntilIdle();
286 const char* GetAlternateProtocolFromParam() {
287 return
288 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
291 // This is the expected return from a current server advertising SPDY.
292 std::string GetAlternateProtocolHttpHeader() {
293 return std::string("Alternate-Protocol: 443:") +
294 GetAlternateProtocolFromParam() + "\r\n\r\n";
297 // Either |write_failure| specifies a write failure or |read_failure|
298 // specifies a read failure when using a reused socket. In either case, the
299 // failure should cause the network transaction to resend the request, and the
300 // other argument should be NULL.
301 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
302 const MockRead* read_failure);
304 // Either |write_failure| specifies a write failure or |read_failure|
305 // specifies a read failure when using a reused socket. In either case, the
306 // failure should cause the network transaction to resend the request, and the
307 // other argument should be NULL.
308 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
309 const MockRead* read_failure,
310 bool use_spdy);
312 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
313 size_t data_count) {
314 SimpleGetHelperResult out;
316 HttpRequestInfo request;
317 request.method = "GET";
318 request.url = GURL("http://www.example.org/");
319 request.load_flags = 0;
321 BoundTestNetLog log;
322 session_deps_.net_log = log.bound().net_log();
323 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
324 scoped_ptr<HttpTransaction> trans(
325 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
327 for (size_t i = 0; i < data_count; ++i) {
328 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
331 TestCompletionCallback callback;
333 EXPECT_TRUE(log.bound().IsCapturing());
334 int rv = trans->Start(&request, callback.callback(), log.bound());
335 EXPECT_EQ(ERR_IO_PENDING, rv);
337 out.rv = callback.WaitForResult();
339 // Even in the failure cases that use this function, connections are always
340 // successfully established before the error.
341 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
342 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
344 if (out.rv != OK)
345 return out;
347 const HttpResponseInfo* response = trans->GetResponseInfo();
348 // Can't use ASSERT_* inside helper functions like this, so
349 // return an error.
350 if (response == NULL || response->headers.get() == NULL) {
351 out.rv = ERR_UNEXPECTED;
352 return out;
354 out.status_line = response->headers->GetStatusLine();
356 EXPECT_EQ("127.0.0.1", response->socket_address.host());
357 EXPECT_EQ(80, response->socket_address.port());
359 rv = ReadTransaction(trans.get(), &out.response_data);
360 EXPECT_EQ(OK, rv);
362 TestNetLogEntry::List entries;
363 log.GetEntries(&entries);
364 size_t pos = ExpectLogContainsSomewhere(
365 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
366 NetLog::PHASE_NONE);
367 ExpectLogContainsSomewhere(
368 entries, pos,
369 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
370 NetLog::PHASE_NONE);
372 std::string line;
373 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
374 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
376 HttpRequestHeaders request_headers;
377 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
378 std::string value;
379 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
380 EXPECT_EQ("www.example.org", value);
381 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
382 EXPECT_EQ("keep-alive", value);
384 std::string response_headers;
385 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
386 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
387 response_headers);
389 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
390 trans->GetConnectionAttempts(&out.connection_attempts);
391 return out;
394 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
395 size_t reads_count) {
396 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
397 StaticSocketDataProvider* data[] = { &reads };
398 return SimpleGetHelperForData(data, 1);
401 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
402 int64 size = 0;
403 for (size_t i = 0; i < reads_count; ++i)
404 size += data_reads[i].data_len;
405 return size;
408 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
409 int expected_status);
411 void ConnectStatusHelper(const MockRead& status);
413 void BypassHostCacheOnRefreshHelper(int load_flags);
415 void CheckErrorIsPassedBack(int error, IoMode mode);
417 SpdyTestUtil spdy_util_;
418 SpdySessionDependencies session_deps_;
420 // Original socket limits. Some tests set these. Safest to always restore
421 // them once each test has been run.
422 int old_max_group_sockets_;
423 int old_max_pool_sockets_;
426 INSTANTIATE_TEST_CASE_P(NextProto,
427 HttpNetworkTransactionTest,
428 testing::Values(kProtoSPDY31,
429 kProtoHTTP2_14,
430 kProtoHTTP2));
432 namespace {
434 class BeforeNetworkStartHandler {
435 public:
436 explicit BeforeNetworkStartHandler(bool defer)
437 : defer_on_before_network_start_(defer),
438 observed_before_network_start_(false) {}
440 void OnBeforeNetworkStart(bool* defer) {
441 *defer = defer_on_before_network_start_;
442 observed_before_network_start_ = true;
445 bool observed_before_network_start() const {
446 return observed_before_network_start_;
449 private:
450 const bool defer_on_before_network_start_;
451 bool observed_before_network_start_;
453 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
456 class BeforeProxyHeadersSentHandler {
457 public:
458 BeforeProxyHeadersSentHandler()
459 : observed_before_proxy_headers_sent_(false) {}
461 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
462 HttpRequestHeaders* request_headers) {
463 observed_before_proxy_headers_sent_ = true;
464 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
467 bool observed_before_proxy_headers_sent() const {
468 return observed_before_proxy_headers_sent_;
471 std::string observed_proxy_server_uri() const {
472 return observed_proxy_server_uri_;
475 private:
476 bool observed_before_proxy_headers_sent_;
477 std::string observed_proxy_server_uri_;
479 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
482 // Fill |str| with a long header list that consumes >= |size| bytes.
483 void FillLargeHeadersString(std::string* str, int size) {
484 const char row[] =
485 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
486 const int sizeof_row = strlen(row);
487 const int num_rows = static_cast<int>(
488 ceil(static_cast<float>(size) / sizeof_row));
489 const int sizeof_data = num_rows * sizeof_row;
490 DCHECK(sizeof_data >= size);
491 str->reserve(sizeof_data);
493 for (int i = 0; i < num_rows; ++i)
494 str->append(row, sizeof_row);
497 // Alternative functions that eliminate randomness and dependency on the local
498 // host name so that the generated NTLM messages are reproducible.
499 void MockGenerateRandom1(uint8* output, size_t n) {
500 static const uint8 bytes[] = {
501 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
503 static size_t current_byte = 0;
504 for (size_t i = 0; i < n; ++i) {
505 output[i] = bytes[current_byte++];
506 current_byte %= arraysize(bytes);
510 void MockGenerateRandom2(uint8* output, size_t n) {
511 static const uint8 bytes[] = {
512 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
513 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
515 static size_t current_byte = 0;
516 for (size_t i = 0; i < n; ++i) {
517 output[i] = bytes[current_byte++];
518 current_byte %= arraysize(bytes);
522 std::string MockGetHostName() {
523 return "WTC-WIN7";
526 template<typename ParentPool>
527 class CaptureGroupNameSocketPool : public ParentPool {
528 public:
529 CaptureGroupNameSocketPool(HostResolver* host_resolver,
530 CertVerifier* cert_verifier);
532 const std::string last_group_name_received() const {
533 return last_group_name_;
536 int RequestSocket(const std::string& group_name,
537 const void* socket_params,
538 RequestPriority priority,
539 ClientSocketHandle* handle,
540 const CompletionCallback& callback,
541 const BoundNetLog& net_log) override {
542 last_group_name_ = group_name;
543 return ERR_IO_PENDING;
545 void CancelRequest(const std::string& group_name,
546 ClientSocketHandle* handle) override {}
547 void ReleaseSocket(const std::string& group_name,
548 scoped_ptr<StreamSocket> socket,
549 int id) override {}
550 void CloseIdleSockets() override {}
551 int IdleSocketCount() const override { return 0; }
552 int IdleSocketCountInGroup(const std::string& group_name) const override {
553 return 0;
555 LoadState GetLoadState(const std::string& group_name,
556 const ClientSocketHandle* handle) const override {
557 return LOAD_STATE_IDLE;
559 base::TimeDelta ConnectionTimeout() const override {
560 return base::TimeDelta();
563 private:
564 std::string last_group_name_;
567 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
568 CaptureGroupNameTransportSocketPool;
569 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
570 CaptureGroupNameHttpProxySocketPool;
571 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
572 CaptureGroupNameSOCKSSocketPool;
573 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
574 CaptureGroupNameSSLSocketPool;
576 template <typename ParentPool>
577 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
578 HostResolver* host_resolver,
579 CertVerifier* /* cert_verifier */)
580 : ParentPool(0, 0, host_resolver, NULL, NULL) {
583 template <>
584 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
585 HostResolver* /* host_resolver */,
586 CertVerifier* /* cert_verifier */)
587 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
590 template <>
591 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
592 HostResolver* /* host_resolver */,
593 CertVerifier* cert_verifier)
594 : SSLClientSocketPool(0,
596 cert_verifier,
597 NULL,
598 NULL,
599 NULL,
600 NULL,
601 std::string(),
602 NULL,
603 NULL,
604 NULL,
605 NULL,
606 NULL,
607 NULL) {
610 //-----------------------------------------------------------------------------
612 // Helper functions for validating that AuthChallengeInfo's are correctly
613 // configured for common cases.
614 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
615 if (!auth_challenge)
616 return false;
617 EXPECT_FALSE(auth_challenge->is_proxy);
618 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
619 EXPECT_EQ("MyRealm1", auth_challenge->realm);
620 EXPECT_EQ("basic", auth_challenge->scheme);
621 return true;
624 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
625 if (!auth_challenge)
626 return false;
627 EXPECT_TRUE(auth_challenge->is_proxy);
628 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
629 EXPECT_EQ("MyRealm1", auth_challenge->realm);
630 EXPECT_EQ("basic", auth_challenge->scheme);
631 return true;
634 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
635 if (!auth_challenge)
636 return false;
637 EXPECT_FALSE(auth_challenge->is_proxy);
638 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
639 EXPECT_EQ("digestive", auth_challenge->realm);
640 EXPECT_EQ("digest", auth_challenge->scheme);
641 return true;
644 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
645 if (!auth_challenge)
646 return false;
647 EXPECT_FALSE(auth_challenge->is_proxy);
648 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
649 EXPECT_EQ(std::string(), auth_challenge->realm);
650 EXPECT_EQ("ntlm", auth_challenge->scheme);
651 return true;
654 } // namespace
656 TEST_P(HttpNetworkTransactionTest, Basic) {
657 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
658 scoped_ptr<HttpTransaction> trans(
659 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
662 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
663 MockRead data_reads[] = {
664 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
665 MockRead("hello world"),
666 MockRead(SYNCHRONOUS, OK),
668 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
669 arraysize(data_reads));
670 EXPECT_EQ(OK, out.rv);
671 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
672 EXPECT_EQ("hello world", out.response_data);
673 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
674 EXPECT_EQ(reads_size, out.totalReceivedBytes);
675 EXPECT_EQ(0u, out.connection_attempts.size());
678 // Response with no status line.
679 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
680 MockRead data_reads[] = {
681 MockRead("hello world"),
682 MockRead(SYNCHRONOUS, OK),
684 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
685 arraysize(data_reads));
686 EXPECT_EQ(OK, out.rv);
687 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
688 EXPECT_EQ("hello world", out.response_data);
689 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
690 EXPECT_EQ(reads_size, out.totalReceivedBytes);
693 // Allow up to 4 bytes of junk to precede status line.
694 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
695 MockRead data_reads[] = {
696 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
697 MockRead(SYNCHRONOUS, OK),
699 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
700 arraysize(data_reads));
701 EXPECT_EQ(OK, out.rv);
702 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
703 EXPECT_EQ("DATA", out.response_data);
704 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
705 EXPECT_EQ(reads_size, out.totalReceivedBytes);
708 // Allow up to 4 bytes of junk to precede status line.
709 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
710 MockRead data_reads[] = {
711 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
712 MockRead(SYNCHRONOUS, OK),
714 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
715 arraysize(data_reads));
716 EXPECT_EQ(OK, out.rv);
717 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
718 EXPECT_EQ("DATA", out.response_data);
719 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
720 EXPECT_EQ(reads_size, out.totalReceivedBytes);
723 // Beyond 4 bytes of slop and it should fail to find a status line.
724 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
725 MockRead data_reads[] = {
726 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
727 MockRead(SYNCHRONOUS, OK),
729 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
730 arraysize(data_reads));
731 EXPECT_EQ(OK, out.rv);
732 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
733 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
734 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
735 EXPECT_EQ(reads_size, out.totalReceivedBytes);
738 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
739 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
740 MockRead data_reads[] = {
741 MockRead("\n"),
742 MockRead("\n"),
743 MockRead("Q"),
744 MockRead("J"),
745 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
746 MockRead(SYNCHRONOUS, OK),
748 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
749 arraysize(data_reads));
750 EXPECT_EQ(OK, out.rv);
751 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
752 EXPECT_EQ("DATA", out.response_data);
753 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
754 EXPECT_EQ(reads_size, out.totalReceivedBytes);
757 // Close the connection before enough bytes to have a status line.
758 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
759 MockRead data_reads[] = {
760 MockRead("HTT"),
761 MockRead(SYNCHRONOUS, OK),
763 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
764 arraysize(data_reads));
765 EXPECT_EQ(OK, out.rv);
766 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
767 EXPECT_EQ("HTT", out.response_data);
768 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
769 EXPECT_EQ(reads_size, out.totalReceivedBytes);
772 // Simulate a 204 response, lacking a Content-Length header, sent over a
773 // persistent connection. The response should still terminate since a 204
774 // cannot have a response body.
775 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
776 char junk[] = "junk";
777 MockRead data_reads[] = {
778 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
779 MockRead(junk), // Should not be read!!
780 MockRead(SYNCHRONOUS, OK),
782 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
783 arraysize(data_reads));
784 EXPECT_EQ(OK, out.rv);
785 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
786 EXPECT_EQ("", out.response_data);
787 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
788 int64 response_size = reads_size - strlen(junk);
789 EXPECT_EQ(response_size, out.totalReceivedBytes);
792 // A simple request using chunked encoding with some extra data after.
793 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
794 std::string final_chunk = "0\r\n\r\n";
795 std::string extra_data = "HTTP/1.1 200 OK\r\n";
796 std::string last_read = final_chunk + extra_data;
797 MockRead data_reads[] = {
798 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
799 MockRead("5\r\nHello\r\n"),
800 MockRead("1\r\n"),
801 MockRead(" \r\n"),
802 MockRead("5\r\nworld\r\n"),
803 MockRead(last_read.data()),
804 MockRead(SYNCHRONOUS, OK),
806 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
807 arraysize(data_reads));
808 EXPECT_EQ(OK, out.rv);
809 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
810 EXPECT_EQ("Hello world", out.response_data);
811 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
812 int64 response_size = reads_size - extra_data.size();
813 EXPECT_EQ(response_size, out.totalReceivedBytes);
816 // Next tests deal with http://crbug.com/56344.
818 TEST_P(HttpNetworkTransactionTest,
819 MultipleContentLengthHeadersNoTransferEncoding) {
820 MockRead data_reads[] = {
821 MockRead("HTTP/1.1 200 OK\r\n"),
822 MockRead("Content-Length: 10\r\n"),
823 MockRead("Content-Length: 5\r\n\r\n"),
825 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
826 arraysize(data_reads));
827 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
830 TEST_P(HttpNetworkTransactionTest,
831 DuplicateContentLengthHeadersNoTransferEncoding) {
832 MockRead data_reads[] = {
833 MockRead("HTTP/1.1 200 OK\r\n"),
834 MockRead("Content-Length: 5\r\n"),
835 MockRead("Content-Length: 5\r\n\r\n"),
836 MockRead("Hello"),
838 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
839 arraysize(data_reads));
840 EXPECT_EQ(OK, out.rv);
841 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
842 EXPECT_EQ("Hello", out.response_data);
845 TEST_P(HttpNetworkTransactionTest,
846 ComplexContentLengthHeadersNoTransferEncoding) {
847 // More than 2 dupes.
849 MockRead data_reads[] = {
850 MockRead("HTTP/1.1 200 OK\r\n"),
851 MockRead("Content-Length: 5\r\n"),
852 MockRead("Content-Length: 5\r\n"),
853 MockRead("Content-Length: 5\r\n\r\n"),
854 MockRead("Hello"),
856 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
857 arraysize(data_reads));
858 EXPECT_EQ(OK, out.rv);
859 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
860 EXPECT_EQ("Hello", out.response_data);
862 // HTTP/1.0
864 MockRead data_reads[] = {
865 MockRead("HTTP/1.0 200 OK\r\n"),
866 MockRead("Content-Length: 5\r\n"),
867 MockRead("Content-Length: 5\r\n"),
868 MockRead("Content-Length: 5\r\n\r\n"),
869 MockRead("Hello"),
871 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
872 arraysize(data_reads));
873 EXPECT_EQ(OK, out.rv);
874 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
875 EXPECT_EQ("Hello", out.response_data);
877 // 2 dupes and one mismatched.
879 MockRead data_reads[] = {
880 MockRead("HTTP/1.1 200 OK\r\n"),
881 MockRead("Content-Length: 10\r\n"),
882 MockRead("Content-Length: 10\r\n"),
883 MockRead("Content-Length: 5\r\n\r\n"),
885 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
886 arraysize(data_reads));
887 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
891 TEST_P(HttpNetworkTransactionTest,
892 MultipleContentLengthHeadersTransferEncoding) {
893 MockRead data_reads[] = {
894 MockRead("HTTP/1.1 200 OK\r\n"),
895 MockRead("Content-Length: 666\r\n"),
896 MockRead("Content-Length: 1337\r\n"),
897 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
898 MockRead("5\r\nHello\r\n"),
899 MockRead("1\r\n"),
900 MockRead(" \r\n"),
901 MockRead("5\r\nworld\r\n"),
902 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
903 MockRead(SYNCHRONOUS, OK),
905 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
906 arraysize(data_reads));
907 EXPECT_EQ(OK, out.rv);
908 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
909 EXPECT_EQ("Hello world", out.response_data);
912 // Next tests deal with http://crbug.com/98895.
914 // Checks that a single Content-Disposition header results in no error.
915 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
916 MockRead data_reads[] = {
917 MockRead("HTTP/1.1 200 OK\r\n"),
918 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
919 MockRead("Content-Length: 5\r\n\r\n"),
920 MockRead("Hello"),
922 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
923 arraysize(data_reads));
924 EXPECT_EQ(OK, out.rv);
925 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
926 EXPECT_EQ("Hello", out.response_data);
929 // Checks that two identical Content-Disposition headers result in no error.
930 TEST_P(HttpNetworkTransactionTest,
931 TwoIdenticalContentDispositionHeaders) {
932 MockRead data_reads[] = {
933 MockRead("HTTP/1.1 200 OK\r\n"),
934 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
935 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
936 MockRead("Content-Length: 5\r\n\r\n"),
937 MockRead("Hello"),
939 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
940 arraysize(data_reads));
941 EXPECT_EQ(OK, out.rv);
942 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
943 EXPECT_EQ("Hello", out.response_data);
946 // Checks that two distinct Content-Disposition headers result in an error.
947 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
948 MockRead data_reads[] = {
949 MockRead("HTTP/1.1 200 OK\r\n"),
950 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
951 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
952 MockRead("Content-Length: 5\r\n\r\n"),
953 MockRead("Hello"),
955 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
956 arraysize(data_reads));
957 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
960 // Checks that two identical Location headers result in no error.
961 // Also tests Location header behavior.
962 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
963 MockRead data_reads[] = {
964 MockRead("HTTP/1.1 302 Redirect\r\n"),
965 MockRead("Location: http://good.com/\r\n"),
966 MockRead("Location: http://good.com/\r\n"),
967 MockRead("Content-Length: 0\r\n\r\n"),
968 MockRead(SYNCHRONOUS, OK),
971 HttpRequestInfo request;
972 request.method = "GET";
973 request.url = GURL("http://redirect.com/");
974 request.load_flags = 0;
976 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
977 scoped_ptr<HttpTransaction> trans(
978 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
980 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
981 session_deps_.socket_factory->AddSocketDataProvider(&data);
983 TestCompletionCallback callback;
985 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
986 EXPECT_EQ(ERR_IO_PENDING, rv);
988 EXPECT_EQ(OK, callback.WaitForResult());
990 const HttpResponseInfo* response = trans->GetResponseInfo();
991 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
992 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
993 std::string url;
994 EXPECT_TRUE(response->headers->IsRedirect(&url));
995 EXPECT_EQ("http://good.com/", url);
996 EXPECT_TRUE(response->proxy_server.IsEmpty());
999 // Checks that two distinct Location headers result in an error.
1000 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
1001 MockRead data_reads[] = {
1002 MockRead("HTTP/1.1 302 Redirect\r\n"),
1003 MockRead("Location: http://good.com/\r\n"),
1004 MockRead("Location: http://evil.com/\r\n"),
1005 MockRead("Content-Length: 0\r\n\r\n"),
1006 MockRead(SYNCHRONOUS, OK),
1008 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1009 arraysize(data_reads));
1010 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1013 // Do a request using the HEAD method. Verify that we don't try to read the
1014 // message body (since HEAD has none).
1015 TEST_P(HttpNetworkTransactionTest, Head) {
1016 HttpRequestInfo request;
1017 request.method = "HEAD";
1018 request.url = GURL("http://www.example.org/");
1019 request.load_flags = 0;
1021 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1022 scoped_ptr<HttpTransaction> trans(
1023 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1024 BeforeProxyHeadersSentHandler proxy_headers_handler;
1025 trans->SetBeforeProxyHeadersSentCallback(
1026 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1027 base::Unretained(&proxy_headers_handler)));
1029 MockWrite data_writes1[] = {
1030 MockWrite(
1031 "HEAD / HTTP/1.1\r\n"
1032 "Host: www.example.org\r\n"
1033 "Connection: keep-alive\r\n"
1034 "Content-Length: 0\r\n\r\n"),
1036 MockRead data_reads1[] = {
1037 MockRead("HTTP/1.1 404 Not Found\r\n"),
1038 MockRead("Server: Blah\r\n"),
1039 MockRead("Content-Length: 1234\r\n\r\n"),
1041 // No response body because the test stops reading here.
1042 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1045 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1046 data_writes1, arraysize(data_writes1));
1047 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1049 TestCompletionCallback callback1;
1051 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1052 EXPECT_EQ(ERR_IO_PENDING, rv);
1054 rv = callback1.WaitForResult();
1055 EXPECT_EQ(OK, rv);
1057 const HttpResponseInfo* response = trans->GetResponseInfo();
1058 ASSERT_TRUE(response != NULL);
1060 // Check that the headers got parsed.
1061 EXPECT_TRUE(response->headers.get() != NULL);
1062 EXPECT_EQ(1234, response->headers->GetContentLength());
1063 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1064 EXPECT_TRUE(response->proxy_server.IsEmpty());
1065 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1067 std::string server_header;
1068 void* iter = NULL;
1069 bool has_server_header = response->headers->EnumerateHeader(
1070 &iter, "Server", &server_header);
1071 EXPECT_TRUE(has_server_header);
1072 EXPECT_EQ("Blah", server_header);
1074 // Reading should give EOF right away, since there is no message body
1075 // (despite non-zero content-length).
1076 std::string response_data;
1077 rv = ReadTransaction(trans.get(), &response_data);
1078 EXPECT_EQ(OK, rv);
1079 EXPECT_EQ("", response_data);
1082 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1083 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1085 MockRead data_reads[] = {
1086 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1087 MockRead("hello"),
1088 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1089 MockRead("world"),
1090 MockRead(SYNCHRONOUS, OK),
1092 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1093 session_deps_.socket_factory->AddSocketDataProvider(&data);
1095 const char* const kExpectedResponseData[] = {
1096 "hello", "world"
1099 for (int i = 0; i < 2; ++i) {
1100 HttpRequestInfo request;
1101 request.method = "GET";
1102 request.url = GURL("http://www.example.org/");
1103 request.load_flags = 0;
1105 scoped_ptr<HttpTransaction> trans(
1106 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1108 TestCompletionCallback callback;
1110 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1111 EXPECT_EQ(ERR_IO_PENDING, rv);
1113 rv = callback.WaitForResult();
1114 EXPECT_EQ(OK, rv);
1116 const HttpResponseInfo* response = trans->GetResponseInfo();
1117 ASSERT_TRUE(response != NULL);
1119 EXPECT_TRUE(response->headers.get() != NULL);
1120 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1121 EXPECT_TRUE(response->proxy_server.IsEmpty());
1123 std::string response_data;
1124 rv = ReadTransaction(trans.get(), &response_data);
1125 EXPECT_EQ(OK, rv);
1126 EXPECT_EQ(kExpectedResponseData[i], response_data);
1130 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1131 ScopedVector<UploadElementReader> element_readers;
1132 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1133 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
1135 HttpRequestInfo request;
1136 request.method = "POST";
1137 request.url = GURL("http://www.foo.com/");
1138 request.upload_data_stream = &upload_data_stream;
1139 request.load_flags = 0;
1141 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1142 scoped_ptr<HttpTransaction> trans(
1143 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1145 MockRead data_reads[] = {
1146 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1147 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1148 MockRead("hello world"),
1149 MockRead(SYNCHRONOUS, OK),
1151 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1152 session_deps_.socket_factory->AddSocketDataProvider(&data);
1154 TestCompletionCallback callback;
1156 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1157 EXPECT_EQ(ERR_IO_PENDING, rv);
1159 rv = callback.WaitForResult();
1160 EXPECT_EQ(OK, rv);
1162 const HttpResponseInfo* response = trans->GetResponseInfo();
1163 ASSERT_TRUE(response != NULL);
1165 EXPECT_TRUE(response->headers.get() != NULL);
1166 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1168 std::string response_data;
1169 rv = ReadTransaction(trans.get(), &response_data);
1170 EXPECT_EQ(OK, rv);
1171 EXPECT_EQ("hello world", response_data);
1174 // This test is almost the same as Ignores100 above, but the response contains
1175 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1176 // HTTP/1.1 and the two status headers are read in one read.
1177 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1178 HttpRequestInfo request;
1179 request.method = "GET";
1180 request.url = GURL("http://www.foo.com/");
1181 request.load_flags = 0;
1183 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1184 scoped_ptr<HttpTransaction> trans(
1185 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1187 MockRead data_reads[] = {
1188 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1189 "HTTP/1.1 200 OK\r\n\r\n"),
1190 MockRead("hello world"),
1191 MockRead(SYNCHRONOUS, OK),
1193 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1194 session_deps_.socket_factory->AddSocketDataProvider(&data);
1196 TestCompletionCallback callback;
1198 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1199 EXPECT_EQ(ERR_IO_PENDING, rv);
1201 rv = callback.WaitForResult();
1202 EXPECT_EQ(OK, rv);
1204 const HttpResponseInfo* response = trans->GetResponseInfo();
1205 ASSERT_TRUE(response != NULL);
1207 EXPECT_TRUE(response->headers.get() != NULL);
1208 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1210 std::string response_data;
1211 rv = ReadTransaction(trans.get(), &response_data);
1212 EXPECT_EQ(OK, rv);
1213 EXPECT_EQ("hello world", response_data);
1216 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1217 HttpRequestInfo request;
1218 request.method = "POST";
1219 request.url = GURL("http://www.foo.com/");
1220 request.load_flags = 0;
1222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1223 scoped_ptr<HttpTransaction> trans(
1224 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1226 MockRead data_reads[] = {
1227 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1228 MockRead(ASYNC, 0),
1230 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1231 session_deps_.socket_factory->AddSocketDataProvider(&data);
1233 TestCompletionCallback callback;
1235 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1236 EXPECT_EQ(ERR_IO_PENDING, rv);
1238 rv = callback.WaitForResult();
1239 EXPECT_EQ(OK, rv);
1241 std::string response_data;
1242 rv = ReadTransaction(trans.get(), &response_data);
1243 EXPECT_EQ(OK, rv);
1244 EXPECT_EQ("", response_data);
1247 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1248 HttpRequestInfo request;
1249 request.method = "POST";
1250 request.url = GURL("http://www.foo.com/");
1251 request.load_flags = 0;
1253 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1254 scoped_ptr<HttpTransaction> trans(
1255 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1257 MockRead data_reads[] = {
1258 MockRead(ASYNC, 0),
1260 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1261 session_deps_.socket_factory->AddSocketDataProvider(&data);
1263 TestCompletionCallback callback;
1265 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1266 EXPECT_EQ(ERR_IO_PENDING, rv);
1268 rv = callback.WaitForResult();
1269 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1272 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1273 const MockWrite* write_failure,
1274 const MockRead* read_failure) {
1275 HttpRequestInfo request;
1276 request.method = "GET";
1277 request.url = GURL("http://www.foo.com/");
1278 request.load_flags = 0;
1280 TestNetLog net_log;
1281 session_deps_.net_log = &net_log;
1282 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1284 // Written data for successfully sending both requests.
1285 MockWrite data1_writes[] = {
1286 MockWrite("GET / HTTP/1.1\r\n"
1287 "Host: www.foo.com\r\n"
1288 "Connection: keep-alive\r\n\r\n"),
1289 MockWrite("GET / HTTP/1.1\r\n"
1290 "Host: www.foo.com\r\n"
1291 "Connection: keep-alive\r\n\r\n")
1294 // Read results for the first request.
1295 MockRead data1_reads[] = {
1296 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1297 MockRead("hello"),
1298 MockRead(ASYNC, OK),
1301 if (write_failure) {
1302 ASSERT_FALSE(read_failure);
1303 data1_writes[1] = *write_failure;
1304 } else {
1305 ASSERT_TRUE(read_failure);
1306 data1_reads[2] = *read_failure;
1309 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1310 data1_writes, arraysize(data1_writes));
1311 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1313 MockRead data2_reads[] = {
1314 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1315 MockRead("world"),
1316 MockRead(ASYNC, OK),
1318 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1319 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1321 const char* const kExpectedResponseData[] = {
1322 "hello", "world"
1325 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1326 for (int i = 0; i < 2; ++i) {
1327 TestCompletionCallback callback;
1329 scoped_ptr<HttpTransaction> trans(
1330 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1332 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1333 EXPECT_EQ(ERR_IO_PENDING, rv);
1335 rv = callback.WaitForResult();
1336 EXPECT_EQ(OK, rv);
1338 LoadTimingInfo load_timing_info;
1339 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1340 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1341 if (i == 0) {
1342 first_socket_log_id = load_timing_info.socket_log_id;
1343 } else {
1344 // The second request should be using a new socket.
1345 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1348 const HttpResponseInfo* response = trans->GetResponseInfo();
1349 ASSERT_TRUE(response != NULL);
1351 EXPECT_TRUE(response->headers.get() != NULL);
1352 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1354 std::string response_data;
1355 rv = ReadTransaction(trans.get(), &response_data);
1356 EXPECT_EQ(OK, rv);
1357 EXPECT_EQ(kExpectedResponseData[i], response_data);
1361 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1362 const MockWrite* write_failure,
1363 const MockRead* read_failure,
1364 bool use_spdy) {
1365 HttpRequestInfo request;
1366 request.method = "GET";
1367 request.url = GURL("https://www.foo.com/");
1368 request.load_flags = 0;
1370 TestNetLog net_log;
1371 session_deps_.net_log = &net_log;
1372 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1374 SSLSocketDataProvider ssl1(ASYNC, OK);
1375 SSLSocketDataProvider ssl2(ASYNC, OK);
1376 if (use_spdy) {
1377 ssl1.SetNextProto(GetParam());
1378 ssl2.SetNextProto(GetParam());
1380 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1381 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1383 // SPDY versions of the request and response.
1384 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1385 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1386 scoped_ptr<SpdyFrame> spdy_response(
1387 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1388 scoped_ptr<SpdyFrame> spdy_data(
1389 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1391 // HTTP/1.1 versions of the request and response.
1392 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1393 "Host: www.foo.com\r\n"
1394 "Connection: keep-alive\r\n\r\n";
1395 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1396 const char kHttpData[] = "hello";
1398 std::vector<MockRead> data1_reads;
1399 std::vector<MockWrite> data1_writes;
1400 if (write_failure) {
1401 ASSERT_FALSE(read_failure);
1402 data1_writes.push_back(*write_failure);
1403 data1_reads.push_back(MockRead(ASYNC, OK));
1404 } else {
1405 ASSERT_TRUE(read_failure);
1406 if (use_spdy) {
1407 data1_writes.push_back(CreateMockWrite(*spdy_request));
1408 } else {
1409 data1_writes.push_back(MockWrite(kHttpRequest));
1411 data1_reads.push_back(*read_failure);
1414 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1415 &data1_writes[0], data1_writes.size());
1416 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1418 std::vector<MockRead> data2_reads;
1419 std::vector<MockWrite> data2_writes;
1421 if (use_spdy) {
1422 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1424 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1425 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1426 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1427 } else {
1428 data2_writes.push_back(
1429 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1431 data2_reads.push_back(
1432 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1433 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1434 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1436 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1437 &data2_writes[0], data2_writes.size());
1438 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1440 // Preconnect a socket.
1441 SSLConfig ssl_config;
1442 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1443 session->GetNextProtos(&ssl_config.next_protos);
1444 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1445 ssl_config);
1446 // Wait for the preconnect to complete.
1447 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1448 base::RunLoop().RunUntilIdle();
1449 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1451 // Make the request.
1452 TestCompletionCallback callback;
1454 scoped_ptr<HttpTransaction> trans(
1455 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1457 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1458 EXPECT_EQ(ERR_IO_PENDING, rv);
1460 rv = callback.WaitForResult();
1461 EXPECT_EQ(OK, rv);
1463 LoadTimingInfo load_timing_info;
1464 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1465 TestLoadTimingNotReused(
1466 load_timing_info,
1467 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1469 const HttpResponseInfo* response = trans->GetResponseInfo();
1470 ASSERT_TRUE(response != NULL);
1472 EXPECT_TRUE(response->headers.get() != NULL);
1473 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1475 std::string response_data;
1476 rv = ReadTransaction(trans.get(), &response_data);
1477 EXPECT_EQ(OK, rv);
1478 EXPECT_EQ(kHttpData, response_data);
1481 TEST_P(HttpNetworkTransactionTest,
1482 KeepAliveConnectionNotConnectedOnWrite) {
1483 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1484 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1487 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1488 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1489 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1492 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1493 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1494 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1497 // Make sure that on a 408 response (Request Timeout), the request is retried,
1498 // if the socket was a reused keep alive socket.
1499 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1500 MockRead read_failure(SYNCHRONOUS,
1501 "HTTP/1.1 408 Request Timeout\r\n"
1502 "Connection: Keep-Alive\r\n"
1503 "Content-Length: 6\r\n\r\n"
1504 "Pickle");
1505 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1508 TEST_P(HttpNetworkTransactionTest,
1509 PreconnectErrorNotConnectedOnWrite) {
1510 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1511 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1514 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1515 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1516 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1519 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1520 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1521 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1524 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1525 MockRead read_failure(ASYNC, OK); // EOF
1526 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1529 // Make sure that on a 408 response (Request Timeout), the request is retried,
1530 // if the socket was a preconnected (UNUSED_IDLE) socket.
1531 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1532 MockRead read_failure(SYNCHRONOUS,
1533 "HTTP/1.1 408 Request Timeout\r\n"
1534 "Connection: Keep-Alive\r\n"
1535 "Content-Length: 6\r\n\r\n"
1536 "Pickle");
1537 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1538 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1541 TEST_P(HttpNetworkTransactionTest,
1542 SpdyPreconnectErrorNotConnectedOnWrite) {
1543 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1544 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1547 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1548 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1549 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1552 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1553 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1554 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1557 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1558 MockRead read_failure(ASYNC, OK); // EOF
1559 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1562 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1563 HttpRequestInfo request;
1564 request.method = "GET";
1565 request.url = GURL("http://www.example.org/");
1566 request.load_flags = 0;
1568 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1569 scoped_ptr<HttpTransaction> trans(
1570 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1572 MockRead data_reads[] = {
1573 MockRead(ASYNC, ERR_CONNECTION_RESET),
1574 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1575 MockRead("hello world"),
1576 MockRead(SYNCHRONOUS, OK),
1578 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1579 session_deps_.socket_factory->AddSocketDataProvider(&data);
1581 TestCompletionCallback callback;
1583 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1584 EXPECT_EQ(ERR_IO_PENDING, rv);
1586 rv = callback.WaitForResult();
1587 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1590 // What do various browsers do when the server closes a non-keepalive
1591 // connection without sending any response header or body?
1593 // IE7: error page
1594 // Safari 3.1.2 (Windows): error page
1595 // Firefox 3.0.1: blank page
1596 // Opera 9.52: after five attempts, blank page
1597 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1598 // Us: error page (EMPTY_RESPONSE)
1599 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1600 MockRead data_reads[] = {
1601 MockRead(SYNCHRONOUS, OK), // EOF
1602 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1603 MockRead("hello world"),
1604 MockRead(SYNCHRONOUS, OK),
1606 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1607 arraysize(data_reads));
1608 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1611 // Test that network access can be deferred and resumed.
1612 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1613 HttpRequestInfo request;
1614 request.method = "GET";
1615 request.url = GURL("http://www.example.org/");
1616 request.load_flags = 0;
1618 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1619 scoped_ptr<HttpTransaction> trans(
1620 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1622 // Defer on OnBeforeNetworkStart.
1623 BeforeNetworkStartHandler net_start_handler(true); // defer
1624 trans->SetBeforeNetworkStartCallback(
1625 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1626 base::Unretained(&net_start_handler)));
1628 MockRead data_reads[] = {
1629 MockRead("HTTP/1.0 200 OK\r\n"),
1630 MockRead("Content-Length: 5\r\n\r\n"),
1631 MockRead("hello"),
1632 MockRead(SYNCHRONOUS, 0),
1634 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1635 session_deps_.socket_factory->AddSocketDataProvider(&data);
1637 TestCompletionCallback callback;
1639 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1640 EXPECT_EQ(ERR_IO_PENDING, rv);
1641 base::MessageLoop::current()->RunUntilIdle();
1643 // Should have deferred for network start.
1644 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1645 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1647 trans->ResumeNetworkStart();
1648 rv = callback.WaitForResult();
1649 EXPECT_EQ(OK, rv);
1650 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1652 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1653 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1654 if (rv == ERR_IO_PENDING)
1655 rv = callback.WaitForResult();
1656 EXPECT_EQ(5, rv);
1657 trans.reset();
1660 // Test that network use can be deferred and canceled.
1661 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1662 HttpRequestInfo request;
1663 request.method = "GET";
1664 request.url = GURL("http://www.example.org/");
1665 request.load_flags = 0;
1667 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1668 scoped_ptr<HttpTransaction> trans(
1669 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1671 // Defer on OnBeforeNetworkStart.
1672 BeforeNetworkStartHandler net_start_handler(true); // defer
1673 trans->SetBeforeNetworkStartCallback(
1674 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1675 base::Unretained(&net_start_handler)));
1677 TestCompletionCallback callback;
1679 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1680 EXPECT_EQ(ERR_IO_PENDING, rv);
1681 base::MessageLoop::current()->RunUntilIdle();
1683 // Should have deferred for network start.
1684 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1685 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1688 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1689 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1690 // destructor in such situations.
1691 // See http://crbug.com/154712 and http://crbug.com/156609.
1692 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1693 HttpRequestInfo request;
1694 request.method = "GET";
1695 request.url = GURL("http://www.example.org/");
1696 request.load_flags = 0;
1698 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1699 scoped_ptr<HttpTransaction> trans(
1700 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1702 MockRead data_reads[] = {
1703 MockRead("HTTP/1.0 200 OK\r\n"),
1704 MockRead("Connection: keep-alive\r\n"),
1705 MockRead("Content-Length: 100\r\n\r\n"),
1706 MockRead("hello"),
1707 MockRead(SYNCHRONOUS, 0),
1709 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1710 session_deps_.socket_factory->AddSocketDataProvider(&data);
1712 TestCompletionCallback callback;
1714 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1715 EXPECT_EQ(ERR_IO_PENDING, rv);
1717 rv = callback.WaitForResult();
1718 EXPECT_EQ(OK, rv);
1720 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1721 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1722 if (rv == ERR_IO_PENDING)
1723 rv = callback.WaitForResult();
1724 EXPECT_EQ(5, rv);
1725 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1726 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1728 trans.reset();
1729 base::MessageLoop::current()->RunUntilIdle();
1730 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1733 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1734 HttpRequestInfo request;
1735 request.method = "GET";
1736 request.url = GURL("http://www.example.org/");
1737 request.load_flags = 0;
1739 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1740 scoped_ptr<HttpTransaction> trans(
1741 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1743 MockRead data_reads[] = {
1744 MockRead("HTTP/1.0 200 OK\r\n"),
1745 MockRead("Connection: keep-alive\r\n"),
1746 MockRead("Content-Length: 100\r\n\r\n"),
1747 MockRead(SYNCHRONOUS, 0),
1749 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1750 session_deps_.socket_factory->AddSocketDataProvider(&data);
1752 TestCompletionCallback callback;
1754 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1755 EXPECT_EQ(ERR_IO_PENDING, rv);
1757 rv = callback.WaitForResult();
1758 EXPECT_EQ(OK, rv);
1760 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1761 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1762 if (rv == ERR_IO_PENDING)
1763 rv = callback.WaitForResult();
1764 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1766 trans.reset();
1767 base::MessageLoop::current()->RunUntilIdle();
1768 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1771 // Test that we correctly reuse a keep-alive connection after not explicitly
1772 // reading the body.
1773 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1774 HttpRequestInfo request;
1775 request.method = "GET";
1776 request.url = GURL("http://www.foo.com/");
1777 request.load_flags = 0;
1779 TestNetLog net_log;
1780 session_deps_.net_log = &net_log;
1781 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1783 // Note that because all these reads happen in the same
1784 // StaticSocketDataProvider, it shows that the same socket is being reused for
1785 // all transactions.
1786 MockRead data1_reads[] = {
1787 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1788 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1789 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1790 MockRead("HTTP/1.1 302 Found\r\n"
1791 "Content-Length: 0\r\n\r\n"),
1792 MockRead("HTTP/1.1 302 Found\r\n"
1793 "Content-Length: 5\r\n\r\n"
1794 "hello"),
1795 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1796 "Content-Length: 0\r\n\r\n"),
1797 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1798 "Content-Length: 5\r\n\r\n"
1799 "hello"),
1800 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1801 MockRead("hello"),
1803 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1804 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1806 MockRead data2_reads[] = {
1807 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1809 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1810 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1812 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1813 std::string response_lines[kNumUnreadBodies];
1815 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1816 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1817 TestCompletionCallback callback;
1819 scoped_ptr<HttpTransaction> trans(
1820 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1822 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1823 EXPECT_EQ(ERR_IO_PENDING, rv);
1825 rv = callback.WaitForResult();
1826 EXPECT_EQ(OK, rv);
1828 LoadTimingInfo load_timing_info;
1829 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1830 if (i == 0) {
1831 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1832 first_socket_log_id = load_timing_info.socket_log_id;
1833 } else {
1834 TestLoadTimingReused(load_timing_info);
1835 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1838 const HttpResponseInfo* response = trans->GetResponseInfo();
1839 ASSERT_TRUE(response != NULL);
1841 ASSERT_TRUE(response->headers.get() != NULL);
1842 response_lines[i] = response->headers->GetStatusLine();
1844 // We intentionally don't read the response bodies.
1847 const char* const kStatusLines[] = {
1848 "HTTP/1.1 204 No Content",
1849 "HTTP/1.1 205 Reset Content",
1850 "HTTP/1.1 304 Not Modified",
1851 "HTTP/1.1 302 Found",
1852 "HTTP/1.1 302 Found",
1853 "HTTP/1.1 301 Moved Permanently",
1854 "HTTP/1.1 301 Moved Permanently",
1857 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1858 "forgot to update kStatusLines");
1860 for (int i = 0; i < kNumUnreadBodies; ++i)
1861 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1863 TestCompletionCallback callback;
1864 scoped_ptr<HttpTransaction> trans(
1865 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1866 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1867 EXPECT_EQ(ERR_IO_PENDING, rv);
1868 rv = callback.WaitForResult();
1869 EXPECT_EQ(OK, rv);
1870 const HttpResponseInfo* response = trans->GetResponseInfo();
1871 ASSERT_TRUE(response != NULL);
1872 ASSERT_TRUE(response->headers.get() != NULL);
1873 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1874 std::string response_data;
1875 rv = ReadTransaction(trans.get(), &response_data);
1876 EXPECT_EQ(OK, rv);
1877 EXPECT_EQ("hello", response_data);
1880 // Test the request-challenge-retry sequence for basic auth.
1881 // (basic auth is the easiest to mock, because it has no randomness).
1882 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1883 HttpRequestInfo request;
1884 request.method = "GET";
1885 request.url = GURL("http://www.example.org/");
1886 request.load_flags = 0;
1888 TestNetLog log;
1889 session_deps_.net_log = &log;
1890 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1891 scoped_ptr<HttpTransaction> trans(
1892 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1894 MockWrite data_writes1[] = {
1895 MockWrite(
1896 "GET / HTTP/1.1\r\n"
1897 "Host: www.example.org\r\n"
1898 "Connection: keep-alive\r\n\r\n"),
1901 MockRead data_reads1[] = {
1902 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1903 // Give a couple authenticate options (only the middle one is actually
1904 // supported).
1905 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1906 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1907 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1909 // Large content-length -- won't matter, as connection will be reset.
1910 MockRead("Content-Length: 10000\r\n\r\n"),
1911 MockRead(SYNCHRONOUS, ERR_FAILED),
1914 // After calling trans->RestartWithAuth(), this is the request we should
1915 // be issuing -- the final header line contains the credentials.
1916 MockWrite data_writes2[] = {
1917 MockWrite(
1918 "GET / HTTP/1.1\r\n"
1919 "Host: www.example.org\r\n"
1920 "Connection: keep-alive\r\n"
1921 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1924 // Lastly, the server responds with the actual content.
1925 MockRead data_reads2[] = {
1926 MockRead("HTTP/1.0 200 OK\r\n"),
1927 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1928 MockRead("Content-Length: 100\r\n\r\n"),
1929 MockRead(SYNCHRONOUS, OK),
1932 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1933 data_writes1, arraysize(data_writes1));
1934 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1935 data_writes2, arraysize(data_writes2));
1936 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1937 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1939 TestCompletionCallback callback1;
1941 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1942 EXPECT_EQ(ERR_IO_PENDING, rv);
1944 rv = callback1.WaitForResult();
1945 EXPECT_EQ(OK, rv);
1947 LoadTimingInfo load_timing_info1;
1948 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1949 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1951 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1952 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1954 const HttpResponseInfo* response = trans->GetResponseInfo();
1955 ASSERT_TRUE(response != NULL);
1956 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1958 TestCompletionCallback callback2;
1960 rv = trans->RestartWithAuth(
1961 AuthCredentials(kFoo, kBar), callback2.callback());
1962 EXPECT_EQ(ERR_IO_PENDING, rv);
1964 rv = callback2.WaitForResult();
1965 EXPECT_EQ(OK, rv);
1967 LoadTimingInfo load_timing_info2;
1968 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1969 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1970 // The load timing after restart should have a new socket ID, and times after
1971 // those of the first load timing.
1972 EXPECT_LE(load_timing_info1.receive_headers_end,
1973 load_timing_info2.connect_timing.connect_start);
1974 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1976 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1977 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1979 response = trans->GetResponseInfo();
1980 ASSERT_TRUE(response != NULL);
1981 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1982 EXPECT_EQ(100, response->headers->GetContentLength());
1985 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1986 HttpRequestInfo request;
1987 request.method = "GET";
1988 request.url = GURL("http://www.example.org/");
1989 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
1991 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1992 scoped_ptr<HttpTransaction> trans(
1993 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1995 MockWrite data_writes[] = {
1996 MockWrite(
1997 "GET / HTTP/1.1\r\n"
1998 "Host: www.example.org\r\n"
1999 "Connection: keep-alive\r\n\r\n"),
2002 MockRead data_reads[] = {
2003 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2004 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2006 // Large content-length -- won't matter, as connection will be reset.
2007 MockRead("Content-Length: 10000\r\n\r\n"),
2008 MockRead(SYNCHRONOUS, ERR_FAILED),
2011 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2012 data_writes, arraysize(data_writes));
2013 session_deps_.socket_factory->AddSocketDataProvider(&data);
2014 TestCompletionCallback callback;
2016 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2017 EXPECT_EQ(ERR_IO_PENDING, rv);
2019 rv = callback.WaitForResult();
2020 EXPECT_EQ(0, rv);
2022 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2023 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2025 const HttpResponseInfo* response = trans->GetResponseInfo();
2026 ASSERT_TRUE(response != NULL);
2027 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2030 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2031 // connection.
2032 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2033 HttpRequestInfo request;
2034 request.method = "GET";
2035 request.url = GURL("http://www.example.org/");
2036 request.load_flags = 0;
2038 TestNetLog log;
2039 session_deps_.net_log = &log;
2040 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2042 MockWrite data_writes1[] = {
2043 MockWrite(
2044 "GET / HTTP/1.1\r\n"
2045 "Host: www.example.org\r\n"
2046 "Connection: keep-alive\r\n\r\n"),
2048 // After calling trans->RestartWithAuth(), this is the request we should
2049 // be issuing -- the final header line contains the credentials.
2050 MockWrite(
2051 "GET / HTTP/1.1\r\n"
2052 "Host: www.example.org\r\n"
2053 "Connection: keep-alive\r\n"
2054 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2057 MockRead data_reads1[] = {
2058 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2059 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2060 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2061 MockRead("Content-Length: 14\r\n\r\n"),
2062 MockRead("Unauthorized\r\n"),
2064 // Lastly, the server responds with the actual content.
2065 MockRead("HTTP/1.1 200 OK\r\n"),
2066 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2067 MockRead("Content-Length: 5\r\n\r\n"),
2068 MockRead("Hello"),
2071 // If there is a regression where we disconnect a Keep-Alive
2072 // connection during an auth roundtrip, we'll end up reading this.
2073 MockRead data_reads2[] = {
2074 MockRead(SYNCHRONOUS, ERR_FAILED),
2077 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2078 data_writes1, arraysize(data_writes1));
2079 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2080 NULL, 0);
2081 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2082 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2084 TestCompletionCallback callback1;
2086 scoped_ptr<HttpTransaction> trans(
2087 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2088 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2089 EXPECT_EQ(ERR_IO_PENDING, rv);
2091 rv = callback1.WaitForResult();
2092 EXPECT_EQ(OK, rv);
2094 LoadTimingInfo load_timing_info1;
2095 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2096 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2098 const HttpResponseInfo* response = trans->GetResponseInfo();
2099 ASSERT_TRUE(response != NULL);
2100 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2102 TestCompletionCallback callback2;
2104 rv = trans->RestartWithAuth(
2105 AuthCredentials(kFoo, kBar), callback2.callback());
2106 EXPECT_EQ(ERR_IO_PENDING, rv);
2108 rv = callback2.WaitForResult();
2109 EXPECT_EQ(OK, rv);
2111 LoadTimingInfo load_timing_info2;
2112 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2113 TestLoadTimingReused(load_timing_info2);
2114 // The load timing after restart should have the same socket ID, and times
2115 // those of the first load timing.
2116 EXPECT_LE(load_timing_info1.receive_headers_end,
2117 load_timing_info2.send_start);
2118 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2120 response = trans->GetResponseInfo();
2121 ASSERT_TRUE(response != NULL);
2122 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2123 EXPECT_EQ(5, response->headers->GetContentLength());
2125 std::string response_data;
2126 rv = ReadTransaction(trans.get(), &response_data);
2127 EXPECT_EQ(OK, rv);
2128 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2129 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2132 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2133 // connection and with no response body to drain.
2134 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2135 HttpRequestInfo request;
2136 request.method = "GET";
2137 request.url = GURL("http://www.example.org/");
2138 request.load_flags = 0;
2140 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2142 MockWrite data_writes1[] = {
2143 MockWrite(
2144 "GET / HTTP/1.1\r\n"
2145 "Host: www.example.org\r\n"
2146 "Connection: keep-alive\r\n\r\n"),
2148 // After calling trans->RestartWithAuth(), this is the request we should
2149 // be issuing -- the final header line contains the credentials.
2150 MockWrite(
2151 "GET / HTTP/1.1\r\n"
2152 "Host: www.example.org\r\n"
2153 "Connection: keep-alive\r\n"
2154 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2157 MockRead data_reads1[] = {
2158 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2159 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2160 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2162 // Lastly, the server responds with the actual content.
2163 MockRead("HTTP/1.1 200 OK\r\n"),
2164 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2165 MockRead("Content-Length: 5\r\n\r\n"),
2166 MockRead("hello"),
2169 // An incorrect reconnect would cause this to be read.
2170 MockRead data_reads2[] = {
2171 MockRead(SYNCHRONOUS, ERR_FAILED),
2174 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2175 data_writes1, arraysize(data_writes1));
2176 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2177 NULL, 0);
2178 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2179 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2181 TestCompletionCallback callback1;
2183 scoped_ptr<HttpTransaction> trans(
2184 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2185 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2186 EXPECT_EQ(ERR_IO_PENDING, rv);
2188 rv = callback1.WaitForResult();
2189 EXPECT_EQ(OK, rv);
2191 const HttpResponseInfo* response = trans->GetResponseInfo();
2192 ASSERT_TRUE(response != NULL);
2193 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2195 TestCompletionCallback callback2;
2197 rv = trans->RestartWithAuth(
2198 AuthCredentials(kFoo, kBar), callback2.callback());
2199 EXPECT_EQ(ERR_IO_PENDING, rv);
2201 rv = callback2.WaitForResult();
2202 EXPECT_EQ(OK, rv);
2204 response = trans->GetResponseInfo();
2205 ASSERT_TRUE(response != NULL);
2206 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2207 EXPECT_EQ(5, response->headers->GetContentLength());
2210 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2211 // connection and with a large response body to drain.
2212 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2213 HttpRequestInfo request;
2214 request.method = "GET";
2215 request.url = GURL("http://www.example.org/");
2216 request.load_flags = 0;
2218 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2220 MockWrite data_writes1[] = {
2221 MockWrite(
2222 "GET / HTTP/1.1\r\n"
2223 "Host: www.example.org\r\n"
2224 "Connection: keep-alive\r\n\r\n"),
2226 // After calling trans->RestartWithAuth(), this is the request we should
2227 // be issuing -- the final header line contains the credentials.
2228 MockWrite(
2229 "GET / HTTP/1.1\r\n"
2230 "Host: www.example.org\r\n"
2231 "Connection: keep-alive\r\n"
2232 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2235 // Respond with 5 kb of response body.
2236 std::string large_body_string("Unauthorized");
2237 large_body_string.append(5 * 1024, ' ');
2238 large_body_string.append("\r\n");
2240 MockRead data_reads1[] = {
2241 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2242 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2244 // 5134 = 12 + 5 * 1024 + 2
2245 MockRead("Content-Length: 5134\r\n\r\n"),
2246 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2248 // Lastly, the server responds with the actual content.
2249 MockRead("HTTP/1.1 200 OK\r\n"),
2250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2251 MockRead("Content-Length: 5\r\n\r\n"),
2252 MockRead("hello"),
2255 // An incorrect reconnect would cause this to be read.
2256 MockRead data_reads2[] = {
2257 MockRead(SYNCHRONOUS, ERR_FAILED),
2260 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2261 data_writes1, arraysize(data_writes1));
2262 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2263 NULL, 0);
2264 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2265 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2267 TestCompletionCallback callback1;
2269 scoped_ptr<HttpTransaction> trans(
2270 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2271 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2272 EXPECT_EQ(ERR_IO_PENDING, rv);
2274 rv = callback1.WaitForResult();
2275 EXPECT_EQ(OK, rv);
2277 const HttpResponseInfo* response = trans->GetResponseInfo();
2278 ASSERT_TRUE(response != NULL);
2279 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2281 TestCompletionCallback callback2;
2283 rv = trans->RestartWithAuth(
2284 AuthCredentials(kFoo, kBar), callback2.callback());
2285 EXPECT_EQ(ERR_IO_PENDING, rv);
2287 rv = callback2.WaitForResult();
2288 EXPECT_EQ(OK, rv);
2290 response = trans->GetResponseInfo();
2291 ASSERT_TRUE(response != NULL);
2292 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2293 EXPECT_EQ(5, response->headers->GetContentLength());
2296 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2297 // connection, but the server gets impatient and closes the connection.
2298 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2299 HttpRequestInfo request;
2300 request.method = "GET";
2301 request.url = GURL("http://www.example.org/");
2302 request.load_flags = 0;
2304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2306 MockWrite data_writes1[] = {
2307 MockWrite(
2308 "GET / HTTP/1.1\r\n"
2309 "Host: www.example.org\r\n"
2310 "Connection: keep-alive\r\n\r\n"),
2311 // This simulates the seemingly successful write to a closed connection
2312 // if the bug is not fixed.
2313 MockWrite(
2314 "GET / HTTP/1.1\r\n"
2315 "Host: www.example.org\r\n"
2316 "Connection: keep-alive\r\n"
2317 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2320 MockRead data_reads1[] = {
2321 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2322 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2323 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2324 MockRead("Content-Length: 14\r\n\r\n"),
2325 // Tell MockTCPClientSocket to simulate the server closing the connection.
2326 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2327 MockRead("Unauthorized\r\n"),
2328 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2331 // After calling trans->RestartWithAuth(), this is the request we should
2332 // be issuing -- the final header line contains the credentials.
2333 MockWrite data_writes2[] = {
2334 MockWrite(
2335 "GET / HTTP/1.1\r\n"
2336 "Host: www.example.org\r\n"
2337 "Connection: keep-alive\r\n"
2338 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2341 // Lastly, the server responds with the actual content.
2342 MockRead data_reads2[] = {
2343 MockRead("HTTP/1.1 200 OK\r\n"),
2344 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2345 MockRead("Content-Length: 5\r\n\r\n"),
2346 MockRead("hello"),
2349 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2350 data_writes1, arraysize(data_writes1));
2351 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2352 data_writes2, arraysize(data_writes2));
2353 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2354 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2356 TestCompletionCallback callback1;
2358 scoped_ptr<HttpTransaction> trans(
2359 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2360 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2361 EXPECT_EQ(ERR_IO_PENDING, rv);
2363 rv = callback1.WaitForResult();
2364 EXPECT_EQ(OK, rv);
2366 const HttpResponseInfo* response = trans->GetResponseInfo();
2367 ASSERT_TRUE(response != NULL);
2368 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2370 TestCompletionCallback callback2;
2372 rv = trans->RestartWithAuth(
2373 AuthCredentials(kFoo, kBar), callback2.callback());
2374 EXPECT_EQ(ERR_IO_PENDING, rv);
2376 rv = callback2.WaitForResult();
2377 EXPECT_EQ(OK, rv);
2379 response = trans->GetResponseInfo();
2380 ASSERT_TRUE(response != NULL);
2381 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2382 EXPECT_EQ(5, response->headers->GetContentLength());
2385 // Test the request-challenge-retry sequence for basic auth, over a connection
2386 // that requires a restart when setting up an SSL tunnel.
2387 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2388 HttpRequestInfo request;
2389 request.method = "GET";
2390 request.url = GURL("https://www.example.org/");
2391 // when the no authentication data flag is set.
2392 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2394 // Configure against proxy server "myproxy:70".
2395 session_deps_.proxy_service.reset(
2396 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2397 BoundTestNetLog log;
2398 session_deps_.net_log = log.bound().net_log();
2399 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2401 // Since we have proxy, should try to establish tunnel.
2402 MockWrite data_writes1[] = {
2403 MockWrite(
2404 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2405 "Host: www.example.org\r\n"
2406 "Proxy-Connection: keep-alive\r\n\r\n"),
2408 // After calling trans->RestartWithAuth(), this is the request we should
2409 // be issuing -- the final header line contains the credentials.
2410 MockWrite(
2411 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2412 "Host: www.example.org\r\n"
2413 "Proxy-Connection: keep-alive\r\n"
2414 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2416 MockWrite(
2417 "GET / HTTP/1.1\r\n"
2418 "Host: www.example.org\r\n"
2419 "Connection: keep-alive\r\n\r\n"),
2422 // The proxy responds to the connect with a 407, using a persistent
2423 // connection.
2424 MockRead data_reads1[] = {
2425 // No credentials.
2426 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2427 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2429 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2431 MockRead("HTTP/1.1 200 OK\r\n"),
2432 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2433 MockRead("Content-Length: 5\r\n\r\n"),
2434 MockRead(SYNCHRONOUS, "hello"),
2437 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2438 data_writes1, arraysize(data_writes1));
2439 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2440 SSLSocketDataProvider ssl(ASYNC, OK);
2441 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2443 TestCompletionCallback callback1;
2445 scoped_ptr<HttpTransaction> trans(
2446 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2448 int rv = trans->Start(&request, callback1.callback(), log.bound());
2449 EXPECT_EQ(ERR_IO_PENDING, rv);
2451 rv = callback1.WaitForResult();
2452 EXPECT_EQ(OK, rv);
2453 TestNetLogEntry::List entries;
2454 log.GetEntries(&entries);
2455 size_t pos = ExpectLogContainsSomewhere(
2456 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2457 NetLog::PHASE_NONE);
2458 ExpectLogContainsSomewhere(
2459 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2460 NetLog::PHASE_NONE);
2462 const HttpResponseInfo* response = trans->GetResponseInfo();
2463 ASSERT_TRUE(response != NULL);
2464 EXPECT_FALSE(response->headers->IsKeepAlive());
2465 ASSERT_FALSE(response->headers.get() == NULL);
2466 EXPECT_EQ(407, response->headers->response_code());
2467 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2468 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2470 LoadTimingInfo load_timing_info;
2471 // CONNECT requests and responses are handled at the connect job level, so
2472 // the transaction does not yet have a connection.
2473 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2475 TestCompletionCallback callback2;
2477 rv =
2478 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2479 EXPECT_EQ(ERR_IO_PENDING, rv);
2481 rv = callback2.WaitForResult();
2482 EXPECT_EQ(OK, rv);
2484 response = trans->GetResponseInfo();
2485 ASSERT_TRUE(response != NULL);
2487 EXPECT_TRUE(response->headers->IsKeepAlive());
2488 EXPECT_EQ(200, response->headers->response_code());
2489 EXPECT_EQ(5, response->headers->GetContentLength());
2490 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2492 // The password prompt info should not be set.
2493 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2495 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2496 TestLoadTimingNotReusedWithPac(load_timing_info,
2497 CONNECT_TIMING_HAS_SSL_TIMES);
2499 trans.reset();
2500 session->CloseAllConnections();
2503 // Test the request-challenge-retry sequence for basic auth, over a connection
2504 // that requires a restart when setting up an SSL tunnel.
2505 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
2506 HttpRequestInfo request;
2507 request.method = "GET";
2508 request.url = GURL("https://www.example.org/");
2509 // when the no authentication data flag is set.
2510 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2512 // Configure against proxy server "myproxy:70".
2513 session_deps_.proxy_service.reset(
2514 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2515 BoundTestNetLog log;
2516 session_deps_.net_log = log.bound().net_log();
2517 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2519 // Since we have proxy, should try to establish tunnel.
2520 MockWrite data_writes1[] = {
2521 MockWrite(
2522 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2523 "Host: www.example.org\r\n"
2524 "Proxy-Connection: keep-alive\r\n\r\n"),
2526 // After calling trans->RestartWithAuth(), this is the request we should
2527 // be issuing -- the final header line contains the credentials.
2528 MockWrite(
2529 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2530 "Host: www.example.org\r\n"
2531 "Proxy-Connection: keep-alive\r\n"
2532 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2534 MockWrite(
2535 "GET / HTTP/1.1\r\n"
2536 "Host: www.example.org\r\n"
2537 "Connection: keep-alive\r\n\r\n"),
2540 // The proxy responds to the connect with a 407, using a persistent
2541 // connection.
2542 MockRead data_reads1[] = {
2543 // No credentials.
2544 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2545 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2546 MockRead("Proxy-Connection: close\r\n\r\n"),
2548 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2550 MockRead("HTTP/1.1 200 OK\r\n"),
2551 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2552 MockRead("Content-Length: 5\r\n\r\n"),
2553 MockRead(SYNCHRONOUS, "hello"),
2556 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2557 data_writes1, arraysize(data_writes1));
2558 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2559 SSLSocketDataProvider ssl(ASYNC, OK);
2560 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2562 TestCompletionCallback callback1;
2564 scoped_ptr<HttpTransaction> trans(
2565 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2567 int rv = trans->Start(&request, callback1.callback(), log.bound());
2568 EXPECT_EQ(ERR_IO_PENDING, rv);
2570 rv = callback1.WaitForResult();
2571 EXPECT_EQ(OK, rv);
2572 TestNetLogEntry::List entries;
2573 log.GetEntries(&entries);
2574 size_t pos = ExpectLogContainsSomewhere(
2575 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2576 NetLog::PHASE_NONE);
2577 ExpectLogContainsSomewhere(
2578 entries, pos,
2579 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2580 NetLog::PHASE_NONE);
2582 const HttpResponseInfo* response = trans->GetResponseInfo();
2583 ASSERT_TRUE(response != NULL);
2584 EXPECT_FALSE(response->headers->IsKeepAlive());
2585 ASSERT_FALSE(response->headers.get() == NULL);
2586 EXPECT_EQ(407, response->headers->response_code());
2587 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2588 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2590 LoadTimingInfo load_timing_info;
2591 // CONNECT requests and responses are handled at the connect job level, so
2592 // the transaction does not yet have a connection.
2593 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2595 TestCompletionCallback callback2;
2597 rv = trans->RestartWithAuth(
2598 AuthCredentials(kFoo, kBar), callback2.callback());
2599 EXPECT_EQ(ERR_IO_PENDING, rv);
2601 rv = callback2.WaitForResult();
2602 EXPECT_EQ(OK, rv);
2604 response = trans->GetResponseInfo();
2605 ASSERT_TRUE(response != NULL);
2607 EXPECT_TRUE(response->headers->IsKeepAlive());
2608 EXPECT_EQ(200, response->headers->response_code());
2609 EXPECT_EQ(5, response->headers->GetContentLength());
2610 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2612 // The password prompt info should not be set.
2613 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2615 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2616 TestLoadTimingNotReusedWithPac(load_timing_info,
2617 CONNECT_TIMING_HAS_SSL_TIMES);
2619 trans.reset();
2620 session->CloseAllConnections();
2623 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2624 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2625 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2626 HttpRequestInfo request;
2627 request.method = "GET";
2628 request.url = GURL("https://www.example.org/");
2629 // Ensure that proxy authentication is attempted even
2630 // when the no authentication data flag is set.
2631 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2633 // Configure against proxy server "myproxy:70".
2634 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2635 BoundTestNetLog log;
2636 session_deps_.net_log = log.bound().net_log();
2637 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2639 scoped_ptr<HttpTransaction> trans(
2640 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2642 // Since we have proxy, should try to establish tunnel.
2643 MockWrite data_writes1[] = {
2644 MockWrite(
2645 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2646 "Host: www.example.org\r\n"
2647 "Proxy-Connection: keep-alive\r\n\r\n"),
2649 // After calling trans->RestartWithAuth(), this is the request we should
2650 // be issuing -- the final header line contains the credentials.
2651 MockWrite(
2652 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2653 "Host: www.example.org\r\n"
2654 "Proxy-Connection: keep-alive\r\n"
2655 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2658 // The proxy responds to the connect with a 407, using a persistent
2659 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2660 MockRead data_reads1[] = {
2661 // No credentials.
2662 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2663 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2664 MockRead("Proxy-Connection: keep-alive\r\n"),
2665 MockRead("Content-Length: 10\r\n\r\n"),
2666 MockRead("0123456789"),
2668 // Wrong credentials (wrong password).
2669 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2670 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2671 MockRead("Proxy-Connection: keep-alive\r\n"),
2672 MockRead("Content-Length: 10\r\n\r\n"),
2673 // No response body because the test stops reading here.
2674 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2677 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2678 data_writes1, arraysize(data_writes1));
2679 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2681 TestCompletionCallback callback1;
2683 int rv = trans->Start(&request, callback1.callback(), log.bound());
2684 EXPECT_EQ(ERR_IO_PENDING, rv);
2686 rv = callback1.WaitForResult();
2687 EXPECT_EQ(OK, rv);
2688 TestNetLogEntry::List entries;
2689 log.GetEntries(&entries);
2690 size_t pos = ExpectLogContainsSomewhere(
2691 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2692 NetLog::PHASE_NONE);
2693 ExpectLogContainsSomewhere(
2694 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2695 NetLog::PHASE_NONE);
2697 const HttpResponseInfo* response = trans->GetResponseInfo();
2698 ASSERT_TRUE(response);
2699 ASSERT_TRUE(response->headers);
2700 EXPECT_TRUE(response->headers->IsKeepAlive());
2701 EXPECT_EQ(407, response->headers->response_code());
2702 EXPECT_EQ(10, response->headers->GetContentLength());
2703 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2704 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2706 TestCompletionCallback callback2;
2708 // Wrong password (should be "bar").
2709 rv =
2710 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2711 EXPECT_EQ(ERR_IO_PENDING, rv);
2713 rv = callback2.WaitForResult();
2714 EXPECT_EQ(OK, rv);
2716 response = trans->GetResponseInfo();
2717 ASSERT_TRUE(response);
2718 ASSERT_TRUE(response->headers);
2719 EXPECT_TRUE(response->headers->IsKeepAlive());
2720 EXPECT_EQ(407, response->headers->response_code());
2721 EXPECT_EQ(10, response->headers->GetContentLength());
2722 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2723 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2725 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2726 // out of scope.
2727 session->CloseAllConnections();
2730 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2731 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2732 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
2733 HttpRequestInfo request;
2734 request.method = "GET";
2735 request.url = GURL("https://www.example.org/");
2736 // Ensure that proxy authentication is attempted even
2737 // when the no authentication data flag is set.
2738 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2740 // Configure against proxy server "myproxy:70".
2741 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2742 BoundTestNetLog log;
2743 session_deps_.net_log = log.bound().net_log();
2744 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2746 scoped_ptr<HttpTransaction> trans(
2747 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2749 // Since we have proxy, should try to establish tunnel.
2750 MockWrite data_writes1[] = {
2751 MockWrite(
2752 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2753 "Host: www.example.org\r\n"
2754 "Proxy-Connection: keep-alive\r\n\r\n"),
2756 // After calling trans->RestartWithAuth(), this is the request we should
2757 // be issuing -- the final header line contains the credentials.
2758 MockWrite(
2759 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2760 "Host: www.example.org\r\n"
2761 "Proxy-Connection: keep-alive\r\n"
2762 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2765 // The proxy responds to the connect with a 407, using a persistent
2766 // connection.
2767 MockRead data_reads1[] = {
2768 // No credentials.
2769 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2770 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2771 MockRead("Content-Length: 10\r\n\r\n"),
2772 MockRead("0123456789"),
2774 // Wrong credentials (wrong password).
2775 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2776 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2777 MockRead("Content-Length: 10\r\n\r\n"),
2778 // No response body because the test stops reading here.
2779 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2782 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2783 data_writes1, arraysize(data_writes1));
2784 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2786 TestCompletionCallback callback1;
2788 int rv = trans->Start(&request, callback1.callback(), log.bound());
2789 EXPECT_EQ(ERR_IO_PENDING, rv);
2791 rv = callback1.WaitForResult();
2792 EXPECT_EQ(OK, rv);
2793 TestNetLogEntry::List entries;
2794 log.GetEntries(&entries);
2795 size_t pos = ExpectLogContainsSomewhere(
2796 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2797 NetLog::PHASE_NONE);
2798 ExpectLogContainsSomewhere(
2799 entries, pos,
2800 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2801 NetLog::PHASE_NONE);
2803 const HttpResponseInfo* response = trans->GetResponseInfo();
2804 ASSERT_TRUE(response);
2805 ASSERT_TRUE(response->headers);
2806 EXPECT_TRUE(response->headers->IsKeepAlive());
2807 EXPECT_EQ(407, response->headers->response_code());
2808 EXPECT_EQ(10, response->headers->GetContentLength());
2809 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2810 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2812 TestCompletionCallback callback2;
2814 // Wrong password (should be "bar").
2815 rv = trans->RestartWithAuth(
2816 AuthCredentials(kFoo, kBaz), callback2.callback());
2817 EXPECT_EQ(ERR_IO_PENDING, rv);
2819 rv = callback2.WaitForResult();
2820 EXPECT_EQ(OK, rv);
2822 response = trans->GetResponseInfo();
2823 ASSERT_TRUE(response);
2824 ASSERT_TRUE(response->headers);
2825 EXPECT_TRUE(response->headers->IsKeepAlive());
2826 EXPECT_EQ(407, response->headers->response_code());
2827 EXPECT_EQ(10, response->headers->GetContentLength());
2828 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2829 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2831 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2832 // out of scope.
2833 session->CloseAllConnections();
2836 // Test that we don't read the response body when we fail to establish a tunnel,
2837 // even if the user cancels the proxy's auth attempt.
2838 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2839 HttpRequestInfo request;
2840 request.method = "GET";
2841 request.url = GURL("https://www.example.org/");
2842 request.load_flags = 0;
2844 // Configure against proxy server "myproxy:70".
2845 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2847 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2849 scoped_ptr<HttpTransaction> trans(
2850 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2852 // Since we have proxy, should try to establish tunnel.
2853 MockWrite data_writes[] = {
2854 MockWrite(
2855 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2856 "Host: www.example.org\r\n"
2857 "Proxy-Connection: keep-alive\r\n\r\n"),
2860 // The proxy responds to the connect with a 407.
2861 MockRead data_reads[] = {
2862 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2863 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2864 MockRead("Content-Length: 10\r\n\r\n"),
2865 MockRead("0123456789"), // Should not be reached.
2866 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
2869 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2870 data_writes, arraysize(data_writes));
2871 session_deps_.socket_factory->AddSocketDataProvider(&data);
2873 TestCompletionCallback callback;
2875 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2876 EXPECT_EQ(ERR_IO_PENDING, rv);
2878 rv = callback.WaitForResult();
2879 EXPECT_EQ(OK, rv);
2881 const HttpResponseInfo* response = trans->GetResponseInfo();
2882 ASSERT_TRUE(response);
2883 ASSERT_TRUE(response->headers);
2884 EXPECT_TRUE(response->headers->IsKeepAlive());
2885 EXPECT_EQ(407, response->headers->response_code());
2886 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2888 std::string response_data;
2889 rv = ReadTransaction(trans.get(), &response_data);
2890 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2892 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2893 session->CloseAllConnections();
2896 // Test that we don't pass extraneous headers from the proxy's response to the
2897 // caller when the proxy responds to CONNECT with 407.
2898 TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
2899 HttpRequestInfo request;
2900 request.method = "GET";
2901 request.url = GURL("https://www.example.org/");
2902 request.load_flags = 0;
2904 // Configure against proxy server "myproxy:70".
2905 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2907 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2909 scoped_ptr<HttpTransaction> trans(
2910 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2912 // Since we have proxy, should try to establish tunnel.
2913 MockWrite data_writes[] = {
2914 MockWrite(
2915 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2916 "Host: www.example.org\r\n"
2917 "Proxy-Connection: keep-alive\r\n\r\n"),
2920 // The proxy responds to the connect with a 407.
2921 MockRead data_reads[] = {
2922 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2923 MockRead("X-Foo: bar\r\n"),
2924 MockRead("Set-Cookie: foo=bar\r\n"),
2925 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2926 MockRead("Content-Length: 10\r\n\r\n"),
2927 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2930 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
2931 arraysize(data_writes));
2932 session_deps_.socket_factory->AddSocketDataProvider(&data);
2934 TestCompletionCallback callback;
2936 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2937 EXPECT_EQ(ERR_IO_PENDING, rv);
2939 rv = callback.WaitForResult();
2940 EXPECT_EQ(OK, rv);
2942 const HttpResponseInfo* response = trans->GetResponseInfo();
2943 ASSERT_TRUE(response);
2944 ASSERT_TRUE(response->headers);
2945 EXPECT_TRUE(response->headers->IsKeepAlive());
2946 EXPECT_EQ(407, response->headers->response_code());
2947 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2948 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
2949 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
2951 std::string response_data;
2952 rv = ReadTransaction(trans.get(), &response_data);
2953 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2955 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2956 session->CloseAllConnections();
2959 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2960 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2961 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2962 HttpRequestInfo request;
2963 request.method = "GET";
2964 request.url = GURL("http://www.example.org/");
2965 request.load_flags = 0;
2967 // We are using a DIRECT connection (i.e. no proxy) for this session.
2968 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2969 scoped_ptr<HttpTransaction> trans(
2970 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2972 MockWrite data_writes1[] = {
2973 MockWrite(
2974 "GET / HTTP/1.1\r\n"
2975 "Host: www.example.org\r\n"
2976 "Connection: keep-alive\r\n\r\n"),
2979 MockRead data_reads1[] = {
2980 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2981 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2982 // Large content-length -- won't matter, as connection will be reset.
2983 MockRead("Content-Length: 10000\r\n\r\n"),
2984 MockRead(SYNCHRONOUS, ERR_FAILED),
2987 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2988 data_writes1, arraysize(data_writes1));
2989 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2991 TestCompletionCallback callback;
2993 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2994 EXPECT_EQ(ERR_IO_PENDING, rv);
2996 rv = callback.WaitForResult();
2997 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3000 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3001 // through a non-authenticating proxy. The request should fail with
3002 // ERR_UNEXPECTED_PROXY_AUTH.
3003 // Note that it is impossible to detect if an HTTP server returns a 407 through
3004 // a non-authenticating proxy - there is nothing to indicate whether the
3005 // response came from the proxy or the server, so it is treated as if the proxy
3006 // issued the challenge.
3007 TEST_P(HttpNetworkTransactionTest,
3008 HttpsServerRequestsProxyAuthThroughProxy) {
3009 HttpRequestInfo request;
3010 request.method = "GET";
3011 request.url = GURL("https://www.example.org/");
3013 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3014 BoundTestNetLog log;
3015 session_deps_.net_log = log.bound().net_log();
3016 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3018 // Since we have proxy, should try to establish tunnel.
3019 MockWrite data_writes1[] = {
3020 MockWrite(
3021 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3022 "Host: www.example.org\r\n"
3023 "Proxy-Connection: keep-alive\r\n\r\n"),
3025 MockWrite(
3026 "GET / HTTP/1.1\r\n"
3027 "Host: www.example.org\r\n"
3028 "Connection: keep-alive\r\n\r\n"),
3031 MockRead data_reads1[] = {
3032 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3034 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3035 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3036 MockRead("\r\n"),
3037 MockRead(SYNCHRONOUS, OK),
3040 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3041 data_writes1, arraysize(data_writes1));
3042 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3043 SSLSocketDataProvider ssl(ASYNC, OK);
3044 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3046 TestCompletionCallback callback1;
3048 scoped_ptr<HttpTransaction> trans(
3049 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3051 int rv = trans->Start(&request, callback1.callback(), log.bound());
3052 EXPECT_EQ(ERR_IO_PENDING, rv);
3054 rv = callback1.WaitForResult();
3055 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3056 TestNetLogEntry::List entries;
3057 log.GetEntries(&entries);
3058 size_t pos = ExpectLogContainsSomewhere(
3059 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3060 NetLog::PHASE_NONE);
3061 ExpectLogContainsSomewhere(
3062 entries, pos,
3063 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3064 NetLog::PHASE_NONE);
3067 // Test the load timing for HTTPS requests with an HTTP proxy.
3068 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
3069 HttpRequestInfo request1;
3070 request1.method = "GET";
3071 request1.url = GURL("https://www.example.org/1");
3073 HttpRequestInfo request2;
3074 request2.method = "GET";
3075 request2.url = GURL("https://www.example.org/2");
3077 // Configure against proxy server "myproxy:70".
3078 session_deps_.proxy_service.reset(
3079 ProxyService::CreateFixed("PROXY myproxy:70"));
3080 BoundTestNetLog log;
3081 session_deps_.net_log = log.bound().net_log();
3082 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3084 // Since we have proxy, should try to establish tunnel.
3085 MockWrite data_writes1[] = {
3086 MockWrite(
3087 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3088 "Host: www.example.org\r\n"
3089 "Proxy-Connection: keep-alive\r\n\r\n"),
3091 MockWrite(
3092 "GET /1 HTTP/1.1\r\n"
3093 "Host: www.example.org\r\n"
3094 "Connection: keep-alive\r\n\r\n"),
3096 MockWrite(
3097 "GET /2 HTTP/1.1\r\n"
3098 "Host: www.example.org\r\n"
3099 "Connection: keep-alive\r\n\r\n"),
3102 // The proxy responds to the connect with a 407, using a persistent
3103 // connection.
3104 MockRead data_reads1[] = {
3105 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3107 MockRead("HTTP/1.1 200 OK\r\n"),
3108 MockRead("Content-Length: 1\r\n\r\n"),
3109 MockRead(SYNCHRONOUS, "1"),
3111 MockRead("HTTP/1.1 200 OK\r\n"),
3112 MockRead("Content-Length: 2\r\n\r\n"),
3113 MockRead(SYNCHRONOUS, "22"),
3116 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3117 data_writes1, arraysize(data_writes1));
3118 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3119 SSLSocketDataProvider ssl(ASYNC, OK);
3120 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3122 TestCompletionCallback callback1;
3123 scoped_ptr<HttpTransaction> trans1(
3124 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3126 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3127 EXPECT_EQ(ERR_IO_PENDING, rv);
3129 rv = callback1.WaitForResult();
3130 EXPECT_EQ(OK, rv);
3132 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3133 ASSERT_TRUE(response1 != NULL);
3134 ASSERT_TRUE(response1->headers.get() != NULL);
3135 EXPECT_EQ(1, response1->headers->GetContentLength());
3137 LoadTimingInfo load_timing_info1;
3138 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3139 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3141 trans1.reset();
3143 TestCompletionCallback callback2;
3144 scoped_ptr<HttpTransaction> trans2(
3145 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3147 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3148 EXPECT_EQ(ERR_IO_PENDING, rv);
3150 rv = callback2.WaitForResult();
3151 EXPECT_EQ(OK, rv);
3153 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3154 ASSERT_TRUE(response2 != NULL);
3155 ASSERT_TRUE(response2->headers.get() != NULL);
3156 EXPECT_EQ(2, response2->headers->GetContentLength());
3158 LoadTimingInfo load_timing_info2;
3159 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3160 TestLoadTimingReused(load_timing_info2);
3162 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3164 trans2.reset();
3165 session->CloseAllConnections();
3168 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3169 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
3170 HttpRequestInfo request1;
3171 request1.method = "GET";
3172 request1.url = GURL("https://www.example.org/1");
3174 HttpRequestInfo request2;
3175 request2.method = "GET";
3176 request2.url = GURL("https://www.example.org/2");
3178 // Configure against proxy server "myproxy:70".
3179 session_deps_.proxy_service.reset(
3180 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3181 BoundTestNetLog log;
3182 session_deps_.net_log = log.bound().net_log();
3183 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3185 // Since we have proxy, should try to establish tunnel.
3186 MockWrite data_writes1[] = {
3187 MockWrite(
3188 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3189 "Host: www.example.org\r\n"
3190 "Proxy-Connection: keep-alive\r\n\r\n"),
3192 MockWrite(
3193 "GET /1 HTTP/1.1\r\n"
3194 "Host: www.example.org\r\n"
3195 "Connection: keep-alive\r\n\r\n"),
3197 MockWrite(
3198 "GET /2 HTTP/1.1\r\n"
3199 "Host: www.example.org\r\n"
3200 "Connection: keep-alive\r\n\r\n"),
3203 // The proxy responds to the connect with a 407, using a persistent
3204 // connection.
3205 MockRead data_reads1[] = {
3206 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3208 MockRead("HTTP/1.1 200 OK\r\n"),
3209 MockRead("Content-Length: 1\r\n\r\n"),
3210 MockRead(SYNCHRONOUS, "1"),
3212 MockRead("HTTP/1.1 200 OK\r\n"),
3213 MockRead("Content-Length: 2\r\n\r\n"),
3214 MockRead(SYNCHRONOUS, "22"),
3217 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3218 data_writes1, arraysize(data_writes1));
3219 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3220 SSLSocketDataProvider ssl(ASYNC, OK);
3221 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3223 TestCompletionCallback callback1;
3224 scoped_ptr<HttpTransaction> trans1(
3225 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3227 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3228 EXPECT_EQ(ERR_IO_PENDING, rv);
3230 rv = callback1.WaitForResult();
3231 EXPECT_EQ(OK, rv);
3233 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3234 ASSERT_TRUE(response1 != NULL);
3235 ASSERT_TRUE(response1->headers.get() != NULL);
3236 EXPECT_EQ(1, response1->headers->GetContentLength());
3238 LoadTimingInfo load_timing_info1;
3239 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3240 TestLoadTimingNotReusedWithPac(load_timing_info1,
3241 CONNECT_TIMING_HAS_SSL_TIMES);
3243 trans1.reset();
3245 TestCompletionCallback callback2;
3246 scoped_ptr<HttpTransaction> trans2(
3247 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3249 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3250 EXPECT_EQ(ERR_IO_PENDING, rv);
3252 rv = callback2.WaitForResult();
3253 EXPECT_EQ(OK, rv);
3255 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3256 ASSERT_TRUE(response2 != NULL);
3257 ASSERT_TRUE(response2->headers.get() != NULL);
3258 EXPECT_EQ(2, response2->headers->GetContentLength());
3260 LoadTimingInfo load_timing_info2;
3261 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3262 TestLoadTimingReusedWithPac(load_timing_info2);
3264 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3266 trans2.reset();
3267 session->CloseAllConnections();
3270 // Test a simple get through an HTTPS Proxy.
3271 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
3272 HttpRequestInfo request;
3273 request.method = "GET";
3274 request.url = GURL("http://www.example.org/");
3276 // Configure against https proxy server "proxy:70".
3277 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3278 "https://proxy:70"));
3279 BoundTestNetLog log;
3280 session_deps_.net_log = log.bound().net_log();
3281 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3283 // Since we have proxy, should use full url
3284 MockWrite data_writes1[] = {
3285 MockWrite(
3286 "GET http://www.example.org/ HTTP/1.1\r\n"
3287 "Host: www.example.org\r\n"
3288 "Proxy-Connection: keep-alive\r\n\r\n"),
3291 MockRead data_reads1[] = {
3292 MockRead("HTTP/1.1 200 OK\r\n"),
3293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3294 MockRead("Content-Length: 100\r\n\r\n"),
3295 MockRead(SYNCHRONOUS, OK),
3298 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3299 data_writes1, arraysize(data_writes1));
3300 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3301 SSLSocketDataProvider ssl(ASYNC, OK);
3302 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3304 TestCompletionCallback callback1;
3306 scoped_ptr<HttpTransaction> trans(
3307 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3309 int rv = trans->Start(&request, callback1.callback(), log.bound());
3310 EXPECT_EQ(ERR_IO_PENDING, rv);
3312 rv = callback1.WaitForResult();
3313 EXPECT_EQ(OK, rv);
3315 LoadTimingInfo load_timing_info;
3316 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3317 TestLoadTimingNotReused(load_timing_info,
3318 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3320 const HttpResponseInfo* response = trans->GetResponseInfo();
3321 ASSERT_TRUE(response != NULL);
3323 EXPECT_TRUE(response->headers->IsKeepAlive());
3324 EXPECT_EQ(200, response->headers->response_code());
3325 EXPECT_EQ(100, response->headers->GetContentLength());
3326 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3328 // The password prompt info should not be set.
3329 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3332 // Test a SPDY get through an HTTPS Proxy.
3333 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3334 HttpRequestInfo request;
3335 request.method = "GET";
3336 request.url = GURL("http://www.example.org/");
3337 request.load_flags = 0;
3339 // Configure against https proxy server "proxy:70".
3340 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3341 "https://proxy:70"));
3342 BoundTestNetLog log;
3343 session_deps_.net_log = log.bound().net_log();
3344 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3346 // fetch http://www.example.org/ via SPDY
3347 scoped_ptr<SpdyFrame> req(
3348 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3349 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3351 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3352 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3353 MockRead spdy_reads[] = {
3354 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3357 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3358 arraysize(spdy_writes));
3359 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3361 SSLSocketDataProvider ssl(ASYNC, OK);
3362 ssl.SetNextProto(GetParam());
3363 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3365 TestCompletionCallback callback1;
3367 scoped_ptr<HttpTransaction> trans(
3368 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3370 int rv = trans->Start(&request, callback1.callback(), log.bound());
3371 EXPECT_EQ(ERR_IO_PENDING, rv);
3373 rv = callback1.WaitForResult();
3374 EXPECT_EQ(OK, rv);
3376 LoadTimingInfo load_timing_info;
3377 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3378 TestLoadTimingNotReused(load_timing_info,
3379 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3381 const HttpResponseInfo* response = trans->GetResponseInfo();
3382 ASSERT_TRUE(response != NULL);
3383 ASSERT_TRUE(response->headers.get() != NULL);
3384 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3386 std::string response_data;
3387 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3388 EXPECT_EQ(kUploadData, response_data);
3391 // Verifies that a session which races and wins against the owning transaction
3392 // (completing prior to host resolution), doesn't fail the transaction.
3393 // Regression test for crbug.com/334413.
3394 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3395 HttpRequestInfo request;
3396 request.method = "GET";
3397 request.url = GURL("http://www.example.org/");
3398 request.load_flags = 0;
3400 // Configure SPDY proxy server "proxy:70".
3401 session_deps_.proxy_service.reset(
3402 ProxyService::CreateFixed("https://proxy:70"));
3403 BoundTestNetLog log;
3404 session_deps_.net_log = log.bound().net_log();
3405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3407 // Fetch http://www.example.org/ through the SPDY proxy.
3408 scoped_ptr<SpdyFrame> req(
3409 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3410 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3412 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3413 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3414 MockRead spdy_reads[] = {
3415 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3418 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3419 arraysize(spdy_writes));
3420 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3422 SSLSocketDataProvider ssl(ASYNC, OK);
3423 ssl.SetNextProto(GetParam());
3424 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3426 TestCompletionCallback callback1;
3428 scoped_ptr<HttpTransaction> trans(
3429 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3431 // Stall the hostname resolution begun by the transaction.
3432 session_deps_.host_resolver->set_synchronous_mode(false);
3433 session_deps_.host_resolver->set_ondemand_mode(true);
3435 int rv = trans->Start(&request, callback1.callback(), log.bound());
3436 EXPECT_EQ(ERR_IO_PENDING, rv);
3438 // Race a session to the proxy, which completes first.
3439 session_deps_.host_resolver->set_ondemand_mode(false);
3440 SpdySessionKey key(
3441 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3442 base::WeakPtr<SpdySession> spdy_session =
3443 CreateSecureSpdySession(session, key, log.bound());
3445 // Unstall the resolution begun by the transaction.
3446 session_deps_.host_resolver->set_ondemand_mode(true);
3447 session_deps_.host_resolver->ResolveAllPending();
3449 EXPECT_FALSE(callback1.have_result());
3450 rv = callback1.WaitForResult();
3451 EXPECT_EQ(OK, rv);
3453 const HttpResponseInfo* response = trans->GetResponseInfo();
3454 ASSERT_TRUE(response != NULL);
3455 ASSERT_TRUE(response->headers.get() != NULL);
3456 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3458 std::string response_data;
3459 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3460 EXPECT_EQ(kUploadData, response_data);
3463 // Test a SPDY get through an HTTPS Proxy.
3464 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3465 HttpRequestInfo request;
3466 request.method = "GET";
3467 request.url = GURL("http://www.example.org/");
3468 request.load_flags = 0;
3470 // Configure against https proxy server "myproxy:70".
3471 session_deps_.proxy_service.reset(
3472 ProxyService::CreateFixed("https://myproxy:70"));
3473 BoundTestNetLog log;
3474 session_deps_.net_log = log.bound().net_log();
3475 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3477 // The first request will be a bare GET, the second request will be a
3478 // GET with a Proxy-Authorization header.
3479 scoped_ptr<SpdyFrame> req_get(
3480 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3481 const char* const kExtraAuthorizationHeaders[] = {
3482 "proxy-authorization", "Basic Zm9vOmJhcg=="
3484 scoped_ptr<SpdyFrame> req_get_authorization(
3485 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3486 arraysize(kExtraAuthorizationHeaders) / 2,
3487 false,
3489 LOWEST,
3490 false));
3491 MockWrite spdy_writes[] = {
3492 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
3495 // The first response is a 407 proxy authentication challenge, and the second
3496 // response will be a 200 response since the second request includes a valid
3497 // Authorization header.
3498 const char* const kExtraAuthenticationHeaders[] = {
3499 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3501 scoped_ptr<SpdyFrame> resp_authentication(
3502 spdy_util_.ConstructSpdySynReplyError(
3503 "407 Proxy Authentication Required",
3504 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3505 1));
3506 scoped_ptr<SpdyFrame> body_authentication(
3507 spdy_util_.ConstructSpdyBodyFrame(1, true));
3508 scoped_ptr<SpdyFrame> resp_data(
3509 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3510 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3511 MockRead spdy_reads[] = {
3512 CreateMockRead(*resp_authentication, 1),
3513 CreateMockRead(*body_authentication, 2),
3514 CreateMockRead(*resp_data, 4),
3515 CreateMockRead(*body_data, 5),
3516 MockRead(ASYNC, 0, 6),
3519 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3520 arraysize(spdy_writes));
3521 session_deps_.socket_factory->AddSocketDataProvider(&data);
3523 SSLSocketDataProvider ssl(ASYNC, OK);
3524 ssl.SetNextProto(GetParam());
3525 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3527 TestCompletionCallback callback1;
3529 scoped_ptr<HttpTransaction> trans(
3530 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3532 int rv = trans->Start(&request, callback1.callback(), log.bound());
3533 EXPECT_EQ(ERR_IO_PENDING, rv);
3535 rv = callback1.WaitForResult();
3536 EXPECT_EQ(OK, rv);
3538 const HttpResponseInfo* const response = trans->GetResponseInfo();
3540 ASSERT_TRUE(response != NULL);
3541 ASSERT_TRUE(response->headers.get() != NULL);
3542 EXPECT_EQ(407, response->headers->response_code());
3543 EXPECT_TRUE(response->was_fetched_via_spdy);
3544 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3546 TestCompletionCallback callback2;
3548 rv = trans->RestartWithAuth(
3549 AuthCredentials(kFoo, kBar), callback2.callback());
3550 EXPECT_EQ(ERR_IO_PENDING, rv);
3552 rv = callback2.WaitForResult();
3553 EXPECT_EQ(OK, rv);
3555 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3557 ASSERT_TRUE(response_restart != NULL);
3558 ASSERT_TRUE(response_restart->headers.get() != NULL);
3559 EXPECT_EQ(200, response_restart->headers->response_code());
3560 // The password prompt info should not be set.
3561 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3564 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3565 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3566 HttpRequestInfo request;
3567 request.method = "GET";
3568 request.url = GURL("https://www.example.org/");
3569 request.load_flags = 0;
3571 // Configure against https proxy server "proxy:70".
3572 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3573 "https://proxy:70"));
3574 BoundTestNetLog log;
3575 session_deps_.net_log = log.bound().net_log();
3576 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3578 scoped_ptr<HttpTransaction> trans(
3579 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3581 // CONNECT to www.example.org:443 via SPDY
3582 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3583 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3584 // fetch https://www.example.org/ via HTTP
3586 const char get[] =
3587 "GET / HTTP/1.1\r\n"
3588 "Host: www.example.org\r\n"
3589 "Connection: keep-alive\r\n\r\n";
3590 scoped_ptr<SpdyFrame> wrapped_get(
3591 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3592 scoped_ptr<SpdyFrame> conn_resp(
3593 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3594 const char resp[] = "HTTP/1.1 200 OK\r\n"
3595 "Content-Length: 10\r\n\r\n";
3596 scoped_ptr<SpdyFrame> wrapped_get_resp(
3597 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3598 scoped_ptr<SpdyFrame> wrapped_body(
3599 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3600 scoped_ptr<SpdyFrame> window_update(
3601 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3603 MockWrite spdy_writes[] = {
3604 CreateMockWrite(*connect, 0),
3605 CreateMockWrite(*wrapped_get, 2),
3606 CreateMockWrite(*window_update, 6),
3609 MockRead spdy_reads[] = {
3610 CreateMockRead(*conn_resp, 1, ASYNC),
3611 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
3612 CreateMockRead(*wrapped_body, 4, ASYNC),
3613 CreateMockRead(*wrapped_body, 5, ASYNC),
3614 MockRead(ASYNC, 0, 7),
3617 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3618 arraysize(spdy_writes));
3619 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3621 SSLSocketDataProvider ssl(ASYNC, OK);
3622 ssl.SetNextProto(GetParam());
3623 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3624 SSLSocketDataProvider ssl2(ASYNC, OK);
3625 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3627 TestCompletionCallback callback1;
3629 int rv = trans->Start(&request, callback1.callback(), log.bound());
3630 EXPECT_EQ(ERR_IO_PENDING, rv);
3632 rv = callback1.WaitForResult();
3633 ASSERT_EQ(OK, rv);
3635 LoadTimingInfo load_timing_info;
3636 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3637 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3639 const HttpResponseInfo* response = trans->GetResponseInfo();
3640 ASSERT_TRUE(response != NULL);
3641 ASSERT_TRUE(response->headers.get() != NULL);
3642 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3644 std::string response_data;
3645 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3646 EXPECT_EQ("1234567890", response_data);
3649 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3650 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3651 HttpRequestInfo request;
3652 request.method = "GET";
3653 request.url = GURL("https://www.example.org/");
3654 request.load_flags = 0;
3656 // Configure against https proxy server "proxy:70".
3657 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3658 "https://proxy:70"));
3659 BoundTestNetLog log;
3660 session_deps_.net_log = log.bound().net_log();
3661 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3663 scoped_ptr<HttpTransaction> trans(
3664 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3666 // CONNECT to www.example.org:443 via SPDY
3667 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3668 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3669 // fetch https://www.example.org/ via SPDY
3670 const char kMyUrl[] = "https://www.example.org/";
3671 scoped_ptr<SpdyFrame> get(
3672 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3673 scoped_ptr<SpdyFrame> wrapped_get(
3674 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3675 scoped_ptr<SpdyFrame> conn_resp(
3676 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3677 scoped_ptr<SpdyFrame> get_resp(
3678 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3679 scoped_ptr<SpdyFrame> wrapped_get_resp(
3680 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3681 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3682 scoped_ptr<SpdyFrame> wrapped_body(
3683 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3684 scoped_ptr<SpdyFrame> window_update_get_resp(
3685 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3686 scoped_ptr<SpdyFrame> window_update_body(
3687 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3689 MockWrite spdy_writes[] = {
3690 CreateMockWrite(*connect, 0),
3691 CreateMockWrite(*wrapped_get, 2),
3692 CreateMockWrite(*window_update_get_resp, 6),
3693 CreateMockWrite(*window_update_body, 7),
3696 MockRead spdy_reads[] = {
3697 CreateMockRead(*conn_resp, 1, ASYNC),
3698 MockRead(ASYNC, ERR_IO_PENDING, 3),
3699 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3700 CreateMockRead(*wrapped_body, 5, ASYNC),
3701 MockRead(ASYNC, 0, 8),
3704 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3705 arraysize(spdy_writes));
3706 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3708 SSLSocketDataProvider ssl(ASYNC, OK);
3709 ssl.SetNextProto(GetParam());
3710 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3711 SSLSocketDataProvider ssl2(ASYNC, OK);
3712 ssl2.SetNextProto(GetParam());
3713 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3715 TestCompletionCallback callback1;
3717 int rv = trans->Start(&request, callback1.callback(), log.bound());
3718 EXPECT_EQ(ERR_IO_PENDING, rv);
3720 // Allow the SpdyProxyClientSocket's write callback to complete.
3721 base::MessageLoop::current()->RunUntilIdle();
3722 // Now allow the read of the response to complete.
3723 spdy_data.CompleteRead();
3724 rv = callback1.WaitForResult();
3725 EXPECT_EQ(OK, rv);
3727 LoadTimingInfo load_timing_info;
3728 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3729 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3731 const HttpResponseInfo* response = trans->GetResponseInfo();
3732 ASSERT_TRUE(response != NULL);
3733 ASSERT_TRUE(response->headers.get() != NULL);
3734 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3736 std::string response_data;
3737 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3738 EXPECT_EQ(kUploadData, response_data);
3741 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3742 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3743 HttpRequestInfo request;
3744 request.method = "GET";
3745 request.url = GURL("https://www.example.org/");
3746 request.load_flags = 0;
3748 // Configure against https proxy server "proxy:70".
3749 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3750 "https://proxy:70"));
3751 BoundTestNetLog log;
3752 session_deps_.net_log = log.bound().net_log();
3753 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3755 scoped_ptr<HttpTransaction> trans(
3756 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3758 // CONNECT to www.example.org:443 via SPDY
3759 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3760 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3761 scoped_ptr<SpdyFrame> get(
3762 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3764 MockWrite spdy_writes[] = {
3765 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
3768 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3769 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3770 MockRead spdy_reads[] = {
3771 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
3774 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3775 arraysize(spdy_writes));
3776 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3778 SSLSocketDataProvider ssl(ASYNC, OK);
3779 ssl.SetNextProto(GetParam());
3780 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3781 SSLSocketDataProvider ssl2(ASYNC, OK);
3782 ssl2.SetNextProto(GetParam());
3783 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3785 TestCompletionCallback callback1;
3787 int rv = trans->Start(&request, callback1.callback(), log.bound());
3788 EXPECT_EQ(ERR_IO_PENDING, rv);
3790 rv = callback1.WaitForResult();
3791 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3793 // TODO(ttuttle): Anything else to check here?
3796 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3797 // HTTPS Proxy to different servers.
3798 TEST_P(HttpNetworkTransactionTest,
3799 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3800 // Configure against https proxy server "proxy:70".
3801 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3802 "https://proxy:70"));
3803 BoundTestNetLog log;
3804 session_deps_.net_log = log.bound().net_log();
3805 scoped_refptr<HttpNetworkSession> session(
3806 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
3808 HttpRequestInfo request1;
3809 request1.method = "GET";
3810 request1.url = GURL("https://www.example.org/");
3811 request1.load_flags = 0;
3813 HttpRequestInfo request2;
3814 request2.method = "GET";
3815 request2.url = GURL("https://mail.example.org/");
3816 request2.load_flags = 0;
3818 // CONNECT to www.example.org:443 via SPDY.
3819 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3820 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3821 scoped_ptr<SpdyFrame> conn_resp1(
3822 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3824 // Fetch https://www.example.org/ via HTTP.
3825 const char get1[] =
3826 "GET / HTTP/1.1\r\n"
3827 "Host: www.example.org\r\n"
3828 "Connection: keep-alive\r\n\r\n";
3829 scoped_ptr<SpdyFrame> wrapped_get1(
3830 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3831 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3832 "Content-Length: 1\r\n\r\n";
3833 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3834 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3835 scoped_ptr<SpdyFrame> wrapped_body1(
3836 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3837 scoped_ptr<SpdyFrame> window_update(
3838 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3840 // CONNECT to mail.example.org:443 via SPDY.
3841 SpdyHeaderBlock connect2_block;
3842 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3843 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
3844 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
3845 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3846 scoped_ptr<SpdyFrame> connect2(
3847 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3849 scoped_ptr<SpdyFrame> conn_resp2(
3850 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3852 // Fetch https://mail.example.org/ via HTTP.
3853 const char get2[] =
3854 "GET / HTTP/1.1\r\n"
3855 "Host: mail.example.org\r\n"
3856 "Connection: keep-alive\r\n\r\n";
3857 scoped_ptr<SpdyFrame> wrapped_get2(
3858 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3859 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3860 "Content-Length: 2\r\n\r\n";
3861 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3862 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3863 scoped_ptr<SpdyFrame> wrapped_body2(
3864 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3866 MockWrite spdy_writes[] = {
3867 CreateMockWrite(*connect1, 0),
3868 CreateMockWrite(*wrapped_get1, 2),
3869 CreateMockWrite(*connect2, 5),
3870 CreateMockWrite(*wrapped_get2, 7),
3873 MockRead spdy_reads[] = {
3874 CreateMockRead(*conn_resp1, 1, ASYNC),
3875 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3876 CreateMockRead(*wrapped_body1, 4, ASYNC),
3877 CreateMockRead(*conn_resp2, 6, ASYNC),
3878 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3879 CreateMockRead(*wrapped_body2, 9, ASYNC),
3880 MockRead(ASYNC, 0, 10),
3883 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3884 arraysize(spdy_writes));
3885 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3887 SSLSocketDataProvider ssl(ASYNC, OK);
3888 ssl.SetNextProto(GetParam());
3889 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3890 SSLSocketDataProvider ssl2(ASYNC, OK);
3891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3892 SSLSocketDataProvider ssl3(ASYNC, OK);
3893 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
3895 TestCompletionCallback callback;
3897 scoped_ptr<HttpTransaction> trans(
3898 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3899 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3900 EXPECT_EQ(OK, callback.GetResult(rv));
3902 LoadTimingInfo load_timing_info;
3903 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3904 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3906 const HttpResponseInfo* response = trans->GetResponseInfo();
3907 ASSERT_TRUE(response != NULL);
3908 ASSERT_TRUE(response->headers.get() != NULL);
3909 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3911 std::string response_data;
3912 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
3913 rv = trans->Read(buf.get(), 256, callback.callback());
3914 EXPECT_EQ(1, callback.GetResult(rv));
3916 scoped_ptr<HttpTransaction> trans2(
3917 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3918 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3919 EXPECT_EQ(OK, callback.GetResult(rv));
3921 LoadTimingInfo load_timing_info2;
3922 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3923 // Even though the SPDY connection is reused, a new tunnelled connection has
3924 // to be created, so the socket's load timing looks like a fresh connection.
3925 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3927 // The requests should have different IDs, since they each are using their own
3928 // separate stream.
3929 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3931 rv = trans2->Read(buf.get(), 256, callback.callback());
3932 EXPECT_EQ(2, callback.GetResult(rv));
3935 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3936 // HTTPS Proxy to the same server.
3937 TEST_P(HttpNetworkTransactionTest,
3938 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3939 // Configure against https proxy server "proxy:70".
3940 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3941 "https://proxy:70"));
3942 BoundTestNetLog log;
3943 session_deps_.net_log = log.bound().net_log();
3944 scoped_refptr<HttpNetworkSession> session(
3945 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
3947 HttpRequestInfo request1;
3948 request1.method = "GET";
3949 request1.url = GURL("https://www.example.org/");
3950 request1.load_flags = 0;
3952 HttpRequestInfo request2;
3953 request2.method = "GET";
3954 request2.url = GURL("https://www.example.org/2");
3955 request2.load_flags = 0;
3957 // CONNECT to www.example.org:443 via SPDY.
3958 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3959 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3960 scoped_ptr<SpdyFrame> conn_resp1(
3961 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3963 // Fetch https://www.example.org/ via HTTP.
3964 const char get1[] =
3965 "GET / HTTP/1.1\r\n"
3966 "Host: www.example.org\r\n"
3967 "Connection: keep-alive\r\n\r\n";
3968 scoped_ptr<SpdyFrame> wrapped_get1(
3969 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3970 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3971 "Content-Length: 1\r\n\r\n";
3972 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3973 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3974 scoped_ptr<SpdyFrame> wrapped_body1(
3975 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3976 scoped_ptr<SpdyFrame> window_update(
3977 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3979 // Fetch https://www.example.org/2 via HTTP.
3980 const char get2[] =
3981 "GET /2 HTTP/1.1\r\n"
3982 "Host: www.example.org\r\n"
3983 "Connection: keep-alive\r\n\r\n";
3984 scoped_ptr<SpdyFrame> wrapped_get2(
3985 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3986 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3987 "Content-Length: 2\r\n\r\n";
3988 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3989 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3990 scoped_ptr<SpdyFrame> wrapped_body2(
3991 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3993 MockWrite spdy_writes[] = {
3994 CreateMockWrite(*connect1, 0),
3995 CreateMockWrite(*wrapped_get1, 2),
3996 CreateMockWrite(*wrapped_get2, 5),
3999 MockRead spdy_reads[] = {
4000 CreateMockRead(*conn_resp1, 1, ASYNC),
4001 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4002 CreateMockRead(*wrapped_body1, 4, ASYNC),
4003 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4004 CreateMockRead(*wrapped_body2, 7, ASYNC),
4005 MockRead(ASYNC, 0, 8),
4008 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4009 arraysize(spdy_writes));
4010 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4012 SSLSocketDataProvider ssl(ASYNC, OK);
4013 ssl.SetNextProto(GetParam());
4014 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4015 SSLSocketDataProvider ssl2(ASYNC, OK);
4016 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4018 TestCompletionCallback callback;
4020 scoped_ptr<HttpTransaction> trans(
4021 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4022 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4023 EXPECT_EQ(ERR_IO_PENDING, rv);
4025 rv = callback.WaitForResult();
4026 EXPECT_EQ(OK, rv);
4028 LoadTimingInfo load_timing_info;
4029 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4030 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4032 const HttpResponseInfo* response = trans->GetResponseInfo();
4033 ASSERT_TRUE(response != NULL);
4034 ASSERT_TRUE(response->headers.get() != NULL);
4035 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4037 std::string response_data;
4038 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4039 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
4040 trans.reset();
4042 scoped_ptr<HttpTransaction> trans2(
4043 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4044 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4045 EXPECT_EQ(ERR_IO_PENDING, rv);
4047 rv = callback.WaitForResult();
4048 EXPECT_EQ(OK, rv);
4050 LoadTimingInfo load_timing_info2;
4051 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4052 TestLoadTimingReused(load_timing_info2);
4054 // The requests should have the same ID.
4055 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4057 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
4060 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4061 // Proxy to different servers.
4062 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
4063 // Configure against https proxy server "proxy:70".
4064 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
4065 "https://proxy:70"));
4066 BoundTestNetLog log;
4067 session_deps_.net_log = log.bound().net_log();
4068 scoped_refptr<HttpNetworkSession> session(
4069 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
4071 HttpRequestInfo request1;
4072 request1.method = "GET";
4073 request1.url = GURL("http://www.example.org/");
4074 request1.load_flags = 0;
4076 HttpRequestInfo request2;
4077 request2.method = "GET";
4078 request2.url = GURL("http://mail.example.org/");
4079 request2.load_flags = 0;
4081 // http://www.example.org/
4082 scoped_ptr<SpdyHeaderBlock> headers(
4083 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4084 scoped_ptr<SpdyFrame> get1(
4085 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4086 scoped_ptr<SpdyFrame> get_resp1(
4087 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4088 scoped_ptr<SpdyFrame> body1(
4089 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
4091 // http://mail.example.org/
4092 scoped_ptr<SpdyHeaderBlock> headers2(
4093 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4094 scoped_ptr<SpdyFrame> get2(
4095 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
4096 scoped_ptr<SpdyFrame> get_resp2(
4097 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4098 scoped_ptr<SpdyFrame> body2(
4099 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
4101 MockWrite spdy_writes[] = {
4102 CreateMockWrite(*get1, 0),
4103 CreateMockWrite(*get2, 3),
4106 MockRead spdy_reads[] = {
4107 CreateMockRead(*get_resp1, 1, ASYNC),
4108 CreateMockRead(*body1, 2, ASYNC),
4109 CreateMockRead(*get_resp2, 4, ASYNC),
4110 CreateMockRead(*body2, 5, ASYNC),
4111 MockRead(ASYNC, 0, 6),
4114 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4115 arraysize(spdy_writes));
4116 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4118 SSLSocketDataProvider ssl(ASYNC, OK);
4119 ssl.SetNextProto(GetParam());
4120 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4122 TestCompletionCallback callback;
4124 scoped_ptr<HttpTransaction> trans(
4125 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4126 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4127 EXPECT_EQ(OK, callback.GetResult(rv));
4129 LoadTimingInfo load_timing_info;
4130 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4131 TestLoadTimingNotReused(load_timing_info,
4132 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4134 const HttpResponseInfo* response = trans->GetResponseInfo();
4135 ASSERT_TRUE(response != NULL);
4136 ASSERT_TRUE(response->headers.get() != NULL);
4137 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4139 std::string response_data;
4140 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4141 rv = trans->Read(buf.get(), 256, callback.callback());
4142 EXPECT_EQ(1, callback.GetResult(rv));
4143 // Delete the first request, so the second one can reuse the socket.
4144 trans.reset();
4146 scoped_ptr<HttpTransaction> trans2(
4147 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4148 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4149 EXPECT_EQ(OK, callback.GetResult(rv));
4151 LoadTimingInfo load_timing_info2;
4152 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4153 TestLoadTimingReused(load_timing_info2);
4155 // The requests should have the same ID.
4156 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4158 rv = trans2->Read(buf.get(), 256, callback.callback());
4159 EXPECT_EQ(2, callback.GetResult(rv));
4162 // Test the challenge-response-retry sequence through an HTTPS Proxy
4163 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
4164 HttpRequestInfo request;
4165 request.method = "GET";
4166 request.url = GURL("http://www.example.org/");
4167 // when the no authentication data flag is set.
4168 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
4170 // Configure against https proxy server "myproxy:70".
4171 session_deps_.proxy_service.reset(
4172 ProxyService::CreateFixed("https://myproxy:70"));
4173 BoundTestNetLog log;
4174 session_deps_.net_log = log.bound().net_log();
4175 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4177 // Since we have proxy, should use full url
4178 MockWrite data_writes1[] = {
4179 MockWrite(
4180 "GET http://www.example.org/ HTTP/1.1\r\n"
4181 "Host: www.example.org\r\n"
4182 "Proxy-Connection: keep-alive\r\n\r\n"),
4184 // After calling trans->RestartWithAuth(), this is the request we should
4185 // be issuing -- the final header line contains the credentials.
4186 MockWrite(
4187 "GET http://www.example.org/ HTTP/1.1\r\n"
4188 "Host: www.example.org\r\n"
4189 "Proxy-Connection: keep-alive\r\n"
4190 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4193 // The proxy responds to the GET with a 407, using a persistent
4194 // connection.
4195 MockRead data_reads1[] = {
4196 // No credentials.
4197 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4198 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4199 MockRead("Proxy-Connection: keep-alive\r\n"),
4200 MockRead("Content-Length: 0\r\n\r\n"),
4202 MockRead("HTTP/1.1 200 OK\r\n"),
4203 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4204 MockRead("Content-Length: 100\r\n\r\n"),
4205 MockRead(SYNCHRONOUS, OK),
4208 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4209 data_writes1, arraysize(data_writes1));
4210 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4211 SSLSocketDataProvider ssl(ASYNC, OK);
4212 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4214 TestCompletionCallback callback1;
4216 scoped_ptr<HttpTransaction> trans(
4217 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4219 int rv = trans->Start(&request, callback1.callback(), log.bound());
4220 EXPECT_EQ(ERR_IO_PENDING, rv);
4222 rv = callback1.WaitForResult();
4223 EXPECT_EQ(OK, rv);
4225 LoadTimingInfo load_timing_info;
4226 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4227 TestLoadTimingNotReused(load_timing_info,
4228 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4230 const HttpResponseInfo* response = trans->GetResponseInfo();
4231 ASSERT_TRUE(response != NULL);
4232 ASSERT_FALSE(response->headers.get() == NULL);
4233 EXPECT_EQ(407, response->headers->response_code());
4234 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4235 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4237 TestCompletionCallback callback2;
4239 rv = trans->RestartWithAuth(
4240 AuthCredentials(kFoo, kBar), callback2.callback());
4241 EXPECT_EQ(ERR_IO_PENDING, rv);
4243 rv = callback2.WaitForResult();
4244 EXPECT_EQ(OK, rv);
4246 load_timing_info = LoadTimingInfo();
4247 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4248 // Retrying with HTTP AUTH is considered to be reusing a socket.
4249 TestLoadTimingReused(load_timing_info);
4251 response = trans->GetResponseInfo();
4252 ASSERT_TRUE(response != NULL);
4254 EXPECT_TRUE(response->headers->IsKeepAlive());
4255 EXPECT_EQ(200, response->headers->response_code());
4256 EXPECT_EQ(100, response->headers->GetContentLength());
4257 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4259 // The password prompt info should not be set.
4260 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4263 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4264 const MockRead& status, int expected_status) {
4265 HttpRequestInfo request;
4266 request.method = "GET";
4267 request.url = GURL("https://www.example.org/");
4268 request.load_flags = 0;
4270 // Configure against proxy server "myproxy:70".
4271 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4272 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4274 // Since we have proxy, should try to establish tunnel.
4275 MockWrite data_writes[] = {
4276 MockWrite(
4277 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4278 "Host: www.example.org\r\n"
4279 "Proxy-Connection: keep-alive\r\n\r\n"),
4282 MockRead data_reads[] = {
4283 status,
4284 MockRead("Content-Length: 10\r\n\r\n"),
4285 // No response body because the test stops reading here.
4286 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4289 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4290 data_writes, arraysize(data_writes));
4291 session_deps_.socket_factory->AddSocketDataProvider(&data);
4293 TestCompletionCallback callback;
4295 scoped_ptr<HttpTransaction> trans(
4296 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4298 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4299 EXPECT_EQ(ERR_IO_PENDING, rv);
4301 rv = callback.WaitForResult();
4302 EXPECT_EQ(expected_status, rv);
4305 void HttpNetworkTransactionTest::ConnectStatusHelper(
4306 const MockRead& status) {
4307 ConnectStatusHelperWithExpectedStatus(
4308 status, ERR_TUNNEL_CONNECTION_FAILED);
4311 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4312 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4315 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4316 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4319 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4320 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4323 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4324 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4327 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4328 ConnectStatusHelper(
4329 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4332 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4333 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4336 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4337 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4340 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4341 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4344 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4345 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4348 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4349 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4352 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4353 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4356 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4357 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4360 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4361 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4364 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4365 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4368 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4369 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4372 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4373 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4376 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4377 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4380 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4381 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4384 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4385 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4388 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4389 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4392 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4393 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4396 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4397 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4400 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4401 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4404 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4405 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4408 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4409 ConnectStatusHelperWithExpectedStatus(
4410 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4411 ERR_PROXY_AUTH_UNSUPPORTED);
4414 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4415 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4418 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4419 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4422 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4423 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4426 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4427 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4430 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4431 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4434 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4435 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4438 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4439 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4442 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4443 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4446 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4447 ConnectStatusHelper(
4448 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4451 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4452 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4455 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4456 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4459 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4460 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4463 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4464 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4467 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4468 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4471 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4472 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4475 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4476 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4479 // Test the flow when both the proxy server AND origin server require
4480 // authentication. Again, this uses basic auth for both since that is
4481 // the simplest to mock.
4482 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4483 HttpRequestInfo request;
4484 request.method = "GET";
4485 request.url = GURL("http://www.example.org/");
4486 request.load_flags = 0;
4488 // Configure against proxy server "myproxy:70".
4489 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4492 scoped_ptr<HttpTransaction> trans(
4493 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4495 MockWrite data_writes1[] = {
4496 MockWrite(
4497 "GET http://www.example.org/ HTTP/1.1\r\n"
4498 "Host: www.example.org\r\n"
4499 "Proxy-Connection: keep-alive\r\n\r\n"),
4502 MockRead data_reads1[] = {
4503 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4504 // Give a couple authenticate options (only the middle one is actually
4505 // supported).
4506 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4507 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4508 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4509 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4510 // Large content-length -- won't matter, as connection will be reset.
4511 MockRead("Content-Length: 10000\r\n\r\n"),
4512 MockRead(SYNCHRONOUS, ERR_FAILED),
4515 // After calling trans->RestartWithAuth() the first time, this is the
4516 // request we should be issuing -- the final header line contains the
4517 // proxy's credentials.
4518 MockWrite data_writes2[] = {
4519 MockWrite(
4520 "GET http://www.example.org/ HTTP/1.1\r\n"
4521 "Host: www.example.org\r\n"
4522 "Proxy-Connection: keep-alive\r\n"
4523 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4526 // Now the proxy server lets the request pass through to origin server.
4527 // The origin server responds with a 401.
4528 MockRead data_reads2[] = {
4529 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4530 // Note: We are using the same realm-name as the proxy server. This is
4531 // completely valid, as realms are unique across hosts.
4532 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4533 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4534 MockRead("Content-Length: 2000\r\n\r\n"),
4535 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4538 // After calling trans->RestartWithAuth() the second time, we should send
4539 // the credentials for both the proxy and origin server.
4540 MockWrite data_writes3[] = {
4541 MockWrite(
4542 "GET http://www.example.org/ HTTP/1.1\r\n"
4543 "Host: www.example.org\r\n"
4544 "Proxy-Connection: keep-alive\r\n"
4545 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4546 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4549 // Lastly we get the desired content.
4550 MockRead data_reads3[] = {
4551 MockRead("HTTP/1.0 200 OK\r\n"),
4552 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4553 MockRead("Content-Length: 100\r\n\r\n"),
4554 MockRead(SYNCHRONOUS, OK),
4557 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4558 data_writes1, arraysize(data_writes1));
4559 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4560 data_writes2, arraysize(data_writes2));
4561 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4562 data_writes3, arraysize(data_writes3));
4563 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4564 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4565 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4567 TestCompletionCallback callback1;
4569 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4570 EXPECT_EQ(ERR_IO_PENDING, rv);
4572 rv = callback1.WaitForResult();
4573 EXPECT_EQ(OK, rv);
4575 const HttpResponseInfo* response = trans->GetResponseInfo();
4576 ASSERT_TRUE(response != NULL);
4577 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4579 TestCompletionCallback callback2;
4581 rv = trans->RestartWithAuth(
4582 AuthCredentials(kFoo, kBar), callback2.callback());
4583 EXPECT_EQ(ERR_IO_PENDING, rv);
4585 rv = callback2.WaitForResult();
4586 EXPECT_EQ(OK, rv);
4588 response = trans->GetResponseInfo();
4589 ASSERT_TRUE(response != NULL);
4590 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4592 TestCompletionCallback callback3;
4594 rv = trans->RestartWithAuth(
4595 AuthCredentials(kFoo2, kBar2), callback3.callback());
4596 EXPECT_EQ(ERR_IO_PENDING, rv);
4598 rv = callback3.WaitForResult();
4599 EXPECT_EQ(OK, rv);
4601 response = trans->GetResponseInfo();
4602 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4603 EXPECT_EQ(100, response->headers->GetContentLength());
4606 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4607 // can't hook into its internals to cause it to generate predictable NTLM
4608 // authorization headers.
4609 #if defined(NTLM_PORTABLE)
4610 // The NTLM authentication unit tests were generated by capturing the HTTP
4611 // requests and responses using Fiddler 2 and inspecting the generated random
4612 // bytes in the debugger.
4614 // Enter the correct password and authenticate successfully.
4615 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4616 HttpRequestInfo request;
4617 request.method = "GET";
4618 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4620 // Ensure load is not disrupted by flags which suppress behaviour specific
4621 // to other auth schemes.
4622 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4624 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4625 MockGetHostName);
4626 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4628 MockWrite data_writes1[] = {
4629 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4630 "Host: 172.22.68.17\r\n"
4631 "Connection: keep-alive\r\n\r\n"),
4634 MockRead data_reads1[] = {
4635 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4636 // Negotiate and NTLM are often requested together. However, we only want
4637 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4638 // the header that requests Negotiate for this test.
4639 MockRead("WWW-Authenticate: NTLM\r\n"),
4640 MockRead("Connection: close\r\n"),
4641 MockRead("Content-Length: 42\r\n"),
4642 MockRead("Content-Type: text/html\r\n\r\n"),
4643 // Missing content -- won't matter, as connection will be reset.
4644 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4647 MockWrite data_writes2[] = {
4648 // After restarting with a null identity, this is the
4649 // request we should be issuing -- the final header line contains a Type
4650 // 1 message.
4651 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4652 "Host: 172.22.68.17\r\n"
4653 "Connection: keep-alive\r\n"
4654 "Authorization: NTLM "
4655 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4657 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4658 // (the credentials for the origin server). The second request continues
4659 // on the same connection.
4660 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4661 "Host: 172.22.68.17\r\n"
4662 "Connection: keep-alive\r\n"
4663 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4664 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4665 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4666 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4667 "ahlhx5I=\r\n\r\n"),
4670 MockRead data_reads2[] = {
4671 // The origin server responds with a Type 2 message.
4672 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4673 MockRead("WWW-Authenticate: NTLM "
4674 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4675 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4676 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4677 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4678 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4679 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4680 "BtAAAAAAA=\r\n"),
4681 MockRead("Content-Length: 42\r\n"),
4682 MockRead("Content-Type: text/html\r\n\r\n"),
4683 MockRead("You are not authorized to view this page\r\n"),
4685 // Lastly we get the desired content.
4686 MockRead("HTTP/1.1 200 OK\r\n"),
4687 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4688 MockRead("Content-Length: 13\r\n\r\n"),
4689 MockRead("Please Login\r\n"),
4690 MockRead(SYNCHRONOUS, OK),
4693 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4694 data_writes1, arraysize(data_writes1));
4695 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4696 data_writes2, arraysize(data_writes2));
4697 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4698 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4700 TestCompletionCallback callback1;
4702 scoped_ptr<HttpTransaction> trans(
4703 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4705 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4706 EXPECT_EQ(ERR_IO_PENDING, rv);
4708 rv = callback1.WaitForResult();
4709 EXPECT_EQ(OK, rv);
4711 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4713 const HttpResponseInfo* response = trans->GetResponseInfo();
4714 ASSERT_FALSE(response == NULL);
4715 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4717 TestCompletionCallback callback2;
4719 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4720 callback2.callback());
4721 EXPECT_EQ(ERR_IO_PENDING, rv);
4723 rv = callback2.WaitForResult();
4724 EXPECT_EQ(OK, rv);
4726 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4728 response = trans->GetResponseInfo();
4729 ASSERT_TRUE(response != NULL);
4730 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4732 TestCompletionCallback callback3;
4734 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4735 EXPECT_EQ(ERR_IO_PENDING, rv);
4737 rv = callback3.WaitForResult();
4738 EXPECT_EQ(OK, rv);
4740 response = trans->GetResponseInfo();
4741 ASSERT_TRUE(response != NULL);
4742 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4743 EXPECT_EQ(13, response->headers->GetContentLength());
4746 // Enter a wrong password, and then the correct one.
4747 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4748 HttpRequestInfo request;
4749 request.method = "GET";
4750 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4751 request.load_flags = 0;
4753 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4754 MockGetHostName);
4755 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4757 MockWrite data_writes1[] = {
4758 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4759 "Host: 172.22.68.17\r\n"
4760 "Connection: keep-alive\r\n\r\n"),
4763 MockRead data_reads1[] = {
4764 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4765 // Negotiate and NTLM are often requested together. However, we only want
4766 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4767 // the header that requests Negotiate for this test.
4768 MockRead("WWW-Authenticate: NTLM\r\n"),
4769 MockRead("Connection: close\r\n"),
4770 MockRead("Content-Length: 42\r\n"),
4771 MockRead("Content-Type: text/html\r\n\r\n"),
4772 // Missing content -- won't matter, as connection will be reset.
4773 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4776 MockWrite data_writes2[] = {
4777 // After restarting with a null identity, this is the
4778 // request we should be issuing -- the final header line contains a Type
4779 // 1 message.
4780 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4781 "Host: 172.22.68.17\r\n"
4782 "Connection: keep-alive\r\n"
4783 "Authorization: NTLM "
4784 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4786 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4787 // (the credentials for the origin server). The second request continues
4788 // on the same connection.
4789 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4790 "Host: 172.22.68.17\r\n"
4791 "Connection: keep-alive\r\n"
4792 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4793 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4794 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4795 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4796 "4Ww7b7E=\r\n\r\n"),
4799 MockRead data_reads2[] = {
4800 // The origin server responds with a Type 2 message.
4801 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4802 MockRead("WWW-Authenticate: NTLM "
4803 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4804 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4805 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4806 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4807 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4808 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4809 "BtAAAAAAA=\r\n"),
4810 MockRead("Content-Length: 42\r\n"),
4811 MockRead("Content-Type: text/html\r\n\r\n"),
4812 MockRead("You are not authorized to view this page\r\n"),
4814 // Wrong password.
4815 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4816 MockRead("WWW-Authenticate: NTLM\r\n"),
4817 MockRead("Connection: close\r\n"),
4818 MockRead("Content-Length: 42\r\n"),
4819 MockRead("Content-Type: text/html\r\n\r\n"),
4820 // Missing content -- won't matter, as connection will be reset.
4821 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4824 MockWrite data_writes3[] = {
4825 // After restarting with a null identity, this is the
4826 // request we should be issuing -- the final header line contains a Type
4827 // 1 message.
4828 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4829 "Host: 172.22.68.17\r\n"
4830 "Connection: keep-alive\r\n"
4831 "Authorization: NTLM "
4832 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4834 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4835 // (the credentials for the origin server). The second request continues
4836 // on the same connection.
4837 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4838 "Host: 172.22.68.17\r\n"
4839 "Connection: keep-alive\r\n"
4840 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4841 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4842 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4843 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4844 "+4MUm7c=\r\n\r\n"),
4847 MockRead data_reads3[] = {
4848 // The origin server responds with a Type 2 message.
4849 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4850 MockRead("WWW-Authenticate: NTLM "
4851 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4852 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4853 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4854 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4855 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4856 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4857 "BtAAAAAAA=\r\n"),
4858 MockRead("Content-Length: 42\r\n"),
4859 MockRead("Content-Type: text/html\r\n\r\n"),
4860 MockRead("You are not authorized to view this page\r\n"),
4862 // Lastly we get the desired content.
4863 MockRead("HTTP/1.1 200 OK\r\n"),
4864 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4865 MockRead("Content-Length: 13\r\n\r\n"),
4866 MockRead("Please Login\r\n"),
4867 MockRead(SYNCHRONOUS, OK),
4870 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4871 data_writes1, arraysize(data_writes1));
4872 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4873 data_writes2, arraysize(data_writes2));
4874 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4875 data_writes3, arraysize(data_writes3));
4876 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4877 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4878 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4880 TestCompletionCallback callback1;
4882 scoped_ptr<HttpTransaction> trans(
4883 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4885 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4886 EXPECT_EQ(ERR_IO_PENDING, rv);
4888 rv = callback1.WaitForResult();
4889 EXPECT_EQ(OK, rv);
4891 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4893 const HttpResponseInfo* response = trans->GetResponseInfo();
4894 ASSERT_TRUE(response != NULL);
4895 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4897 TestCompletionCallback callback2;
4899 // Enter the wrong password.
4900 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4901 callback2.callback());
4902 EXPECT_EQ(ERR_IO_PENDING, rv);
4904 rv = callback2.WaitForResult();
4905 EXPECT_EQ(OK, rv);
4907 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4908 TestCompletionCallback callback3;
4909 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4910 EXPECT_EQ(ERR_IO_PENDING, rv);
4911 rv = callback3.WaitForResult();
4912 EXPECT_EQ(OK, rv);
4913 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4915 response = trans->GetResponseInfo();
4916 ASSERT_FALSE(response == NULL);
4917 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4919 TestCompletionCallback callback4;
4921 // Now enter the right password.
4922 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4923 callback4.callback());
4924 EXPECT_EQ(ERR_IO_PENDING, rv);
4926 rv = callback4.WaitForResult();
4927 EXPECT_EQ(OK, rv);
4929 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4931 TestCompletionCallback callback5;
4933 // One more roundtrip
4934 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4935 EXPECT_EQ(ERR_IO_PENDING, rv);
4937 rv = callback5.WaitForResult();
4938 EXPECT_EQ(OK, rv);
4940 response = trans->GetResponseInfo();
4941 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4942 EXPECT_EQ(13, response->headers->GetContentLength());
4944 #endif // NTLM_PORTABLE
4946 // Test reading a server response which has only headers, and no body.
4947 // After some maximum number of bytes is consumed, the transaction should
4948 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4949 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4950 HttpRequestInfo request;
4951 request.method = "GET";
4952 request.url = GURL("http://www.example.org/");
4953 request.load_flags = 0;
4955 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4956 scoped_ptr<HttpTransaction> trans(
4957 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4959 // Respond with 300 kb of headers (we should fail after 256 kb).
4960 std::string large_headers_string;
4961 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4963 MockRead data_reads[] = {
4964 MockRead("HTTP/1.0 200 OK\r\n"),
4965 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4966 MockRead("\r\nBODY"),
4967 MockRead(SYNCHRONOUS, OK),
4969 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4970 session_deps_.socket_factory->AddSocketDataProvider(&data);
4972 TestCompletionCallback callback;
4974 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4975 EXPECT_EQ(ERR_IO_PENDING, rv);
4977 rv = callback.WaitForResult();
4978 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4981 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4982 // establish tunnel.
4983 // http://code.google.com/p/chromium/issues/detail?id=3772
4984 TEST_P(HttpNetworkTransactionTest,
4985 DontRecycleTransportSocketForSSLTunnel) {
4986 HttpRequestInfo request;
4987 request.method = "GET";
4988 request.url = GURL("https://www.example.org/");
4989 request.load_flags = 0;
4991 // Configure against proxy server "myproxy:70".
4992 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4994 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4996 scoped_ptr<HttpTransaction> trans(
4997 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4999 // Since we have proxy, should try to establish tunnel.
5000 MockWrite data_writes1[] = {
5001 MockWrite(
5002 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5003 "Host: www.example.org\r\n"
5004 "Proxy-Connection: keep-alive\r\n\r\n"),
5007 // The proxy responds to the connect with a 404, using a persistent
5008 // connection. Usually a proxy would return 501 (not implemented),
5009 // or 200 (tunnel established).
5010 MockRead data_reads1[] = {
5011 MockRead("HTTP/1.1 404 Not Found\r\n"),
5012 MockRead("Content-Length: 10\r\n\r\n"),
5013 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
5016 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5017 data_writes1, arraysize(data_writes1));
5018 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5020 TestCompletionCallback callback1;
5022 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5023 EXPECT_EQ(ERR_IO_PENDING, rv);
5025 rv = callback1.WaitForResult();
5026 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5028 // Empty the current queue. This is necessary because idle sockets are
5029 // added to the connection pool asynchronously with a PostTask.
5030 base::MessageLoop::current()->RunUntilIdle();
5032 // We now check to make sure the TCPClientSocket was not added back to
5033 // the pool.
5034 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5035 trans.reset();
5036 base::MessageLoop::current()->RunUntilIdle();
5037 // Make sure that the socket didn't get recycled after calling the destructor.
5038 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5041 // Make sure that we recycle a socket after reading all of the response body.
5042 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
5043 HttpRequestInfo request;
5044 request.method = "GET";
5045 request.url = GURL("http://www.example.org/");
5046 request.load_flags = 0;
5048 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5050 scoped_ptr<HttpTransaction> trans(
5051 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5053 MockRead data_reads[] = {
5054 // A part of the response body is received with the response headers.
5055 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5056 // The rest of the response body is received in two parts.
5057 MockRead("lo"),
5058 MockRead(" world"),
5059 MockRead("junk"), // Should not be read!!
5060 MockRead(SYNCHRONOUS, OK),
5063 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5064 session_deps_.socket_factory->AddSocketDataProvider(&data);
5066 TestCompletionCallback callback;
5068 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5069 EXPECT_EQ(ERR_IO_PENDING, rv);
5071 rv = callback.WaitForResult();
5072 EXPECT_EQ(OK, rv);
5074 const HttpResponseInfo* response = trans->GetResponseInfo();
5075 ASSERT_TRUE(response != NULL);
5077 EXPECT_TRUE(response->headers.get() != NULL);
5078 std::string status_line = response->headers->GetStatusLine();
5079 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5081 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5083 std::string response_data;
5084 rv = ReadTransaction(trans.get(), &response_data);
5085 EXPECT_EQ(OK, rv);
5086 EXPECT_EQ("hello world", response_data);
5088 // Empty the current queue. This is necessary because idle sockets are
5089 // added to the connection pool asynchronously with a PostTask.
5090 base::MessageLoop::current()->RunUntilIdle();
5092 // We now check to make sure the socket was added back to the pool.
5093 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5096 // Make sure that we recycle a SSL socket after reading all of the response
5097 // body.
5098 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
5099 HttpRequestInfo request;
5100 request.method = "GET";
5101 request.url = GURL("https://www.example.org/");
5102 request.load_flags = 0;
5104 MockWrite data_writes[] = {
5105 MockWrite(
5106 "GET / HTTP/1.1\r\n"
5107 "Host: www.example.org\r\n"
5108 "Connection: keep-alive\r\n\r\n"),
5111 MockRead data_reads[] = {
5112 MockRead("HTTP/1.1 200 OK\r\n"),
5113 MockRead("Content-Length: 11\r\n\r\n"),
5114 MockRead("hello world"),
5115 MockRead(SYNCHRONOUS, OK),
5118 SSLSocketDataProvider ssl(ASYNC, OK);
5119 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5121 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5122 data_writes, arraysize(data_writes));
5123 session_deps_.socket_factory->AddSocketDataProvider(&data);
5125 TestCompletionCallback callback;
5127 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5128 scoped_ptr<HttpTransaction> trans(
5129 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5131 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5133 EXPECT_EQ(ERR_IO_PENDING, rv);
5134 EXPECT_EQ(OK, callback.WaitForResult());
5136 const HttpResponseInfo* response = trans->GetResponseInfo();
5137 ASSERT_TRUE(response != NULL);
5138 ASSERT_TRUE(response->headers.get() != NULL);
5139 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5141 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5143 std::string response_data;
5144 rv = ReadTransaction(trans.get(), &response_data);
5145 EXPECT_EQ(OK, rv);
5146 EXPECT_EQ("hello world", response_data);
5148 // Empty the current queue. This is necessary because idle sockets are
5149 // added to the connection pool asynchronously with a PostTask.
5150 base::MessageLoop::current()->RunUntilIdle();
5152 // We now check to make sure the socket was added back to the pool.
5153 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5156 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5157 // from the pool and make sure that we recover okay.
5158 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
5159 HttpRequestInfo request;
5160 request.method = "GET";
5161 request.url = GURL("https://www.example.org/");
5162 request.load_flags = 0;
5164 MockWrite data_writes[] = {
5165 MockWrite(
5166 "GET / HTTP/1.1\r\n"
5167 "Host: www.example.org\r\n"
5168 "Connection: keep-alive\r\n\r\n"),
5169 MockWrite(
5170 "GET / HTTP/1.1\r\n"
5171 "Host: www.example.org\r\n"
5172 "Connection: keep-alive\r\n\r\n"),
5175 MockRead data_reads[] = {
5176 MockRead("HTTP/1.1 200 OK\r\n"),
5177 MockRead("Content-Length: 11\r\n\r\n"),
5178 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
5179 MockRead("hello world"),
5180 MockRead(ASYNC, 0, 0) // EOF
5183 SSLSocketDataProvider ssl(ASYNC, OK);
5184 SSLSocketDataProvider ssl2(ASYNC, OK);
5185 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5186 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5188 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5189 data_writes, arraysize(data_writes));
5190 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5191 data_writes, arraysize(data_writes));
5192 session_deps_.socket_factory->AddSocketDataProvider(&data);
5193 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5195 TestCompletionCallback callback;
5197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5198 scoped_ptr<HttpTransaction> trans(
5199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5201 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5203 EXPECT_EQ(ERR_IO_PENDING, rv);
5204 EXPECT_EQ(OK, callback.WaitForResult());
5206 const HttpResponseInfo* response = trans->GetResponseInfo();
5207 ASSERT_TRUE(response != NULL);
5208 ASSERT_TRUE(response->headers.get() != NULL);
5209 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5211 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5213 std::string response_data;
5214 rv = ReadTransaction(trans.get(), &response_data);
5215 EXPECT_EQ(OK, rv);
5216 EXPECT_EQ("hello world", response_data);
5218 // Empty the current queue. This is necessary because idle sockets are
5219 // added to the connection pool asynchronously with a PostTask.
5220 base::MessageLoop::current()->RunUntilIdle();
5222 // We now check to make sure the socket was added back to the pool.
5223 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5225 // Now start the second transaction, which should reuse the previous socket.
5227 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5229 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5231 EXPECT_EQ(ERR_IO_PENDING, rv);
5232 EXPECT_EQ(OK, callback.WaitForResult());
5234 response = trans->GetResponseInfo();
5235 ASSERT_TRUE(response != NULL);
5236 ASSERT_TRUE(response->headers.get() != NULL);
5237 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5239 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5241 rv = ReadTransaction(trans.get(), &response_data);
5242 EXPECT_EQ(OK, rv);
5243 EXPECT_EQ("hello world", response_data);
5245 // Empty the current queue. This is necessary because idle sockets are
5246 // added to the connection pool asynchronously with a PostTask.
5247 base::MessageLoop::current()->RunUntilIdle();
5249 // We now check to make sure the socket was added back to the pool.
5250 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5253 // Make sure that we recycle a socket after a zero-length response.
5254 // http://crbug.com/9880
5255 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
5256 HttpRequestInfo request;
5257 request.method = "GET";
5258 request.url = GURL(
5259 "http://www.example.org/csi?v=3&s=web&action=&"
5260 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5261 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5262 "rt=prt.2642,ol.2649,xjs.2951");
5263 request.load_flags = 0;
5265 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5267 scoped_ptr<HttpTransaction> trans(
5268 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5270 MockRead data_reads[] = {
5271 MockRead("HTTP/1.1 204 No Content\r\n"
5272 "Content-Length: 0\r\n"
5273 "Content-Type: text/html\r\n\r\n"),
5274 MockRead("junk"), // Should not be read!!
5275 MockRead(SYNCHRONOUS, OK),
5278 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5279 session_deps_.socket_factory->AddSocketDataProvider(&data);
5281 TestCompletionCallback callback;
5283 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5284 EXPECT_EQ(ERR_IO_PENDING, rv);
5286 rv = callback.WaitForResult();
5287 EXPECT_EQ(OK, rv);
5289 const HttpResponseInfo* response = trans->GetResponseInfo();
5290 ASSERT_TRUE(response != NULL);
5292 EXPECT_TRUE(response->headers.get() != NULL);
5293 std::string status_line = response->headers->GetStatusLine();
5294 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5296 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5298 std::string response_data;
5299 rv = ReadTransaction(trans.get(), &response_data);
5300 EXPECT_EQ(OK, rv);
5301 EXPECT_EQ("", response_data);
5303 // Empty the current queue. This is necessary because idle sockets are
5304 // added to the connection pool asynchronously with a PostTask.
5305 base::MessageLoop::current()->RunUntilIdle();
5307 // We now check to make sure the socket was added back to the pool.
5308 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5311 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5312 ScopedVector<UploadElementReader> element_readers;
5313 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5314 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
5316 HttpRequestInfo request[2];
5317 // Transaction 1: a GET request that succeeds. The socket is recycled
5318 // after use.
5319 request[0].method = "GET";
5320 request[0].url = GURL("http://www.google.com/");
5321 request[0].load_flags = 0;
5322 // Transaction 2: a POST request. Reuses the socket kept alive from
5323 // transaction 1. The first attempts fails when writing the POST data.
5324 // This causes the transaction to retry with a new socket. The second
5325 // attempt succeeds.
5326 request[1].method = "POST";
5327 request[1].url = GURL("http://www.google.com/login.cgi");
5328 request[1].upload_data_stream = &upload_data_stream;
5329 request[1].load_flags = 0;
5331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5333 // The first socket is used for transaction 1 and the first attempt of
5334 // transaction 2.
5336 // The response of transaction 1.
5337 MockRead data_reads1[] = {
5338 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5339 MockRead("hello world"),
5340 MockRead(SYNCHRONOUS, OK),
5342 // The mock write results of transaction 1 and the first attempt of
5343 // transaction 2.
5344 MockWrite data_writes1[] = {
5345 MockWrite(SYNCHRONOUS, 64), // GET
5346 MockWrite(SYNCHRONOUS, 93), // POST
5347 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5349 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5350 data_writes1, arraysize(data_writes1));
5352 // The second socket is used for the second attempt of transaction 2.
5354 // The response of transaction 2.
5355 MockRead data_reads2[] = {
5356 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5357 MockRead("welcome"),
5358 MockRead(SYNCHRONOUS, OK),
5360 // The mock write results of the second attempt of transaction 2.
5361 MockWrite data_writes2[] = {
5362 MockWrite(SYNCHRONOUS, 93), // POST
5363 MockWrite(SYNCHRONOUS, 3), // POST data
5365 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5366 data_writes2, arraysize(data_writes2));
5368 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5369 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5371 const char* const kExpectedResponseData[] = {
5372 "hello world", "welcome"
5375 for (int i = 0; i < 2; ++i) {
5376 scoped_ptr<HttpTransaction> trans(
5377 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5379 TestCompletionCallback callback;
5381 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5382 EXPECT_EQ(ERR_IO_PENDING, rv);
5384 rv = callback.WaitForResult();
5385 EXPECT_EQ(OK, rv);
5387 const HttpResponseInfo* response = trans->GetResponseInfo();
5388 ASSERT_TRUE(response != NULL);
5390 EXPECT_TRUE(response->headers.get() != NULL);
5391 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5393 std::string response_data;
5394 rv = ReadTransaction(trans.get(), &response_data);
5395 EXPECT_EQ(OK, rv);
5396 EXPECT_EQ(kExpectedResponseData[i], response_data);
5400 // Test the request-challenge-retry sequence for basic auth when there is
5401 // an identity in the URL. The request should be sent as normal, but when
5402 // it fails the identity from the URL is used to answer the challenge.
5403 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5404 HttpRequestInfo request;
5405 request.method = "GET";
5406 request.url = GURL("http://foo:b@r@www.example.org/");
5407 request.load_flags = LOAD_NORMAL;
5409 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5410 scoped_ptr<HttpTransaction> trans(
5411 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5413 // The password contains an escaped character -- for this test to pass it
5414 // will need to be unescaped by HttpNetworkTransaction.
5415 EXPECT_EQ("b%40r", request.url.password());
5417 MockWrite data_writes1[] = {
5418 MockWrite(
5419 "GET / HTTP/1.1\r\n"
5420 "Host: www.example.org\r\n"
5421 "Connection: keep-alive\r\n\r\n"),
5424 MockRead data_reads1[] = {
5425 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5426 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5427 MockRead("Content-Length: 10\r\n\r\n"),
5428 MockRead(SYNCHRONOUS, ERR_FAILED),
5431 // After the challenge above, the transaction will be restarted using the
5432 // identity from the url (foo, b@r) to answer the challenge.
5433 MockWrite data_writes2[] = {
5434 MockWrite(
5435 "GET / HTTP/1.1\r\n"
5436 "Host: www.example.org\r\n"
5437 "Connection: keep-alive\r\n"
5438 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5441 MockRead data_reads2[] = {
5442 MockRead("HTTP/1.0 200 OK\r\n"),
5443 MockRead("Content-Length: 100\r\n\r\n"),
5444 MockRead(SYNCHRONOUS, OK),
5447 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5448 data_writes1, arraysize(data_writes1));
5449 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5450 data_writes2, arraysize(data_writes2));
5451 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5452 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5454 TestCompletionCallback callback1;
5455 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5456 EXPECT_EQ(ERR_IO_PENDING, rv);
5457 rv = callback1.WaitForResult();
5458 EXPECT_EQ(OK, rv);
5459 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5461 TestCompletionCallback callback2;
5462 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5463 EXPECT_EQ(ERR_IO_PENDING, rv);
5464 rv = callback2.WaitForResult();
5465 EXPECT_EQ(OK, rv);
5466 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5468 const HttpResponseInfo* response = trans->GetResponseInfo();
5469 ASSERT_TRUE(response != NULL);
5471 // There is no challenge info, since the identity in URL worked.
5472 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5474 EXPECT_EQ(100, response->headers->GetContentLength());
5476 // Empty the current queue.
5477 base::MessageLoop::current()->RunUntilIdle();
5480 // Test the request-challenge-retry sequence for basic auth when there is an
5481 // incorrect identity in the URL. The identity from the URL should be used only
5482 // once.
5483 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5484 HttpRequestInfo request;
5485 request.method = "GET";
5486 // Note: the URL has a username:password in it. The password "baz" is
5487 // wrong (should be "bar").
5488 request.url = GURL("http://foo:baz@www.example.org/");
5490 request.load_flags = LOAD_NORMAL;
5492 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5493 scoped_ptr<HttpTransaction> trans(
5494 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5496 MockWrite data_writes1[] = {
5497 MockWrite(
5498 "GET / HTTP/1.1\r\n"
5499 "Host: www.example.org\r\n"
5500 "Connection: keep-alive\r\n\r\n"),
5503 MockRead data_reads1[] = {
5504 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5505 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5506 MockRead("Content-Length: 10\r\n\r\n"),
5507 MockRead(SYNCHRONOUS, ERR_FAILED),
5510 // After the challenge above, the transaction will be restarted using the
5511 // identity from the url (foo, baz) to answer the challenge.
5512 MockWrite data_writes2[] = {
5513 MockWrite(
5514 "GET / HTTP/1.1\r\n"
5515 "Host: www.example.org\r\n"
5516 "Connection: keep-alive\r\n"
5517 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5520 MockRead data_reads2[] = {
5521 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5522 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5523 MockRead("Content-Length: 10\r\n\r\n"),
5524 MockRead(SYNCHRONOUS, ERR_FAILED),
5527 // After the challenge above, the transaction will be restarted using the
5528 // identity supplied by the user (foo, bar) to answer the challenge.
5529 MockWrite data_writes3[] = {
5530 MockWrite(
5531 "GET / HTTP/1.1\r\n"
5532 "Host: www.example.org\r\n"
5533 "Connection: keep-alive\r\n"
5534 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5537 MockRead data_reads3[] = {
5538 MockRead("HTTP/1.0 200 OK\r\n"),
5539 MockRead("Content-Length: 100\r\n\r\n"),
5540 MockRead(SYNCHRONOUS, OK),
5543 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5544 data_writes1, arraysize(data_writes1));
5545 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5546 data_writes2, arraysize(data_writes2));
5547 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5548 data_writes3, arraysize(data_writes3));
5549 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5550 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5551 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5553 TestCompletionCallback callback1;
5555 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5556 EXPECT_EQ(ERR_IO_PENDING, rv);
5558 rv = callback1.WaitForResult();
5559 EXPECT_EQ(OK, rv);
5561 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5562 TestCompletionCallback callback2;
5563 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5564 EXPECT_EQ(ERR_IO_PENDING, rv);
5565 rv = callback2.WaitForResult();
5566 EXPECT_EQ(OK, rv);
5567 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5569 const HttpResponseInfo* response = trans->GetResponseInfo();
5570 ASSERT_TRUE(response != NULL);
5571 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5573 TestCompletionCallback callback3;
5574 rv = trans->RestartWithAuth(
5575 AuthCredentials(kFoo, kBar), callback3.callback());
5576 EXPECT_EQ(ERR_IO_PENDING, rv);
5577 rv = callback3.WaitForResult();
5578 EXPECT_EQ(OK, rv);
5579 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5581 response = trans->GetResponseInfo();
5582 ASSERT_TRUE(response != NULL);
5584 // There is no challenge info, since the identity worked.
5585 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5587 EXPECT_EQ(100, response->headers->GetContentLength());
5589 // Empty the current queue.
5590 base::MessageLoop::current()->RunUntilIdle();
5594 // Test the request-challenge-retry sequence for basic auth when there is a
5595 // correct identity in the URL, but its use is being suppressed. The identity
5596 // from the URL should never be used.
5597 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5598 HttpRequestInfo request;
5599 request.method = "GET";
5600 request.url = GURL("http://foo:bar@www.example.org/");
5601 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5603 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5604 scoped_ptr<HttpTransaction> trans(
5605 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5607 MockWrite data_writes1[] = {
5608 MockWrite(
5609 "GET / HTTP/1.1\r\n"
5610 "Host: www.example.org\r\n"
5611 "Connection: keep-alive\r\n\r\n"),
5614 MockRead data_reads1[] = {
5615 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5616 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5617 MockRead("Content-Length: 10\r\n\r\n"),
5618 MockRead(SYNCHRONOUS, ERR_FAILED),
5621 // After the challenge above, the transaction will be restarted using the
5622 // identity supplied by the user, not the one in the URL, to answer the
5623 // challenge.
5624 MockWrite data_writes3[] = {
5625 MockWrite(
5626 "GET / HTTP/1.1\r\n"
5627 "Host: www.example.org\r\n"
5628 "Connection: keep-alive\r\n"
5629 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5632 MockRead data_reads3[] = {
5633 MockRead("HTTP/1.0 200 OK\r\n"),
5634 MockRead("Content-Length: 100\r\n\r\n"),
5635 MockRead(SYNCHRONOUS, OK),
5638 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5639 data_writes1, arraysize(data_writes1));
5640 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5641 data_writes3, arraysize(data_writes3));
5642 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5643 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5645 TestCompletionCallback callback1;
5646 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5647 EXPECT_EQ(ERR_IO_PENDING, rv);
5648 rv = callback1.WaitForResult();
5649 EXPECT_EQ(OK, rv);
5650 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5652 const HttpResponseInfo* response = trans->GetResponseInfo();
5653 ASSERT_TRUE(response != NULL);
5654 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5656 TestCompletionCallback callback3;
5657 rv = trans->RestartWithAuth(
5658 AuthCredentials(kFoo, kBar), callback3.callback());
5659 EXPECT_EQ(ERR_IO_PENDING, rv);
5660 rv = callback3.WaitForResult();
5661 EXPECT_EQ(OK, rv);
5662 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5664 response = trans->GetResponseInfo();
5665 ASSERT_TRUE(response != NULL);
5667 // There is no challenge info, since the identity worked.
5668 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5669 EXPECT_EQ(100, response->headers->GetContentLength());
5671 // Empty the current queue.
5672 base::MessageLoop::current()->RunUntilIdle();
5675 // Test that previously tried username/passwords for a realm get re-used.
5676 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5677 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5679 // Transaction 1: authenticate (foo, bar) on MyRealm1
5681 HttpRequestInfo request;
5682 request.method = "GET";
5683 request.url = GURL("http://www.example.org/x/y/z");
5684 request.load_flags = 0;
5686 scoped_ptr<HttpTransaction> trans(
5687 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5689 MockWrite data_writes1[] = {
5690 MockWrite(
5691 "GET /x/y/z HTTP/1.1\r\n"
5692 "Host: www.example.org\r\n"
5693 "Connection: keep-alive\r\n\r\n"),
5696 MockRead data_reads1[] = {
5697 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5698 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5699 MockRead("Content-Length: 10000\r\n\r\n"),
5700 MockRead(SYNCHRONOUS, ERR_FAILED),
5703 // Resend with authorization (username=foo, password=bar)
5704 MockWrite data_writes2[] = {
5705 MockWrite(
5706 "GET /x/y/z HTTP/1.1\r\n"
5707 "Host: www.example.org\r\n"
5708 "Connection: keep-alive\r\n"
5709 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5712 // Sever accepts the authorization.
5713 MockRead data_reads2[] = {
5714 MockRead("HTTP/1.0 200 OK\r\n"),
5715 MockRead("Content-Length: 100\r\n\r\n"),
5716 MockRead(SYNCHRONOUS, OK),
5719 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5720 data_writes1, arraysize(data_writes1));
5721 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5722 data_writes2, arraysize(data_writes2));
5723 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5724 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5726 TestCompletionCallback callback1;
5728 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5729 EXPECT_EQ(ERR_IO_PENDING, rv);
5731 rv = callback1.WaitForResult();
5732 EXPECT_EQ(OK, rv);
5734 const HttpResponseInfo* response = trans->GetResponseInfo();
5735 ASSERT_TRUE(response != NULL);
5736 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5738 TestCompletionCallback callback2;
5740 rv = trans->RestartWithAuth(
5741 AuthCredentials(kFoo, kBar), callback2.callback());
5742 EXPECT_EQ(ERR_IO_PENDING, rv);
5744 rv = callback2.WaitForResult();
5745 EXPECT_EQ(OK, rv);
5747 response = trans->GetResponseInfo();
5748 ASSERT_TRUE(response != NULL);
5749 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5750 EXPECT_EQ(100, response->headers->GetContentLength());
5753 // ------------------------------------------------------------------------
5755 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5757 HttpRequestInfo request;
5758 request.method = "GET";
5759 // Note that Transaction 1 was at /x/y/z, so this is in the same
5760 // protection space as MyRealm1.
5761 request.url = GURL("http://www.example.org/x/y/a/b");
5762 request.load_flags = 0;
5764 scoped_ptr<HttpTransaction> trans(
5765 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5767 MockWrite data_writes1[] = {
5768 MockWrite(
5769 "GET /x/y/a/b HTTP/1.1\r\n"
5770 "Host: www.example.org\r\n"
5771 "Connection: keep-alive\r\n"
5772 // Send preemptive authorization for MyRealm1
5773 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5776 // The server didn't like the preemptive authorization, and
5777 // challenges us for a different realm (MyRealm2).
5778 MockRead data_reads1[] = {
5779 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5780 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5781 MockRead("Content-Length: 10000\r\n\r\n"),
5782 MockRead(SYNCHRONOUS, ERR_FAILED),
5785 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5786 MockWrite data_writes2[] = {
5787 MockWrite(
5788 "GET /x/y/a/b HTTP/1.1\r\n"
5789 "Host: www.example.org\r\n"
5790 "Connection: keep-alive\r\n"
5791 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5794 // Sever accepts the authorization.
5795 MockRead data_reads2[] = {
5796 MockRead("HTTP/1.0 200 OK\r\n"),
5797 MockRead("Content-Length: 100\r\n\r\n"),
5798 MockRead(SYNCHRONOUS, OK),
5801 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5802 data_writes1, arraysize(data_writes1));
5803 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5804 data_writes2, arraysize(data_writes2));
5805 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5806 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5808 TestCompletionCallback callback1;
5810 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5811 EXPECT_EQ(ERR_IO_PENDING, rv);
5813 rv = callback1.WaitForResult();
5814 EXPECT_EQ(OK, rv);
5816 const HttpResponseInfo* response = trans->GetResponseInfo();
5817 ASSERT_TRUE(response != NULL);
5818 ASSERT_TRUE(response->auth_challenge.get());
5819 EXPECT_FALSE(response->auth_challenge->is_proxy);
5820 EXPECT_EQ("www.example.org:80",
5821 response->auth_challenge->challenger.ToString());
5822 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5823 EXPECT_EQ("basic", response->auth_challenge->scheme);
5825 TestCompletionCallback callback2;
5827 rv = trans->RestartWithAuth(
5828 AuthCredentials(kFoo2, kBar2), callback2.callback());
5829 EXPECT_EQ(ERR_IO_PENDING, rv);
5831 rv = callback2.WaitForResult();
5832 EXPECT_EQ(OK, rv);
5834 response = trans->GetResponseInfo();
5835 ASSERT_TRUE(response != NULL);
5836 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5837 EXPECT_EQ(100, response->headers->GetContentLength());
5840 // ------------------------------------------------------------------------
5842 // Transaction 3: Resend a request in MyRealm's protection space --
5843 // succeed with preemptive authorization.
5845 HttpRequestInfo request;
5846 request.method = "GET";
5847 request.url = GURL("http://www.example.org/x/y/z2");
5848 request.load_flags = 0;
5850 scoped_ptr<HttpTransaction> trans(
5851 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5853 MockWrite data_writes1[] = {
5854 MockWrite(
5855 "GET /x/y/z2 HTTP/1.1\r\n"
5856 "Host: www.example.org\r\n"
5857 "Connection: keep-alive\r\n"
5858 // The authorization for MyRealm1 gets sent preemptively
5859 // (since the url is in the same protection space)
5860 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5863 // Sever accepts the preemptive authorization
5864 MockRead data_reads1[] = {
5865 MockRead("HTTP/1.0 200 OK\r\n"),
5866 MockRead("Content-Length: 100\r\n\r\n"),
5867 MockRead(SYNCHRONOUS, OK),
5870 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5871 data_writes1, arraysize(data_writes1));
5872 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5874 TestCompletionCallback callback1;
5876 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5877 EXPECT_EQ(ERR_IO_PENDING, rv);
5879 rv = callback1.WaitForResult();
5880 EXPECT_EQ(OK, rv);
5882 const HttpResponseInfo* response = trans->GetResponseInfo();
5883 ASSERT_TRUE(response != NULL);
5885 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5886 EXPECT_EQ(100, response->headers->GetContentLength());
5889 // ------------------------------------------------------------------------
5891 // Transaction 4: request another URL in MyRealm (however the
5892 // url is not known to belong to the protection space, so no pre-auth).
5894 HttpRequestInfo request;
5895 request.method = "GET";
5896 request.url = GURL("http://www.example.org/x/1");
5897 request.load_flags = 0;
5899 scoped_ptr<HttpTransaction> trans(
5900 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5902 MockWrite data_writes1[] = {
5903 MockWrite(
5904 "GET /x/1 HTTP/1.1\r\n"
5905 "Host: www.example.org\r\n"
5906 "Connection: keep-alive\r\n\r\n"),
5909 MockRead data_reads1[] = {
5910 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5911 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5912 MockRead("Content-Length: 10000\r\n\r\n"),
5913 MockRead(SYNCHRONOUS, ERR_FAILED),
5916 // Resend with authorization from MyRealm's cache.
5917 MockWrite data_writes2[] = {
5918 MockWrite(
5919 "GET /x/1 HTTP/1.1\r\n"
5920 "Host: www.example.org\r\n"
5921 "Connection: keep-alive\r\n"
5922 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5925 // Sever accepts the authorization.
5926 MockRead data_reads2[] = {
5927 MockRead("HTTP/1.0 200 OK\r\n"),
5928 MockRead("Content-Length: 100\r\n\r\n"),
5929 MockRead(SYNCHRONOUS, OK),
5932 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5933 data_writes1, arraysize(data_writes1));
5934 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5935 data_writes2, arraysize(data_writes2));
5936 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5937 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5939 TestCompletionCallback callback1;
5941 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5942 EXPECT_EQ(ERR_IO_PENDING, rv);
5944 rv = callback1.WaitForResult();
5945 EXPECT_EQ(OK, rv);
5947 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5948 TestCompletionCallback callback2;
5949 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5950 EXPECT_EQ(ERR_IO_PENDING, rv);
5951 rv = callback2.WaitForResult();
5952 EXPECT_EQ(OK, rv);
5953 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5955 const HttpResponseInfo* response = trans->GetResponseInfo();
5956 ASSERT_TRUE(response != NULL);
5957 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5958 EXPECT_EQ(100, response->headers->GetContentLength());
5961 // ------------------------------------------------------------------------
5963 // Transaction 5: request a URL in MyRealm, but the server rejects the
5964 // cached identity. Should invalidate and re-prompt.
5966 HttpRequestInfo request;
5967 request.method = "GET";
5968 request.url = GURL("http://www.example.org/p/q/t");
5969 request.load_flags = 0;
5971 scoped_ptr<HttpTransaction> trans(
5972 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5974 MockWrite data_writes1[] = {
5975 MockWrite(
5976 "GET /p/q/t HTTP/1.1\r\n"
5977 "Host: www.example.org\r\n"
5978 "Connection: keep-alive\r\n\r\n"),
5981 MockRead data_reads1[] = {
5982 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5983 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5984 MockRead("Content-Length: 10000\r\n\r\n"),
5985 MockRead(SYNCHRONOUS, ERR_FAILED),
5988 // Resend with authorization from cache for MyRealm.
5989 MockWrite data_writes2[] = {
5990 MockWrite(
5991 "GET /p/q/t HTTP/1.1\r\n"
5992 "Host: www.example.org\r\n"
5993 "Connection: keep-alive\r\n"
5994 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5997 // Sever rejects the authorization.
5998 MockRead data_reads2[] = {
5999 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6000 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6001 MockRead("Content-Length: 10000\r\n\r\n"),
6002 MockRead(SYNCHRONOUS, ERR_FAILED),
6005 // At this point we should prompt for new credentials for MyRealm.
6006 // Restart with username=foo3, password=foo4.
6007 MockWrite data_writes3[] = {
6008 MockWrite(
6009 "GET /p/q/t HTTP/1.1\r\n"
6010 "Host: www.example.org\r\n"
6011 "Connection: keep-alive\r\n"
6012 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6015 // Sever accepts the authorization.
6016 MockRead data_reads3[] = {
6017 MockRead("HTTP/1.0 200 OK\r\n"),
6018 MockRead("Content-Length: 100\r\n\r\n"),
6019 MockRead(SYNCHRONOUS, OK),
6022 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6023 data_writes1, arraysize(data_writes1));
6024 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6025 data_writes2, arraysize(data_writes2));
6026 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6027 data_writes3, arraysize(data_writes3));
6028 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6029 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6030 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6032 TestCompletionCallback callback1;
6034 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6035 EXPECT_EQ(ERR_IO_PENDING, rv);
6037 rv = callback1.WaitForResult();
6038 EXPECT_EQ(OK, rv);
6040 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6041 TestCompletionCallback callback2;
6042 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6043 EXPECT_EQ(ERR_IO_PENDING, rv);
6044 rv = callback2.WaitForResult();
6045 EXPECT_EQ(OK, rv);
6046 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6048 const HttpResponseInfo* response = trans->GetResponseInfo();
6049 ASSERT_TRUE(response != NULL);
6050 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6052 TestCompletionCallback callback3;
6054 rv = trans->RestartWithAuth(
6055 AuthCredentials(kFoo3, kBar3), callback3.callback());
6056 EXPECT_EQ(ERR_IO_PENDING, rv);
6058 rv = callback3.WaitForResult();
6059 EXPECT_EQ(OK, rv);
6061 response = trans->GetResponseInfo();
6062 ASSERT_TRUE(response != NULL);
6063 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6064 EXPECT_EQ(100, response->headers->GetContentLength());
6068 // Tests that nonce count increments when multiple auth attempts
6069 // are started with the same nonce.
6070 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
6071 HttpAuthHandlerDigest::Factory* digest_factory =
6072 new HttpAuthHandlerDigest::Factory();
6073 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6074 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6075 digest_factory->set_nonce_generator(nonce_generator);
6076 session_deps_.http_auth_handler_factory.reset(digest_factory);
6077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6079 // Transaction 1: authenticate (foo, bar) on MyRealm1
6081 HttpRequestInfo request;
6082 request.method = "GET";
6083 request.url = GURL("http://www.example.org/x/y/z");
6084 request.load_flags = 0;
6086 scoped_ptr<HttpTransaction> trans(
6087 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6089 MockWrite data_writes1[] = {
6090 MockWrite(
6091 "GET /x/y/z HTTP/1.1\r\n"
6092 "Host: www.example.org\r\n"
6093 "Connection: keep-alive\r\n\r\n"),
6096 MockRead data_reads1[] = {
6097 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6098 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6099 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6100 MockRead(SYNCHRONOUS, OK),
6103 // Resend with authorization (username=foo, password=bar)
6104 MockWrite data_writes2[] = {
6105 MockWrite(
6106 "GET /x/y/z HTTP/1.1\r\n"
6107 "Host: www.example.org\r\n"
6108 "Connection: keep-alive\r\n"
6109 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6110 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6111 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6112 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6115 // Sever accepts the authorization.
6116 MockRead data_reads2[] = {
6117 MockRead("HTTP/1.0 200 OK\r\n"),
6118 MockRead(SYNCHRONOUS, OK),
6121 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6122 data_writes1, arraysize(data_writes1));
6123 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6124 data_writes2, arraysize(data_writes2));
6125 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6126 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6128 TestCompletionCallback callback1;
6130 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6131 EXPECT_EQ(ERR_IO_PENDING, rv);
6133 rv = callback1.WaitForResult();
6134 EXPECT_EQ(OK, rv);
6136 const HttpResponseInfo* response = trans->GetResponseInfo();
6137 ASSERT_TRUE(response != NULL);
6138 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
6140 TestCompletionCallback callback2;
6142 rv = trans->RestartWithAuth(
6143 AuthCredentials(kFoo, kBar), callback2.callback());
6144 EXPECT_EQ(ERR_IO_PENDING, rv);
6146 rv = callback2.WaitForResult();
6147 EXPECT_EQ(OK, rv);
6149 response = trans->GetResponseInfo();
6150 ASSERT_TRUE(response != NULL);
6151 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6154 // ------------------------------------------------------------------------
6156 // Transaction 2: Request another resource in digestive's protection space.
6157 // This will preemptively add an Authorization header which should have an
6158 // "nc" value of 2 (as compared to 1 in the first use.
6160 HttpRequestInfo request;
6161 request.method = "GET";
6162 // Note that Transaction 1 was at /x/y/z, so this is in the same
6163 // protection space as digest.
6164 request.url = GURL("http://www.example.org/x/y/a/b");
6165 request.load_flags = 0;
6167 scoped_ptr<HttpTransaction> trans(
6168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6170 MockWrite data_writes1[] = {
6171 MockWrite(
6172 "GET /x/y/a/b HTTP/1.1\r\n"
6173 "Host: www.example.org\r\n"
6174 "Connection: keep-alive\r\n"
6175 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6176 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6177 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6178 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6181 // Sever accepts the authorization.
6182 MockRead data_reads1[] = {
6183 MockRead("HTTP/1.0 200 OK\r\n"),
6184 MockRead("Content-Length: 100\r\n\r\n"),
6185 MockRead(SYNCHRONOUS, OK),
6188 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6189 data_writes1, arraysize(data_writes1));
6190 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6192 TestCompletionCallback callback1;
6194 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6195 EXPECT_EQ(ERR_IO_PENDING, rv);
6197 rv = callback1.WaitForResult();
6198 EXPECT_EQ(OK, rv);
6200 const HttpResponseInfo* response = trans->GetResponseInfo();
6201 ASSERT_TRUE(response != NULL);
6202 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6206 // Test the ResetStateForRestart() private method.
6207 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
6208 // Create a transaction (the dependencies aren't important).
6209 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6210 scoped_ptr<HttpNetworkTransaction> trans(
6211 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6213 // Setup some state (which we expect ResetStateForRestart() will clear).
6214 trans->read_buf_ = new IOBuffer(15);
6215 trans->read_buf_len_ = 15;
6216 trans->request_headers_.SetHeader("Authorization", "NTLM");
6218 // Setup state in response_
6219 HttpResponseInfo* response = &trans->response_;
6220 response->auth_challenge = new AuthChallengeInfo();
6221 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
6222 response->response_time = base::Time::Now();
6223 response->was_cached = true; // (Wouldn't ever actually be true...)
6225 { // Setup state for response_.vary_data
6226 HttpRequestInfo request;
6227 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6228 std::replace(temp.begin(), temp.end(), '\n', '\0');
6229 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
6230 request.extra_headers.SetHeader("Foo", "1");
6231 request.extra_headers.SetHeader("bar", "23");
6232 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
6235 // Cause the above state to be reset.
6236 trans->ResetStateForRestart();
6238 // Verify that the state that needed to be reset, has been reset.
6239 EXPECT_TRUE(trans->read_buf_.get() == NULL);
6240 EXPECT_EQ(0, trans->read_buf_len_);
6241 EXPECT_TRUE(trans->request_headers_.IsEmpty());
6242 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6243 EXPECT_TRUE(response->headers.get() == NULL);
6244 EXPECT_FALSE(response->was_cached);
6245 EXPECT_EQ(0U, response->ssl_info.cert_status);
6246 EXPECT_FALSE(response->vary_data.is_valid());
6249 // Test HTTPS connections to a site with a bad certificate
6250 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
6251 HttpRequestInfo request;
6252 request.method = "GET";
6253 request.url = GURL("https://www.example.org/");
6254 request.load_flags = 0;
6256 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6257 scoped_ptr<HttpTransaction> trans(
6258 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6260 MockWrite data_writes[] = {
6261 MockWrite(
6262 "GET / HTTP/1.1\r\n"
6263 "Host: www.example.org\r\n"
6264 "Connection: keep-alive\r\n\r\n"),
6267 MockRead data_reads[] = {
6268 MockRead("HTTP/1.0 200 OK\r\n"),
6269 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6270 MockRead("Content-Length: 100\r\n\r\n"),
6271 MockRead(SYNCHRONOUS, OK),
6274 StaticSocketDataProvider ssl_bad_certificate;
6275 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6276 data_writes, arraysize(data_writes));
6277 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6278 SSLSocketDataProvider ssl(ASYNC, OK);
6280 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6281 session_deps_.socket_factory->AddSocketDataProvider(&data);
6282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6283 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6285 TestCompletionCallback callback;
6287 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6288 EXPECT_EQ(ERR_IO_PENDING, rv);
6290 rv = callback.WaitForResult();
6291 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6293 rv = trans->RestartIgnoringLastError(callback.callback());
6294 EXPECT_EQ(ERR_IO_PENDING, rv);
6296 rv = callback.WaitForResult();
6297 EXPECT_EQ(OK, rv);
6299 const HttpResponseInfo* response = trans->GetResponseInfo();
6301 ASSERT_TRUE(response != NULL);
6302 EXPECT_EQ(100, response->headers->GetContentLength());
6305 // Test HTTPS connections to a site with a bad certificate, going through a
6306 // proxy
6307 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
6308 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6310 HttpRequestInfo request;
6311 request.method = "GET";
6312 request.url = GURL("https://www.example.org/");
6313 request.load_flags = 0;
6315 MockWrite proxy_writes[] = {
6316 MockWrite(
6317 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6318 "Host: www.example.org\r\n"
6319 "Proxy-Connection: keep-alive\r\n\r\n"),
6322 MockRead proxy_reads[] = {
6323 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6324 MockRead(SYNCHRONOUS, OK)
6327 MockWrite data_writes[] = {
6328 MockWrite(
6329 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6330 "Host: www.example.org\r\n"
6331 "Proxy-Connection: keep-alive\r\n\r\n"),
6332 MockWrite(
6333 "GET / HTTP/1.1\r\n"
6334 "Host: www.example.org\r\n"
6335 "Connection: keep-alive\r\n\r\n"),
6338 MockRead data_reads[] = {
6339 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6340 MockRead("HTTP/1.0 200 OK\r\n"),
6341 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6342 MockRead("Content-Length: 100\r\n\r\n"),
6343 MockRead(SYNCHRONOUS, OK),
6346 StaticSocketDataProvider ssl_bad_certificate(
6347 proxy_reads, arraysize(proxy_reads),
6348 proxy_writes, arraysize(proxy_writes));
6349 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6350 data_writes, arraysize(data_writes));
6351 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6352 SSLSocketDataProvider ssl(ASYNC, OK);
6354 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6355 session_deps_.socket_factory->AddSocketDataProvider(&data);
6356 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6357 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6359 TestCompletionCallback callback;
6361 for (int i = 0; i < 2; i++) {
6362 session_deps_.socket_factory->ResetNextMockIndexes();
6364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6365 scoped_ptr<HttpTransaction> trans(
6366 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6368 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6369 EXPECT_EQ(ERR_IO_PENDING, rv);
6371 rv = callback.WaitForResult();
6372 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6374 rv = trans->RestartIgnoringLastError(callback.callback());
6375 EXPECT_EQ(ERR_IO_PENDING, rv);
6377 rv = callback.WaitForResult();
6378 EXPECT_EQ(OK, rv);
6380 const HttpResponseInfo* response = trans->GetResponseInfo();
6382 ASSERT_TRUE(response != NULL);
6383 EXPECT_EQ(100, response->headers->GetContentLength());
6388 // Test HTTPS connections to a site, going through an HTTPS proxy
6389 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6390 session_deps_.proxy_service.reset(
6391 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6392 TestNetLog net_log;
6393 session_deps_.net_log = &net_log;
6395 HttpRequestInfo request;
6396 request.method = "GET";
6397 request.url = GURL("https://www.example.org/");
6398 request.load_flags = 0;
6400 MockWrite data_writes[] = {
6401 MockWrite(
6402 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6403 "Host: www.example.org\r\n"
6404 "Proxy-Connection: keep-alive\r\n\r\n"),
6405 MockWrite(
6406 "GET / HTTP/1.1\r\n"
6407 "Host: www.example.org\r\n"
6408 "Connection: keep-alive\r\n\r\n"),
6411 MockRead data_reads[] = {
6412 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6413 MockRead("HTTP/1.1 200 OK\r\n"),
6414 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6415 MockRead("Content-Length: 100\r\n\r\n"),
6416 MockRead(SYNCHRONOUS, OK),
6419 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6420 data_writes, arraysize(data_writes));
6421 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6422 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6424 session_deps_.socket_factory->AddSocketDataProvider(&data);
6425 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6426 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6428 TestCompletionCallback callback;
6430 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6431 scoped_ptr<HttpTransaction> trans(
6432 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6434 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6435 EXPECT_EQ(ERR_IO_PENDING, rv);
6437 rv = callback.WaitForResult();
6438 EXPECT_EQ(OK, rv);
6439 const HttpResponseInfo* response = trans->GetResponseInfo();
6441 ASSERT_TRUE(response != NULL);
6443 EXPECT_TRUE(response->headers->IsKeepAlive());
6444 EXPECT_EQ(200, response->headers->response_code());
6445 EXPECT_EQ(100, response->headers->GetContentLength());
6446 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6448 LoadTimingInfo load_timing_info;
6449 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6450 TestLoadTimingNotReusedWithPac(load_timing_info,
6451 CONNECT_TIMING_HAS_SSL_TIMES);
6454 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6455 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6456 session_deps_.proxy_service.reset(
6457 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6458 TestNetLog net_log;
6459 session_deps_.net_log = &net_log;
6461 HttpRequestInfo request;
6462 request.method = "GET";
6463 request.url = GURL("https://www.example.org/");
6464 request.load_flags = 0;
6466 MockWrite data_writes[] = {
6467 MockWrite(
6468 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6469 "Host: www.example.org\r\n"
6470 "Proxy-Connection: keep-alive\r\n\r\n"),
6473 MockRead data_reads[] = {
6474 MockRead("HTTP/1.1 302 Redirect\r\n"),
6475 MockRead("Location: http://login.example.com/\r\n"),
6476 MockRead("Content-Length: 0\r\n\r\n"),
6477 MockRead(SYNCHRONOUS, OK),
6480 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6481 data_writes, arraysize(data_writes));
6482 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6484 session_deps_.socket_factory->AddSocketDataProvider(&data);
6485 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6487 TestCompletionCallback callback;
6489 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6490 scoped_ptr<HttpTransaction> trans(
6491 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6493 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6494 EXPECT_EQ(ERR_IO_PENDING, rv);
6496 rv = callback.WaitForResult();
6497 EXPECT_EQ(OK, rv);
6498 const HttpResponseInfo* response = trans->GetResponseInfo();
6500 ASSERT_TRUE(response != NULL);
6502 EXPECT_EQ(302, response->headers->response_code());
6503 std::string url;
6504 EXPECT_TRUE(response->headers->IsRedirect(&url));
6505 EXPECT_EQ("http://login.example.com/", url);
6507 // In the case of redirects from proxies, HttpNetworkTransaction returns
6508 // timing for the proxy connection instead of the connection to the host,
6509 // and no send / receive times.
6510 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6511 LoadTimingInfo load_timing_info;
6512 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6514 EXPECT_FALSE(load_timing_info.socket_reused);
6515 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6517 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6518 EXPECT_LE(load_timing_info.proxy_resolve_start,
6519 load_timing_info.proxy_resolve_end);
6520 EXPECT_LE(load_timing_info.proxy_resolve_end,
6521 load_timing_info.connect_timing.connect_start);
6522 ExpectConnectTimingHasTimes(
6523 load_timing_info.connect_timing,
6524 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6526 EXPECT_TRUE(load_timing_info.send_start.is_null());
6527 EXPECT_TRUE(load_timing_info.send_end.is_null());
6528 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6531 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6532 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6533 session_deps_.proxy_service.reset(
6534 ProxyService::CreateFixed("https://proxy:70"));
6536 HttpRequestInfo request;
6537 request.method = "GET";
6538 request.url = GURL("https://www.example.org/");
6539 request.load_flags = 0;
6541 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6542 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6543 scoped_ptr<SpdyFrame> goaway(
6544 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6545 MockWrite data_writes[] = {
6546 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6547 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
6550 static const char* const kExtraHeaders[] = {
6551 "location",
6552 "http://login.example.com/",
6554 scoped_ptr<SpdyFrame> resp(
6555 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6556 arraysize(kExtraHeaders)/2, 1));
6557 MockRead data_reads[] = {
6558 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
6561 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6562 arraysize(data_writes));
6563 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6564 proxy_ssl.SetNextProto(GetParam());
6566 session_deps_.socket_factory->AddSocketDataProvider(&data);
6567 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6569 TestCompletionCallback callback;
6571 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6572 scoped_ptr<HttpTransaction> trans(
6573 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6575 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6576 EXPECT_EQ(ERR_IO_PENDING, rv);
6578 rv = callback.WaitForResult();
6579 EXPECT_EQ(OK, rv);
6580 const HttpResponseInfo* response = trans->GetResponseInfo();
6582 ASSERT_TRUE(response != NULL);
6584 EXPECT_EQ(302, response->headers->response_code());
6585 std::string url;
6586 EXPECT_TRUE(response->headers->IsRedirect(&url));
6587 EXPECT_EQ("http://login.example.com/", url);
6590 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6591 TEST_P(HttpNetworkTransactionTest,
6592 ErrorResponseToHttpsConnectViaHttpsProxy) {
6593 session_deps_.proxy_service.reset(
6594 ProxyService::CreateFixed("https://proxy:70"));
6596 HttpRequestInfo request;
6597 request.method = "GET";
6598 request.url = GURL("https://www.example.org/");
6599 request.load_flags = 0;
6601 MockWrite data_writes[] = {
6602 MockWrite(
6603 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6604 "Host: www.example.org\r\n"
6605 "Proxy-Connection: keep-alive\r\n\r\n"),
6608 MockRead data_reads[] = {
6609 MockRead("HTTP/1.1 404 Not Found\r\n"),
6610 MockRead("Content-Length: 23\r\n\r\n"),
6611 MockRead("The host does not exist"),
6612 MockRead(SYNCHRONOUS, OK),
6615 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6616 data_writes, arraysize(data_writes));
6617 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6619 session_deps_.socket_factory->AddSocketDataProvider(&data);
6620 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6622 TestCompletionCallback callback;
6624 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6625 scoped_ptr<HttpTransaction> trans(
6626 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6628 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6629 EXPECT_EQ(ERR_IO_PENDING, rv);
6631 rv = callback.WaitForResult();
6632 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6634 // TODO(ttuttle): Anything else to check here?
6637 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6638 TEST_P(HttpNetworkTransactionTest,
6639 ErrorResponseToHttpsConnectViaSpdyProxy) {
6640 session_deps_.proxy_service.reset(
6641 ProxyService::CreateFixed("https://proxy:70"));
6643 HttpRequestInfo request;
6644 request.method = "GET";
6645 request.url = GURL("https://www.example.org/");
6646 request.load_flags = 0;
6648 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6649 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6650 scoped_ptr<SpdyFrame> rst(
6651 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6652 MockWrite data_writes[] = {
6653 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
6656 static const char* const kExtraHeaders[] = {
6657 "location",
6658 "http://login.example.com/",
6660 scoped_ptr<SpdyFrame> resp(
6661 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6662 arraysize(kExtraHeaders)/2, 1));
6663 scoped_ptr<SpdyFrame> body(
6664 spdy_util_.ConstructSpdyBodyFrame(
6665 1, "The host does not exist", 23, true));
6666 MockRead data_reads[] = {
6667 CreateMockRead(*resp.get(), 1),
6668 CreateMockRead(*body.get(), 2),
6669 MockRead(ASYNC, 0, 4), // EOF
6672 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6673 arraysize(data_writes));
6674 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6675 proxy_ssl.SetNextProto(GetParam());
6677 session_deps_.socket_factory->AddSocketDataProvider(&data);
6678 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6680 TestCompletionCallback callback;
6682 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6683 scoped_ptr<HttpTransaction> trans(
6684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6686 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6687 EXPECT_EQ(ERR_IO_PENDING, rv);
6689 rv = callback.WaitForResult();
6690 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6692 // TODO(ttuttle): Anything else to check here?
6695 // Test the request-challenge-retry sequence for basic auth, through
6696 // a SPDY proxy over a single SPDY session.
6697 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6698 HttpRequestInfo request;
6699 request.method = "GET";
6700 request.url = GURL("https://www.example.org/");
6701 // when the no authentication data flag is set.
6702 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
6704 // Configure against https proxy server "myproxy:70".
6705 session_deps_.proxy_service.reset(
6706 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6707 BoundTestNetLog log;
6708 session_deps_.net_log = log.bound().net_log();
6709 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6711 // Since we have proxy, should try to establish tunnel.
6712 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
6713 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6714 scoped_ptr<SpdyFrame> rst(
6715 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6717 // After calling trans->RestartWithAuth(), this is the request we should
6718 // be issuing -- the final header line contains the credentials.
6719 const char* const kAuthCredentials[] = {
6720 "proxy-authorization", "Basic Zm9vOmJhcg==",
6722 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6723 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
6724 HostPortPair("www.example.org", 443)));
6725 // fetch https://www.example.org/ via HTTP
6726 const char get[] =
6727 "GET / HTTP/1.1\r\n"
6728 "Host: www.example.org\r\n"
6729 "Connection: keep-alive\r\n\r\n";
6730 scoped_ptr<SpdyFrame> wrapped_get(
6731 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6733 MockWrite spdy_writes[] = {
6734 CreateMockWrite(*req, 0, ASYNC),
6735 CreateMockWrite(*rst, 2, ASYNC),
6736 CreateMockWrite(*connect2, 3),
6737 CreateMockWrite(*wrapped_get, 5),
6740 // The proxy responds to the connect with a 407, using a persistent
6741 // connection.
6742 const char kAuthStatus[] = "407";
6743 const char* const kAuthChallenge[] = {
6744 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6746 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6747 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6749 scoped_ptr<SpdyFrame> conn_resp(
6750 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6751 const char resp[] = "HTTP/1.1 200 OK\r\n"
6752 "Content-Length: 5\r\n\r\n";
6754 scoped_ptr<SpdyFrame> wrapped_get_resp(
6755 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6756 scoped_ptr<SpdyFrame> wrapped_body(
6757 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6758 MockRead spdy_reads[] = {
6759 CreateMockRead(*conn_auth_resp, 1, ASYNC),
6760 CreateMockRead(*conn_resp, 4, ASYNC),
6761 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
6762 CreateMockRead(*wrapped_body, 7, ASYNC),
6763 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
6766 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6767 arraysize(spdy_writes));
6768 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6769 // Negotiate SPDY to the proxy
6770 SSLSocketDataProvider proxy(ASYNC, OK);
6771 proxy.SetNextProto(GetParam());
6772 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6773 // Vanilla SSL to the server
6774 SSLSocketDataProvider server(ASYNC, OK);
6775 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6777 TestCompletionCallback callback1;
6779 scoped_ptr<HttpTransaction> trans(
6780 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6782 int rv = trans->Start(&request, callback1.callback(), log.bound());
6783 EXPECT_EQ(ERR_IO_PENDING, rv);
6785 rv = callback1.WaitForResult();
6786 EXPECT_EQ(OK, rv);
6787 TestNetLogEntry::List entries;
6788 log.GetEntries(&entries);
6789 size_t pos = ExpectLogContainsSomewhere(
6790 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6791 NetLog::PHASE_NONE);
6792 ExpectLogContainsSomewhere(
6793 entries, pos,
6794 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6795 NetLog::PHASE_NONE);
6797 const HttpResponseInfo* response = trans->GetResponseInfo();
6798 ASSERT_TRUE(response != NULL);
6799 ASSERT_FALSE(response->headers.get() == NULL);
6800 EXPECT_EQ(407, response->headers->response_code());
6801 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6802 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6803 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6805 TestCompletionCallback callback2;
6807 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6808 callback2.callback());
6809 EXPECT_EQ(ERR_IO_PENDING, rv);
6811 rv = callback2.WaitForResult();
6812 EXPECT_EQ(OK, rv);
6814 response = trans->GetResponseInfo();
6815 ASSERT_TRUE(response != NULL);
6817 EXPECT_TRUE(response->headers->IsKeepAlive());
6818 EXPECT_EQ(200, response->headers->response_code());
6819 EXPECT_EQ(5, response->headers->GetContentLength());
6820 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6822 // The password prompt info should not be set.
6823 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6825 LoadTimingInfo load_timing_info;
6826 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6827 TestLoadTimingNotReusedWithPac(load_timing_info,
6828 CONNECT_TIMING_HAS_SSL_TIMES);
6830 trans.reset();
6831 session->CloseAllConnections();
6834 // Test that an explicitly trusted SPDY proxy can push a resource from an
6835 // origin that is different from that of its associated resource.
6836 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6837 HttpRequestInfo request;
6838 HttpRequestInfo push_request;
6840 request.method = "GET";
6841 request.url = GURL("http://www.example.org/");
6842 push_request.method = "GET";
6843 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6845 // Configure against https proxy server "myproxy:70".
6846 session_deps_.proxy_service.reset(
6847 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6848 BoundTestNetLog log;
6849 session_deps_.net_log = log.bound().net_log();
6851 // Enable cross-origin push.
6852 session_deps_.trusted_spdy_proxy = "myproxy:70";
6854 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6856 scoped_ptr<SpdyFrame> stream1_syn(
6857 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6859 MockWrite spdy_writes[] = {
6860 CreateMockWrite(*stream1_syn, 0, ASYNC),
6863 scoped_ptr<SpdyFrame>
6864 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6866 scoped_ptr<SpdyFrame>
6867 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6869 scoped_ptr<SpdyFrame>
6870 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6874 "http://www.another-origin.com/foo.dat"));
6875 const char kPushedData[] = "pushed";
6876 scoped_ptr<SpdyFrame> stream2_body(
6877 spdy_util_.ConstructSpdyBodyFrame(
6878 2, kPushedData, strlen(kPushedData), true));
6880 MockRead spdy_reads[] = {
6881 CreateMockRead(*stream1_reply, 1, ASYNC),
6882 CreateMockRead(*stream2_syn, 2, ASYNC),
6883 CreateMockRead(*stream1_body, 3, ASYNC),
6884 CreateMockRead(*stream2_body, 4, ASYNC),
6885 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
6888 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6889 arraysize(spdy_writes));
6890 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6891 // Negotiate SPDY to the proxy
6892 SSLSocketDataProvider proxy(ASYNC, OK);
6893 proxy.SetNextProto(GetParam());
6894 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6896 scoped_ptr<HttpTransaction> trans(
6897 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6898 TestCompletionCallback callback;
6899 int rv = trans->Start(&request, callback.callback(), log.bound());
6900 EXPECT_EQ(ERR_IO_PENDING, rv);
6902 rv = callback.WaitForResult();
6903 EXPECT_EQ(OK, rv);
6904 const HttpResponseInfo* response = trans->GetResponseInfo();
6906 scoped_ptr<HttpTransaction> push_trans(
6907 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6908 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6909 EXPECT_EQ(ERR_IO_PENDING, rv);
6911 rv = callback.WaitForResult();
6912 EXPECT_EQ(OK, rv);
6913 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6915 ASSERT_TRUE(response != NULL);
6916 EXPECT_TRUE(response->headers->IsKeepAlive());
6918 EXPECT_EQ(200, response->headers->response_code());
6919 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6921 std::string response_data;
6922 rv = ReadTransaction(trans.get(), &response_data);
6923 EXPECT_EQ(OK, rv);
6924 EXPECT_EQ("hello!", response_data);
6926 LoadTimingInfo load_timing_info;
6927 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6928 TestLoadTimingNotReusedWithPac(load_timing_info,
6929 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6931 // Verify the pushed stream.
6932 EXPECT_TRUE(push_response->headers.get() != NULL);
6933 EXPECT_EQ(200, push_response->headers->response_code());
6935 rv = ReadTransaction(push_trans.get(), &response_data);
6936 EXPECT_EQ(OK, rv);
6937 EXPECT_EQ("pushed", response_data);
6939 LoadTimingInfo push_load_timing_info;
6940 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6941 TestLoadTimingReusedWithPac(push_load_timing_info);
6942 // The transactions should share a socket ID, despite being for different
6943 // origins.
6944 EXPECT_EQ(load_timing_info.socket_log_id,
6945 push_load_timing_info.socket_log_id);
6947 trans.reset();
6948 push_trans.reset();
6949 session->CloseAllConnections();
6952 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6953 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6954 HttpRequestInfo request;
6956 request.method = "GET";
6957 request.url = GURL("http://www.example.org/");
6959 // Configure against https proxy server "myproxy:70".
6960 session_deps_.proxy_service.reset(
6961 ProxyService::CreateFixed("https://myproxy:70"));
6962 BoundTestNetLog log;
6963 session_deps_.net_log = log.bound().net_log();
6965 // Enable cross-origin push.
6966 session_deps_.trusted_spdy_proxy = "myproxy:70";
6968 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6970 scoped_ptr<SpdyFrame> stream1_syn(
6971 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6973 scoped_ptr<SpdyFrame> push_rst(
6974 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6976 MockWrite spdy_writes[] = {
6977 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
6980 scoped_ptr<SpdyFrame>
6981 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6983 scoped_ptr<SpdyFrame>
6984 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6986 scoped_ptr<SpdyFrame>
6987 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6991 "https://www.another-origin.com/foo.dat"));
6993 MockRead spdy_reads[] = {
6994 CreateMockRead(*stream1_reply, 1, ASYNC),
6995 CreateMockRead(*stream2_syn, 2, ASYNC),
6996 CreateMockRead(*stream1_body, 4, ASYNC),
6997 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
7000 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7001 arraysize(spdy_writes));
7002 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7003 // Negotiate SPDY to the proxy
7004 SSLSocketDataProvider proxy(ASYNC, OK);
7005 proxy.SetNextProto(GetParam());
7006 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7008 scoped_ptr<HttpTransaction> trans(
7009 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7010 TestCompletionCallback callback;
7011 int rv = trans->Start(&request, callback.callback(), log.bound());
7012 EXPECT_EQ(ERR_IO_PENDING, rv);
7014 rv = callback.WaitForResult();
7015 EXPECT_EQ(OK, rv);
7016 const HttpResponseInfo* response = trans->GetResponseInfo();
7018 ASSERT_TRUE(response != NULL);
7019 EXPECT_TRUE(response->headers->IsKeepAlive());
7021 EXPECT_EQ(200, response->headers->response_code());
7022 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7024 std::string response_data;
7025 rv = ReadTransaction(trans.get(), &response_data);
7026 EXPECT_EQ(OK, rv);
7027 EXPECT_EQ("hello!", response_data);
7029 trans.reset();
7030 session->CloseAllConnections();
7033 // Test HTTPS connections to a site with a bad certificate, going through an
7034 // HTTPS proxy
7035 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
7036 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
7037 "https://proxy:70"));
7039 HttpRequestInfo request;
7040 request.method = "GET";
7041 request.url = GURL("https://www.example.org/");
7042 request.load_flags = 0;
7044 // Attempt to fetch the URL from a server with a bad cert
7045 MockWrite bad_cert_writes[] = {
7046 MockWrite(
7047 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7048 "Host: www.example.org\r\n"
7049 "Proxy-Connection: keep-alive\r\n\r\n"),
7052 MockRead bad_cert_reads[] = {
7053 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7054 MockRead(SYNCHRONOUS, OK)
7057 // Attempt to fetch the URL with a good cert
7058 MockWrite good_data_writes[] = {
7059 MockWrite(
7060 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7061 "Host: www.example.org\r\n"
7062 "Proxy-Connection: keep-alive\r\n\r\n"),
7063 MockWrite(
7064 "GET / HTTP/1.1\r\n"
7065 "Host: www.example.org\r\n"
7066 "Connection: keep-alive\r\n\r\n"),
7069 MockRead good_cert_reads[] = {
7070 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7071 MockRead("HTTP/1.0 200 OK\r\n"),
7072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7073 MockRead("Content-Length: 100\r\n\r\n"),
7074 MockRead(SYNCHRONOUS, OK),
7077 StaticSocketDataProvider ssl_bad_certificate(
7078 bad_cert_reads, arraysize(bad_cert_reads),
7079 bad_cert_writes, arraysize(bad_cert_writes));
7080 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7081 good_data_writes, arraysize(good_data_writes));
7082 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7083 SSLSocketDataProvider ssl(ASYNC, OK);
7085 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7086 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7087 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7088 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7090 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7091 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7092 session_deps_.socket_factory->AddSocketDataProvider(&data);
7093 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7095 TestCompletionCallback callback;
7097 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7098 scoped_ptr<HttpTransaction> trans(
7099 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7101 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7102 EXPECT_EQ(ERR_IO_PENDING, rv);
7104 rv = callback.WaitForResult();
7105 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7107 rv = trans->RestartIgnoringLastError(callback.callback());
7108 EXPECT_EQ(ERR_IO_PENDING, rv);
7110 rv = callback.WaitForResult();
7111 EXPECT_EQ(OK, rv);
7113 const HttpResponseInfo* response = trans->GetResponseInfo();
7115 ASSERT_TRUE(response != NULL);
7116 EXPECT_EQ(100, response->headers->GetContentLength());
7119 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
7120 HttpRequestInfo request;
7121 request.method = "GET";
7122 request.url = GURL("http://www.example.org/");
7123 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7124 "Chromium Ultra Awesome X Edition");
7126 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7127 scoped_ptr<HttpTransaction> trans(
7128 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7130 MockWrite data_writes[] = {
7131 MockWrite(
7132 "GET / HTTP/1.1\r\n"
7133 "Host: www.example.org\r\n"
7134 "Connection: keep-alive\r\n"
7135 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7138 // Lastly, the server responds with the actual content.
7139 MockRead data_reads[] = {
7140 MockRead("HTTP/1.0 200 OK\r\n"),
7141 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7142 MockRead("Content-Length: 100\r\n\r\n"),
7143 MockRead(SYNCHRONOUS, OK),
7146 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7147 data_writes, arraysize(data_writes));
7148 session_deps_.socket_factory->AddSocketDataProvider(&data);
7150 TestCompletionCallback callback;
7152 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7153 EXPECT_EQ(ERR_IO_PENDING, rv);
7155 rv = callback.WaitForResult();
7156 EXPECT_EQ(OK, rv);
7159 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
7160 HttpRequestInfo request;
7161 request.method = "GET";
7162 request.url = GURL("https://www.example.org/");
7163 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7164 "Chromium Ultra Awesome X Edition");
7166 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7167 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7168 scoped_ptr<HttpTransaction> trans(
7169 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7171 MockWrite data_writes[] = {
7172 MockWrite(
7173 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7174 "Host: www.example.org\r\n"
7175 "Proxy-Connection: keep-alive\r\n"
7176 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7178 MockRead data_reads[] = {
7179 // Return an error, so the transaction stops here (this test isn't
7180 // interested in the rest).
7181 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7182 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7183 MockRead("Proxy-Connection: close\r\n\r\n"),
7186 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7187 data_writes, arraysize(data_writes));
7188 session_deps_.socket_factory->AddSocketDataProvider(&data);
7190 TestCompletionCallback callback;
7192 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7193 EXPECT_EQ(ERR_IO_PENDING, rv);
7195 rv = callback.WaitForResult();
7196 EXPECT_EQ(OK, rv);
7199 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
7200 HttpRequestInfo request;
7201 request.method = "GET";
7202 request.url = GURL("http://www.example.org/");
7203 request.load_flags = 0;
7204 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7205 "http://the.previous.site.com/");
7207 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7208 scoped_ptr<HttpTransaction> trans(
7209 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7211 MockWrite data_writes[] = {
7212 MockWrite(
7213 "GET / HTTP/1.1\r\n"
7214 "Host: www.example.org\r\n"
7215 "Connection: keep-alive\r\n"
7216 "Referer: http://the.previous.site.com/\r\n\r\n"),
7219 // Lastly, the server responds with the actual content.
7220 MockRead data_reads[] = {
7221 MockRead("HTTP/1.0 200 OK\r\n"),
7222 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7223 MockRead("Content-Length: 100\r\n\r\n"),
7224 MockRead(SYNCHRONOUS, OK),
7227 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7228 data_writes, arraysize(data_writes));
7229 session_deps_.socket_factory->AddSocketDataProvider(&data);
7231 TestCompletionCallback callback;
7233 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7234 EXPECT_EQ(ERR_IO_PENDING, rv);
7236 rv = callback.WaitForResult();
7237 EXPECT_EQ(OK, rv);
7240 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
7241 HttpRequestInfo request;
7242 request.method = "POST";
7243 request.url = GURL("http://www.example.org/");
7245 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7246 scoped_ptr<HttpTransaction> trans(
7247 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7249 MockWrite data_writes[] = {
7250 MockWrite(
7251 "POST / HTTP/1.1\r\n"
7252 "Host: www.example.org\r\n"
7253 "Connection: keep-alive\r\n"
7254 "Content-Length: 0\r\n\r\n"),
7257 // Lastly, the server responds with the actual content.
7258 MockRead data_reads[] = {
7259 MockRead("HTTP/1.0 200 OK\r\n"),
7260 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7261 MockRead("Content-Length: 100\r\n\r\n"),
7262 MockRead(SYNCHRONOUS, OK),
7265 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7266 data_writes, arraysize(data_writes));
7267 session_deps_.socket_factory->AddSocketDataProvider(&data);
7269 TestCompletionCallback callback;
7271 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7272 EXPECT_EQ(ERR_IO_PENDING, rv);
7274 rv = callback.WaitForResult();
7275 EXPECT_EQ(OK, rv);
7278 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
7279 HttpRequestInfo request;
7280 request.method = "PUT";
7281 request.url = GURL("http://www.example.org/");
7283 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7284 scoped_ptr<HttpTransaction> trans(
7285 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7287 MockWrite data_writes[] = {
7288 MockWrite(
7289 "PUT / HTTP/1.1\r\n"
7290 "Host: www.example.org\r\n"
7291 "Connection: keep-alive\r\n"
7292 "Content-Length: 0\r\n\r\n"),
7295 // Lastly, the server responds with the actual content.
7296 MockRead data_reads[] = {
7297 MockRead("HTTP/1.0 200 OK\r\n"),
7298 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7299 MockRead("Content-Length: 100\r\n\r\n"),
7300 MockRead(SYNCHRONOUS, OK),
7303 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7304 data_writes, arraysize(data_writes));
7305 session_deps_.socket_factory->AddSocketDataProvider(&data);
7307 TestCompletionCallback callback;
7309 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7310 EXPECT_EQ(ERR_IO_PENDING, rv);
7312 rv = callback.WaitForResult();
7313 EXPECT_EQ(OK, rv);
7316 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
7317 HttpRequestInfo request;
7318 request.method = "HEAD";
7319 request.url = GURL("http://www.example.org/");
7321 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7322 scoped_ptr<HttpTransaction> trans(
7323 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7325 MockWrite data_writes[] = {
7326 MockWrite(
7327 "HEAD / HTTP/1.1\r\n"
7328 "Host: www.example.org\r\n"
7329 "Connection: keep-alive\r\n"
7330 "Content-Length: 0\r\n\r\n"),
7333 // Lastly, the server responds with the actual content.
7334 MockRead data_reads[] = {
7335 MockRead("HTTP/1.0 200 OK\r\n"),
7336 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7337 MockRead("Content-Length: 100\r\n\r\n"),
7338 MockRead(SYNCHRONOUS, OK),
7341 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7342 data_writes, arraysize(data_writes));
7343 session_deps_.socket_factory->AddSocketDataProvider(&data);
7345 TestCompletionCallback callback;
7347 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7348 EXPECT_EQ(ERR_IO_PENDING, rv);
7350 rv = callback.WaitForResult();
7351 EXPECT_EQ(OK, rv);
7354 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7355 HttpRequestInfo request;
7356 request.method = "GET";
7357 request.url = GURL("http://www.example.org/");
7358 request.load_flags = LOAD_BYPASS_CACHE;
7360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7361 scoped_ptr<HttpTransaction> trans(
7362 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7364 MockWrite data_writes[] = {
7365 MockWrite(
7366 "GET / HTTP/1.1\r\n"
7367 "Host: www.example.org\r\n"
7368 "Connection: keep-alive\r\n"
7369 "Pragma: no-cache\r\n"
7370 "Cache-Control: no-cache\r\n\r\n"),
7373 // Lastly, the server responds with the actual content.
7374 MockRead data_reads[] = {
7375 MockRead("HTTP/1.0 200 OK\r\n"),
7376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7377 MockRead("Content-Length: 100\r\n\r\n"),
7378 MockRead(SYNCHRONOUS, OK),
7381 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7382 data_writes, arraysize(data_writes));
7383 session_deps_.socket_factory->AddSocketDataProvider(&data);
7385 TestCompletionCallback callback;
7387 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7388 EXPECT_EQ(ERR_IO_PENDING, rv);
7390 rv = callback.WaitForResult();
7391 EXPECT_EQ(OK, rv);
7394 TEST_P(HttpNetworkTransactionTest,
7395 BuildRequest_CacheControlValidateCache) {
7396 HttpRequestInfo request;
7397 request.method = "GET";
7398 request.url = GURL("http://www.example.org/");
7399 request.load_flags = LOAD_VALIDATE_CACHE;
7401 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7402 scoped_ptr<HttpTransaction> trans(
7403 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7405 MockWrite data_writes[] = {
7406 MockWrite(
7407 "GET / HTTP/1.1\r\n"
7408 "Host: www.example.org\r\n"
7409 "Connection: keep-alive\r\n"
7410 "Cache-Control: max-age=0\r\n\r\n"),
7413 // Lastly, the server responds with the actual content.
7414 MockRead data_reads[] = {
7415 MockRead("HTTP/1.0 200 OK\r\n"),
7416 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7417 MockRead("Content-Length: 100\r\n\r\n"),
7418 MockRead(SYNCHRONOUS, OK),
7421 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7422 data_writes, arraysize(data_writes));
7423 session_deps_.socket_factory->AddSocketDataProvider(&data);
7425 TestCompletionCallback callback;
7427 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7428 EXPECT_EQ(ERR_IO_PENDING, rv);
7430 rv = callback.WaitForResult();
7431 EXPECT_EQ(OK, rv);
7434 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7435 HttpRequestInfo request;
7436 request.method = "GET";
7437 request.url = GURL("http://www.example.org/");
7438 request.extra_headers.SetHeader("FooHeader", "Bar");
7440 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7441 scoped_ptr<HttpTransaction> trans(
7442 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7444 MockWrite data_writes[] = {
7445 MockWrite(
7446 "GET / HTTP/1.1\r\n"
7447 "Host: www.example.org\r\n"
7448 "Connection: keep-alive\r\n"
7449 "FooHeader: Bar\r\n\r\n"),
7452 // Lastly, the server responds with the actual content.
7453 MockRead data_reads[] = {
7454 MockRead("HTTP/1.0 200 OK\r\n"),
7455 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7456 MockRead("Content-Length: 100\r\n\r\n"),
7457 MockRead(SYNCHRONOUS, OK),
7460 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7461 data_writes, arraysize(data_writes));
7462 session_deps_.socket_factory->AddSocketDataProvider(&data);
7464 TestCompletionCallback callback;
7466 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7467 EXPECT_EQ(ERR_IO_PENDING, rv);
7469 rv = callback.WaitForResult();
7470 EXPECT_EQ(OK, rv);
7473 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7474 HttpRequestInfo request;
7475 request.method = "GET";
7476 request.url = GURL("http://www.example.org/");
7477 request.extra_headers.SetHeader("referer", "www.foo.com");
7478 request.extra_headers.SetHeader("hEllo", "Kitty");
7479 request.extra_headers.SetHeader("FoO", "bar");
7481 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7482 scoped_ptr<HttpTransaction> trans(
7483 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7485 MockWrite data_writes[] = {
7486 MockWrite(
7487 "GET / HTTP/1.1\r\n"
7488 "Host: www.example.org\r\n"
7489 "Connection: keep-alive\r\n"
7490 "referer: www.foo.com\r\n"
7491 "hEllo: Kitty\r\n"
7492 "FoO: bar\r\n\r\n"),
7495 // Lastly, the server responds with the actual content.
7496 MockRead data_reads[] = {
7497 MockRead("HTTP/1.0 200 OK\r\n"),
7498 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7499 MockRead("Content-Length: 100\r\n\r\n"),
7500 MockRead(SYNCHRONOUS, OK),
7503 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7504 data_writes, arraysize(data_writes));
7505 session_deps_.socket_factory->AddSocketDataProvider(&data);
7507 TestCompletionCallback callback;
7509 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7510 EXPECT_EQ(ERR_IO_PENDING, rv);
7512 rv = callback.WaitForResult();
7513 EXPECT_EQ(OK, rv);
7516 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7517 HttpRequestInfo request;
7518 request.method = "GET";
7519 request.url = GURL("http://www.example.org/");
7520 request.load_flags = 0;
7522 session_deps_.proxy_service.reset(
7523 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7524 TestNetLog net_log;
7525 session_deps_.net_log = &net_log;
7527 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7528 scoped_ptr<HttpTransaction> trans(
7529 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7531 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7532 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7534 MockWrite data_writes[] = {
7535 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7536 MockWrite(
7537 "GET / HTTP/1.1\r\n"
7538 "Host: www.example.org\r\n"
7539 "Connection: keep-alive\r\n\r\n")};
7541 MockRead data_reads[] = {
7542 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7543 MockRead("HTTP/1.0 200 OK\r\n"),
7544 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7545 MockRead("Payload"),
7546 MockRead(SYNCHRONOUS, OK)
7549 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7550 data_writes, arraysize(data_writes));
7551 session_deps_.socket_factory->AddSocketDataProvider(&data);
7553 TestCompletionCallback callback;
7555 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7556 EXPECT_EQ(ERR_IO_PENDING, rv);
7558 rv = callback.WaitForResult();
7559 EXPECT_EQ(OK, rv);
7561 const HttpResponseInfo* response = trans->GetResponseInfo();
7562 ASSERT_TRUE(response != NULL);
7564 LoadTimingInfo load_timing_info;
7565 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7566 TestLoadTimingNotReusedWithPac(load_timing_info,
7567 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7569 std::string response_text;
7570 rv = ReadTransaction(trans.get(), &response_text);
7571 EXPECT_EQ(OK, rv);
7572 EXPECT_EQ("Payload", response_text);
7575 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7576 HttpRequestInfo request;
7577 request.method = "GET";
7578 request.url = GURL("https://www.example.org/");
7579 request.load_flags = 0;
7581 session_deps_.proxy_service.reset(
7582 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7583 TestNetLog net_log;
7584 session_deps_.net_log = &net_log;
7586 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7587 scoped_ptr<HttpTransaction> trans(
7588 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7590 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7591 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7593 MockWrite data_writes[] = {
7594 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7595 arraysize(write_buffer)),
7596 MockWrite(
7597 "GET / HTTP/1.1\r\n"
7598 "Host: www.example.org\r\n"
7599 "Connection: keep-alive\r\n\r\n")};
7601 MockRead data_reads[] = {
7602 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7603 arraysize(read_buffer)),
7604 MockRead("HTTP/1.0 200 OK\r\n"),
7605 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7606 MockRead("Payload"),
7607 MockRead(SYNCHRONOUS, OK)
7610 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7611 data_writes, arraysize(data_writes));
7612 session_deps_.socket_factory->AddSocketDataProvider(&data);
7614 SSLSocketDataProvider ssl(ASYNC, OK);
7615 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7617 TestCompletionCallback callback;
7619 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7620 EXPECT_EQ(ERR_IO_PENDING, rv);
7622 rv = callback.WaitForResult();
7623 EXPECT_EQ(OK, rv);
7625 LoadTimingInfo load_timing_info;
7626 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7627 TestLoadTimingNotReusedWithPac(load_timing_info,
7628 CONNECT_TIMING_HAS_SSL_TIMES);
7630 const HttpResponseInfo* response = trans->GetResponseInfo();
7631 ASSERT_TRUE(response != NULL);
7633 std::string response_text;
7634 rv = ReadTransaction(trans.get(), &response_text);
7635 EXPECT_EQ(OK, rv);
7636 EXPECT_EQ("Payload", response_text);
7639 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7640 HttpRequestInfo request;
7641 request.method = "GET";
7642 request.url = GURL("http://www.example.org/");
7643 request.load_flags = 0;
7645 session_deps_.proxy_service.reset(
7646 ProxyService::CreateFixed("socks4://myproxy:1080"));
7647 TestNetLog net_log;
7648 session_deps_.net_log = &net_log;
7650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7651 scoped_ptr<HttpTransaction> trans(
7652 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7654 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7655 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7657 MockWrite data_writes[] = {
7658 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7659 MockWrite(
7660 "GET / HTTP/1.1\r\n"
7661 "Host: www.example.org\r\n"
7662 "Connection: keep-alive\r\n\r\n")};
7664 MockRead data_reads[] = {
7665 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7666 MockRead("HTTP/1.0 200 OK\r\n"),
7667 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7668 MockRead("Payload"),
7669 MockRead(SYNCHRONOUS, OK)
7672 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7673 data_writes, arraysize(data_writes));
7674 session_deps_.socket_factory->AddSocketDataProvider(&data);
7676 TestCompletionCallback callback;
7678 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7679 EXPECT_EQ(ERR_IO_PENDING, rv);
7681 rv = callback.WaitForResult();
7682 EXPECT_EQ(OK, rv);
7684 const HttpResponseInfo* response = trans->GetResponseInfo();
7685 ASSERT_TRUE(response != NULL);
7687 LoadTimingInfo load_timing_info;
7688 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7689 TestLoadTimingNotReused(load_timing_info,
7690 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7692 std::string response_text;
7693 rv = ReadTransaction(trans.get(), &response_text);
7694 EXPECT_EQ(OK, rv);
7695 EXPECT_EQ("Payload", response_text);
7698 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7699 HttpRequestInfo request;
7700 request.method = "GET";
7701 request.url = GURL("http://www.example.org/");
7702 request.load_flags = 0;
7704 session_deps_.proxy_service.reset(
7705 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7706 TestNetLog net_log;
7707 session_deps_.net_log = &net_log;
7709 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7710 scoped_ptr<HttpTransaction> trans(
7711 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7713 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7714 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7715 const char kSOCKS5OkRequest[] = {
7716 0x05, // Version
7717 0x01, // Command (CONNECT)
7718 0x00, // Reserved.
7719 0x03, // Address type (DOMAINNAME).
7720 0x0F, // Length of domain (15)
7721 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7722 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7724 const char kSOCKS5OkResponse[] =
7725 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7727 MockWrite data_writes[] = {
7728 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7729 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7730 MockWrite(
7731 "GET / HTTP/1.1\r\n"
7732 "Host: www.example.org\r\n"
7733 "Connection: keep-alive\r\n\r\n")};
7735 MockRead data_reads[] = {
7736 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7737 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7738 MockRead("HTTP/1.0 200 OK\r\n"),
7739 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7740 MockRead("Payload"),
7741 MockRead(SYNCHRONOUS, OK)
7744 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7745 data_writes, arraysize(data_writes));
7746 session_deps_.socket_factory->AddSocketDataProvider(&data);
7748 TestCompletionCallback callback;
7750 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7751 EXPECT_EQ(ERR_IO_PENDING, rv);
7753 rv = callback.WaitForResult();
7754 EXPECT_EQ(OK, rv);
7756 const HttpResponseInfo* response = trans->GetResponseInfo();
7757 ASSERT_TRUE(response != NULL);
7759 LoadTimingInfo load_timing_info;
7760 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7761 TestLoadTimingNotReusedWithPac(load_timing_info,
7762 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7764 std::string response_text;
7765 rv = ReadTransaction(trans.get(), &response_text);
7766 EXPECT_EQ(OK, rv);
7767 EXPECT_EQ("Payload", response_text);
7770 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7771 HttpRequestInfo request;
7772 request.method = "GET";
7773 request.url = GURL("https://www.example.org/");
7774 request.load_flags = 0;
7776 session_deps_.proxy_service.reset(
7777 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7778 TestNetLog net_log;
7779 session_deps_.net_log = &net_log;
7781 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7782 scoped_ptr<HttpTransaction> trans(
7783 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7785 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7786 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7787 const unsigned char kSOCKS5OkRequest[] = {
7788 0x05, // Version
7789 0x01, // Command (CONNECT)
7790 0x00, // Reserved.
7791 0x03, // Address type (DOMAINNAME).
7792 0x0F, // Length of domain (15)
7793 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7794 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7797 const char kSOCKS5OkResponse[] =
7798 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7800 MockWrite data_writes[] = {
7801 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7802 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7803 arraysize(kSOCKS5OkRequest)),
7804 MockWrite(
7805 "GET / HTTP/1.1\r\n"
7806 "Host: www.example.org\r\n"
7807 "Connection: keep-alive\r\n\r\n")};
7809 MockRead data_reads[] = {
7810 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7811 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7812 MockRead("HTTP/1.0 200 OK\r\n"),
7813 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7814 MockRead("Payload"),
7815 MockRead(SYNCHRONOUS, OK)
7818 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7819 data_writes, arraysize(data_writes));
7820 session_deps_.socket_factory->AddSocketDataProvider(&data);
7822 SSLSocketDataProvider ssl(ASYNC, OK);
7823 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7825 TestCompletionCallback callback;
7827 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7828 EXPECT_EQ(ERR_IO_PENDING, rv);
7830 rv = callback.WaitForResult();
7831 EXPECT_EQ(OK, rv);
7833 const HttpResponseInfo* response = trans->GetResponseInfo();
7834 ASSERT_TRUE(response != NULL);
7836 LoadTimingInfo load_timing_info;
7837 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7838 TestLoadTimingNotReusedWithPac(load_timing_info,
7839 CONNECT_TIMING_HAS_SSL_TIMES);
7841 std::string response_text;
7842 rv = ReadTransaction(trans.get(), &response_text);
7843 EXPECT_EQ(OK, rv);
7844 EXPECT_EQ("Payload", response_text);
7847 namespace {
7849 // Tests that for connection endpoints the group names are correctly set.
7851 struct GroupNameTest {
7852 std::string proxy_server;
7853 std::string url;
7854 std::string expected_group_name;
7855 bool ssl;
7858 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7859 NextProto next_proto,
7860 SpdySessionDependencies* session_deps_) {
7861 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7863 base::WeakPtr<HttpServerProperties> http_server_properties =
7864 session->http_server_properties();
7865 AlternativeService alternative_service(
7866 AlternateProtocolFromNextProto(next_proto), "", 443);
7867 http_server_properties->SetAlternativeService(
7868 HostPortPair("host.with.alternate", 80), alternative_service, 1.0);
7870 return session;
7873 int GroupNameTransactionHelper(
7874 const std::string& url,
7875 const scoped_refptr<HttpNetworkSession>& session) {
7876 HttpRequestInfo request;
7877 request.method = "GET";
7878 request.url = GURL(url);
7879 request.load_flags = 0;
7881 scoped_ptr<HttpTransaction> trans(
7882 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7884 TestCompletionCallback callback;
7886 // We do not complete this request, the dtor will clean the transaction up.
7887 return trans->Start(&request, callback.callback(), BoundNetLog());
7890 } // namespace
7892 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7893 const GroupNameTest tests[] = {
7895 "", // unused
7896 "http://www.example.org/direct",
7897 "www.example.org:80",
7898 false,
7901 "", // unused
7902 "http://[2001:1418:13:1::25]/direct",
7903 "[2001:1418:13:1::25]:80",
7904 false,
7907 // SSL Tests
7909 "", // unused
7910 "https://www.example.org/direct_ssl",
7911 "ssl/www.example.org:443",
7912 true,
7915 "", // unused
7916 "https://[2001:1418:13:1::25]/direct",
7917 "ssl/[2001:1418:13:1::25]:443",
7918 true,
7921 "", // unused
7922 "http://host.with.alternate/direct",
7923 "ssl/host.with.alternate:443",
7924 true,
7928 session_deps_.use_alternate_protocols = true;
7930 for (size_t i = 0; i < arraysize(tests); ++i) {
7931 session_deps_.proxy_service.reset(
7932 ProxyService::CreateFixed(tests[i].proxy_server));
7933 scoped_refptr<HttpNetworkSession> session(
7934 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7936 HttpNetworkSessionPeer peer(session);
7937 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7938 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7939 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7940 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7941 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7942 new MockClientSocketPoolManager);
7943 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7944 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7945 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
7947 EXPECT_EQ(ERR_IO_PENDING,
7948 GroupNameTransactionHelper(tests[i].url, session));
7949 if (tests[i].ssl)
7950 EXPECT_EQ(tests[i].expected_group_name,
7951 ssl_conn_pool->last_group_name_received());
7952 else
7953 EXPECT_EQ(tests[i].expected_group_name,
7954 transport_conn_pool->last_group_name_received());
7959 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7960 const GroupNameTest tests[] = {
7962 "http_proxy",
7963 "http://www.example.org/http_proxy_normal",
7964 "www.example.org:80",
7965 false,
7968 // SSL Tests
7970 "http_proxy",
7971 "https://www.example.org/http_connect_ssl",
7972 "ssl/www.example.org:443",
7973 true,
7977 "http_proxy",
7978 "http://host.with.alternate/direct",
7979 "ssl/host.with.alternate:443",
7980 true,
7984 "http_proxy",
7985 "ftp://ftp.google.com/http_proxy_normal",
7986 "ftp/ftp.google.com:21",
7987 false,
7991 session_deps_.use_alternate_protocols = true;
7993 for (size_t i = 0; i < arraysize(tests); ++i) {
7994 session_deps_.proxy_service.reset(
7995 ProxyService::CreateFixed(tests[i].proxy_server));
7996 scoped_refptr<HttpNetworkSession> session(
7997 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7999 HttpNetworkSessionPeer peer(session);
8001 HostPortPair proxy_host("http_proxy", 80);
8002 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
8003 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
8004 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8005 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8007 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8008 new MockClientSocketPoolManager);
8009 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8010 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8011 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8013 EXPECT_EQ(ERR_IO_PENDING,
8014 GroupNameTransactionHelper(tests[i].url, session));
8015 if (tests[i].ssl)
8016 EXPECT_EQ(tests[i].expected_group_name,
8017 ssl_conn_pool->last_group_name_received());
8018 else
8019 EXPECT_EQ(tests[i].expected_group_name,
8020 http_proxy_pool->last_group_name_received());
8024 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
8025 const GroupNameTest tests[] = {
8027 "socks4://socks_proxy:1080",
8028 "http://www.example.org/socks4_direct",
8029 "socks4/www.example.org:80",
8030 false,
8033 "socks5://socks_proxy:1080",
8034 "http://www.example.org/socks5_direct",
8035 "socks5/www.example.org:80",
8036 false,
8039 // SSL Tests
8041 "socks4://socks_proxy:1080",
8042 "https://www.example.org/socks4_ssl",
8043 "socks4/ssl/www.example.org:443",
8044 true,
8047 "socks5://socks_proxy:1080",
8048 "https://www.example.org/socks5_ssl",
8049 "socks5/ssl/www.example.org:443",
8050 true,
8054 "socks4://socks_proxy:1080",
8055 "http://host.with.alternate/direct",
8056 "socks4/ssl/host.with.alternate:443",
8057 true,
8061 session_deps_.use_alternate_protocols = true;
8063 for (size_t i = 0; i < arraysize(tests); ++i) {
8064 session_deps_.proxy_service.reset(
8065 ProxyService::CreateFixed(tests[i].proxy_server));
8066 scoped_refptr<HttpNetworkSession> session(
8067 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8069 HttpNetworkSessionPeer peer(session);
8071 HostPortPair proxy_host("socks_proxy", 1080);
8072 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
8073 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
8074 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8075 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8077 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8078 new MockClientSocketPoolManager);
8079 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8080 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8081 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8083 scoped_ptr<HttpTransaction> trans(
8084 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8086 EXPECT_EQ(ERR_IO_PENDING,
8087 GroupNameTransactionHelper(tests[i].url, session));
8088 if (tests[i].ssl)
8089 EXPECT_EQ(tests[i].expected_group_name,
8090 ssl_conn_pool->last_group_name_received());
8091 else
8092 EXPECT_EQ(tests[i].expected_group_name,
8093 socks_conn_pool->last_group_name_received());
8097 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
8098 HttpRequestInfo request;
8099 request.method = "GET";
8100 request.url = GURL("http://www.example.org/");
8102 session_deps_.proxy_service.reset(
8103 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8105 // This simulates failure resolving all hostnames; that means we will fail
8106 // connecting to both proxies (myproxy:70 and foobar:80).
8107 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
8109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8110 scoped_ptr<HttpTransaction> trans(
8111 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8113 TestCompletionCallback callback;
8115 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8116 EXPECT_EQ(ERR_IO_PENDING, rv);
8118 rv = callback.WaitForResult();
8119 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
8122 // Base test to make sure that when the load flags for a request specify to
8123 // bypass the cache, the DNS cache is not used.
8124 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8125 int load_flags) {
8126 // Issue a request, asking to bypass the cache(s).
8127 HttpRequestInfo request;
8128 request.method = "GET";
8129 request.load_flags = load_flags;
8130 request.url = GURL("http://www.example.org/");
8132 // Select a host resolver that does caching.
8133 session_deps_.host_resolver.reset(new MockCachingHostResolver);
8135 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8136 scoped_ptr<HttpTransaction> trans(
8137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8139 // Warm up the host cache so it has an entry for "www.example.org".
8140 AddressList addrlist;
8141 TestCompletionCallback callback;
8142 int rv = session_deps_.host_resolver->Resolve(
8143 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8144 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8145 EXPECT_EQ(ERR_IO_PENDING, rv);
8146 rv = callback.WaitForResult();
8147 EXPECT_EQ(OK, rv);
8149 // Verify that it was added to host cache, by doing a subsequent async lookup
8150 // and confirming it completes synchronously.
8151 rv = session_deps_.host_resolver->Resolve(
8152 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8153 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8154 ASSERT_EQ(OK, rv);
8156 // Inject a failure the next time that "www.example.org" is resolved. This way
8157 // we can tell if the next lookup hit the cache, or the "network".
8158 // (cache --> success, "network" --> failure).
8159 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
8161 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8162 // first read -- this won't be reached as the host resolution will fail first.
8163 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
8164 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8165 session_deps_.socket_factory->AddSocketDataProvider(&data);
8167 // Run the request.
8168 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8169 ASSERT_EQ(ERR_IO_PENDING, rv);
8170 rv = callback.WaitForResult();
8172 // If we bypassed the cache, we would have gotten a failure while resolving
8173 // "www.example.org".
8174 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8177 // There are multiple load flags that should trigger the host cache bypass.
8178 // Test each in isolation:
8179 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
8180 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8183 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
8184 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8187 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
8188 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8191 // Make sure we can handle an error when writing the request.
8192 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
8193 HttpRequestInfo request;
8194 request.method = "GET";
8195 request.url = GURL("http://www.foo.com/");
8196 request.load_flags = 0;
8198 MockWrite write_failure[] = {
8199 MockWrite(ASYNC, ERR_CONNECTION_RESET),
8201 StaticSocketDataProvider data(NULL, 0,
8202 write_failure, arraysize(write_failure));
8203 session_deps_.socket_factory->AddSocketDataProvider(&data);
8204 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8206 TestCompletionCallback callback;
8208 scoped_ptr<HttpTransaction> trans(
8209 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8211 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8212 EXPECT_EQ(ERR_IO_PENDING, rv);
8214 rv = callback.WaitForResult();
8215 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
8218 // Check that a connection closed after the start of the headers finishes ok.
8219 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
8220 HttpRequestInfo request;
8221 request.method = "GET";
8222 request.url = GURL("http://www.foo.com/");
8223 request.load_flags = 0;
8225 MockRead data_reads[] = {
8226 MockRead("HTTP/1."),
8227 MockRead(SYNCHRONOUS, OK),
8230 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8231 session_deps_.socket_factory->AddSocketDataProvider(&data);
8232 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8234 TestCompletionCallback callback;
8236 scoped_ptr<HttpTransaction> trans(
8237 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8239 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8240 EXPECT_EQ(ERR_IO_PENDING, rv);
8242 rv = callback.WaitForResult();
8243 EXPECT_EQ(OK, rv);
8245 const HttpResponseInfo* response = trans->GetResponseInfo();
8246 ASSERT_TRUE(response != NULL);
8248 EXPECT_TRUE(response->headers.get() != NULL);
8249 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8251 std::string response_data;
8252 rv = ReadTransaction(trans.get(), &response_data);
8253 EXPECT_EQ(OK, rv);
8254 EXPECT_EQ("", response_data);
8257 // Make sure that a dropped connection while draining the body for auth
8258 // restart does the right thing.
8259 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
8260 HttpRequestInfo request;
8261 request.method = "GET";
8262 request.url = GURL("http://www.example.org/");
8263 request.load_flags = 0;
8265 MockWrite data_writes1[] = {
8266 MockWrite(
8267 "GET / HTTP/1.1\r\n"
8268 "Host: www.example.org\r\n"
8269 "Connection: keep-alive\r\n\r\n"),
8272 MockRead data_reads1[] = {
8273 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8274 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8275 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8276 MockRead("Content-Length: 14\r\n\r\n"),
8277 MockRead("Unauth"),
8278 MockRead(ASYNC, ERR_CONNECTION_RESET),
8281 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8282 data_writes1, arraysize(data_writes1));
8283 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8285 // After calling trans->RestartWithAuth(), this is the request we should
8286 // be issuing -- the final header line contains the credentials.
8287 MockWrite data_writes2[] = {
8288 MockWrite(
8289 "GET / HTTP/1.1\r\n"
8290 "Host: www.example.org\r\n"
8291 "Connection: keep-alive\r\n"
8292 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8295 // Lastly, the server responds with the actual content.
8296 MockRead data_reads2[] = {
8297 MockRead("HTTP/1.1 200 OK\r\n"),
8298 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8299 MockRead("Content-Length: 100\r\n\r\n"),
8300 MockRead(SYNCHRONOUS, OK),
8303 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8304 data_writes2, arraysize(data_writes2));
8305 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8306 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8308 TestCompletionCallback callback1;
8310 scoped_ptr<HttpTransaction> trans(
8311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8313 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8314 EXPECT_EQ(ERR_IO_PENDING, rv);
8316 rv = callback1.WaitForResult();
8317 EXPECT_EQ(OK, rv);
8319 const HttpResponseInfo* response = trans->GetResponseInfo();
8320 ASSERT_TRUE(response != NULL);
8321 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8323 TestCompletionCallback callback2;
8325 rv = trans->RestartWithAuth(
8326 AuthCredentials(kFoo, kBar), callback2.callback());
8327 EXPECT_EQ(ERR_IO_PENDING, rv);
8329 rv = callback2.WaitForResult();
8330 EXPECT_EQ(OK, rv);
8332 response = trans->GetResponseInfo();
8333 ASSERT_TRUE(response != NULL);
8334 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8335 EXPECT_EQ(100, response->headers->GetContentLength());
8338 // Test HTTPS connections going through a proxy that sends extra data.
8339 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8340 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8342 HttpRequestInfo request;
8343 request.method = "GET";
8344 request.url = GURL("https://www.example.org/");
8345 request.load_flags = 0;
8347 MockRead proxy_reads[] = {
8348 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8349 MockRead(SYNCHRONOUS, OK)
8352 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8353 SSLSocketDataProvider ssl(ASYNC, OK);
8355 session_deps_.socket_factory->AddSocketDataProvider(&data);
8356 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8358 TestCompletionCallback callback;
8360 session_deps_.socket_factory->ResetNextMockIndexes();
8362 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8363 scoped_ptr<HttpTransaction> trans(
8364 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8366 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8367 EXPECT_EQ(ERR_IO_PENDING, rv);
8369 rv = callback.WaitForResult();
8370 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8373 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8374 HttpRequestInfo request;
8375 request.method = "GET";
8376 request.url = GURL("http://www.example.org/");
8377 request.load_flags = 0;
8379 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8380 scoped_ptr<HttpTransaction> trans(
8381 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8383 MockRead data_reads[] = {
8384 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8385 MockRead(SYNCHRONOUS, OK),
8388 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8389 session_deps_.socket_factory->AddSocketDataProvider(&data);
8391 TestCompletionCallback callback;
8393 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8394 EXPECT_EQ(ERR_IO_PENDING, rv);
8396 EXPECT_EQ(OK, callback.WaitForResult());
8398 const HttpResponseInfo* response = trans->GetResponseInfo();
8399 ASSERT_TRUE(response != NULL);
8401 EXPECT_TRUE(response->headers.get() != NULL);
8402 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8404 std::string response_data;
8405 rv = ReadTransaction(trans.get(), &response_data);
8406 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8409 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8410 base::FilePath temp_file_path;
8411 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8412 const uint64 kFakeSize = 100000; // file is actually blank
8413 UploadFileElementReader::ScopedOverridingContentLengthForTests
8414 overriding_content_length(kFakeSize);
8416 ScopedVector<UploadElementReader> element_readers;
8417 element_readers.push_back(
8418 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8419 temp_file_path, 0, kuint64max, base::Time()));
8420 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8422 HttpRequestInfo request;
8423 request.method = "POST";
8424 request.url = GURL("http://www.example.org/upload");
8425 request.upload_data_stream = &upload_data_stream;
8426 request.load_flags = 0;
8428 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8429 scoped_ptr<HttpTransaction> trans(
8430 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8432 MockRead data_reads[] = {
8433 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8434 MockRead("hello world"),
8435 MockRead(SYNCHRONOUS, OK),
8437 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8438 session_deps_.socket_factory->AddSocketDataProvider(&data);
8440 TestCompletionCallback callback;
8442 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8443 EXPECT_EQ(ERR_IO_PENDING, rv);
8445 rv = callback.WaitForResult();
8446 EXPECT_EQ(OK, rv);
8448 const HttpResponseInfo* response = trans->GetResponseInfo();
8449 ASSERT_TRUE(response != NULL);
8451 EXPECT_TRUE(response->headers.get() != NULL);
8452 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8454 std::string response_data;
8455 rv = ReadTransaction(trans.get(), &response_data);
8456 EXPECT_EQ(OK, rv);
8457 EXPECT_EQ("hello world", response_data);
8459 base::DeleteFile(temp_file_path, false);
8462 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8463 base::FilePath temp_file;
8464 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8465 std::string temp_file_content("Unreadable file.");
8466 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8467 temp_file_content.length()));
8468 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
8470 ScopedVector<UploadElementReader> element_readers;
8471 element_readers.push_back(
8472 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8473 temp_file, 0, kuint64max, base::Time()));
8474 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8476 HttpRequestInfo request;
8477 request.method = "POST";
8478 request.url = GURL("http://www.example.org/upload");
8479 request.upload_data_stream = &upload_data_stream;
8480 request.load_flags = 0;
8482 // If we try to upload an unreadable file, the transaction should fail.
8483 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8484 scoped_ptr<HttpTransaction> trans(
8485 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8487 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8488 session_deps_.socket_factory->AddSocketDataProvider(&data);
8490 TestCompletionCallback callback;
8492 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8493 EXPECT_EQ(ERR_IO_PENDING, rv);
8495 rv = callback.WaitForResult();
8496 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8498 base::DeleteFile(temp_file, false);
8501 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8502 class FakeUploadElementReader : public UploadElementReader {
8503 public:
8504 FakeUploadElementReader() {}
8505 ~FakeUploadElementReader() override {}
8507 const CompletionCallback& callback() const { return callback_; }
8509 // UploadElementReader overrides:
8510 int Init(const CompletionCallback& callback) override {
8511 callback_ = callback;
8512 return ERR_IO_PENDING;
8514 uint64 GetContentLength() const override { return 0; }
8515 uint64 BytesRemaining() const override { return 0; }
8516 int Read(IOBuffer* buf,
8517 int buf_length,
8518 const CompletionCallback& callback) override {
8519 return ERR_FAILED;
8522 private:
8523 CompletionCallback callback_;
8526 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8527 ScopedVector<UploadElementReader> element_readers;
8528 element_readers.push_back(fake_reader);
8529 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8531 HttpRequestInfo request;
8532 request.method = "POST";
8533 request.url = GURL("http://www.example.org/upload");
8534 request.upload_data_stream = &upload_data_stream;
8535 request.load_flags = 0;
8537 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8538 scoped_ptr<HttpTransaction> trans(
8539 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8541 StaticSocketDataProvider data;
8542 session_deps_.socket_factory->AddSocketDataProvider(&data);
8544 TestCompletionCallback callback;
8545 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8546 EXPECT_EQ(ERR_IO_PENDING, rv);
8547 base::MessageLoop::current()->RunUntilIdle();
8549 // Transaction is pending on request body initialization.
8550 ASSERT_FALSE(fake_reader->callback().is_null());
8552 // Return Init()'s result after the transaction gets destroyed.
8553 trans.reset();
8554 fake_reader->callback().Run(OK); // Should not crash.
8557 // Tests that changes to Auth realms are treated like auth rejections.
8558 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8560 HttpRequestInfo request;
8561 request.method = "GET";
8562 request.url = GURL("http://www.example.org/");
8563 request.load_flags = 0;
8565 // First transaction will request a resource and receive a Basic challenge
8566 // with realm="first_realm".
8567 MockWrite data_writes1[] = {
8568 MockWrite(
8569 "GET / HTTP/1.1\r\n"
8570 "Host: www.example.org\r\n"
8571 "Connection: keep-alive\r\n"
8572 "\r\n"),
8574 MockRead data_reads1[] = {
8575 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8576 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8577 "\r\n"),
8580 // After calling trans->RestartWithAuth(), provide an Authentication header
8581 // for first_realm. The server will reject and provide a challenge with
8582 // second_realm.
8583 MockWrite data_writes2[] = {
8584 MockWrite(
8585 "GET / HTTP/1.1\r\n"
8586 "Host: www.example.org\r\n"
8587 "Connection: keep-alive\r\n"
8588 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8589 "\r\n"),
8591 MockRead data_reads2[] = {
8592 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8593 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8594 "\r\n"),
8597 // This again fails, and goes back to first_realm. Make sure that the
8598 // entry is removed from cache.
8599 MockWrite data_writes3[] = {
8600 MockWrite(
8601 "GET / HTTP/1.1\r\n"
8602 "Host: www.example.org\r\n"
8603 "Connection: keep-alive\r\n"
8604 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8605 "\r\n"),
8607 MockRead data_reads3[] = {
8608 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8609 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8610 "\r\n"),
8613 // Try one last time (with the correct password) and get the resource.
8614 MockWrite data_writes4[] = {
8615 MockWrite(
8616 "GET / HTTP/1.1\r\n"
8617 "Host: www.example.org\r\n"
8618 "Connection: keep-alive\r\n"
8619 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8620 "\r\n"),
8622 MockRead data_reads4[] = {
8623 MockRead("HTTP/1.1 200 OK\r\n"
8624 "Content-Type: text/html; charset=iso-8859-1\r\n"
8625 "Content-Length: 5\r\n"
8626 "\r\n"
8627 "hello"),
8630 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8631 data_writes1, arraysize(data_writes1));
8632 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8633 data_writes2, arraysize(data_writes2));
8634 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8635 data_writes3, arraysize(data_writes3));
8636 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8637 data_writes4, arraysize(data_writes4));
8638 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8639 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8640 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8641 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8643 TestCompletionCallback callback1;
8645 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8646 scoped_ptr<HttpTransaction> trans(
8647 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8649 // Issue the first request with Authorize headers. There should be a
8650 // password prompt for first_realm waiting to be filled in after the
8651 // transaction completes.
8652 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8653 EXPECT_EQ(ERR_IO_PENDING, rv);
8654 rv = callback1.WaitForResult();
8655 EXPECT_EQ(OK, rv);
8656 const HttpResponseInfo* response = trans->GetResponseInfo();
8657 ASSERT_TRUE(response != NULL);
8658 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8659 ASSERT_FALSE(challenge == NULL);
8660 EXPECT_FALSE(challenge->is_proxy);
8661 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8662 EXPECT_EQ("first_realm", challenge->realm);
8663 EXPECT_EQ("basic", challenge->scheme);
8665 // Issue the second request with an incorrect password. There should be a
8666 // password prompt for second_realm waiting to be filled in after the
8667 // transaction completes.
8668 TestCompletionCallback callback2;
8669 rv = trans->RestartWithAuth(
8670 AuthCredentials(kFirst, kBaz), callback2.callback());
8671 EXPECT_EQ(ERR_IO_PENDING, rv);
8672 rv = callback2.WaitForResult();
8673 EXPECT_EQ(OK, rv);
8674 response = trans->GetResponseInfo();
8675 ASSERT_TRUE(response != NULL);
8676 challenge = response->auth_challenge.get();
8677 ASSERT_FALSE(challenge == NULL);
8678 EXPECT_FALSE(challenge->is_proxy);
8679 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8680 EXPECT_EQ("second_realm", challenge->realm);
8681 EXPECT_EQ("basic", challenge->scheme);
8683 // Issue the third request with another incorrect password. There should be
8684 // a password prompt for first_realm waiting to be filled in. If the password
8685 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8686 // first_realm was not correctly removed.
8687 TestCompletionCallback callback3;
8688 rv = trans->RestartWithAuth(
8689 AuthCredentials(kSecond, kFou), callback3.callback());
8690 EXPECT_EQ(ERR_IO_PENDING, rv);
8691 rv = callback3.WaitForResult();
8692 EXPECT_EQ(OK, rv);
8693 response = trans->GetResponseInfo();
8694 ASSERT_TRUE(response != NULL);
8695 challenge = response->auth_challenge.get();
8696 ASSERT_FALSE(challenge == NULL);
8697 EXPECT_FALSE(challenge->is_proxy);
8698 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8699 EXPECT_EQ("first_realm", challenge->realm);
8700 EXPECT_EQ("basic", challenge->scheme);
8702 // Issue the fourth request with the correct password and username.
8703 TestCompletionCallback callback4;
8704 rv = trans->RestartWithAuth(
8705 AuthCredentials(kFirst, kBar), callback4.callback());
8706 EXPECT_EQ(ERR_IO_PENDING, rv);
8707 rv = callback4.WaitForResult();
8708 EXPECT_EQ(OK, rv);
8709 response = trans->GetResponseInfo();
8710 ASSERT_TRUE(response != NULL);
8711 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8714 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8715 session_deps_.next_protos = SpdyNextProtos();
8716 session_deps_.use_alternate_protocols = true;
8718 std::string alternate_protocol_http_header =
8719 GetAlternateProtocolHttpHeader();
8721 MockRead data_reads[] = {
8722 MockRead("HTTP/1.1 200 OK\r\n"),
8723 MockRead(alternate_protocol_http_header.c_str()),
8724 MockRead("hello world"),
8725 MockRead(SYNCHRONOUS, OK),
8728 HttpRequestInfo request;
8729 request.method = "GET";
8730 request.url = GURL("http://www.example.org/");
8731 request.load_flags = 0;
8733 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8735 session_deps_.socket_factory->AddSocketDataProvider(&data);
8737 TestCompletionCallback callback;
8739 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8740 scoped_ptr<HttpTransaction> trans(
8741 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8743 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8744 EXPECT_EQ(ERR_IO_PENDING, rv);
8746 HostPortPair http_host_port_pair("www.example.org", 80);
8747 HttpServerProperties& http_server_properties =
8748 *session->http_server_properties();
8749 AlternativeServiceVector alternative_service_vector =
8750 http_server_properties.GetAlternativeServices(http_host_port_pair);
8751 EXPECT_TRUE(alternative_service_vector.empty());
8753 EXPECT_EQ(OK, callback.WaitForResult());
8755 const HttpResponseInfo* response = trans->GetResponseInfo();
8756 ASSERT_TRUE(response != NULL);
8757 ASSERT_TRUE(response->headers.get() != NULL);
8758 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8759 EXPECT_FALSE(response->was_fetched_via_spdy);
8760 EXPECT_FALSE(response->was_npn_negotiated);
8762 std::string response_data;
8763 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8764 EXPECT_EQ("hello world", response_data);
8766 alternative_service_vector =
8767 http_server_properties.GetAlternativeServices(http_host_port_pair);
8768 ASSERT_EQ(1u, alternative_service_vector.size());
8769 EXPECT_EQ(443, alternative_service_vector[0].port);
8770 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8771 alternative_service_vector[0].protocol);
8774 TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
8775 session_deps_.next_protos = SpdyNextProtos();
8776 session_deps_.use_alternate_protocols = true;
8778 MockRead data_reads[] = {
8779 MockRead("HTTP/1.1 200 OK\r\n"),
8780 MockRead("Alternate-Protocol: \r\n\r\n"),
8781 MockRead("hello world"),
8782 MockRead(SYNCHRONOUS, OK),
8785 HttpRequestInfo request;
8786 request.method = "GET";
8787 request.url = GURL("http://www.example.org/");
8788 request.load_flags = 0;
8790 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8792 session_deps_.socket_factory->AddSocketDataProvider(&data);
8794 TestCompletionCallback callback;
8796 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8798 HostPortPair http_host_port_pair("www.example.org", 80);
8799 HttpServerProperties& http_server_properties =
8800 *session->http_server_properties();
8801 AlternativeService alternative_service(QUIC, "", 80);
8802 http_server_properties.SetAlternativeService(http_host_port_pair,
8803 alternative_service, 1.0);
8805 AlternativeServiceVector alternative_service_vector =
8806 http_server_properties.GetAlternativeServices(http_host_port_pair);
8807 ASSERT_EQ(1u, alternative_service_vector.size());
8808 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
8810 scoped_ptr<HttpTransaction> trans(
8811 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8813 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8814 EXPECT_EQ(ERR_IO_PENDING, rv);
8816 EXPECT_EQ(OK, callback.WaitForResult());
8818 const HttpResponseInfo* response = trans->GetResponseInfo();
8819 ASSERT_TRUE(response != NULL);
8820 ASSERT_TRUE(response->headers.get() != NULL);
8821 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8822 EXPECT_FALSE(response->was_fetched_via_spdy);
8823 EXPECT_FALSE(response->was_npn_negotiated);
8825 std::string response_data;
8826 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8827 EXPECT_EQ("hello world", response_data);
8829 alternative_service_vector =
8830 http_server_properties.GetAlternativeServices(http_host_port_pair);
8831 EXPECT_TRUE(alternative_service_vector.empty());
8834 TEST_P(HttpNetworkTransactionTest,
8835 MarkBrokenAlternateProtocolAndFallback) {
8836 session_deps_.use_alternate_protocols = true;
8838 HttpRequestInfo request;
8839 request.method = "GET";
8840 request.url = GURL("http://www.example.org/");
8841 request.load_flags = 0;
8843 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8844 StaticSocketDataProvider first_data;
8845 first_data.set_connect_data(mock_connect);
8846 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8848 MockRead data_reads[] = {
8849 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8850 MockRead("hello world"),
8851 MockRead(ASYNC, OK),
8853 StaticSocketDataProvider second_data(
8854 data_reads, arraysize(data_reads), NULL, 0);
8855 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8857 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8859 base::WeakPtr<HttpServerProperties> http_server_properties =
8860 session->http_server_properties();
8861 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
8862 // Port must be < 1024, or the header will be ignored (since initial port was
8863 // port 80 (another restricted port).
8864 const AlternativeService alternative_service(
8865 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8866 666); // Port is ignored by MockConnect anyway.
8867 http_server_properties->SetAlternativeService(host_port_pair,
8868 alternative_service, 1.0);
8870 scoped_ptr<HttpTransaction> trans(
8871 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8872 TestCompletionCallback callback;
8874 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8875 EXPECT_EQ(ERR_IO_PENDING, rv);
8876 EXPECT_EQ(OK, callback.WaitForResult());
8878 const HttpResponseInfo* response = trans->GetResponseInfo();
8879 ASSERT_TRUE(response != NULL);
8880 ASSERT_TRUE(response->headers.get() != NULL);
8881 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8883 std::string response_data;
8884 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8885 EXPECT_EQ("hello world", response_data);
8887 const AlternativeServiceVector alternative_service_vector =
8888 http_server_properties->GetAlternativeServices(host_port_pair);
8889 ASSERT_EQ(1u, alternative_service_vector.size());
8890 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
8891 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
8892 alternative_service_vector[0]));
8895 TEST_P(HttpNetworkTransactionTest,
8896 AlternateProtocolPortRestrictedBlocked) {
8897 // Ensure that we're not allowed to redirect traffic via an alternate
8898 // protocol to an unrestricted (port >= 1024) when the original traffic was
8899 // on a restricted port (port < 1024). Ensure that we can redirect in all
8900 // other cases.
8901 session_deps_.use_alternate_protocols = true;
8903 HttpRequestInfo restricted_port_request;
8904 restricted_port_request.method = "GET";
8905 restricted_port_request.url = GURL("http://www.example.org:1023/");
8906 restricted_port_request.load_flags = 0;
8908 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8909 StaticSocketDataProvider first_data;
8910 first_data.set_connect_data(mock_connect);
8911 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8913 MockRead data_reads[] = {
8914 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8915 MockRead("hello world"),
8916 MockRead(ASYNC, OK),
8918 StaticSocketDataProvider second_data(
8919 data_reads, arraysize(data_reads), NULL, 0);
8920 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8922 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8924 base::WeakPtr<HttpServerProperties> http_server_properties =
8925 session->http_server_properties();
8926 const int kUnrestrictedAlternatePort = 1024;
8927 AlternativeService alternative_service(
8928 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8929 kUnrestrictedAlternatePort);
8930 http_server_properties->SetAlternativeService(
8931 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
8932 1.0);
8934 scoped_ptr<HttpTransaction> trans(
8935 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8936 TestCompletionCallback callback;
8938 int rv = trans->Start(
8939 &restricted_port_request,
8940 callback.callback(), BoundNetLog());
8941 EXPECT_EQ(ERR_IO_PENDING, rv);
8942 // Invalid change to unrestricted port should fail.
8943 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8946 TEST_P(HttpNetworkTransactionTest,
8947 AlternateProtocolPortRestrictedPermitted) {
8948 // Ensure that we're allowed to redirect traffic via an alternate
8949 // protocol to an unrestricted (port >= 1024) when the original traffic was
8950 // on a restricted port (port < 1024) if we set
8951 // enable_user_alternate_protocol_ports.
8953 session_deps_.use_alternate_protocols = true;
8954 session_deps_.enable_user_alternate_protocol_ports = true;
8956 HttpRequestInfo restricted_port_request;
8957 restricted_port_request.method = "GET";
8958 restricted_port_request.url = GURL("http://www.example.org:1023/");
8959 restricted_port_request.load_flags = 0;
8961 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8962 StaticSocketDataProvider first_data;
8963 first_data.set_connect_data(mock_connect);
8964 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8966 MockRead data_reads[] = {
8967 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8968 MockRead("hello world"),
8969 MockRead(ASYNC, OK),
8971 StaticSocketDataProvider second_data(
8972 data_reads, arraysize(data_reads), NULL, 0);
8973 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8975 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8977 base::WeakPtr<HttpServerProperties> http_server_properties =
8978 session->http_server_properties();
8979 const int kUnrestrictedAlternatePort = 1024;
8980 AlternativeService alternative_service(
8981 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8982 kUnrestrictedAlternatePort);
8983 http_server_properties->SetAlternativeService(
8984 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
8985 1.0);
8987 scoped_ptr<HttpTransaction> trans(
8988 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8989 TestCompletionCallback callback;
8991 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8992 &restricted_port_request,
8993 callback.callback(), BoundNetLog()));
8994 // Change to unrestricted port should succeed.
8995 EXPECT_EQ(OK, callback.WaitForResult());
8998 TEST_P(HttpNetworkTransactionTest,
8999 AlternateProtocolPortRestrictedAllowed) {
9000 // Ensure that we're not allowed to redirect traffic via an alternate
9001 // protocol to an unrestricted (port >= 1024) when the original traffic was
9002 // on a restricted port (port < 1024). Ensure that we can redirect in all
9003 // other cases.
9004 session_deps_.use_alternate_protocols = true;
9006 HttpRequestInfo restricted_port_request;
9007 restricted_port_request.method = "GET";
9008 restricted_port_request.url = GURL("http://www.example.org:1023/");
9009 restricted_port_request.load_flags = 0;
9011 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9012 StaticSocketDataProvider first_data;
9013 first_data.set_connect_data(mock_connect);
9014 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9016 MockRead data_reads[] = {
9017 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9018 MockRead("hello world"),
9019 MockRead(ASYNC, OK),
9021 StaticSocketDataProvider second_data(
9022 data_reads, arraysize(data_reads), NULL, 0);
9023 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9025 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9027 base::WeakPtr<HttpServerProperties> http_server_properties =
9028 session->http_server_properties();
9029 const int kRestrictedAlternatePort = 80;
9030 AlternativeService alternative_service(
9031 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9032 kRestrictedAlternatePort);
9033 http_server_properties->SetAlternativeService(
9034 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9035 1.0);
9037 scoped_ptr<HttpTransaction> trans(
9038 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9039 TestCompletionCallback callback;
9041 int rv = trans->Start(
9042 &restricted_port_request,
9043 callback.callback(), BoundNetLog());
9044 EXPECT_EQ(ERR_IO_PENDING, rv);
9045 // Valid change to restricted port should pass.
9046 EXPECT_EQ(OK, callback.WaitForResult());
9049 TEST_P(HttpNetworkTransactionTest,
9050 AlternateProtocolPortUnrestrictedAllowed1) {
9051 // Ensure that we're not allowed to redirect traffic via an alternate
9052 // protocol to an unrestricted (port >= 1024) when the original traffic was
9053 // on a restricted port (port < 1024). Ensure that we can redirect in all
9054 // other cases.
9055 session_deps_.use_alternate_protocols = true;
9057 HttpRequestInfo unrestricted_port_request;
9058 unrestricted_port_request.method = "GET";
9059 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9060 unrestricted_port_request.load_flags = 0;
9062 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9063 StaticSocketDataProvider first_data;
9064 first_data.set_connect_data(mock_connect);
9065 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9067 MockRead data_reads[] = {
9068 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9069 MockRead("hello world"),
9070 MockRead(ASYNC, OK),
9072 StaticSocketDataProvider second_data(
9073 data_reads, arraysize(data_reads), NULL, 0);
9074 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9076 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9078 base::WeakPtr<HttpServerProperties> http_server_properties =
9079 session->http_server_properties();
9080 const int kRestrictedAlternatePort = 80;
9081 AlternativeService alternative_service(
9082 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9083 kRestrictedAlternatePort);
9084 http_server_properties->SetAlternativeService(
9085 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9086 1.0);
9088 scoped_ptr<HttpTransaction> trans(
9089 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9090 TestCompletionCallback callback;
9092 int rv = trans->Start(
9093 &unrestricted_port_request, callback.callback(), BoundNetLog());
9094 EXPECT_EQ(ERR_IO_PENDING, rv);
9095 // Valid change to restricted port should pass.
9096 EXPECT_EQ(OK, callback.WaitForResult());
9099 TEST_P(HttpNetworkTransactionTest,
9100 AlternateProtocolPortUnrestrictedAllowed2) {
9101 // Ensure that we're not allowed to redirect traffic via an alternate
9102 // protocol to an unrestricted (port >= 1024) when the original traffic was
9103 // on a restricted port (port < 1024). Ensure that we can redirect in all
9104 // other cases.
9105 session_deps_.use_alternate_protocols = true;
9107 HttpRequestInfo unrestricted_port_request;
9108 unrestricted_port_request.method = "GET";
9109 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9110 unrestricted_port_request.load_flags = 0;
9112 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9113 StaticSocketDataProvider first_data;
9114 first_data.set_connect_data(mock_connect);
9115 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9117 MockRead data_reads[] = {
9118 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9119 MockRead("hello world"),
9120 MockRead(ASYNC, OK),
9122 StaticSocketDataProvider second_data(
9123 data_reads, arraysize(data_reads), NULL, 0);
9124 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9126 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9128 base::WeakPtr<HttpServerProperties> http_server_properties =
9129 session->http_server_properties();
9130 const int kUnrestrictedAlternatePort = 1025;
9131 AlternativeService alternative_service(
9132 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9133 kUnrestrictedAlternatePort);
9134 http_server_properties->SetAlternativeService(
9135 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9136 1.0);
9138 scoped_ptr<HttpTransaction> trans(
9139 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9140 TestCompletionCallback callback;
9142 int rv = trans->Start(
9143 &unrestricted_port_request, callback.callback(), BoundNetLog());
9144 EXPECT_EQ(ERR_IO_PENDING, rv);
9145 // Valid change to an unrestricted port should pass.
9146 EXPECT_EQ(OK, callback.WaitForResult());
9149 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
9150 // Ensure that we're not allowed to redirect traffic via an alternate
9151 // protocol to an unsafe port, and that we resume the second
9152 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9153 session_deps_.use_alternate_protocols = true;
9155 HttpRequestInfo request;
9156 request.method = "GET";
9157 request.url = GURL("http://www.example.org/");
9158 request.load_flags = 0;
9160 // The alternate protocol request will error out before we attempt to connect,
9161 // so only the standard HTTP request will try to connect.
9162 MockRead data_reads[] = {
9163 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9164 MockRead("hello world"),
9165 MockRead(ASYNC, OK),
9167 StaticSocketDataProvider data(
9168 data_reads, arraysize(data_reads), NULL, 0);
9169 session_deps_.socket_factory->AddSocketDataProvider(&data);
9171 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9173 base::WeakPtr<HttpServerProperties> http_server_properties =
9174 session->http_server_properties();
9175 const int kUnsafePort = 7;
9176 AlternativeService alternative_service(
9177 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9178 kUnsafePort);
9179 http_server_properties->SetAlternativeService(
9180 HostPortPair::FromURL(request.url), alternative_service, 1.0);
9182 scoped_ptr<HttpTransaction> trans(
9183 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9184 TestCompletionCallback callback;
9186 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9187 EXPECT_EQ(ERR_IO_PENDING, rv);
9188 // The HTTP request should succeed.
9189 EXPECT_EQ(OK, callback.WaitForResult());
9191 // Disable alternate protocol before the asserts.
9192 // HttpStreamFactory::set_use_alternate_protocols(false);
9194 const HttpResponseInfo* response = trans->GetResponseInfo();
9195 ASSERT_TRUE(response != NULL);
9196 ASSERT_TRUE(response->headers.get() != NULL);
9197 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9199 std::string response_data;
9200 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9201 EXPECT_EQ("hello world", response_data);
9204 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
9205 session_deps_.use_alternate_protocols = true;
9206 session_deps_.next_protos = SpdyNextProtos();
9208 HttpRequestInfo request;
9209 request.method = "GET";
9210 request.url = GURL("http://www.example.org/");
9211 request.load_flags = 0;
9213 std::string alternate_protocol_http_header =
9214 GetAlternateProtocolHttpHeader();
9216 MockRead data_reads[] = {
9217 MockRead("HTTP/1.1 200 OK\r\n"),
9218 MockRead(alternate_protocol_http_header.c_str()),
9219 MockRead("hello world"),
9220 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9221 MockRead(ASYNC, OK)
9224 StaticSocketDataProvider first_transaction(
9225 data_reads, arraysize(data_reads), NULL, 0);
9226 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9228 SSLSocketDataProvider ssl(ASYNC, OK);
9229 ssl.SetNextProto(GetParam());
9230 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9231 ASSERT_TRUE(ssl.cert.get());
9232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9234 scoped_ptr<SpdyFrame> req(
9235 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9236 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9238 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9239 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9240 MockRead spdy_reads[] = {
9241 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9244 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9245 arraysize(spdy_writes));
9246 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9248 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9249 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9250 NULL, 0, NULL, 0);
9251 hanging_non_alternate_protocol_socket.set_connect_data(
9252 never_finishing_connect);
9253 session_deps_.socket_factory->AddSocketDataProvider(
9254 &hanging_non_alternate_protocol_socket);
9256 TestCompletionCallback callback;
9258 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9259 scoped_ptr<HttpTransaction> trans(
9260 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9262 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9263 EXPECT_EQ(ERR_IO_PENDING, rv);
9264 EXPECT_EQ(OK, callback.WaitForResult());
9266 const HttpResponseInfo* response = trans->GetResponseInfo();
9267 ASSERT_TRUE(response != NULL);
9268 ASSERT_TRUE(response->headers.get() != NULL);
9269 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9271 std::string response_data;
9272 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9273 EXPECT_EQ("hello world", response_data);
9275 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9277 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9278 EXPECT_EQ(ERR_IO_PENDING, rv);
9279 EXPECT_EQ(OK, callback.WaitForResult());
9281 response = trans->GetResponseInfo();
9282 ASSERT_TRUE(response != NULL);
9283 ASSERT_TRUE(response->headers.get() != NULL);
9284 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9285 EXPECT_TRUE(response->was_fetched_via_spdy);
9286 EXPECT_TRUE(response->was_npn_negotiated);
9288 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9289 EXPECT_EQ("hello!", response_data);
9292 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
9293 session_deps_.use_alternate_protocols = true;
9294 session_deps_.next_protos = SpdyNextProtos();
9296 HttpRequestInfo request;
9297 request.method = "GET";
9298 request.url = GURL("http://www.example.org/");
9299 request.load_flags = 0;
9301 std::string alternate_protocol_http_header =
9302 GetAlternateProtocolHttpHeader();
9304 MockRead data_reads[] = {
9305 MockRead("HTTP/1.1 200 OK\r\n"),
9306 MockRead(alternate_protocol_http_header.c_str()),
9307 MockRead("hello world"),
9308 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9309 MockRead(ASYNC, OK),
9312 StaticSocketDataProvider first_transaction(
9313 data_reads, arraysize(data_reads), NULL, 0);
9314 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9315 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9317 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9318 StaticSocketDataProvider hanging_socket(
9319 NULL, 0, NULL, 0);
9320 hanging_socket.set_connect_data(never_finishing_connect);
9321 // Socket 2 and 3 are the hanging Alternate-Protocol and
9322 // non-Alternate-Protocol jobs from the 2nd transaction.
9323 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9324 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9326 SSLSocketDataProvider ssl(ASYNC, OK);
9327 ssl.SetNextProto(GetParam());
9328 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9329 ASSERT_TRUE(ssl.cert.get());
9330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9332 scoped_ptr<SpdyFrame> req1(
9333 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9334 scoped_ptr<SpdyFrame> req2(
9335 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9336 MockWrite spdy_writes[] = {
9337 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
9339 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9340 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
9341 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9342 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9343 MockRead spdy_reads[] = {
9344 CreateMockRead(*resp1, 2),
9345 CreateMockRead(*data1, 3),
9346 CreateMockRead(*resp2, 4),
9347 CreateMockRead(*data2, 5),
9348 MockRead(ASYNC, 0, 6),
9351 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9352 arraysize(spdy_writes));
9353 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9354 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9356 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9357 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9359 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9360 TestCompletionCallback callback1;
9361 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9363 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
9364 EXPECT_EQ(ERR_IO_PENDING, rv);
9365 EXPECT_EQ(OK, callback1.WaitForResult());
9367 const HttpResponseInfo* response = trans1.GetResponseInfo();
9368 ASSERT_TRUE(response != NULL);
9369 ASSERT_TRUE(response->headers.get() != NULL);
9370 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9372 std::string response_data;
9373 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9374 EXPECT_EQ("hello world", response_data);
9376 TestCompletionCallback callback2;
9377 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9378 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
9379 EXPECT_EQ(ERR_IO_PENDING, rv);
9381 TestCompletionCallback callback3;
9382 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
9383 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
9384 EXPECT_EQ(ERR_IO_PENDING, rv);
9386 EXPECT_EQ(OK, callback2.WaitForResult());
9387 EXPECT_EQ(OK, callback3.WaitForResult());
9389 response = trans2.GetResponseInfo();
9390 ASSERT_TRUE(response != NULL);
9391 ASSERT_TRUE(response->headers.get() != NULL);
9392 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9393 EXPECT_TRUE(response->was_fetched_via_spdy);
9394 EXPECT_TRUE(response->was_npn_negotiated);
9395 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9396 EXPECT_EQ("hello!", response_data);
9398 response = trans3.GetResponseInfo();
9399 ASSERT_TRUE(response != NULL);
9400 ASSERT_TRUE(response->headers.get() != NULL);
9401 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9402 EXPECT_TRUE(response->was_fetched_via_spdy);
9403 EXPECT_TRUE(response->was_npn_negotiated);
9404 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9405 EXPECT_EQ("hello!", response_data);
9408 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9409 session_deps_.use_alternate_protocols = true;
9410 session_deps_.next_protos = SpdyNextProtos();
9412 HttpRequestInfo request;
9413 request.method = "GET";
9414 request.url = GURL("http://www.example.org/");
9415 request.load_flags = 0;
9417 std::string alternate_protocol_http_header =
9418 GetAlternateProtocolHttpHeader();
9420 MockRead data_reads[] = {
9421 MockRead("HTTP/1.1 200 OK\r\n"),
9422 MockRead(alternate_protocol_http_header.c_str()),
9423 MockRead("hello world"),
9424 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9425 MockRead(ASYNC, OK),
9428 StaticSocketDataProvider first_transaction(
9429 data_reads, arraysize(data_reads), NULL, 0);
9430 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9432 SSLSocketDataProvider ssl(ASYNC, OK);
9433 ssl.SetNextProto(GetParam());
9434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9436 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9437 StaticSocketDataProvider hanging_alternate_protocol_socket(
9438 NULL, 0, NULL, 0);
9439 hanging_alternate_protocol_socket.set_connect_data(
9440 never_finishing_connect);
9441 session_deps_.socket_factory->AddSocketDataProvider(
9442 &hanging_alternate_protocol_socket);
9444 // 2nd request is just a copy of the first one, over HTTP again.
9445 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9447 TestCompletionCallback callback;
9449 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9450 scoped_ptr<HttpTransaction> trans(
9451 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9453 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9454 EXPECT_EQ(ERR_IO_PENDING, rv);
9455 EXPECT_EQ(OK, callback.WaitForResult());
9457 const HttpResponseInfo* response = trans->GetResponseInfo();
9458 ASSERT_TRUE(response != NULL);
9459 ASSERT_TRUE(response->headers.get() != NULL);
9460 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9462 std::string response_data;
9463 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9464 EXPECT_EQ("hello world", response_data);
9466 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9468 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9469 EXPECT_EQ(ERR_IO_PENDING, rv);
9470 EXPECT_EQ(OK, callback.WaitForResult());
9472 response = trans->GetResponseInfo();
9473 ASSERT_TRUE(response != NULL);
9474 ASSERT_TRUE(response->headers.get() != NULL);
9475 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9476 EXPECT_FALSE(response->was_fetched_via_spdy);
9477 EXPECT_FALSE(response->was_npn_negotiated);
9479 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9480 EXPECT_EQ("hello world", response_data);
9483 class CapturingProxyResolver : public ProxyResolver {
9484 public:
9485 CapturingProxyResolver() {}
9486 ~CapturingProxyResolver() override {}
9488 int GetProxyForURL(const GURL& url,
9489 ProxyInfo* results,
9490 const CompletionCallback& callback,
9491 RequestHandle* request,
9492 const BoundNetLog& net_log) override {
9493 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9494 HostPortPair("myproxy", 80));
9495 results->UseProxyServer(proxy_server);
9496 resolved_.push_back(url);
9497 return OK;
9500 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
9502 LoadState GetLoadState(RequestHandle request) const override {
9503 NOTREACHED();
9504 return LOAD_STATE_IDLE;
9507 const std::vector<GURL>& resolved() const { return resolved_; }
9509 private:
9510 std::vector<GURL> resolved_;
9512 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9515 class CapturingProxyResolverFactory : public ProxyResolverFactory {
9516 public:
9517 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
9518 : ProxyResolverFactory(false), resolver_(resolver) {}
9520 int CreateProxyResolver(
9521 const scoped_refptr<ProxyResolverScriptData>& pac_script,
9522 scoped_ptr<ProxyResolver>* resolver,
9523 const net::CompletionCallback& callback,
9524 scoped_ptr<Request>* request) override {
9525 resolver->reset(new ForwardingProxyResolver(resolver_));
9526 return OK;
9529 private:
9530 ProxyResolver* resolver_;
9533 TEST_P(HttpNetworkTransactionTest,
9534 UseAlternateProtocolForTunneledNpnSpdy) {
9535 session_deps_.use_alternate_protocols = true;
9536 session_deps_.next_protos = SpdyNextProtos();
9538 ProxyConfig proxy_config;
9539 proxy_config.set_auto_detect(true);
9540 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9542 CapturingProxyResolver capturing_proxy_resolver;
9543 session_deps_.proxy_service.reset(new ProxyService(
9544 new ProxyConfigServiceFixed(proxy_config),
9545 make_scoped_ptr(
9546 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
9547 NULL));
9548 TestNetLog net_log;
9549 session_deps_.net_log = &net_log;
9551 HttpRequestInfo request;
9552 request.method = "GET";
9553 request.url = GURL("http://www.example.org/");
9554 request.load_flags = 0;
9556 std::string alternate_protocol_http_header =
9557 GetAlternateProtocolHttpHeader();
9559 MockRead data_reads[] = {
9560 MockRead("HTTP/1.1 200 OK\r\n"),
9561 MockRead(alternate_protocol_http_header.c_str()),
9562 MockRead("hello world"),
9563 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9564 MockRead(ASYNC, OK),
9567 StaticSocketDataProvider first_transaction(
9568 data_reads, arraysize(data_reads), NULL, 0);
9569 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9571 SSLSocketDataProvider ssl(ASYNC, OK);
9572 ssl.SetNextProto(GetParam());
9573 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9574 ASSERT_TRUE(ssl.cert.get());
9575 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9577 scoped_ptr<SpdyFrame> req(
9578 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9579 MockWrite spdy_writes[] = {
9580 MockWrite(ASYNC, 0,
9581 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9582 "Host: www.example.org\r\n"
9583 "Proxy-Connection: keep-alive\r\n\r\n"),
9584 CreateMockWrite(*req, 2),
9587 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9589 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9590 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9591 MockRead spdy_reads[] = {
9592 MockRead(ASYNC, 1, kCONNECTResponse),
9593 CreateMockRead(*resp.get(), 3),
9594 CreateMockRead(*data.get(), 4),
9595 MockRead(ASYNC, ERR_IO_PENDING, 5),
9598 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9599 arraysize(spdy_writes));
9600 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9602 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9603 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9604 NULL, 0, NULL, 0);
9605 hanging_non_alternate_protocol_socket.set_connect_data(
9606 never_finishing_connect);
9607 session_deps_.socket_factory->AddSocketDataProvider(
9608 &hanging_non_alternate_protocol_socket);
9610 TestCompletionCallback callback;
9612 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9613 scoped_ptr<HttpTransaction> trans(
9614 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9616 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9617 EXPECT_EQ(ERR_IO_PENDING, rv);
9618 EXPECT_EQ(OK, callback.WaitForResult());
9620 const HttpResponseInfo* response = trans->GetResponseInfo();
9621 ASSERT_TRUE(response != NULL);
9622 ASSERT_TRUE(response->headers.get() != NULL);
9623 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9624 EXPECT_FALSE(response->was_fetched_via_spdy);
9625 EXPECT_FALSE(response->was_npn_negotiated);
9627 std::string response_data;
9628 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9629 EXPECT_EQ("hello world", response_data);
9631 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9633 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9634 EXPECT_EQ(ERR_IO_PENDING, rv);
9635 EXPECT_EQ(OK, callback.WaitForResult());
9637 response = trans->GetResponseInfo();
9638 ASSERT_TRUE(response != NULL);
9639 ASSERT_TRUE(response->headers.get() != NULL);
9640 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9641 EXPECT_TRUE(response->was_fetched_via_spdy);
9642 EXPECT_TRUE(response->was_npn_negotiated);
9644 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9645 EXPECT_EQ("hello!", response_data);
9646 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
9647 EXPECT_EQ("http://www.example.org/",
9648 capturing_proxy_resolver.resolved()[0].spec());
9649 EXPECT_EQ("https://www.example.org/",
9650 capturing_proxy_resolver.resolved()[1].spec());
9652 LoadTimingInfo load_timing_info;
9653 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9654 TestLoadTimingNotReusedWithPac(load_timing_info,
9655 CONNECT_TIMING_HAS_SSL_TIMES);
9658 TEST_P(HttpNetworkTransactionTest,
9659 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9660 session_deps_.use_alternate_protocols = true;
9661 session_deps_.next_protos = SpdyNextProtos();
9663 HttpRequestInfo request;
9664 request.method = "GET";
9665 request.url = GURL("http://www.example.org/");
9666 request.load_flags = 0;
9668 std::string alternate_protocol_http_header =
9669 GetAlternateProtocolHttpHeader();
9671 MockRead data_reads[] = {
9672 MockRead("HTTP/1.1 200 OK\r\n"),
9673 MockRead(alternate_protocol_http_header.c_str()),
9674 MockRead("hello world"),
9675 MockRead(ASYNC, OK),
9678 StaticSocketDataProvider first_transaction(
9679 data_reads, arraysize(data_reads), NULL, 0);
9680 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9682 SSLSocketDataProvider ssl(ASYNC, OK);
9683 ssl.SetNextProto(GetParam());
9684 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9685 ASSERT_TRUE(ssl.cert.get());
9686 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9688 scoped_ptr<SpdyFrame> req(
9689 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9690 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9692 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9693 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9694 MockRead spdy_reads[] = {
9695 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9698 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9699 arraysize(spdy_writes));
9700 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9702 TestCompletionCallback callback;
9704 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9706 scoped_ptr<HttpTransaction> trans(
9707 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9709 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9710 EXPECT_EQ(ERR_IO_PENDING, rv);
9711 EXPECT_EQ(OK, callback.WaitForResult());
9713 const HttpResponseInfo* response = trans->GetResponseInfo();
9714 ASSERT_TRUE(response != NULL);
9715 ASSERT_TRUE(response->headers.get() != NULL);
9716 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9718 std::string response_data;
9719 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9720 EXPECT_EQ("hello world", response_data);
9722 // Set up an initial SpdySession in the pool to reuse.
9723 HostPortPair host_port_pair("www.example.org", 443);
9724 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9725 PRIVACY_MODE_DISABLED);
9726 base::WeakPtr<SpdySession> spdy_session =
9727 CreateSecureSpdySession(session, key, BoundNetLog());
9729 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9731 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9732 EXPECT_EQ(ERR_IO_PENDING, rv);
9733 EXPECT_EQ(OK, callback.WaitForResult());
9735 response = trans->GetResponseInfo();
9736 ASSERT_TRUE(response != NULL);
9737 ASSERT_TRUE(response->headers.get() != NULL);
9738 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9739 EXPECT_TRUE(response->was_fetched_via_spdy);
9740 EXPECT_TRUE(response->was_npn_negotiated);
9742 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9743 EXPECT_EQ("hello!", response_data);
9746 // GenerateAuthToken is a mighty big test.
9747 // It tests all permutation of GenerateAuthToken behavior:
9748 // - Synchronous and Asynchronous completion.
9749 // - OK or error on completion.
9750 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9751 // - HTTP or HTTPS backend (to include proxy tunneling).
9752 // - Non-authenticating and authenticating backend.
9754 // In all, there are 44 reasonable permuations (for example, if there are
9755 // problems generating an auth token for an authenticating proxy, we don't
9756 // need to test all permutations of the backend server).
9758 // The test proceeds by going over each of the configuration cases, and
9759 // potentially running up to three rounds in each of the tests. The TestConfig
9760 // specifies both the configuration for the test as well as the expectations
9761 // for the results.
9762 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9763 static const char kServer[] = "http://www.example.com";
9764 static const char kSecureServer[] = "https://www.example.com";
9765 static const char kProxy[] = "myproxy:70";
9766 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9768 enum AuthTiming {
9769 AUTH_NONE,
9770 AUTH_SYNC,
9771 AUTH_ASYNC,
9774 const MockWrite kGet(
9775 "GET / HTTP/1.1\r\n"
9776 "Host: www.example.com\r\n"
9777 "Connection: keep-alive\r\n\r\n");
9778 const MockWrite kGetProxy(
9779 "GET http://www.example.com/ HTTP/1.1\r\n"
9780 "Host: www.example.com\r\n"
9781 "Proxy-Connection: keep-alive\r\n\r\n");
9782 const MockWrite kGetAuth(
9783 "GET / HTTP/1.1\r\n"
9784 "Host: www.example.com\r\n"
9785 "Connection: keep-alive\r\n"
9786 "Authorization: auth_token\r\n\r\n");
9787 const MockWrite kGetProxyAuth(
9788 "GET http://www.example.com/ HTTP/1.1\r\n"
9789 "Host: www.example.com\r\n"
9790 "Proxy-Connection: keep-alive\r\n"
9791 "Proxy-Authorization: auth_token\r\n\r\n");
9792 const MockWrite kGetAuthThroughProxy(
9793 "GET http://www.example.com/ HTTP/1.1\r\n"
9794 "Host: www.example.com\r\n"
9795 "Proxy-Connection: keep-alive\r\n"
9796 "Authorization: auth_token\r\n\r\n");
9797 const MockWrite kGetAuthWithProxyAuth(
9798 "GET http://www.example.com/ HTTP/1.1\r\n"
9799 "Host: www.example.com\r\n"
9800 "Proxy-Connection: keep-alive\r\n"
9801 "Proxy-Authorization: auth_token\r\n"
9802 "Authorization: auth_token\r\n\r\n");
9803 const MockWrite kConnect(
9804 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9805 "Host: www.example.com\r\n"
9806 "Proxy-Connection: keep-alive\r\n\r\n");
9807 const MockWrite kConnectProxyAuth(
9808 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9809 "Host: www.example.com\r\n"
9810 "Proxy-Connection: keep-alive\r\n"
9811 "Proxy-Authorization: auth_token\r\n\r\n");
9813 const MockRead kSuccess(
9814 "HTTP/1.1 200 OK\r\n"
9815 "Content-Type: text/html; charset=iso-8859-1\r\n"
9816 "Content-Length: 3\r\n\r\n"
9817 "Yes");
9818 const MockRead kFailure(
9819 "Should not be called.");
9820 const MockRead kServerChallenge(
9821 "HTTP/1.1 401 Unauthorized\r\n"
9822 "WWW-Authenticate: Mock realm=server\r\n"
9823 "Content-Type: text/html; charset=iso-8859-1\r\n"
9824 "Content-Length: 14\r\n\r\n"
9825 "Unauthorized\r\n");
9826 const MockRead kProxyChallenge(
9827 "HTTP/1.1 407 Unauthorized\r\n"
9828 "Proxy-Authenticate: Mock realm=proxy\r\n"
9829 "Proxy-Connection: close\r\n"
9830 "Content-Type: text/html; charset=iso-8859-1\r\n"
9831 "Content-Length: 14\r\n\r\n"
9832 "Unauthorized\r\n");
9833 const MockRead kProxyConnected(
9834 "HTTP/1.1 200 Connection Established\r\n\r\n");
9836 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9837 // no constructors, but the C++ compiler on Windows warns about
9838 // unspecified data in compound literals. So, moved to using constructors,
9839 // and TestRound's created with the default constructor should not be used.
9840 struct TestRound {
9841 TestRound()
9842 : expected_rv(ERR_UNEXPECTED),
9843 extra_write(NULL),
9844 extra_read(NULL) {
9846 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9847 int expected_rv_arg)
9848 : write(write_arg),
9849 read(read_arg),
9850 expected_rv(expected_rv_arg),
9851 extra_write(NULL),
9852 extra_read(NULL) {
9854 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9855 int expected_rv_arg, const MockWrite* extra_write_arg,
9856 const MockRead* extra_read_arg)
9857 : write(write_arg),
9858 read(read_arg),
9859 expected_rv(expected_rv_arg),
9860 extra_write(extra_write_arg),
9861 extra_read(extra_read_arg) {
9863 MockWrite write;
9864 MockRead read;
9865 int expected_rv;
9866 const MockWrite* extra_write;
9867 const MockRead* extra_read;
9870 static const int kNoSSL = 500;
9872 struct TestConfig {
9873 const char* const proxy_url;
9874 AuthTiming proxy_auth_timing;
9875 int proxy_auth_rv;
9876 const char* const server_url;
9877 AuthTiming server_auth_timing;
9878 int server_auth_rv;
9879 int num_auth_rounds;
9880 int first_ssl_round;
9881 TestRound rounds[3];
9882 } test_configs[] = {
9883 // Non-authenticating HTTP server with a direct connection.
9884 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9885 { TestRound(kGet, kSuccess, OK)}},
9886 // Authenticating HTTP server with a direct connection.
9887 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9888 { TestRound(kGet, kServerChallenge, OK),
9889 TestRound(kGetAuth, kSuccess, OK)}},
9890 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9891 { TestRound(kGet, kServerChallenge, OK),
9892 TestRound(kGetAuth, kFailure, kAuthErr)}},
9893 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9894 { TestRound(kGet, kServerChallenge, OK),
9895 TestRound(kGetAuth, kSuccess, OK)}},
9896 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9897 { TestRound(kGet, kServerChallenge, OK),
9898 TestRound(kGetAuth, kFailure, kAuthErr)}},
9899 // Non-authenticating HTTP server through a non-authenticating proxy.
9900 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9901 { TestRound(kGetProxy, kSuccess, OK)}},
9902 // Authenticating HTTP server through a non-authenticating proxy.
9903 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9904 { TestRound(kGetProxy, kServerChallenge, OK),
9905 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9906 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9907 { TestRound(kGetProxy, kServerChallenge, OK),
9908 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9909 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9910 { TestRound(kGetProxy, kServerChallenge, OK),
9911 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9912 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9913 { TestRound(kGetProxy, kServerChallenge, OK),
9914 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9915 // Non-authenticating HTTP server through an authenticating proxy.
9916 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9917 { TestRound(kGetProxy, kProxyChallenge, OK),
9918 TestRound(kGetProxyAuth, kSuccess, OK)}},
9919 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9920 { TestRound(kGetProxy, kProxyChallenge, OK),
9921 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9922 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9923 { TestRound(kGetProxy, kProxyChallenge, OK),
9924 TestRound(kGetProxyAuth, kSuccess, OK)}},
9925 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9926 { TestRound(kGetProxy, kProxyChallenge, OK),
9927 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9928 // Authenticating HTTP server through an authenticating proxy.
9929 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9930 { TestRound(kGetProxy, kProxyChallenge, OK),
9931 TestRound(kGetProxyAuth, kServerChallenge, OK),
9932 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9933 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9934 { TestRound(kGetProxy, kProxyChallenge, OK),
9935 TestRound(kGetProxyAuth, kServerChallenge, OK),
9936 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9937 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9938 { TestRound(kGetProxy, kProxyChallenge, OK),
9939 TestRound(kGetProxyAuth, kServerChallenge, OK),
9940 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9941 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9942 { TestRound(kGetProxy, kProxyChallenge, OK),
9943 TestRound(kGetProxyAuth, kServerChallenge, OK),
9944 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9945 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9946 { TestRound(kGetProxy, kProxyChallenge, OK),
9947 TestRound(kGetProxyAuth, kServerChallenge, OK),
9948 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9949 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9950 { TestRound(kGetProxy, kProxyChallenge, OK),
9951 TestRound(kGetProxyAuth, kServerChallenge, OK),
9952 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9953 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9954 { TestRound(kGetProxy, kProxyChallenge, OK),
9955 TestRound(kGetProxyAuth, kServerChallenge, OK),
9956 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9957 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9958 { TestRound(kGetProxy, kProxyChallenge, OK),
9959 TestRound(kGetProxyAuth, kServerChallenge, OK),
9960 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9961 // Non-authenticating HTTPS server with a direct connection.
9962 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9963 { TestRound(kGet, kSuccess, OK)}},
9964 // Authenticating HTTPS server with a direct connection.
9965 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9966 { TestRound(kGet, kServerChallenge, OK),
9967 TestRound(kGetAuth, kSuccess, OK)}},
9968 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9969 { TestRound(kGet, kServerChallenge, OK),
9970 TestRound(kGetAuth, kFailure, kAuthErr)}},
9971 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9972 { TestRound(kGet, kServerChallenge, OK),
9973 TestRound(kGetAuth, kSuccess, OK)}},
9974 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9975 { TestRound(kGet, kServerChallenge, OK),
9976 TestRound(kGetAuth, kFailure, kAuthErr)}},
9977 // Non-authenticating HTTPS server with a non-authenticating proxy.
9978 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9979 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9980 // Authenticating HTTPS server through a non-authenticating proxy.
9981 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9982 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9983 TestRound(kGetAuth, kSuccess, OK)}},
9984 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9985 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9986 TestRound(kGetAuth, kFailure, kAuthErr)}},
9987 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9988 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9989 TestRound(kGetAuth, kSuccess, OK)}},
9990 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9991 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9992 TestRound(kGetAuth, kFailure, kAuthErr)}},
9993 // Non-Authenticating HTTPS server through an authenticating proxy.
9994 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9995 { TestRound(kConnect, kProxyChallenge, OK),
9996 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9997 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9998 { TestRound(kConnect, kProxyChallenge, OK),
9999 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10000 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10001 { TestRound(kConnect, kProxyChallenge, OK),
10002 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10003 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10004 { TestRound(kConnect, kProxyChallenge, OK),
10005 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10006 // Authenticating HTTPS server through an authenticating proxy.
10007 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10008 { TestRound(kConnect, kProxyChallenge, OK),
10009 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10010 &kGet, &kServerChallenge),
10011 TestRound(kGetAuth, kSuccess, OK)}},
10012 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10013 { TestRound(kConnect, kProxyChallenge, OK),
10014 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10015 &kGet, &kServerChallenge),
10016 TestRound(kGetAuth, kFailure, kAuthErr)}},
10017 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10018 { TestRound(kConnect, kProxyChallenge, OK),
10019 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10020 &kGet, &kServerChallenge),
10021 TestRound(kGetAuth, kSuccess, OK)}},
10022 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10023 { TestRound(kConnect, kProxyChallenge, OK),
10024 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10025 &kGet, &kServerChallenge),
10026 TestRound(kGetAuth, kFailure, kAuthErr)}},
10027 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10028 { TestRound(kConnect, kProxyChallenge, OK),
10029 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10030 &kGet, &kServerChallenge),
10031 TestRound(kGetAuth, kSuccess, OK)}},
10032 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10033 { TestRound(kConnect, kProxyChallenge, OK),
10034 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10035 &kGet, &kServerChallenge),
10036 TestRound(kGetAuth, kFailure, kAuthErr)}},
10037 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10038 { TestRound(kConnect, kProxyChallenge, OK),
10039 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10040 &kGet, &kServerChallenge),
10041 TestRound(kGetAuth, kSuccess, OK)}},
10042 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10043 { TestRound(kConnect, kProxyChallenge, OK),
10044 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10045 &kGet, &kServerChallenge),
10046 TestRound(kGetAuth, kFailure, kAuthErr)}},
10049 for (size_t i = 0; i < arraysize(test_configs); ++i) {
10050 HttpAuthHandlerMock::Factory* auth_factory(
10051 new HttpAuthHandlerMock::Factory());
10052 session_deps_.http_auth_handler_factory.reset(auth_factory);
10053 const TestConfig& test_config = test_configs[i];
10055 // Set up authentication handlers as necessary.
10056 if (test_config.proxy_auth_timing != AUTH_NONE) {
10057 for (int n = 0; n < 2; n++) {
10058 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10059 std::string auth_challenge = "Mock realm=proxy";
10060 GURL origin(test_config.proxy_url);
10061 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10062 auth_challenge.end());
10063 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
10064 origin, BoundNetLog());
10065 auth_handler->SetGenerateExpectation(
10066 test_config.proxy_auth_timing == AUTH_ASYNC,
10067 test_config.proxy_auth_rv);
10068 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10071 if (test_config.server_auth_timing != AUTH_NONE) {
10072 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10073 std::string auth_challenge = "Mock realm=server";
10074 GURL origin(test_config.server_url);
10075 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10076 auth_challenge.end());
10077 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10078 origin, BoundNetLog());
10079 auth_handler->SetGenerateExpectation(
10080 test_config.server_auth_timing == AUTH_ASYNC,
10081 test_config.server_auth_rv);
10082 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10084 if (test_config.proxy_url) {
10085 session_deps_.proxy_service.reset(
10086 ProxyService::CreateFixed(test_config.proxy_url));
10087 } else {
10088 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10091 HttpRequestInfo request;
10092 request.method = "GET";
10093 request.url = GURL(test_config.server_url);
10094 request.load_flags = 0;
10096 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10097 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10099 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
10101 std::vector<std::vector<MockRead>> mock_reads(1);
10102 std::vector<std::vector<MockWrite>> mock_writes(1);
10103 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10104 const TestRound& read_write_round = test_config.rounds[round];
10106 // Set up expected reads and writes.
10107 mock_reads.back().push_back(read_write_round.read);
10108 mock_writes.back().push_back(read_write_round.write);
10110 // kProxyChallenge uses Proxy-Connection: close which means that the
10111 // socket is closed and a new one will be created for the next request.
10112 if (read_write_round.read.data == kProxyChallenge.data &&
10113 read_write_round.write.data != kConnect.data) {
10114 mock_reads.push_back(std::vector<MockRead>());
10115 mock_writes.push_back(std::vector<MockWrite>());
10118 if (read_write_round.extra_read) {
10119 mock_reads.back().push_back(*read_write_round.extra_read);
10121 if (read_write_round.extra_write) {
10122 mock_writes.back().push_back(*read_write_round.extra_write);
10125 // Add an SSL sequence if necessary.
10126 if (round >= test_config.first_ssl_round)
10127 session_deps_.socket_factory->AddSSLSocketDataProvider(
10128 &ssl_socket_data_provider);
10131 ScopedVector<StaticSocketDataProvider> data_providers;
10132 for (size_t i = 0; i < mock_reads.size(); ++i) {
10133 data_providers.push_back(new StaticSocketDataProvider(
10134 vector_as_array(&mock_reads[i]), mock_reads[i].size(),
10135 vector_as_array(&mock_writes[i]), mock_writes[i].size()));
10136 session_deps_.socket_factory->AddSocketDataProvider(
10137 data_providers.back());
10140 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10141 const TestRound& read_write_round = test_config.rounds[round];
10142 // Start or restart the transaction.
10143 TestCompletionCallback callback;
10144 int rv;
10145 if (round == 0) {
10146 rv = trans.Start(&request, callback.callback(), BoundNetLog());
10147 } else {
10148 rv = trans.RestartWithAuth(
10149 AuthCredentials(kFoo, kBar), callback.callback());
10151 if (rv == ERR_IO_PENDING)
10152 rv = callback.WaitForResult();
10154 // Compare results with expected data.
10155 EXPECT_EQ(read_write_round.expected_rv, rv);
10156 const HttpResponseInfo* response = trans.GetResponseInfo();
10157 if (read_write_round.expected_rv != OK) {
10158 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
10159 continue;
10161 if (round + 1 < test_config.num_auth_rounds) {
10162 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10163 } else {
10164 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10170 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
10171 // Do multi-round authentication and make sure it works correctly.
10172 HttpAuthHandlerMock::Factory* auth_factory(
10173 new HttpAuthHandlerMock::Factory());
10174 session_deps_.http_auth_handler_factory.reset(auth_factory);
10175 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10176 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
10177 session_deps_.host_resolver->set_synchronous_mode(true);
10179 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10180 auth_handler->set_connection_based(true);
10181 std::string auth_challenge = "Mock realm=server";
10182 GURL origin("http://www.example.com");
10183 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10184 auth_challenge.end());
10185 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10186 origin, BoundNetLog());
10187 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10189 int rv = OK;
10190 const HttpResponseInfo* response = NULL;
10191 HttpRequestInfo request;
10192 request.method = "GET";
10193 request.url = origin;
10194 request.load_flags = 0;
10196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10198 // Use a TCP Socket Pool with only one connection per group. This is used
10199 // to validate that the TCP socket is not released to the pool between
10200 // each round of multi-round authentication.
10201 HttpNetworkSessionPeer session_peer(session);
10202 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
10203 50, // Max sockets for pool
10204 1, // Max sockets per group
10205 session_deps_.host_resolver.get(),
10206 session_deps_.socket_factory.get(),
10207 session_deps_.net_log);
10208 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
10209 new MockClientSocketPoolManager);
10210 mock_pool_manager->SetTransportSocketPool(transport_pool);
10211 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
10213 scoped_ptr<HttpTransaction> trans(
10214 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10215 TestCompletionCallback callback;
10217 const MockWrite kGet(
10218 "GET / HTTP/1.1\r\n"
10219 "Host: www.example.com\r\n"
10220 "Connection: keep-alive\r\n\r\n");
10221 const MockWrite kGetAuth(
10222 "GET / HTTP/1.1\r\n"
10223 "Host: www.example.com\r\n"
10224 "Connection: keep-alive\r\n"
10225 "Authorization: auth_token\r\n\r\n");
10227 const MockRead kServerChallenge(
10228 "HTTP/1.1 401 Unauthorized\r\n"
10229 "WWW-Authenticate: Mock realm=server\r\n"
10230 "Content-Type: text/html; charset=iso-8859-1\r\n"
10231 "Content-Length: 14\r\n\r\n"
10232 "Unauthorized\r\n");
10233 const MockRead kSuccess(
10234 "HTTP/1.1 200 OK\r\n"
10235 "Content-Type: text/html; charset=iso-8859-1\r\n"
10236 "Content-Length: 3\r\n\r\n"
10237 "Yes");
10239 MockWrite writes[] = {
10240 // First round
10241 kGet,
10242 // Second round
10243 kGetAuth,
10244 // Third round
10245 kGetAuth,
10246 // Fourth round
10247 kGetAuth,
10248 // Competing request
10249 kGet,
10251 MockRead reads[] = {
10252 // First round
10253 kServerChallenge,
10254 // Second round
10255 kServerChallenge,
10256 // Third round
10257 kServerChallenge,
10258 // Fourth round
10259 kSuccess,
10260 // Competing response
10261 kSuccess,
10263 StaticSocketDataProvider data_provider(reads, arraysize(reads),
10264 writes, arraysize(writes));
10265 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10267 const char kSocketGroup[] = "www.example.com:80";
10269 // First round of authentication.
10270 auth_handler->SetGenerateExpectation(false, OK);
10271 rv = trans->Start(&request, callback.callback(), BoundNetLog());
10272 if (rv == ERR_IO_PENDING)
10273 rv = callback.WaitForResult();
10274 EXPECT_EQ(OK, rv);
10275 response = trans->GetResponseInfo();
10276 ASSERT_TRUE(response != NULL);
10277 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10278 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10280 // In between rounds, another request comes in for the same domain.
10281 // It should not be able to grab the TCP socket that trans has already
10282 // claimed.
10283 scoped_ptr<HttpTransaction> trans_compete(
10284 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10285 TestCompletionCallback callback_compete;
10286 rv = trans_compete->Start(
10287 &request, callback_compete.callback(), BoundNetLog());
10288 EXPECT_EQ(ERR_IO_PENDING, rv);
10289 // callback_compete.WaitForResult at this point would stall forever,
10290 // since the HttpNetworkTransaction does not release the request back to
10291 // the pool until after authentication completes.
10293 // Second round of authentication.
10294 auth_handler->SetGenerateExpectation(false, OK);
10295 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
10296 if (rv == ERR_IO_PENDING)
10297 rv = callback.WaitForResult();
10298 EXPECT_EQ(OK, rv);
10299 response = trans->GetResponseInfo();
10300 ASSERT_TRUE(response != NULL);
10301 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10302 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10304 // Third round of authentication.
10305 auth_handler->SetGenerateExpectation(false, OK);
10306 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10307 if (rv == ERR_IO_PENDING)
10308 rv = callback.WaitForResult();
10309 EXPECT_EQ(OK, rv);
10310 response = trans->GetResponseInfo();
10311 ASSERT_TRUE(response != NULL);
10312 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10313 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10315 // Fourth round of authentication, which completes successfully.
10316 auth_handler->SetGenerateExpectation(false, OK);
10317 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10318 if (rv == ERR_IO_PENDING)
10319 rv = callback.WaitForResult();
10320 EXPECT_EQ(OK, rv);
10321 response = trans->GetResponseInfo();
10322 ASSERT_TRUE(response != NULL);
10323 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10324 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10326 // Read the body since the fourth round was successful. This will also
10327 // release the socket back to the pool.
10328 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
10329 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10330 if (rv == ERR_IO_PENDING)
10331 rv = callback.WaitForResult();
10332 EXPECT_EQ(3, rv);
10333 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10334 EXPECT_EQ(0, rv);
10335 // There are still 0 idle sockets, since the trans_compete transaction
10336 // will be handed it immediately after trans releases it to the group.
10337 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10339 // The competing request can now finish. Wait for the headers and then
10340 // read the body.
10341 rv = callback_compete.WaitForResult();
10342 EXPECT_EQ(OK, rv);
10343 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10344 if (rv == ERR_IO_PENDING)
10345 rv = callback.WaitForResult();
10346 EXPECT_EQ(3, rv);
10347 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10348 EXPECT_EQ(0, rv);
10350 // Finally, the socket is released to the group.
10351 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10354 // This tests the case that a request is issued via http instead of spdy after
10355 // npn is negotiated.
10356 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
10357 session_deps_.use_alternate_protocols = true;
10358 NextProtoVector next_protos;
10359 next_protos.push_back(kProtoHTTP11);
10360 session_deps_.next_protos = next_protos;
10362 HttpRequestInfo request;
10363 request.method = "GET";
10364 request.url = GURL("https://www.example.org/");
10365 request.load_flags = 0;
10367 MockWrite data_writes[] = {
10368 MockWrite(
10369 "GET / HTTP/1.1\r\n"
10370 "Host: www.example.org\r\n"
10371 "Connection: keep-alive\r\n\r\n"),
10374 std::string alternate_protocol_http_header =
10375 GetAlternateProtocolHttpHeader();
10377 MockRead data_reads[] = {
10378 MockRead("HTTP/1.1 200 OK\r\n"),
10379 MockRead(alternate_protocol_http_header.c_str()),
10380 MockRead("hello world"),
10381 MockRead(SYNCHRONOUS, OK),
10384 SSLSocketDataProvider ssl(ASYNC, OK);
10385 ssl.SetNextProto(kProtoHTTP11);
10387 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10389 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
10390 data_writes, arraysize(data_writes));
10391 session_deps_.socket_factory->AddSocketDataProvider(&data);
10393 TestCompletionCallback callback;
10395 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10396 scoped_ptr<HttpTransaction> trans(
10397 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10399 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10401 EXPECT_EQ(ERR_IO_PENDING, rv);
10402 EXPECT_EQ(OK, callback.WaitForResult());
10404 const HttpResponseInfo* response = trans->GetResponseInfo();
10405 ASSERT_TRUE(response != NULL);
10406 ASSERT_TRUE(response->headers.get() != NULL);
10407 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10409 std::string response_data;
10410 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10411 EXPECT_EQ("hello world", response_data);
10413 EXPECT_FALSE(response->was_fetched_via_spdy);
10414 EXPECT_TRUE(response->was_npn_negotiated);
10417 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
10418 // Simulate the SSL handshake completing with an NPN negotiation
10419 // followed by an immediate server closing of the socket.
10420 // Fix crash: http://crbug.com/46369
10421 session_deps_.use_alternate_protocols = true;
10422 session_deps_.next_protos = SpdyNextProtos();
10424 HttpRequestInfo request;
10425 request.method = "GET";
10426 request.url = GURL("https://www.example.org/");
10427 request.load_flags = 0;
10429 SSLSocketDataProvider ssl(ASYNC, OK);
10430 ssl.SetNextProto(GetParam());
10431 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10433 scoped_ptr<SpdyFrame> req(
10434 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10435 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
10437 MockRead spdy_reads[] = {
10438 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10441 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10442 arraysize(spdy_writes));
10443 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10445 TestCompletionCallback callback;
10447 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10448 scoped_ptr<HttpTransaction> trans(
10449 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10451 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10452 EXPECT_EQ(ERR_IO_PENDING, rv);
10453 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10456 // A subclass of HttpAuthHandlerMock that records the request URL when
10457 // it gets it. This is needed since the auth handler may get destroyed
10458 // before we get a chance to query it.
10459 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10460 public:
10461 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10463 ~UrlRecordingHttpAuthHandlerMock() override {}
10465 protected:
10466 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10467 const HttpRequestInfo* request,
10468 const CompletionCallback& callback,
10469 std::string* auth_token) override {
10470 *url_ = request->url;
10471 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10472 credentials, request, callback, auth_token);
10475 private:
10476 GURL* url_;
10479 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10480 // This test ensures that the URL passed into the proxy is upgraded
10481 // to https when doing an Alternate Protocol upgrade.
10482 session_deps_.use_alternate_protocols = true;
10483 session_deps_.next_protos = SpdyNextProtos();
10485 session_deps_.proxy_service.reset(
10486 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10487 TestNetLog net_log;
10488 session_deps_.net_log = &net_log;
10489 GURL request_url;
10491 HttpAuthHandlerMock::Factory* auth_factory =
10492 new HttpAuthHandlerMock::Factory();
10493 UrlRecordingHttpAuthHandlerMock* auth_handler =
10494 new UrlRecordingHttpAuthHandlerMock(&request_url);
10495 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10496 auth_factory->set_do_init_from_challenge(true);
10497 session_deps_.http_auth_handler_factory.reset(auth_factory);
10500 HttpRequestInfo request;
10501 request.method = "GET";
10502 request.url = GURL("http://www.example.org");
10503 request.load_flags = 0;
10505 // First round goes unauthenticated through the proxy.
10506 MockWrite data_writes_1[] = {
10507 MockWrite(
10508 "GET http://www.example.org/ HTTP/1.1\r\n"
10509 "Host: www.example.org\r\n"
10510 "Proxy-Connection: keep-alive\r\n"
10511 "\r\n"),
10513 MockRead data_reads_1[] = {
10514 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10515 MockRead("HTTP/1.1 200 OK\r\n"),
10516 MockRead("Alternate-Protocol: 443:"),
10517 MockRead(GetAlternateProtocolFromParam()),
10518 MockRead("\r\n"),
10519 MockRead("Proxy-Connection: close\r\n"),
10520 MockRead("\r\n"),
10522 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10523 data_writes_1, arraysize(data_writes_1));
10525 // Second round tries to tunnel to www.example.org due to the
10526 // Alternate-Protocol announcement in the first round. It fails due
10527 // to a proxy authentication challenge.
10528 // After the failure, a tunnel is established to www.example.org using
10529 // Proxy-Authorization headers. There is then a SPDY request round.
10531 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10532 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10533 // does a Disconnect and Connect on the same socket, rather than trying
10534 // to obtain a new one.
10536 // NOTE: Originally, the proxy response to the second CONNECT request
10537 // simply returned another 407 so the unit test could skip the SSL connection
10538 // establishment and SPDY framing issues. Alas, the
10539 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10540 // complicated to set up expectations for than the SPDY session.
10542 scoped_ptr<SpdyFrame> req(
10543 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10544 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10545 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10547 MockWrite data_writes_2[] = {
10548 // First connection attempt without Proxy-Authorization.
10549 MockWrite(ASYNC, 0,
10550 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10551 "Host: www.example.org\r\n"
10552 "Proxy-Connection: keep-alive\r\n"
10553 "\r\n"),
10555 // Second connection attempt with Proxy-Authorization.
10556 MockWrite(ASYNC, 2,
10557 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10558 "Host: www.example.org\r\n"
10559 "Proxy-Connection: keep-alive\r\n"
10560 "Proxy-Authorization: auth_token\r\n"
10561 "\r\n"),
10563 // SPDY request
10564 CreateMockWrite(*req, 4),
10566 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10567 "Proxy-Authenticate: Mock\r\n"
10568 "Proxy-Connection: close\r\n"
10569 "\r\n");
10570 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10571 MockRead data_reads_2[] = {
10572 // First connection attempt fails
10573 MockRead(ASYNC, kRejectConnectResponse,
10574 arraysize(kRejectConnectResponse) - 1, 1),
10576 // Second connection attempt passes
10577 MockRead(ASYNC, kAcceptConnectResponse,
10578 arraysize(kAcceptConnectResponse) - 1, 3),
10580 // SPDY response
10581 CreateMockRead(*resp.get(), 5),
10582 CreateMockRead(*data.get(), 6),
10583 MockRead(ASYNC, 0, 0, 7),
10585 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
10586 data_writes_2, arraysize(data_writes_2));
10588 SSLSocketDataProvider ssl(ASYNC, OK);
10589 ssl.SetNextProto(GetParam());
10590 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10591 ASSERT_TRUE(ssl.cert.get());
10593 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10594 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10595 NULL, 0, NULL, 0);
10596 hanging_non_alternate_protocol_socket.set_connect_data(
10597 never_finishing_connect);
10599 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10600 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10601 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10602 session_deps_.socket_factory->AddSocketDataProvider(
10603 &hanging_non_alternate_protocol_socket);
10604 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10606 // First round should work and provide the Alternate-Protocol state.
10607 TestCompletionCallback callback_1;
10608 scoped_ptr<HttpTransaction> trans_1(
10609 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10610 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10611 EXPECT_EQ(ERR_IO_PENDING, rv);
10612 EXPECT_EQ(OK, callback_1.WaitForResult());
10614 // Second round should attempt a tunnel connect and get an auth challenge.
10615 TestCompletionCallback callback_2;
10616 scoped_ptr<HttpTransaction> trans_2(
10617 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10618 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10619 EXPECT_EQ(ERR_IO_PENDING, rv);
10620 EXPECT_EQ(OK, callback_2.WaitForResult());
10621 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10622 ASSERT_TRUE(response != NULL);
10623 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10625 // Restart with auth. Tunnel should work and response received.
10626 TestCompletionCallback callback_3;
10627 rv = trans_2->RestartWithAuth(
10628 AuthCredentials(kFoo, kBar), callback_3.callback());
10629 EXPECT_EQ(ERR_IO_PENDING, rv);
10630 EXPECT_EQ(OK, callback_3.WaitForResult());
10632 // After all that work, these two lines (or actually, just the scheme) are
10633 // what this test is all about. Make sure it happens correctly.
10634 EXPECT_EQ("https", request_url.scheme());
10635 EXPECT_EQ("www.example.org", request_url.host());
10637 LoadTimingInfo load_timing_info;
10638 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10639 TestLoadTimingNotReusedWithPac(load_timing_info,
10640 CONNECT_TIMING_HAS_SSL_TIMES);
10643 // Test that if we cancel the transaction as the connection is completing, that
10644 // everything tears down correctly.
10645 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10646 // Setup everything about the connection to complete synchronously, so that
10647 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10648 // for is the callback from the HttpStreamRequest.
10649 // Then cancel the transaction.
10650 // Verify that we don't crash.
10651 MockConnect mock_connect(SYNCHRONOUS, OK);
10652 MockRead data_reads[] = {
10653 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10654 MockRead(SYNCHRONOUS, "hello world"),
10655 MockRead(SYNCHRONOUS, OK),
10658 HttpRequestInfo request;
10659 request.method = "GET";
10660 request.url = GURL("http://www.example.org/");
10661 request.load_flags = 0;
10663 session_deps_.host_resolver->set_synchronous_mode(true);
10664 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10665 scoped_ptr<HttpTransaction> trans(
10666 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10668 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10669 data.set_connect_data(mock_connect);
10670 session_deps_.socket_factory->AddSocketDataProvider(&data);
10672 TestCompletionCallback callback;
10674 BoundTestNetLog log;
10675 int rv = trans->Start(&request, callback.callback(), log.bound());
10676 EXPECT_EQ(ERR_IO_PENDING, rv);
10677 trans.reset(); // Cancel the transaction here.
10679 base::MessageLoop::current()->RunUntilIdle();
10682 // Test that if a transaction is cancelled after receiving the headers, the
10683 // stream is drained properly and added back to the socket pool. The main
10684 // purpose of this test is to make sure that an HttpStreamParser can be read
10685 // from after the HttpNetworkTransaction and the objects it owns have been
10686 // deleted.
10687 // See http://crbug.com/368418
10688 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10689 MockRead data_reads[] = {
10690 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10691 MockRead(ASYNC, "Content-Length: 2\r\n"),
10692 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10693 MockRead(ASYNC, "1"),
10694 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10695 // HttpNetworkTransaction has been deleted.
10696 MockRead(ASYNC, "2"),
10697 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10699 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10700 session_deps_.socket_factory->AddSocketDataProvider(&data);
10702 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10705 HttpRequestInfo request;
10706 request.method = "GET";
10707 request.url = GURL("http://www.example.org/");
10708 request.load_flags = 0;
10710 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10711 TestCompletionCallback callback;
10713 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10714 EXPECT_EQ(ERR_IO_PENDING, rv);
10715 callback.WaitForResult();
10717 const HttpResponseInfo* response = trans.GetResponseInfo();
10718 ASSERT_TRUE(response != NULL);
10719 EXPECT_TRUE(response->headers.get() != NULL);
10720 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10722 // The transaction and HttpRequestInfo are deleted.
10725 // Let the HttpResponseBodyDrainer drain the socket.
10726 base::MessageLoop::current()->RunUntilIdle();
10728 // Socket should now be idle, waiting to be reused.
10729 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
10732 // Test a basic GET request through a proxy.
10733 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10734 session_deps_.proxy_service.reset(
10735 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10736 BoundTestNetLog log;
10737 session_deps_.net_log = log.bound().net_log();
10738 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10740 HttpRequestInfo request;
10741 request.method = "GET";
10742 request.url = GURL("http://www.example.org/");
10744 MockWrite data_writes1[] = {
10745 MockWrite(
10746 "GET http://www.example.org/ HTTP/1.1\r\n"
10747 "Host: www.example.org\r\n"
10748 "Proxy-Connection: keep-alive\r\n\r\n"),
10751 MockRead data_reads1[] = {
10752 MockRead("HTTP/1.1 200 OK\r\n"),
10753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10754 MockRead("Content-Length: 100\r\n\r\n"),
10755 MockRead(SYNCHRONOUS, OK),
10758 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10759 data_writes1, arraysize(data_writes1));
10760 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10762 TestCompletionCallback callback1;
10764 scoped_ptr<HttpTransaction> trans(
10765 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10766 BeforeProxyHeadersSentHandler proxy_headers_handler;
10767 trans->SetBeforeProxyHeadersSentCallback(
10768 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
10769 base::Unretained(&proxy_headers_handler)));
10771 int rv = trans->Start(&request, callback1.callback(), log.bound());
10772 EXPECT_EQ(ERR_IO_PENDING, rv);
10774 rv = callback1.WaitForResult();
10775 EXPECT_EQ(OK, rv);
10777 const HttpResponseInfo* response = trans->GetResponseInfo();
10778 ASSERT_TRUE(response != NULL);
10780 EXPECT_TRUE(response->headers->IsKeepAlive());
10781 EXPECT_EQ(200, response->headers->response_code());
10782 EXPECT_EQ(100, response->headers->GetContentLength());
10783 EXPECT_TRUE(response->was_fetched_via_proxy);
10784 EXPECT_TRUE(
10785 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10786 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
10787 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
10788 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10790 LoadTimingInfo load_timing_info;
10791 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10792 TestLoadTimingNotReusedWithPac(load_timing_info,
10793 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10796 // Test a basic HTTPS GET request through a proxy.
10797 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10798 session_deps_.proxy_service.reset(
10799 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10800 BoundTestNetLog log;
10801 session_deps_.net_log = log.bound().net_log();
10802 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10804 HttpRequestInfo request;
10805 request.method = "GET";
10806 request.url = GURL("https://www.example.org/");
10808 // Since we have proxy, should try to establish tunnel.
10809 MockWrite data_writes1[] = {
10810 MockWrite(
10811 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10812 "Host: www.example.org\r\n"
10813 "Proxy-Connection: keep-alive\r\n\r\n"),
10815 MockWrite(
10816 "GET / HTTP/1.1\r\n"
10817 "Host: www.example.org\r\n"
10818 "Connection: keep-alive\r\n\r\n"),
10821 MockRead data_reads1[] = {
10822 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10824 MockRead("HTTP/1.1 200 OK\r\n"),
10825 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10826 MockRead("Content-Length: 100\r\n\r\n"),
10827 MockRead(SYNCHRONOUS, OK),
10830 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10831 data_writes1, arraysize(data_writes1));
10832 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10833 SSLSocketDataProvider ssl(ASYNC, OK);
10834 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10836 TestCompletionCallback callback1;
10838 scoped_ptr<HttpTransaction> trans(
10839 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10841 int rv = trans->Start(&request, callback1.callback(), log.bound());
10842 EXPECT_EQ(ERR_IO_PENDING, rv);
10844 rv = callback1.WaitForResult();
10845 EXPECT_EQ(OK, rv);
10846 TestNetLogEntry::List entries;
10847 log.GetEntries(&entries);
10848 size_t pos = ExpectLogContainsSomewhere(
10849 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10850 NetLog::PHASE_NONE);
10851 ExpectLogContainsSomewhere(
10852 entries, pos,
10853 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10854 NetLog::PHASE_NONE);
10856 const HttpResponseInfo* response = trans->GetResponseInfo();
10857 ASSERT_TRUE(response != NULL);
10859 EXPECT_TRUE(response->headers->IsKeepAlive());
10860 EXPECT_EQ(200, response->headers->response_code());
10861 EXPECT_EQ(100, response->headers->GetContentLength());
10862 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10863 EXPECT_TRUE(response->was_fetched_via_proxy);
10864 EXPECT_TRUE(
10865 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10867 LoadTimingInfo load_timing_info;
10868 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10869 TestLoadTimingNotReusedWithPac(load_timing_info,
10870 CONNECT_TIMING_HAS_SSL_TIMES);
10873 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10874 // while establishing the tunnel.
10875 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10876 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10877 BoundTestNetLog log;
10878 session_deps_.net_log = log.bound().net_log();
10879 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10881 HttpRequestInfo request;
10882 request.method = "GET";
10883 request.url = GURL("https://www.example.org/");
10885 // Since we have proxy, should try to establish tunnel.
10886 MockWrite data_writes1[] = {
10887 MockWrite(
10888 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10889 "Host: www.example.org\r\n"
10890 "Proxy-Connection: keep-alive\r\n\r\n"),
10892 MockWrite(
10893 "GET / HTTP/1.1\r\n"
10894 "Host: www.example.org\r\n"
10895 "Connection: keep-alive\r\n\r\n"),
10898 MockRead data_reads1[] = {
10899 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10900 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10901 MockRead(ASYNC, 0, 0), // EOF
10904 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10905 data_writes1, arraysize(data_writes1));
10906 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10907 SSLSocketDataProvider ssl(ASYNC, OK);
10908 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10910 TestCompletionCallback callback1;
10912 scoped_ptr<HttpTransaction> trans(
10913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10915 int rv = trans->Start(&request, callback1.callback(), log.bound());
10916 EXPECT_EQ(ERR_IO_PENDING, rv);
10918 rv = callback1.WaitForResult();
10919 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10920 TestNetLogEntry::List entries;
10921 log.GetEntries(&entries);
10922 size_t pos = ExpectLogContainsSomewhere(
10923 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10924 NetLog::PHASE_NONE);
10925 ExpectLogContainsSomewhere(
10926 entries, pos,
10927 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10928 NetLog::PHASE_NONE);
10931 // Test for crbug.com/55424.
10932 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10933 scoped_ptr<SpdyFrame> req(
10934 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
10935 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
10937 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10938 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10939 MockRead spdy_reads[] = {
10940 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
10943 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10944 arraysize(spdy_writes));
10945 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10947 SSLSocketDataProvider ssl(ASYNC, OK);
10948 ssl.SetNextProto(GetParam());
10949 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10951 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10953 // Set up an initial SpdySession in the pool to reuse.
10954 HostPortPair host_port_pair("www.example.org", 443);
10955 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10956 PRIVACY_MODE_DISABLED);
10957 base::WeakPtr<SpdySession> spdy_session =
10958 CreateInsecureSpdySession(session, key, BoundNetLog());
10960 HttpRequestInfo request;
10961 request.method = "GET";
10962 request.url = GURL("https://www.example.org/");
10963 request.load_flags = 0;
10965 // This is the important line that marks this as a preconnect.
10966 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10968 scoped_ptr<HttpTransaction> trans(
10969 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10971 TestCompletionCallback callback;
10972 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10973 EXPECT_EQ(ERR_IO_PENDING, rv);
10974 EXPECT_EQ(OK, callback.WaitForResult());
10977 // Given a net error, cause that error to be returned from the first Write()
10978 // call and verify that the HttpTransaction fails with that error.
10979 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10980 int error, IoMode mode) {
10981 HttpRequestInfo request_info;
10982 request_info.url = GURL("https://www.example.com/");
10983 request_info.method = "GET";
10984 request_info.load_flags = LOAD_NORMAL;
10986 SSLSocketDataProvider ssl_data(mode, OK);
10987 MockWrite data_writes[] = {
10988 MockWrite(mode, error),
10990 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
10991 session_deps_.socket_factory->AddSocketDataProvider(&data);
10992 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10994 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10995 scoped_ptr<HttpTransaction> trans(
10996 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10998 TestCompletionCallback callback;
10999 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11000 if (rv == ERR_IO_PENDING)
11001 rv = callback.WaitForResult();
11002 ASSERT_EQ(error, rv);
11005 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
11006 // Just check a grab bag of cert errors.
11007 static const int kErrors[] = {
11008 ERR_CERT_COMMON_NAME_INVALID,
11009 ERR_CERT_AUTHORITY_INVALID,
11010 ERR_CERT_DATE_INVALID,
11012 for (size_t i = 0; i < arraysize(kErrors); i++) {
11013 CheckErrorIsPassedBack(kErrors[i], ASYNC);
11014 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
11018 // Ensure that a client certificate is removed from the SSL client auth
11019 // cache when:
11020 // 1) No proxy is involved.
11021 // 2) TLS False Start is disabled.
11022 // 3) The initial TLS handshake requests a client certificate.
11023 // 4) The client supplies an invalid/unacceptable certificate.
11024 TEST_P(HttpNetworkTransactionTest,
11025 ClientAuthCertCache_Direct_NoFalseStart) {
11026 HttpRequestInfo request_info;
11027 request_info.url = GURL("https://www.example.com/");
11028 request_info.method = "GET";
11029 request_info.load_flags = LOAD_NORMAL;
11031 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11032 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11034 // [ssl_]data1 contains the data for the first SSL handshake. When a
11035 // CertificateRequest is received for the first time, the handshake will
11036 // be aborted to allow the caller to provide a certificate.
11037 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11038 ssl_data1.cert_request_info = cert_request.get();
11039 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11040 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11041 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11043 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11044 // False Start is not being used, the result of the SSL handshake will be
11045 // returned as part of the SSLClientSocket::Connect() call. This test
11046 // matches the result of a server sending a handshake_failure alert,
11047 // rather than a Finished message, because it requires a client
11048 // certificate and none was supplied.
11049 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11050 ssl_data2.cert_request_info = cert_request.get();
11051 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11052 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11053 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11055 // [ssl_]data3 contains the data for the third SSL handshake. When a
11056 // connection to a server fails during an SSL handshake,
11057 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11058 // connection was attempted with TLSv1.2. This is transparent to the caller
11059 // of the HttpNetworkTransaction. Because this test failure is due to
11060 // requiring a client certificate, this fallback handshake should also
11061 // fail.
11062 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11063 ssl_data3.cert_request_info = cert_request.get();
11064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11065 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11066 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11068 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11069 // connection to a server fails during an SSL handshake,
11070 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11071 // connection was attempted with TLSv1.1. This is transparent to the caller
11072 // of the HttpNetworkTransaction. Because this test failure is due to
11073 // requiring a client certificate, this fallback handshake should also
11074 // fail.
11075 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11076 ssl_data4.cert_request_info = cert_request.get();
11077 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11078 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
11079 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11081 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11082 scoped_ptr<HttpTransaction> trans(
11083 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11085 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11086 TestCompletionCallback callback;
11087 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11088 ASSERT_EQ(ERR_IO_PENDING, rv);
11090 // Complete the SSL handshake, which should abort due to requiring a
11091 // client certificate.
11092 rv = callback.WaitForResult();
11093 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11095 // Indicate that no certificate should be supplied. From the perspective
11096 // of SSLClientCertCache, NULL is just as meaningful as a real
11097 // certificate, so this is the same as supply a
11098 // legitimate-but-unacceptable certificate.
11099 rv = trans->RestartWithCertificate(NULL, callback.callback());
11100 ASSERT_EQ(ERR_IO_PENDING, rv);
11102 // Ensure the certificate was added to the client auth cache before
11103 // allowing the connection to continue restarting.
11104 scoped_refptr<X509Certificate> client_cert;
11105 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11106 HostPortPair("www.example.com", 443), &client_cert));
11107 ASSERT_EQ(NULL, client_cert.get());
11109 // Restart the handshake. This will consume ssl_data2, which fails, and
11110 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11111 // The result code is checked against what ssl_data4 should return.
11112 rv = callback.WaitForResult();
11113 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11115 // Ensure that the client certificate is removed from the cache on a
11116 // handshake failure.
11117 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11118 HostPortPair("www.example.com", 443), &client_cert));
11121 // Ensure that a client certificate is removed from the SSL client auth
11122 // cache when:
11123 // 1) No proxy is involved.
11124 // 2) TLS False Start is enabled.
11125 // 3) The initial TLS handshake requests a client certificate.
11126 // 4) The client supplies an invalid/unacceptable certificate.
11127 TEST_P(HttpNetworkTransactionTest,
11128 ClientAuthCertCache_Direct_FalseStart) {
11129 HttpRequestInfo request_info;
11130 request_info.url = GURL("https://www.example.com/");
11131 request_info.method = "GET";
11132 request_info.load_flags = LOAD_NORMAL;
11134 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11135 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11137 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11138 // return successfully after reading up to the peer's Certificate message.
11139 // This is to allow the caller to call SSLClientSocket::Write(), which can
11140 // enqueue application data to be sent in the same packet as the
11141 // ChangeCipherSpec and Finished messages.
11142 // The actual handshake will be finished when SSLClientSocket::Read() is
11143 // called, which expects to process the peer's ChangeCipherSpec and
11144 // Finished messages. If there was an error negotiating with the peer,
11145 // such as due to the peer requiring a client certificate when none was
11146 // supplied, the alert sent by the peer won't be processed until Read() is
11147 // called.
11149 // Like the non-False Start case, when a client certificate is requested by
11150 // the peer, the handshake is aborted during the Connect() call.
11151 // [ssl_]data1 represents the initial SSL handshake with the peer.
11152 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11153 ssl_data1.cert_request_info = cert_request.get();
11154 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11155 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11156 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11158 // When a client certificate is supplied, Connect() will not be aborted
11159 // when the peer requests the certificate. Instead, the handshake will
11160 // artificially succeed, allowing the caller to write the HTTP request to
11161 // the socket. The handshake messages are not processed until Read() is
11162 // called, which then detects that the handshake was aborted, due to the
11163 // peer sending a handshake_failure because it requires a client
11164 // certificate.
11165 SSLSocketDataProvider ssl_data2(ASYNC, OK);
11166 ssl_data2.cert_request_info = cert_request.get();
11167 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11168 MockRead data2_reads[] = {
11169 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
11171 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
11172 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11174 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11175 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11176 // TLSv1. It has the same behaviour as [ssl_]data2.
11177 SSLSocketDataProvider ssl_data3(ASYNC, OK);
11178 ssl_data3.cert_request_info = cert_request.get();
11179 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11180 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
11181 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11183 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11184 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11185 SSLSocketDataProvider ssl_data4(ASYNC, OK);
11186 ssl_data4.cert_request_info = cert_request.get();
11187 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11188 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
11189 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11191 // Need one more if TLSv1.2 is enabled.
11192 SSLSocketDataProvider ssl_data5(ASYNC, OK);
11193 ssl_data5.cert_request_info = cert_request.get();
11194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11195 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
11196 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11198 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11199 scoped_ptr<HttpTransaction> trans(
11200 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11202 // Begin the initial SSL handshake.
11203 TestCompletionCallback callback;
11204 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11205 ASSERT_EQ(ERR_IO_PENDING, rv);
11207 // Complete the SSL handshake, which should abort due to requiring a
11208 // client certificate.
11209 rv = callback.WaitForResult();
11210 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11212 // Indicate that no certificate should be supplied. From the perspective
11213 // of SSLClientCertCache, NULL is just as meaningful as a real
11214 // certificate, so this is the same as supply a
11215 // legitimate-but-unacceptable certificate.
11216 rv = trans->RestartWithCertificate(NULL, callback.callback());
11217 ASSERT_EQ(ERR_IO_PENDING, rv);
11219 // Ensure the certificate was added to the client auth cache before
11220 // allowing the connection to continue restarting.
11221 scoped_refptr<X509Certificate> client_cert;
11222 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11223 HostPortPair("www.example.com", 443), &client_cert));
11224 ASSERT_EQ(NULL, client_cert.get());
11226 // Restart the handshake. This will consume ssl_data2, which fails, and
11227 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11228 // The result code is checked against what ssl_data4 should return.
11229 rv = callback.WaitForResult();
11230 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11232 // Ensure that the client certificate is removed from the cache on a
11233 // handshake failure.
11234 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11235 HostPortPair("www.example.com", 443), &client_cert));
11238 // Ensure that a client certificate is removed from the SSL client auth
11239 // cache when:
11240 // 1) An HTTPS proxy is involved.
11241 // 3) The HTTPS proxy requests a client certificate.
11242 // 4) The client supplies an invalid/unacceptable certificate for the
11243 // proxy.
11244 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11245 // then for connecting to an HTTP endpoint.
11246 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
11247 session_deps_.proxy_service.reset(
11248 ProxyService::CreateFixed("https://proxy:70"));
11249 BoundTestNetLog log;
11250 session_deps_.net_log = log.bound().net_log();
11252 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11253 cert_request->host_and_port = HostPortPair("proxy", 70);
11255 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11256 // [ssl_]data[1-3]. Rather than represending the endpoint
11257 // (www.example.com:443), they represent failures with the HTTPS proxy
11258 // (proxy:70).
11259 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11260 ssl_data1.cert_request_info = cert_request.get();
11261 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11262 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11263 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11265 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11266 ssl_data2.cert_request_info = cert_request.get();
11267 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11268 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11269 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11271 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11272 #if 0
11273 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11274 ssl_data3.cert_request_info = cert_request.get();
11275 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11276 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11277 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11278 #endif
11280 HttpRequestInfo requests[2];
11281 requests[0].url = GURL("https://www.example.com/");
11282 requests[0].method = "GET";
11283 requests[0].load_flags = LOAD_NORMAL;
11285 requests[1].url = GURL("http://www.example.com/");
11286 requests[1].method = "GET";
11287 requests[1].load_flags = LOAD_NORMAL;
11289 for (size_t i = 0; i < arraysize(requests); ++i) {
11290 session_deps_.socket_factory->ResetNextMockIndexes();
11291 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11292 scoped_ptr<HttpNetworkTransaction> trans(
11293 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11295 // Begin the SSL handshake with the proxy.
11296 TestCompletionCallback callback;
11297 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
11298 ASSERT_EQ(ERR_IO_PENDING, rv);
11300 // Complete the SSL handshake, which should abort due to requiring a
11301 // client certificate.
11302 rv = callback.WaitForResult();
11303 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11305 // Indicate that no certificate should be supplied. From the perspective
11306 // of SSLClientCertCache, NULL is just as meaningful as a real
11307 // certificate, so this is the same as supply a
11308 // legitimate-but-unacceptable certificate.
11309 rv = trans->RestartWithCertificate(NULL, callback.callback());
11310 ASSERT_EQ(ERR_IO_PENDING, rv);
11312 // Ensure the certificate was added to the client auth cache before
11313 // allowing the connection to continue restarting.
11314 scoped_refptr<X509Certificate> client_cert;
11315 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11316 HostPortPair("proxy", 70), &client_cert));
11317 ASSERT_EQ(NULL, client_cert.get());
11318 // Ensure the certificate was NOT cached for the endpoint. This only
11319 // applies to HTTPS requests, but is fine to check for HTTP requests.
11320 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11321 HostPortPair("www.example.com", 443), &client_cert));
11323 // Restart the handshake. This will consume ssl_data2, which fails, and
11324 // then consume ssl_data3, which should also fail. The result code is
11325 // checked against what ssl_data3 should return.
11326 rv = callback.WaitForResult();
11327 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
11329 // Now that the new handshake has failed, ensure that the client
11330 // certificate was removed from the client auth cache.
11331 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11332 HostPortPair("proxy", 70), &client_cert));
11333 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11334 HostPortPair("www.example.com", 443), &client_cert));
11338 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
11339 session_deps_.use_alternate_protocols = true;
11340 session_deps_.next_protos = SpdyNextProtos();
11342 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11343 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11344 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11345 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11346 pool_peer.DisableDomainAuthenticationVerification();
11348 SSLSocketDataProvider ssl(ASYNC, OK);
11349 ssl.SetNextProto(GetParam());
11350 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11352 scoped_ptr<SpdyFrame> host1_req(
11353 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11354 scoped_ptr<SpdyFrame> host2_req(
11355 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11356 MockWrite spdy_writes[] = {
11357 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11359 scoped_ptr<SpdyFrame> host1_resp(
11360 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11361 scoped_ptr<SpdyFrame> host1_resp_body(
11362 spdy_util_.ConstructSpdyBodyFrame(1, true));
11363 scoped_ptr<SpdyFrame> host2_resp(
11364 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11365 scoped_ptr<SpdyFrame> host2_resp_body(
11366 spdy_util_.ConstructSpdyBodyFrame(3, true));
11367 MockRead spdy_reads[] = {
11368 CreateMockRead(*host1_resp, 1),
11369 CreateMockRead(*host1_resp_body, 2),
11370 CreateMockRead(*host2_resp, 4),
11371 CreateMockRead(*host2_resp_body, 5),
11372 MockRead(ASYNC, 0, 6),
11375 IPAddressNumber ip;
11376 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11377 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11378 MockConnect connect(ASYNC, OK, peer_addr);
11379 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11380 spdy_writes, arraysize(spdy_writes));
11381 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11383 TestCompletionCallback callback;
11384 HttpRequestInfo request1;
11385 request1.method = "GET";
11386 request1.url = GURL("https://www.example.org/");
11387 request1.load_flags = 0;
11388 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11390 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11391 EXPECT_EQ(ERR_IO_PENDING, rv);
11392 EXPECT_EQ(OK, callback.WaitForResult());
11394 const HttpResponseInfo* response = trans1.GetResponseInfo();
11395 ASSERT_TRUE(response != NULL);
11396 ASSERT_TRUE(response->headers.get() != NULL);
11397 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11399 std::string response_data;
11400 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11401 EXPECT_EQ("hello!", response_data);
11403 // Preload www.gmail.com into HostCache.
11404 HostPortPair host_port("www.gmail.com", 443);
11405 HostResolver::RequestInfo resolve_info(host_port);
11406 AddressList ignored;
11407 rv = session_deps_.host_resolver->Resolve(resolve_info,
11408 DEFAULT_PRIORITY,
11409 &ignored,
11410 callback.callback(),
11411 NULL,
11412 BoundNetLog());
11413 EXPECT_EQ(ERR_IO_PENDING, rv);
11414 rv = callback.WaitForResult();
11415 EXPECT_EQ(OK, rv);
11417 HttpRequestInfo request2;
11418 request2.method = "GET";
11419 request2.url = GURL("https://www.gmail.com/");
11420 request2.load_flags = 0;
11421 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11423 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11424 EXPECT_EQ(ERR_IO_PENDING, rv);
11425 EXPECT_EQ(OK, callback.WaitForResult());
11427 response = trans2.GetResponseInfo();
11428 ASSERT_TRUE(response != NULL);
11429 ASSERT_TRUE(response->headers.get() != NULL);
11430 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11431 EXPECT_TRUE(response->was_fetched_via_spdy);
11432 EXPECT_TRUE(response->was_npn_negotiated);
11433 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11434 EXPECT_EQ("hello!", response_data);
11437 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11438 session_deps_.use_alternate_protocols = true;
11439 session_deps_.next_protos = SpdyNextProtos();
11441 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11442 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11443 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11444 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11445 pool_peer.DisableDomainAuthenticationVerification();
11447 SSLSocketDataProvider ssl(ASYNC, OK);
11448 ssl.SetNextProto(GetParam());
11449 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11451 scoped_ptr<SpdyFrame> host1_req(
11452 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11453 scoped_ptr<SpdyFrame> host2_req(
11454 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11455 MockWrite spdy_writes[] = {
11456 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11458 scoped_ptr<SpdyFrame> host1_resp(
11459 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11460 scoped_ptr<SpdyFrame> host1_resp_body(
11461 spdy_util_.ConstructSpdyBodyFrame(1, true));
11462 scoped_ptr<SpdyFrame> host2_resp(
11463 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11464 scoped_ptr<SpdyFrame> host2_resp_body(
11465 spdy_util_.ConstructSpdyBodyFrame(3, true));
11466 MockRead spdy_reads[] = {
11467 CreateMockRead(*host1_resp, 1),
11468 CreateMockRead(*host1_resp_body, 2),
11469 CreateMockRead(*host2_resp, 4),
11470 CreateMockRead(*host2_resp_body, 5),
11471 MockRead(ASYNC, 0, 6),
11474 IPAddressNumber ip;
11475 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11476 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11477 MockConnect connect(ASYNC, OK, peer_addr);
11478 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11479 spdy_writes, arraysize(spdy_writes));
11480 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11482 TestCompletionCallback callback;
11483 HttpRequestInfo request1;
11484 request1.method = "GET";
11485 request1.url = GURL("https://www.example.org/");
11486 request1.load_flags = 0;
11487 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11489 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11490 EXPECT_EQ(ERR_IO_PENDING, rv);
11491 EXPECT_EQ(OK, callback.WaitForResult());
11493 const HttpResponseInfo* response = trans1.GetResponseInfo();
11494 ASSERT_TRUE(response != NULL);
11495 ASSERT_TRUE(response->headers.get() != NULL);
11496 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11498 std::string response_data;
11499 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11500 EXPECT_EQ("hello!", response_data);
11502 HttpRequestInfo request2;
11503 request2.method = "GET";
11504 request2.url = GURL("https://www.gmail.com/");
11505 request2.load_flags = 0;
11506 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11508 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11509 EXPECT_EQ(ERR_IO_PENDING, rv);
11510 EXPECT_EQ(OK, callback.WaitForResult());
11512 response = trans2.GetResponseInfo();
11513 ASSERT_TRUE(response != NULL);
11514 ASSERT_TRUE(response->headers.get() != NULL);
11515 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11516 EXPECT_TRUE(response->was_fetched_via_spdy);
11517 EXPECT_TRUE(response->was_npn_negotiated);
11518 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11519 EXPECT_EQ("hello!", response_data);
11522 class OneTimeCachingHostResolver : public HostResolver {
11523 public:
11524 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11525 : host_port_(host_port) {}
11526 ~OneTimeCachingHostResolver() override {}
11528 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11530 // HostResolver methods:
11531 int Resolve(const RequestInfo& info,
11532 RequestPriority priority,
11533 AddressList* addresses,
11534 const CompletionCallback& callback,
11535 RequestHandle* out_req,
11536 const BoundNetLog& net_log) override {
11537 return host_resolver_.Resolve(
11538 info, priority, addresses, callback, out_req, net_log);
11541 int ResolveFromCache(const RequestInfo& info,
11542 AddressList* addresses,
11543 const BoundNetLog& net_log) override {
11544 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11545 if (rv == OK && info.host_port_pair().Equals(host_port_))
11546 host_resolver_.GetHostCache()->clear();
11547 return rv;
11550 void CancelRequest(RequestHandle req) override {
11551 host_resolver_.CancelRequest(req);
11554 MockCachingHostResolver* GetMockHostResolver() {
11555 return &host_resolver_;
11558 private:
11559 MockCachingHostResolver host_resolver_;
11560 const HostPortPair host_port_;
11563 TEST_P(HttpNetworkTransactionTest,
11564 UseIPConnectionPoolingWithHostCacheExpiration) {
11565 session_deps_.use_alternate_protocols = true;
11566 session_deps_.next_protos = SpdyNextProtos();
11568 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11569 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11570 HttpNetworkSession::Params params =
11571 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11572 params.host_resolver = &host_resolver;
11573 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11574 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11575 pool_peer.DisableDomainAuthenticationVerification();
11577 SSLSocketDataProvider ssl(ASYNC, OK);
11578 ssl.SetNextProto(GetParam());
11579 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11581 scoped_ptr<SpdyFrame> host1_req(
11582 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11583 scoped_ptr<SpdyFrame> host2_req(
11584 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11585 MockWrite spdy_writes[] = {
11586 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11588 scoped_ptr<SpdyFrame> host1_resp(
11589 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11590 scoped_ptr<SpdyFrame> host1_resp_body(
11591 spdy_util_.ConstructSpdyBodyFrame(1, true));
11592 scoped_ptr<SpdyFrame> host2_resp(
11593 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11594 scoped_ptr<SpdyFrame> host2_resp_body(
11595 spdy_util_.ConstructSpdyBodyFrame(3, true));
11596 MockRead spdy_reads[] = {
11597 CreateMockRead(*host1_resp, 1),
11598 CreateMockRead(*host1_resp_body, 2),
11599 CreateMockRead(*host2_resp, 4),
11600 CreateMockRead(*host2_resp_body, 5),
11601 MockRead(ASYNC, 0, 6),
11604 IPAddressNumber ip;
11605 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11606 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11607 MockConnect connect(ASYNC, OK, peer_addr);
11608 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11609 spdy_writes, arraysize(spdy_writes));
11610 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11612 TestCompletionCallback callback;
11613 HttpRequestInfo request1;
11614 request1.method = "GET";
11615 request1.url = GURL("https://www.example.org/");
11616 request1.load_flags = 0;
11617 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11619 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11620 EXPECT_EQ(ERR_IO_PENDING, rv);
11621 EXPECT_EQ(OK, callback.WaitForResult());
11623 const HttpResponseInfo* response = trans1.GetResponseInfo();
11624 ASSERT_TRUE(response != NULL);
11625 ASSERT_TRUE(response->headers.get() != NULL);
11626 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11628 std::string response_data;
11629 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11630 EXPECT_EQ("hello!", response_data);
11632 // Preload cache entries into HostCache.
11633 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11634 AddressList ignored;
11635 rv = host_resolver.Resolve(resolve_info,
11636 DEFAULT_PRIORITY,
11637 &ignored,
11638 callback.callback(),
11639 NULL,
11640 BoundNetLog());
11641 EXPECT_EQ(ERR_IO_PENDING, rv);
11642 rv = callback.WaitForResult();
11643 EXPECT_EQ(OK, rv);
11645 HttpRequestInfo request2;
11646 request2.method = "GET";
11647 request2.url = GURL("https://www.gmail.com/");
11648 request2.load_flags = 0;
11649 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11651 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11652 EXPECT_EQ(ERR_IO_PENDING, rv);
11653 EXPECT_EQ(OK, callback.WaitForResult());
11655 response = trans2.GetResponseInfo();
11656 ASSERT_TRUE(response != NULL);
11657 ASSERT_TRUE(response->headers.get() != NULL);
11658 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11659 EXPECT_TRUE(response->was_fetched_via_spdy);
11660 EXPECT_TRUE(response->was_npn_negotiated);
11661 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11662 EXPECT_EQ("hello!", response_data);
11665 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11666 const std::string https_url = "https://www.example.org:8080/";
11667 const std::string http_url = "http://www.example.org:8080/";
11669 // SPDY GET for HTTPS URL
11670 scoped_ptr<SpdyFrame> req1(
11671 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11673 MockWrite writes1[] = {
11674 CreateMockWrite(*req1, 0),
11677 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11678 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11679 MockRead reads1[] = {
11680 CreateMockRead(*resp1, 1),
11681 CreateMockRead(*body1, 2),
11682 MockRead(ASYNC, ERR_IO_PENDING, 3)
11685 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
11686 arraysize(writes1));
11687 MockConnect connect_data1(ASYNC, OK);
11688 data1.set_connect_data(connect_data1);
11690 // HTTP GET for the HTTP URL
11691 MockWrite writes2[] = {
11692 MockWrite(ASYNC, 0,
11693 "GET / HTTP/1.1\r\n"
11694 "Host: www.example.org:8080\r\n"
11695 "Connection: keep-alive\r\n\r\n"),
11698 MockRead reads2[] = {
11699 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11700 MockRead(ASYNC, 2, "hello"),
11701 MockRead(ASYNC, OK, 3),
11704 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
11705 arraysize(writes2));
11707 SSLSocketDataProvider ssl(ASYNC, OK);
11708 ssl.SetNextProto(GetParam());
11709 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11710 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11711 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11713 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11715 // Start the first transaction to set up the SpdySession
11716 HttpRequestInfo request1;
11717 request1.method = "GET";
11718 request1.url = GURL(https_url);
11719 request1.load_flags = 0;
11720 HttpNetworkTransaction trans1(LOWEST, session.get());
11721 TestCompletionCallback callback1;
11722 EXPECT_EQ(ERR_IO_PENDING,
11723 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11724 base::MessageLoop::current()->RunUntilIdle();
11726 EXPECT_EQ(OK, callback1.WaitForResult());
11727 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11729 // Now, start the HTTP request
11730 HttpRequestInfo request2;
11731 request2.method = "GET";
11732 request2.url = GURL(http_url);
11733 request2.load_flags = 0;
11734 HttpNetworkTransaction trans2(MEDIUM, session.get());
11735 TestCompletionCallback callback2;
11736 EXPECT_EQ(ERR_IO_PENDING,
11737 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11738 base::MessageLoop::current()->RunUntilIdle();
11740 EXPECT_EQ(OK, callback2.WaitForResult());
11741 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11744 class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
11745 public:
11746 void Run(bool pooling, bool valid) {
11747 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
11748 443);
11749 HostPortPair alternative("www.example.org", 443);
11751 base::FilePath certs_dir = GetTestCertsDirectory();
11752 scoped_refptr<X509Certificate> cert(
11753 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
11754 ASSERT_TRUE(cert.get());
11755 bool common_name_fallback_used;
11756 EXPECT_EQ(valid,
11757 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
11758 EXPECT_TRUE(
11759 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
11760 SSLSocketDataProvider ssl(ASYNC, OK);
11761 ssl.SetNextProto(GetParam());
11762 ssl.cert = cert;
11763 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11765 // If pooling, then start a request to alternative first to create a
11766 // SpdySession.
11767 std::string url0 = "https://www.example.org:443";
11768 // Second request to origin, which has an alternative service, and could
11769 // open a connection to the alternative host or pool to the existing one.
11770 std::string url1("https://");
11771 url1.append(origin.host());
11772 url1.append(":443");
11774 scoped_ptr<SpdyFrame> req0;
11775 scoped_ptr<SpdyFrame> req1;
11776 scoped_ptr<SpdyFrame> resp0;
11777 scoped_ptr<SpdyFrame> body0;
11778 scoped_ptr<SpdyFrame> resp1;
11779 scoped_ptr<SpdyFrame> body1;
11780 std::vector<MockWrite> writes;
11781 std::vector<MockRead> reads;
11783 if (pooling) {
11784 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
11785 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
11787 writes.push_back(CreateMockWrite(*req0, 0));
11788 writes.push_back(CreateMockWrite(*req1, 3));
11790 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11791 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
11792 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11793 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
11795 reads.push_back(CreateMockRead(*resp0, 1));
11796 reads.push_back(CreateMockRead(*body0, 2));
11797 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
11798 reads.push_back(CreateMockRead(*resp1, 5));
11799 reads.push_back(CreateMockRead(*body1, 6));
11800 reads.push_back(MockRead(ASYNC, OK, 7));
11801 } else {
11802 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
11804 writes.push_back(CreateMockWrite(*req1, 0));
11806 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11807 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
11809 reads.push_back(CreateMockRead(*resp1, 1));
11810 reads.push_back(CreateMockRead(*body1, 2));
11811 reads.push_back(MockRead(ASYNC, OK, 3));
11814 SequencedSocketData data(vector_as_array(&reads), reads.size(),
11815 vector_as_array(&writes), writes.size());
11816 session_deps_.socket_factory->AddSocketDataProvider(&data);
11818 // Connection to the origin fails.
11819 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11820 StaticSocketDataProvider data_refused;
11821 data_refused.set_connect_data(mock_connect);
11822 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
11824 session_deps_.use_alternate_protocols = true;
11825 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11826 base::WeakPtr<HttpServerProperties> http_server_properties =
11827 session->http_server_properties();
11828 AlternativeService alternative_service(
11829 AlternateProtocolFromNextProto(GetParam()), alternative);
11830 http_server_properties->SetAlternativeService(origin, alternative_service,
11831 1.0);
11833 // First request to alternative.
11834 if (pooling) {
11835 scoped_ptr<HttpTransaction> trans0(
11836 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11837 HttpRequestInfo request0;
11838 request0.method = "GET";
11839 request0.url = GURL(url0);
11840 request0.load_flags = 0;
11841 TestCompletionCallback callback0;
11843 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
11844 EXPECT_EQ(ERR_IO_PENDING, rv);
11845 rv = callback0.WaitForResult();
11846 EXPECT_EQ(OK, rv);
11849 // Second request to origin.
11850 scoped_ptr<HttpTransaction> trans1(
11851 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11852 HttpRequestInfo request1;
11853 request1.method = "GET";
11854 request1.url = GURL(url1);
11855 request1.load_flags = 0;
11856 TestCompletionCallback callback1;
11858 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
11859 EXPECT_EQ(ERR_IO_PENDING, rv);
11860 base::MessageLoop::current()->RunUntilIdle();
11861 if (data.IsReadPaused()) {
11862 data.CompleteRead();
11864 rv = callback1.WaitForResult();
11865 if (valid) {
11866 EXPECT_EQ(OK, rv);
11867 } else {
11868 if (pooling) {
11869 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11870 } else {
11871 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
11877 INSTANTIATE_TEST_CASE_P(NextProto,
11878 AltSvcCertificateVerificationTest,
11879 testing::Values(kProtoSPDY31,
11880 kProtoHTTP2_14,
11881 kProtoHTTP2));
11883 // The alternative service host must exhibit a certificate that is valid for the
11884 // origin host. Test that this is enforced when pooling to an existing
11885 // connection.
11886 TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
11887 Run(true, true);
11890 TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
11891 Run(true, false);
11894 // The alternative service host must exhibit a certificate that is valid for the
11895 // origin host. Test that this is enforced when opening a new connection.
11896 TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
11897 Run(false, true);
11900 TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
11901 Run(false, false);
11904 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
11905 // with the alternative server. That connection should not be used.
11906 TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
11907 HostPortPair origin("origin.example.org", 443);
11908 HostPortPair alternative("alternative.example.org", 443);
11910 // Negotiate HTTP/1.1 with alternative.example.org.
11911 SSLSocketDataProvider ssl(ASYNC, OK);
11912 ssl.SetNextProto(kProtoHTTP11);
11913 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11915 // No data should be read from the alternative, because HTTP/1.1 is
11916 // negotiated.
11917 StaticSocketDataProvider data;
11918 session_deps_.socket_factory->AddSocketDataProvider(&data);
11920 // This test documents that an alternate Job should not be used if HTTP/1.1 is
11921 // negotiated. In order to test this, a failed connection to the origin is
11922 // mocked. This way the request relies on the alternate Job.
11923 StaticSocketDataProvider data_refused;
11924 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
11925 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
11927 // Set up alternative service for origin.
11928 session_deps_.use_alternate_protocols = true;
11929 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11930 base::WeakPtr<HttpServerProperties> http_server_properties =
11931 session->http_server_properties();
11932 AlternativeService alternative_service(
11933 AlternateProtocolFromNextProto(GetParam()), alternative);
11934 http_server_properties->SetAlternativeService(origin, alternative_service,
11935 1.0);
11937 scoped_ptr<HttpTransaction> trans(
11938 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11939 HttpRequestInfo request;
11940 request.method = "GET";
11941 request.url = GURL("https://origin.example.org:443");
11942 request.load_flags = 0;
11943 TestCompletionCallback callback;
11945 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
11946 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
11947 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11948 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
11951 // A request to a server with an alternative service fires two Jobs: one to the
11952 // origin, and an alternate one to the alternative server. If the former
11953 // succeeds, the request should succeed, even if the latter fails because
11954 // HTTP/1.1 is negotiated which is insufficient for alternative service.
11955 TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
11956 HostPortPair origin("origin.example.org", 443);
11957 HostPortPair alternative("alternative.example.org", 443);
11959 // Negotiate HTTP/1.1 with alternative.
11960 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
11961 alternative_ssl.SetNextProto(kProtoHTTP11);
11962 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
11964 // No data should be read from the alternative, because HTTP/1.1 is
11965 // negotiated.
11966 StaticSocketDataProvider data;
11967 session_deps_.socket_factory->AddSocketDataProvider(&data);
11969 // Negotiate HTTP/1.1 with origin.
11970 SSLSocketDataProvider origin_ssl(ASYNC, OK);
11971 origin_ssl.SetNextProto(kProtoHTTP11);
11972 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
11974 MockWrite http_writes[] = {
11975 MockWrite(
11976 "GET / HTTP/1.1\r\n"
11977 "Host: origin.example.org\r\n"
11978 "Connection: keep-alive\r\n\r\n"),
11979 MockWrite(
11980 "GET /second HTTP/1.1\r\n"
11981 "Host: origin.example.org\r\n"
11982 "Connection: keep-alive\r\n\r\n"),
11985 MockRead http_reads[] = {
11986 MockRead("HTTP/1.1 200 OK\r\n"),
11987 MockRead("Content-Type: text/html\r\n"),
11988 MockRead("Content-Length: 6\r\n\r\n"),
11989 MockRead("foobar"),
11990 MockRead("HTTP/1.1 200 OK\r\n"),
11991 MockRead("Content-Type: text/html\r\n"),
11992 MockRead("Content-Length: 7\r\n\r\n"),
11993 MockRead("another"),
11995 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
11996 http_writes, arraysize(http_writes));
11997 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11999 // Set up alternative service for origin.
12000 session_deps_.use_alternate_protocols = true;
12001 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12002 base::WeakPtr<HttpServerProperties> http_server_properties =
12003 session->http_server_properties();
12004 AlternativeService alternative_service(
12005 AlternateProtocolFromNextProto(GetParam()), alternative);
12006 http_server_properties->SetAlternativeService(origin, alternative_service,
12007 1.0);
12009 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
12010 HttpRequestInfo request1;
12011 request1.method = "GET";
12012 request1.url = GURL("https://origin.example.org:443");
12013 request1.load_flags = 0;
12014 TestCompletionCallback callback1;
12016 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
12017 rv = callback1.GetResult(rv);
12018 EXPECT_EQ(OK, rv);
12020 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
12021 ASSERT_TRUE(response1 != nullptr);
12022 ASSERT_TRUE(response1->headers.get() != nullptr);
12023 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12025 std::string response_data1;
12026 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
12027 EXPECT_EQ("foobar", response_data1);
12029 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12030 // for alternative service.
12031 EXPECT_TRUE(
12032 http_server_properties->IsAlternativeServiceBroken(alternative_service));
12034 // Since |alternative_service| is broken, a second transaction to origin
12035 // should not start an alternate Job. It should pool to existing connection
12036 // to origin.
12037 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
12038 HttpRequestInfo request2;
12039 request2.method = "GET";
12040 request2.url = GURL("https://origin.example.org:443/second");
12041 request2.load_flags = 0;
12042 TestCompletionCallback callback2;
12044 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
12045 rv = callback2.GetResult(rv);
12046 EXPECT_EQ(OK, rv);
12048 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
12049 ASSERT_TRUE(response2 != nullptr);
12050 ASSERT_TRUE(response2->headers.get() != nullptr);
12051 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
12053 std::string response_data2;
12054 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
12055 EXPECT_EQ("another", response_data2);
12058 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12059 // HTTP/1.1 socket open to the alternative server. That socket should not be
12060 // used.
12061 TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
12062 HostPortPair origin("origin.example.org", 443);
12063 HostPortPair alternative("alternative.example.org", 443);
12064 std::string origin_url = "https://origin.example.org:443";
12065 std::string alternative_url = "https://alternative.example.org:443";
12067 // Negotiate HTTP/1.1 with alternative.example.org.
12068 SSLSocketDataProvider ssl(ASYNC, OK);
12069 ssl.SetNextProto(kProtoHTTP11);
12070 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12072 // HTTP/1.1 data for |request1| and |request2|.
12073 MockWrite http_writes[] = {
12074 MockWrite(
12075 "GET / HTTP/1.1\r\n"
12076 "Host: alternative.example.org\r\n"
12077 "Connection: keep-alive\r\n\r\n"),
12078 MockWrite(
12079 "GET / HTTP/1.1\r\n"
12080 "Host: alternative.example.org\r\n"
12081 "Connection: keep-alive\r\n\r\n"),
12084 MockRead http_reads[] = {
12085 MockRead(
12086 "HTTP/1.1 200 OK\r\n"
12087 "Content-Type: text/html; charset=iso-8859-1\r\n"
12088 "Content-Length: 40\r\n\r\n"
12089 "first HTTP/1.1 response from alternative"),
12090 MockRead(
12091 "HTTP/1.1 200 OK\r\n"
12092 "Content-Type: text/html; charset=iso-8859-1\r\n"
12093 "Content-Length: 41\r\n\r\n"
12094 "second HTTP/1.1 response from alternative"),
12096 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12097 http_writes, arraysize(http_writes));
12098 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12100 // This test documents that an alternate Job should not pool to an already
12101 // existing HTTP/1.1 connection. In order to test this, a failed connection
12102 // to the origin is mocked. This way |request2| relies on the alternate Job.
12103 StaticSocketDataProvider data_refused;
12104 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12105 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12107 // Set up alternative service for origin.
12108 session_deps_.use_alternate_protocols = true;
12109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12110 base::WeakPtr<HttpServerProperties> http_server_properties =
12111 session->http_server_properties();
12112 AlternativeService alternative_service(
12113 AlternateProtocolFromNextProto(GetParam()), alternative);
12114 http_server_properties->SetAlternativeService(origin, alternative_service,
12115 1.0);
12117 // First transaction to alternative to open an HTTP/1.1 socket.
12118 scoped_ptr<HttpTransaction> trans1(
12119 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12120 HttpRequestInfo request1;
12121 request1.method = "GET";
12122 request1.url = GURL(alternative_url);
12123 request1.load_flags = 0;
12124 TestCompletionCallback callback1;
12126 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12127 EXPECT_EQ(OK, callback1.GetResult(rv));
12128 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12129 ASSERT_TRUE(response1);
12130 ASSERT_TRUE(response1->headers.get());
12131 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12132 EXPECT_TRUE(response1->was_npn_negotiated);
12133 EXPECT_FALSE(response1->was_fetched_via_spdy);
12134 std::string response_data1;
12135 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
12136 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
12138 // Request for origin.example.org, which has an alternative service. This
12139 // will start two Jobs: the alternative looks for connections to pool to,
12140 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12141 // open other connections to alternative server. The Job to origin fails, so
12142 // this request fails.
12143 scoped_ptr<HttpTransaction> trans2(
12144 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12145 HttpRequestInfo request2;
12146 request2.method = "GET";
12147 request2.url = GURL(origin_url);
12148 request2.load_flags = 0;
12149 TestCompletionCallback callback2;
12151 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
12152 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
12154 // Another transaction to alternative. This is to test that the HTTP/1.1
12155 // socket is still open and in the pool.
12156 scoped_ptr<HttpTransaction> trans3(
12157 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12158 HttpRequestInfo request3;
12159 request3.method = "GET";
12160 request3.url = GURL(alternative_url);
12161 request3.load_flags = 0;
12162 TestCompletionCallback callback3;
12164 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
12165 EXPECT_EQ(OK, callback3.GetResult(rv));
12166 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
12167 ASSERT_TRUE(response3);
12168 ASSERT_TRUE(response3->headers.get());
12169 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
12170 EXPECT_TRUE(response3->was_npn_negotiated);
12171 EXPECT_FALSE(response3->was_fetched_via_spdy);
12172 std::string response_data3;
12173 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
12174 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
12177 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
12178 const std::string https_url = "https://www.example.org:8080/";
12179 const std::string http_url = "http://www.example.org:8080/";
12181 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12182 const HostPortPair host_port_pair("www.example.org", 8080);
12183 scoped_ptr<SpdyFrame> connect(
12184 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
12185 scoped_ptr<SpdyFrame> req1(
12186 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
12187 scoped_ptr<SpdyFrame> wrapped_req1(
12188 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
12190 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12191 SpdyHeaderBlock req2_block;
12192 req2_block[spdy_util_.GetMethodKey()] = "GET";
12193 req2_block[spdy_util_.GetPathKey()] = "/";
12194 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
12195 req2_block[spdy_util_.GetSchemeKey()] = "http";
12196 spdy_util_.MaybeAddVersionHeader(&req2_block);
12197 scoped_ptr<SpdyFrame> req2(
12198 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
12200 MockWrite writes1[] = {
12201 CreateMockWrite(*connect, 0),
12202 CreateMockWrite(*wrapped_req1, 2),
12203 CreateMockWrite(*req2, 5),
12206 scoped_ptr<SpdyFrame> conn_resp(
12207 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12208 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12209 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12210 scoped_ptr<SpdyFrame> wrapped_resp1(
12211 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
12212 scoped_ptr<SpdyFrame> wrapped_body1(
12213 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
12214 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12215 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
12216 MockRead reads1[] = {
12217 CreateMockRead(*conn_resp, 1),
12218 CreateMockRead(*wrapped_resp1, 3),
12219 CreateMockRead(*wrapped_body1, 4),
12220 CreateMockRead(*resp2, 6),
12221 CreateMockRead(*body2, 7),
12222 MockRead(ASYNC, ERR_IO_PENDING, 8)
12225 DeterministicSocketData data1(reads1, arraysize(reads1),
12226 writes1, arraysize(writes1));
12227 MockConnect connect_data1(ASYNC, OK);
12228 data1.set_connect_data(connect_data1);
12230 session_deps_.proxy_service.reset(
12231 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12232 TestNetLog log;
12233 session_deps_.net_log = &log;
12234 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12235 ssl1.SetNextProto(GetParam());
12236 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12237 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12238 ssl2.SetNextProto(GetParam());
12239 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12240 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
12242 scoped_refptr<HttpNetworkSession> session(
12243 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12245 // Start the first transaction to set up the SpdySession
12246 HttpRequestInfo request1;
12247 request1.method = "GET";
12248 request1.url = GURL(https_url);
12249 request1.load_flags = 0;
12250 HttpNetworkTransaction trans1(LOWEST, session.get());
12251 TestCompletionCallback callback1;
12252 EXPECT_EQ(ERR_IO_PENDING,
12253 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12254 base::MessageLoop::current()->RunUntilIdle();
12255 data1.RunFor(4);
12257 EXPECT_EQ(OK, callback1.WaitForResult());
12258 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12260 LoadTimingInfo load_timing_info1;
12261 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
12262 TestLoadTimingNotReusedWithPac(load_timing_info1,
12263 CONNECT_TIMING_HAS_SSL_TIMES);
12265 // Now, start the HTTP request
12266 HttpRequestInfo request2;
12267 request2.method = "GET";
12268 request2.url = GURL(http_url);
12269 request2.load_flags = 0;
12270 HttpNetworkTransaction trans2(MEDIUM, session.get());
12271 TestCompletionCallback callback2;
12272 EXPECT_EQ(ERR_IO_PENDING,
12273 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12274 base::MessageLoop::current()->RunUntilIdle();
12275 data1.RunFor(3);
12277 EXPECT_EQ(OK, callback2.WaitForResult());
12278 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12280 LoadTimingInfo load_timing_info2;
12281 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
12282 // The established SPDY sessions is considered reused by the HTTP request.
12283 TestLoadTimingReusedWithPac(load_timing_info2);
12284 // HTTP requests over a SPDY session should have a different connection
12285 // socket_log_id than requests over a tunnel.
12286 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
12289 // Test that in the case where we have a SPDY session to a SPDY proxy
12290 // that we do not pool other origins that resolve to the same IP when
12291 // the certificate does not match the new origin.
12292 // http://crbug.com/134690
12293 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
12294 const std::string url1 = "http://www.example.org/";
12295 const std::string url2 = "https://news.example.org/";
12296 const std::string ip_addr = "1.2.3.4";
12298 // SPDY GET for HTTP URL (through SPDY proxy)
12299 scoped_ptr<SpdyHeaderBlock> headers(
12300 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12301 scoped_ptr<SpdyFrame> req1(
12302 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
12304 MockWrite writes1[] = {
12305 CreateMockWrite(*req1, 0),
12308 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12309 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12310 MockRead reads1[] = {
12311 CreateMockRead(*resp1, 1),
12312 CreateMockRead(*body1, 2),
12313 MockRead(ASYNC, OK, 3) // EOF
12316 scoped_ptr<DeterministicSocketData> data1(
12317 new DeterministicSocketData(reads1, arraysize(reads1),
12318 writes1, arraysize(writes1)));
12319 IPAddressNumber ip;
12320 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
12321 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12322 MockConnect connect_data1(ASYNC, OK, peer_addr);
12323 data1->set_connect_data(connect_data1);
12325 // SPDY GET for HTTPS URL (direct)
12326 scoped_ptr<SpdyFrame> req2(
12327 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
12329 MockWrite writes2[] = {
12330 CreateMockWrite(*req2, 0),
12333 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12334 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12335 MockRead reads2[] = {
12336 CreateMockRead(*resp2, 1),
12337 CreateMockRead(*body2, 2),
12338 MockRead(ASYNC, OK, 3) // EOF
12341 scoped_ptr<DeterministicSocketData> data2(
12342 new DeterministicSocketData(reads2, arraysize(reads2),
12343 writes2, arraysize(writes2)));
12344 MockConnect connect_data2(ASYNC, OK);
12345 data2->set_connect_data(connect_data2);
12347 // Set up a proxy config that sends HTTP requests to a proxy, and
12348 // all others direct.
12349 ProxyConfig proxy_config;
12350 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
12351 session_deps_.proxy_service.reset(new ProxyService(
12352 new ProxyConfigServiceFixed(proxy_config), nullptr, NULL));
12354 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12355 ssl1.SetNextProto(GetParam());
12356 // Load a valid cert. Note, that this does not need to
12357 // be valid for proxy because the MockSSLClientSocket does
12358 // not actually verify it. But SpdySession will use this
12359 // to see if it is valid for the new origin
12360 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12361 ASSERT_TRUE(ssl1.cert.get());
12362 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12363 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12364 data1.get());
12366 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12367 ssl2.SetNextProto(GetParam());
12368 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12369 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12370 data2.get());
12372 session_deps_.host_resolver.reset(new MockCachingHostResolver());
12373 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
12374 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
12376 scoped_refptr<HttpNetworkSession> session(
12377 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12379 // Start the first transaction to set up the SpdySession
12380 HttpRequestInfo request1;
12381 request1.method = "GET";
12382 request1.url = GURL(url1);
12383 request1.load_flags = 0;
12384 HttpNetworkTransaction trans1(LOWEST, session.get());
12385 TestCompletionCallback callback1;
12386 ASSERT_EQ(ERR_IO_PENDING,
12387 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12388 data1->RunFor(3);
12390 ASSERT_TRUE(callback1.have_result());
12391 EXPECT_EQ(OK, callback1.WaitForResult());
12392 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12394 // Now, start the HTTP request
12395 HttpRequestInfo request2;
12396 request2.method = "GET";
12397 request2.url = GURL(url2);
12398 request2.load_flags = 0;
12399 HttpNetworkTransaction trans2(MEDIUM, session.get());
12400 TestCompletionCallback callback2;
12401 EXPECT_EQ(ERR_IO_PENDING,
12402 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12403 base::MessageLoop::current()->RunUntilIdle();
12404 data2->RunFor(3);
12406 ASSERT_TRUE(callback2.have_result());
12407 EXPECT_EQ(OK, callback2.WaitForResult());
12408 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12411 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12412 // error) in SPDY session, removes the socket from pool and closes the SPDY
12413 // session. Verify that new url's from the same HttpNetworkSession (and a new
12414 // SpdySession) do work. http://crbug.com/224701
12415 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
12416 const std::string https_url = "https://www.example.org/";
12418 MockRead reads1[] = {
12419 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
12422 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
12424 scoped_ptr<SpdyFrame> req2(
12425 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
12426 MockWrite writes2[] = {
12427 CreateMockWrite(*req2, 0),
12430 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12431 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12432 MockRead reads2[] = {
12433 CreateMockRead(*resp2, 1),
12434 CreateMockRead(*body2, 2),
12435 MockRead(ASYNC, OK, 3) // EOF
12438 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
12439 arraysize(writes2));
12441 SSLSocketDataProvider ssl1(ASYNC, OK);
12442 ssl1.SetNextProto(GetParam());
12443 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12444 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12446 SSLSocketDataProvider ssl2(ASYNC, OK);
12447 ssl2.SetNextProto(GetParam());
12448 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12449 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12451 scoped_refptr<HttpNetworkSession> session(
12452 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
12454 // Start the first transaction to set up the SpdySession and verify that
12455 // connection was closed.
12456 HttpRequestInfo request1;
12457 request1.method = "GET";
12458 request1.url = GURL(https_url);
12459 request1.load_flags = 0;
12460 HttpNetworkTransaction trans1(MEDIUM, session.get());
12461 TestCompletionCallback callback1;
12462 EXPECT_EQ(ERR_IO_PENDING,
12463 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12464 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
12466 // Now, start the second request and make sure it succeeds.
12467 HttpRequestInfo request2;
12468 request2.method = "GET";
12469 request2.url = GURL(https_url);
12470 request2.load_flags = 0;
12471 HttpNetworkTransaction trans2(MEDIUM, session.get());
12472 TestCompletionCallback callback2;
12473 EXPECT_EQ(ERR_IO_PENDING,
12474 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12476 ASSERT_EQ(OK, callback2.WaitForResult());
12477 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12480 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
12481 session_deps_.next_protos = SpdyNextProtos();
12482 ClientSocketPoolManager::set_max_sockets_per_group(
12483 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12484 ClientSocketPoolManager::set_max_sockets_per_pool(
12485 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12487 // Use two different hosts with different IPs so they don't get pooled.
12488 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
12489 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
12490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12492 SSLSocketDataProvider ssl1(ASYNC, OK);
12493 ssl1.SetNextProto(GetParam());
12494 SSLSocketDataProvider ssl2(ASYNC, OK);
12495 ssl2.SetNextProto(GetParam());
12496 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12497 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12499 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
12500 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
12501 MockWrite spdy1_writes[] = {
12502 CreateMockWrite(*host1_req, 0),
12504 scoped_ptr<SpdyFrame> host1_resp(
12505 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12506 scoped_ptr<SpdyFrame> host1_resp_body(
12507 spdy_util_.ConstructSpdyBodyFrame(1, true));
12508 MockRead spdy1_reads[] = {
12509 CreateMockRead(*host1_resp, 1),
12510 CreateMockRead(*host1_resp_body, 2),
12511 MockRead(ASYNC, ERR_IO_PENDING, 3),
12514 scoped_ptr<SequencedSocketData> spdy1_data(
12515 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
12516 arraysize(spdy1_writes)));
12517 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
12519 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
12520 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
12521 MockWrite spdy2_writes[] = {
12522 CreateMockWrite(*host2_req, 0),
12524 scoped_ptr<SpdyFrame> host2_resp(
12525 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12526 scoped_ptr<SpdyFrame> host2_resp_body(
12527 spdy_util_.ConstructSpdyBodyFrame(1, true));
12528 MockRead spdy2_reads[] = {
12529 CreateMockRead(*host2_resp, 1),
12530 CreateMockRead(*host2_resp_body, 2),
12531 MockRead(ASYNC, ERR_IO_PENDING, 3),
12534 scoped_ptr<SequencedSocketData> spdy2_data(
12535 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
12536 arraysize(spdy2_writes)));
12537 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
12539 MockWrite http_write[] = {
12540 MockWrite("GET / HTTP/1.1\r\n"
12541 "Host: www.a.com\r\n"
12542 "Connection: keep-alive\r\n\r\n"),
12545 MockRead http_read[] = {
12546 MockRead("HTTP/1.1 200 OK\r\n"),
12547 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12548 MockRead("Content-Length: 6\r\n\r\n"),
12549 MockRead("hello!"),
12551 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
12552 http_write, arraysize(http_write));
12553 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12555 HostPortPair host_port_pair_a("www.a.com", 443);
12556 SpdySessionKey spdy_session_key_a(
12557 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12558 EXPECT_FALSE(
12559 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12561 TestCompletionCallback callback;
12562 HttpRequestInfo request1;
12563 request1.method = "GET";
12564 request1.url = GURL("https://www.a.com/");
12565 request1.load_flags = 0;
12566 scoped_ptr<HttpNetworkTransaction> trans(
12567 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12569 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
12570 EXPECT_EQ(ERR_IO_PENDING, rv);
12571 EXPECT_EQ(OK, callback.WaitForResult());
12573 const HttpResponseInfo* response = trans->GetResponseInfo();
12574 ASSERT_TRUE(response != NULL);
12575 ASSERT_TRUE(response->headers.get() != NULL);
12576 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12577 EXPECT_TRUE(response->was_fetched_via_spdy);
12578 EXPECT_TRUE(response->was_npn_negotiated);
12580 std::string response_data;
12581 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12582 EXPECT_EQ("hello!", response_data);
12583 trans.reset();
12584 EXPECT_TRUE(
12585 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12587 HostPortPair host_port_pair_b("www.b.com", 443);
12588 SpdySessionKey spdy_session_key_b(
12589 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12590 EXPECT_FALSE(
12591 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12592 HttpRequestInfo request2;
12593 request2.method = "GET";
12594 request2.url = GURL("https://www.b.com/");
12595 request2.load_flags = 0;
12596 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12598 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
12599 EXPECT_EQ(ERR_IO_PENDING, rv);
12600 EXPECT_EQ(OK, callback.WaitForResult());
12602 response = trans->GetResponseInfo();
12603 ASSERT_TRUE(response != NULL);
12604 ASSERT_TRUE(response->headers.get() != NULL);
12605 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12606 EXPECT_TRUE(response->was_fetched_via_spdy);
12607 EXPECT_TRUE(response->was_npn_negotiated);
12608 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12609 EXPECT_EQ("hello!", response_data);
12610 EXPECT_FALSE(
12611 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12612 EXPECT_TRUE(
12613 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12615 HostPortPair host_port_pair_a1("www.a.com", 80);
12616 SpdySessionKey spdy_session_key_a1(
12617 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12618 EXPECT_FALSE(
12619 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
12620 HttpRequestInfo request3;
12621 request3.method = "GET";
12622 request3.url = GURL("http://www.a.com/");
12623 request3.load_flags = 0;
12624 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12626 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
12627 EXPECT_EQ(ERR_IO_PENDING, rv);
12628 EXPECT_EQ(OK, callback.WaitForResult());
12630 response = trans->GetResponseInfo();
12631 ASSERT_TRUE(response != NULL);
12632 ASSERT_TRUE(response->headers.get() != NULL);
12633 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12634 EXPECT_FALSE(response->was_fetched_via_spdy);
12635 EXPECT_FALSE(response->was_npn_negotiated);
12636 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12637 EXPECT_EQ("hello!", response_data);
12638 EXPECT_FALSE(
12639 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12640 EXPECT_FALSE(
12641 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12644 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
12645 HttpRequestInfo request;
12646 request.method = "GET";
12647 request.url = GURL("http://www.example.org/");
12648 request.load_flags = 0;
12650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12651 scoped_ptr<HttpTransaction> trans(
12652 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12654 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
12655 StaticSocketDataProvider data;
12656 data.set_connect_data(mock_connect);
12657 session_deps_.socket_factory->AddSocketDataProvider(&data);
12659 TestCompletionCallback callback;
12661 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12662 EXPECT_EQ(ERR_IO_PENDING, rv);
12664 rv = callback.WaitForResult();
12665 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12667 // We don't care whether this succeeds or fails, but it shouldn't crash.
12668 HttpRequestHeaders request_headers;
12669 trans->GetFullRequestHeaders(&request_headers);
12671 ConnectionAttempts attempts;
12672 trans->GetConnectionAttempts(&attempts);
12673 ASSERT_EQ(1u, attempts.size());
12674 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12677 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
12678 HttpRequestInfo request;
12679 request.method = "GET";
12680 request.url = GURL("http://www.example.org/");
12681 request.load_flags = 0;
12683 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12684 scoped_ptr<HttpTransaction> trans(
12685 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12687 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12688 StaticSocketDataProvider data;
12689 data.set_connect_data(mock_connect);
12690 session_deps_.socket_factory->AddSocketDataProvider(&data);
12692 TestCompletionCallback callback;
12694 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12695 EXPECT_EQ(ERR_IO_PENDING, rv);
12697 rv = callback.WaitForResult();
12698 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12700 // We don't care whether this succeeds or fails, but it shouldn't crash.
12701 HttpRequestHeaders request_headers;
12702 trans->GetFullRequestHeaders(&request_headers);
12704 ConnectionAttempts attempts;
12705 trans->GetConnectionAttempts(&attempts);
12706 ASSERT_EQ(1u, attempts.size());
12707 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12710 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
12711 HttpRequestInfo request;
12712 request.method = "GET";
12713 request.url = GURL("http://www.example.org/");
12714 request.load_flags = 0;
12716 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12717 scoped_ptr<HttpTransaction> trans(
12718 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12720 MockWrite data_writes[] = {
12721 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12723 MockRead data_reads[] = {
12724 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12727 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12728 data_writes, arraysize(data_writes));
12729 session_deps_.socket_factory->AddSocketDataProvider(&data);
12731 TestCompletionCallback callback;
12733 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12734 EXPECT_EQ(ERR_IO_PENDING, rv);
12736 rv = callback.WaitForResult();
12737 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12739 HttpRequestHeaders request_headers;
12740 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12741 EXPECT_TRUE(request_headers.HasHeader("Host"));
12744 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
12745 HttpRequestInfo request;
12746 request.method = "GET";
12747 request.url = GURL("http://www.example.org/");
12748 request.load_flags = 0;
12750 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12751 scoped_ptr<HttpTransaction> trans(
12752 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12754 MockWrite data_writes[] = {
12755 MockWrite(ASYNC, ERR_CONNECTION_RESET),
12757 MockRead data_reads[] = {
12758 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12761 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12762 data_writes, arraysize(data_writes));
12763 session_deps_.socket_factory->AddSocketDataProvider(&data);
12765 TestCompletionCallback callback;
12767 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12768 EXPECT_EQ(ERR_IO_PENDING, rv);
12770 rv = callback.WaitForResult();
12771 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12773 HttpRequestHeaders request_headers;
12774 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12775 EXPECT_TRUE(request_headers.HasHeader("Host"));
12778 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
12779 HttpRequestInfo request;
12780 request.method = "GET";
12781 request.url = GURL("http://www.example.org/");
12782 request.load_flags = 0;
12784 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12785 scoped_ptr<HttpTransaction> trans(
12786 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12788 MockWrite data_writes[] = {
12789 MockWrite(
12790 "GET / HTTP/1.1\r\n"
12791 "Host: www.example.org\r\n"
12792 "Connection: keep-alive\r\n\r\n"),
12794 MockRead data_reads[] = {
12795 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
12798 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12799 data_writes, arraysize(data_writes));
12800 session_deps_.socket_factory->AddSocketDataProvider(&data);
12802 TestCompletionCallback callback;
12804 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12805 EXPECT_EQ(ERR_IO_PENDING, rv);
12807 rv = callback.WaitForResult();
12808 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12810 HttpRequestHeaders request_headers;
12811 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12812 EXPECT_TRUE(request_headers.HasHeader("Host"));
12815 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
12816 HttpRequestInfo request;
12817 request.method = "GET";
12818 request.url = GURL("http://www.example.org/");
12819 request.load_flags = 0;
12821 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12822 scoped_ptr<HttpTransaction> trans(
12823 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12825 MockWrite data_writes[] = {
12826 MockWrite(
12827 "GET / HTTP/1.1\r\n"
12828 "Host: www.example.org\r\n"
12829 "Connection: keep-alive\r\n\r\n"),
12831 MockRead data_reads[] = {
12832 MockRead(ASYNC, ERR_CONNECTION_RESET),
12835 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12836 data_writes, arraysize(data_writes));
12837 session_deps_.socket_factory->AddSocketDataProvider(&data);
12839 TestCompletionCallback callback;
12841 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12842 EXPECT_EQ(ERR_IO_PENDING, rv);
12844 rv = callback.WaitForResult();
12845 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12847 HttpRequestHeaders request_headers;
12848 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12849 EXPECT_TRUE(request_headers.HasHeader("Host"));
12852 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12853 HttpRequestInfo request;
12854 request.method = "GET";
12855 request.url = GURL("http://www.example.org/");
12856 request.load_flags = 0;
12857 request.extra_headers.SetHeader("X-Foo", "bar");
12859 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12860 scoped_ptr<HttpTransaction> trans(
12861 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12863 MockWrite data_writes[] = {
12864 MockWrite(
12865 "GET / HTTP/1.1\r\n"
12866 "Host: www.example.org\r\n"
12867 "Connection: keep-alive\r\n"
12868 "X-Foo: bar\r\n\r\n"),
12870 MockRead data_reads[] = {
12871 MockRead("HTTP/1.1 200 OK\r\n"
12872 "Content-Length: 5\r\n\r\n"
12873 "hello"),
12874 MockRead(ASYNC, ERR_UNEXPECTED),
12877 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12878 data_writes, arraysize(data_writes));
12879 session_deps_.socket_factory->AddSocketDataProvider(&data);
12881 TestCompletionCallback callback;
12883 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12884 EXPECT_EQ(ERR_IO_PENDING, rv);
12886 rv = callback.WaitForResult();
12887 EXPECT_EQ(OK, rv);
12889 HttpRequestHeaders request_headers;
12890 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12891 std::string foo;
12892 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12893 EXPECT_EQ("bar", foo);
12896 namespace {
12898 // Fake HttpStream that simply records calls to SetPriority().
12899 class FakeStream : public HttpStream,
12900 public base::SupportsWeakPtr<FakeStream> {
12901 public:
12902 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12903 ~FakeStream() override {}
12905 RequestPriority priority() const { return priority_; }
12907 int InitializeStream(const HttpRequestInfo* request_info,
12908 RequestPriority priority,
12909 const BoundNetLog& net_log,
12910 const CompletionCallback& callback) override {
12911 return ERR_IO_PENDING;
12914 int SendRequest(const HttpRequestHeaders& request_headers,
12915 HttpResponseInfo* response,
12916 const CompletionCallback& callback) override {
12917 ADD_FAILURE();
12918 return ERR_UNEXPECTED;
12921 int ReadResponseHeaders(const CompletionCallback& callback) override {
12922 ADD_FAILURE();
12923 return ERR_UNEXPECTED;
12926 int ReadResponseBody(IOBuffer* buf,
12927 int buf_len,
12928 const CompletionCallback& callback) override {
12929 ADD_FAILURE();
12930 return ERR_UNEXPECTED;
12933 void Close(bool not_reusable) override {}
12935 bool IsResponseBodyComplete() const override {
12936 ADD_FAILURE();
12937 return false;
12940 bool CanFindEndOfResponse() const override { return false; }
12942 bool IsConnectionReused() const override {
12943 ADD_FAILURE();
12944 return false;
12947 void SetConnectionReused() override { ADD_FAILURE(); }
12949 bool IsConnectionReusable() const override {
12950 ADD_FAILURE();
12951 return false;
12954 int64 GetTotalReceivedBytes() const override {
12955 ADD_FAILURE();
12956 return 0;
12959 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
12960 ADD_FAILURE();
12961 return false;
12964 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
12966 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
12967 ADD_FAILURE();
12970 bool IsSpdyHttpStream() const override {
12971 ADD_FAILURE();
12972 return false;
12975 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
12977 void SetPriority(RequestPriority priority) override { priority_ = priority; }
12979 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
12981 HttpStream* RenewStreamForAuth() override { return NULL; }
12983 private:
12984 RequestPriority priority_;
12986 DISALLOW_COPY_AND_ASSIGN(FakeStream);
12989 // Fake HttpStreamRequest that simply records calls to SetPriority()
12990 // and vends FakeStreams with its current priority.
12991 class FakeStreamRequest : public HttpStreamRequest,
12992 public base::SupportsWeakPtr<FakeStreamRequest> {
12993 public:
12994 FakeStreamRequest(RequestPriority priority,
12995 HttpStreamRequest::Delegate* delegate)
12996 : priority_(priority),
12997 delegate_(delegate),
12998 websocket_stream_create_helper_(NULL) {}
13000 FakeStreamRequest(RequestPriority priority,
13001 HttpStreamRequest::Delegate* delegate,
13002 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
13003 : priority_(priority),
13004 delegate_(delegate),
13005 websocket_stream_create_helper_(create_helper) {}
13007 ~FakeStreamRequest() override {}
13009 RequestPriority priority() const { return priority_; }
13011 const WebSocketHandshakeStreamBase::CreateHelper*
13012 websocket_stream_create_helper() const {
13013 return websocket_stream_create_helper_;
13016 // Create a new FakeStream and pass it to the request's
13017 // delegate. Returns a weak pointer to the FakeStream.
13018 base::WeakPtr<FakeStream> FinishStreamRequest() {
13019 FakeStream* fake_stream = new FakeStream(priority_);
13020 // Do this before calling OnStreamReady() as OnStreamReady() may
13021 // immediately delete |fake_stream|.
13022 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
13023 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
13024 return weak_stream;
13027 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
13028 ADD_FAILURE();
13029 return ERR_UNEXPECTED;
13032 LoadState GetLoadState() const override {
13033 ADD_FAILURE();
13034 return LoadState();
13037 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13039 bool was_npn_negotiated() const override { return false; }
13041 NextProto protocol_negotiated() const override { return kProtoUnknown; }
13043 bool using_spdy() const override { return false; }
13045 const ConnectionAttempts& connection_attempts() const override {
13046 static ConnectionAttempts no_attempts;
13047 return no_attempts;
13050 private:
13051 RequestPriority priority_;
13052 HttpStreamRequest::Delegate* const delegate_;
13053 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
13055 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
13058 // Fake HttpStreamFactory that vends FakeStreamRequests.
13059 class FakeStreamFactory : public HttpStreamFactory {
13060 public:
13061 FakeStreamFactory() {}
13062 ~FakeStreamFactory() override {}
13064 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13065 // RequestStream() (which may be NULL if it was destroyed already).
13066 base::WeakPtr<FakeStreamRequest> last_stream_request() {
13067 return last_stream_request_;
13070 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
13071 RequestPriority priority,
13072 const SSLConfig& server_ssl_config,
13073 const SSLConfig& proxy_ssl_config,
13074 HttpStreamRequest::Delegate* delegate,
13075 const BoundNetLog& net_log) override {
13076 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
13077 last_stream_request_ = fake_request->AsWeakPtr();
13078 return fake_request;
13081 HttpStreamRequest* RequestWebSocketHandshakeStream(
13082 const HttpRequestInfo& info,
13083 RequestPriority priority,
13084 const SSLConfig& server_ssl_config,
13085 const SSLConfig& proxy_ssl_config,
13086 HttpStreamRequest::Delegate* delegate,
13087 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
13088 const BoundNetLog& net_log) override {
13089 FakeStreamRequest* fake_request =
13090 new FakeStreamRequest(priority, delegate, create_helper);
13091 last_stream_request_ = fake_request->AsWeakPtr();
13092 return fake_request;
13095 void PreconnectStreams(int num_streams,
13096 const HttpRequestInfo& info,
13097 const SSLConfig& server_ssl_config,
13098 const SSLConfig& proxy_ssl_config) override {
13099 ADD_FAILURE();
13102 const HostMappingRules* GetHostMappingRules() const override {
13103 ADD_FAILURE();
13104 return NULL;
13107 private:
13108 base::WeakPtr<FakeStreamRequest> last_stream_request_;
13110 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
13113 // TODO(ricea): Maybe unify this with the one in
13114 // url_request_http_job_unittest.cc ?
13115 class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
13116 public:
13117 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
13118 bool using_proxy)
13119 : state_(connection.release(), using_proxy) {}
13121 // Fake implementation of HttpStreamBase methods.
13122 // This ends up being quite "real" because this object has to really send data
13123 // on the mock socket. It might be easier to use the real implementation, but
13124 // the fact that the WebSocket code is not compiled on iOS makes that
13125 // difficult.
13126 int InitializeStream(const HttpRequestInfo* request_info,
13127 RequestPriority priority,
13128 const BoundNetLog& net_log,
13129 const CompletionCallback& callback) override {
13130 state_.Initialize(request_info, priority, net_log, callback);
13131 return OK;
13134 int SendRequest(const HttpRequestHeaders& request_headers,
13135 HttpResponseInfo* response,
13136 const CompletionCallback& callback) override {
13137 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
13138 response, callback);
13141 int ReadResponseHeaders(const CompletionCallback& callback) override {
13142 return parser()->ReadResponseHeaders(callback);
13145 int ReadResponseBody(IOBuffer* buf,
13146 int buf_len,
13147 const CompletionCallback& callback) override {
13148 NOTREACHED();
13149 return ERR_IO_PENDING;
13152 void Close(bool not_reusable) override {
13153 if (parser())
13154 parser()->Close(true);
13157 bool IsResponseBodyComplete() const override {
13158 NOTREACHED();
13159 return false;
13162 bool CanFindEndOfResponse() const override {
13163 return parser()->CanFindEndOfResponse();
13166 bool IsConnectionReused() const override {
13167 NOTREACHED();
13168 return false;
13170 void SetConnectionReused() override { NOTREACHED(); }
13172 bool IsConnectionReusable() const override {
13173 NOTREACHED();
13174 return false;
13177 int64 GetTotalReceivedBytes() const override {
13178 NOTREACHED();
13179 return 0;
13182 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13183 NOTREACHED();
13184 return false;
13187 void GetSSLInfo(SSLInfo* ssl_info) override {}
13189 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13190 NOTREACHED();
13193 bool IsSpdyHttpStream() const override {
13194 NOTREACHED();
13195 return false;
13198 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
13200 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
13202 UploadProgress GetUploadProgress() const override {
13203 NOTREACHED();
13204 return UploadProgress();
13207 HttpStream* RenewStreamForAuth() override {
13208 NOTREACHED();
13209 return nullptr;
13212 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13213 scoped_ptr<WebSocketStream> Upgrade() override {
13214 NOTREACHED();
13215 return scoped_ptr<WebSocketStream>();
13218 private:
13219 HttpStreamParser* parser() const { return state_.parser(); }
13220 HttpBasicState state_;
13222 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
13225 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13226 // worth doing.
13227 class FakeWebSocketStreamCreateHelper :
13228 public WebSocketHandshakeStreamBase::CreateHelper {
13229 public:
13230 WebSocketHandshakeStreamBase* CreateBasicStream(
13231 scoped_ptr<ClientSocketHandle> connection,
13232 bool using_proxy) override {
13233 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
13234 using_proxy);
13237 WebSocketHandshakeStreamBase* CreateSpdyStream(
13238 const base::WeakPtr<SpdySession>& session,
13239 bool use_relative_url) override {
13240 NOTREACHED();
13241 return NULL;
13244 ~FakeWebSocketStreamCreateHelper() override {}
13246 virtual scoped_ptr<WebSocketStream> Upgrade() {
13247 NOTREACHED();
13248 return scoped_ptr<WebSocketStream>();
13252 } // namespace
13254 // Make sure that HttpNetworkTransaction passes on its priority to its
13255 // stream request on start.
13256 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
13257 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13258 HttpNetworkSessionPeer peer(session);
13259 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13260 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13262 HttpNetworkTransaction trans(LOW, session.get());
13264 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
13266 HttpRequestInfo request;
13267 TestCompletionCallback callback;
13268 EXPECT_EQ(ERR_IO_PENDING,
13269 trans.Start(&request, callback.callback(), BoundNetLog()));
13271 base::WeakPtr<FakeStreamRequest> fake_request =
13272 fake_factory->last_stream_request();
13273 ASSERT_TRUE(fake_request != NULL);
13274 EXPECT_EQ(LOW, fake_request->priority());
13277 // Make sure that HttpNetworkTransaction passes on its priority
13278 // updates to its stream request.
13279 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
13280 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13281 HttpNetworkSessionPeer peer(session);
13282 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13283 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13285 HttpNetworkTransaction trans(LOW, session.get());
13287 HttpRequestInfo request;
13288 TestCompletionCallback callback;
13289 EXPECT_EQ(ERR_IO_PENDING,
13290 trans.Start(&request, callback.callback(), BoundNetLog()));
13292 base::WeakPtr<FakeStreamRequest> fake_request =
13293 fake_factory->last_stream_request();
13294 ASSERT_TRUE(fake_request != NULL);
13295 EXPECT_EQ(LOW, fake_request->priority());
13297 trans.SetPriority(LOWEST);
13298 ASSERT_TRUE(fake_request != NULL);
13299 EXPECT_EQ(LOWEST, fake_request->priority());
13302 // Make sure that HttpNetworkTransaction passes on its priority
13303 // updates to its stream.
13304 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
13305 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13306 HttpNetworkSessionPeer peer(session);
13307 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13308 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13310 HttpNetworkTransaction trans(LOW, session.get());
13312 HttpRequestInfo request;
13313 TestCompletionCallback callback;
13314 EXPECT_EQ(ERR_IO_PENDING,
13315 trans.Start(&request, callback.callback(), BoundNetLog()));
13317 base::WeakPtr<FakeStreamRequest> fake_request =
13318 fake_factory->last_stream_request();
13319 ASSERT_TRUE(fake_request != NULL);
13320 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
13321 ASSERT_TRUE(fake_stream != NULL);
13322 EXPECT_EQ(LOW, fake_stream->priority());
13324 trans.SetPriority(LOWEST);
13325 EXPECT_EQ(LOWEST, fake_stream->priority());
13328 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
13329 // The same logic needs to be tested for both ws: and wss: schemes, but this
13330 // test is already parameterised on NextProto, so it uses a loop to verify
13331 // that the different schemes work.
13332 std::string test_cases[] = {"ws://www.example.org/",
13333 "wss://www.example.org/"};
13334 for (size_t i = 0; i < arraysize(test_cases); ++i) {
13335 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13336 HttpNetworkSessionPeer peer(session);
13337 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13338 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13339 peer.SetHttpStreamFactoryForWebSocket(
13340 scoped_ptr<HttpStreamFactory>(fake_factory));
13342 HttpNetworkTransaction trans(LOW, session.get());
13343 trans.SetWebSocketHandshakeStreamCreateHelper(
13344 &websocket_stream_create_helper);
13346 HttpRequestInfo request;
13347 TestCompletionCallback callback;
13348 request.method = "GET";
13349 request.url = GURL(test_cases[i]);
13351 EXPECT_EQ(ERR_IO_PENDING,
13352 trans.Start(&request, callback.callback(), BoundNetLog()));
13354 base::WeakPtr<FakeStreamRequest> fake_request =
13355 fake_factory->last_stream_request();
13356 ASSERT_TRUE(fake_request != NULL);
13357 EXPECT_EQ(&websocket_stream_create_helper,
13358 fake_request->websocket_stream_create_helper());
13362 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13363 // if the transport socket pool is stalled on the global socket limit.
13364 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
13365 ClientSocketPoolManager::set_max_sockets_per_group(
13366 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13367 ClientSocketPoolManager::set_max_sockets_per_pool(
13368 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13370 // Set up SSL request.
13372 HttpRequestInfo ssl_request;
13373 ssl_request.method = "GET";
13374 ssl_request.url = GURL("https://www.example.org/");
13376 MockWrite ssl_writes[] = {
13377 MockWrite(
13378 "GET / HTTP/1.1\r\n"
13379 "Host: www.example.org\r\n"
13380 "Connection: keep-alive\r\n\r\n"),
13382 MockRead ssl_reads[] = {
13383 MockRead("HTTP/1.1 200 OK\r\n"),
13384 MockRead("Content-Length: 11\r\n\r\n"),
13385 MockRead("hello world"),
13386 MockRead(SYNCHRONOUS, OK),
13388 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
13389 ssl_writes, arraysize(ssl_writes));
13390 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13392 SSLSocketDataProvider ssl(ASYNC, OK);
13393 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13395 // Set up HTTP request.
13397 HttpRequestInfo http_request;
13398 http_request.method = "GET";
13399 http_request.url = GURL("http://www.example.org/");
13401 MockWrite http_writes[] = {
13402 MockWrite(
13403 "GET / HTTP/1.1\r\n"
13404 "Host: www.example.org\r\n"
13405 "Connection: keep-alive\r\n\r\n"),
13407 MockRead http_reads[] = {
13408 MockRead("HTTP/1.1 200 OK\r\n"),
13409 MockRead("Content-Length: 7\r\n\r\n"),
13410 MockRead("falafel"),
13411 MockRead(SYNCHRONOUS, OK),
13413 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13414 http_writes, arraysize(http_writes));
13415 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13417 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13419 // Start the SSL request.
13420 TestCompletionCallback ssl_callback;
13421 scoped_ptr<HttpTransaction> ssl_trans(
13422 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13423 ASSERT_EQ(ERR_IO_PENDING,
13424 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
13425 BoundNetLog()));
13427 // Start the HTTP request. Pool should stall.
13428 TestCompletionCallback http_callback;
13429 scoped_ptr<HttpTransaction> http_trans(
13430 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13431 ASSERT_EQ(ERR_IO_PENDING,
13432 http_trans->Start(&http_request, http_callback.callback(),
13433 BoundNetLog()));
13434 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13436 // Wait for response from SSL request.
13437 ASSERT_EQ(OK, ssl_callback.WaitForResult());
13438 std::string response_data;
13439 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
13440 EXPECT_EQ("hello world", response_data);
13442 // The SSL socket should automatically be closed, so the HTTP request can
13443 // start.
13444 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13445 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
13447 // The HTTP request can now complete.
13448 ASSERT_EQ(OK, http_callback.WaitForResult());
13449 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13450 EXPECT_EQ("falafel", response_data);
13452 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13455 // Tests that when a SSL connection is established but there's no corresponding
13456 // request that needs it, the new socket is closed if the transport socket pool
13457 // is stalled on the global socket limit.
13458 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
13459 ClientSocketPoolManager::set_max_sockets_per_group(
13460 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13461 ClientSocketPoolManager::set_max_sockets_per_pool(
13462 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13464 // Set up an ssl request.
13466 HttpRequestInfo ssl_request;
13467 ssl_request.method = "GET";
13468 ssl_request.url = GURL("https://www.foopy.com/");
13470 // No data will be sent on the SSL socket.
13471 StaticSocketDataProvider ssl_data;
13472 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13474 SSLSocketDataProvider ssl(ASYNC, OK);
13475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13477 // Set up HTTP request.
13479 HttpRequestInfo http_request;
13480 http_request.method = "GET";
13481 http_request.url = GURL("http://www.example.org/");
13483 MockWrite http_writes[] = {
13484 MockWrite(
13485 "GET / HTTP/1.1\r\n"
13486 "Host: www.example.org\r\n"
13487 "Connection: keep-alive\r\n\r\n"),
13489 MockRead http_reads[] = {
13490 MockRead("HTTP/1.1 200 OK\r\n"),
13491 MockRead("Content-Length: 7\r\n\r\n"),
13492 MockRead("falafel"),
13493 MockRead(SYNCHRONOUS, OK),
13495 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13496 http_writes, arraysize(http_writes));
13497 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13499 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13501 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13502 // cancelled when a normal transaction is cancelled.
13503 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
13504 SSLConfig ssl_config;
13505 session->ssl_config_service()->GetSSLConfig(&ssl_config);
13506 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
13507 ssl_config);
13508 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13510 // Start the HTTP request. Pool should stall.
13511 TestCompletionCallback http_callback;
13512 scoped_ptr<HttpTransaction> http_trans(
13513 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13514 ASSERT_EQ(ERR_IO_PENDING,
13515 http_trans->Start(&http_request, http_callback.callback(),
13516 BoundNetLog()));
13517 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13519 // The SSL connection will automatically be closed once the connection is
13520 // established, to let the HTTP request start.
13521 ASSERT_EQ(OK, http_callback.WaitForResult());
13522 std::string response_data;
13523 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13524 EXPECT_EQ("falafel", response_data);
13526 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13529 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
13530 ScopedVector<UploadElementReader> element_readers;
13531 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13532 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13534 HttpRequestInfo request;
13535 request.method = "POST";
13536 request.url = GURL("http://www.foo.com/");
13537 request.upload_data_stream = &upload_data_stream;
13538 request.load_flags = 0;
13540 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13541 scoped_ptr<HttpTransaction> trans(
13542 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13543 // Send headers successfully, but get an error while sending the body.
13544 MockWrite data_writes[] = {
13545 MockWrite("POST / HTTP/1.1\r\n"
13546 "Host: www.foo.com\r\n"
13547 "Connection: keep-alive\r\n"
13548 "Content-Length: 3\r\n\r\n"),
13549 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13552 MockRead data_reads[] = {
13553 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13554 MockRead("hello world"),
13555 MockRead(SYNCHRONOUS, OK),
13557 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13558 arraysize(data_writes));
13559 session_deps_.socket_factory->AddSocketDataProvider(&data);
13561 TestCompletionCallback callback;
13563 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13564 EXPECT_EQ(ERR_IO_PENDING, rv);
13566 rv = callback.WaitForResult();
13567 EXPECT_EQ(OK, rv);
13569 const HttpResponseInfo* response = trans->GetResponseInfo();
13570 ASSERT_TRUE(response != NULL);
13572 EXPECT_TRUE(response->headers.get() != NULL);
13573 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13575 std::string response_data;
13576 rv = ReadTransaction(trans.get(), &response_data);
13577 EXPECT_EQ(OK, rv);
13578 EXPECT_EQ("hello world", response_data);
13581 // This test makes sure the retry logic doesn't trigger when reading an error
13582 // response from a server that rejected a POST with a CONNECTION_RESET.
13583 TEST_P(HttpNetworkTransactionTest,
13584 PostReadsErrorResponseAfterResetOnReusedSocket) {
13585 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13586 MockWrite data_writes[] = {
13587 MockWrite("GET / HTTP/1.1\r\n"
13588 "Host: www.foo.com\r\n"
13589 "Connection: keep-alive\r\n\r\n"),
13590 MockWrite("POST / HTTP/1.1\r\n"
13591 "Host: www.foo.com\r\n"
13592 "Connection: keep-alive\r\n"
13593 "Content-Length: 3\r\n\r\n"),
13594 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13597 MockRead data_reads[] = {
13598 MockRead("HTTP/1.1 200 Peachy\r\n"
13599 "Content-Length: 14\r\n\r\n"),
13600 MockRead("first response"),
13601 MockRead("HTTP/1.1 400 Not OK\r\n"
13602 "Content-Length: 15\r\n\r\n"),
13603 MockRead("second response"),
13604 MockRead(SYNCHRONOUS, OK),
13606 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13607 arraysize(data_writes));
13608 session_deps_.socket_factory->AddSocketDataProvider(&data);
13610 TestCompletionCallback callback;
13611 HttpRequestInfo request1;
13612 request1.method = "GET";
13613 request1.url = GURL("http://www.foo.com/");
13614 request1.load_flags = 0;
13616 scoped_ptr<HttpTransaction> trans1(
13617 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13618 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
13619 EXPECT_EQ(ERR_IO_PENDING, rv);
13621 rv = callback.WaitForResult();
13622 EXPECT_EQ(OK, rv);
13624 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13625 ASSERT_TRUE(response1 != NULL);
13627 EXPECT_TRUE(response1->headers.get() != NULL);
13628 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
13630 std::string response_data1;
13631 rv = ReadTransaction(trans1.get(), &response_data1);
13632 EXPECT_EQ(OK, rv);
13633 EXPECT_EQ("first response", response_data1);
13634 // Delete the transaction to release the socket back into the socket pool.
13635 trans1.reset();
13637 ScopedVector<UploadElementReader> element_readers;
13638 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13639 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13641 HttpRequestInfo request2;
13642 request2.method = "POST";
13643 request2.url = GURL("http://www.foo.com/");
13644 request2.upload_data_stream = &upload_data_stream;
13645 request2.load_flags = 0;
13647 scoped_ptr<HttpTransaction> trans2(
13648 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13649 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
13650 EXPECT_EQ(ERR_IO_PENDING, rv);
13652 rv = callback.WaitForResult();
13653 EXPECT_EQ(OK, rv);
13655 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
13656 ASSERT_TRUE(response2 != NULL);
13658 EXPECT_TRUE(response2->headers.get() != NULL);
13659 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
13661 std::string response_data2;
13662 rv = ReadTransaction(trans2.get(), &response_data2);
13663 EXPECT_EQ(OK, rv);
13664 EXPECT_EQ("second response", response_data2);
13667 TEST_P(HttpNetworkTransactionTest,
13668 PostReadsErrorResponseAfterResetPartialBodySent) {
13669 ScopedVector<UploadElementReader> element_readers;
13670 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13671 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13673 HttpRequestInfo request;
13674 request.method = "POST";
13675 request.url = GURL("http://www.foo.com/");
13676 request.upload_data_stream = &upload_data_stream;
13677 request.load_flags = 0;
13679 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13680 scoped_ptr<HttpTransaction> trans(
13681 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13682 // Send headers successfully, but get an error while sending the body.
13683 MockWrite data_writes[] = {
13684 MockWrite("POST / HTTP/1.1\r\n"
13685 "Host: www.foo.com\r\n"
13686 "Connection: keep-alive\r\n"
13687 "Content-Length: 3\r\n\r\n"
13688 "fo"),
13689 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13692 MockRead data_reads[] = {
13693 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13694 MockRead("hello world"),
13695 MockRead(SYNCHRONOUS, OK),
13697 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13698 arraysize(data_writes));
13699 session_deps_.socket_factory->AddSocketDataProvider(&data);
13701 TestCompletionCallback callback;
13703 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13704 EXPECT_EQ(ERR_IO_PENDING, rv);
13706 rv = callback.WaitForResult();
13707 EXPECT_EQ(OK, rv);
13709 const HttpResponseInfo* response = trans->GetResponseInfo();
13710 ASSERT_TRUE(response != NULL);
13712 EXPECT_TRUE(response->headers.get() != NULL);
13713 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13715 std::string response_data;
13716 rv = ReadTransaction(trans.get(), &response_data);
13717 EXPECT_EQ(OK, rv);
13718 EXPECT_EQ("hello world", response_data);
13721 // This tests the more common case than the previous test, where headers and
13722 // body are not merged into a single request.
13723 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
13724 ScopedVector<UploadElementReader> element_readers;
13725 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13726 ChunkedUploadDataStream upload_data_stream(0);
13728 HttpRequestInfo request;
13729 request.method = "POST";
13730 request.url = GURL("http://www.foo.com/");
13731 request.upload_data_stream = &upload_data_stream;
13732 request.load_flags = 0;
13734 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13735 scoped_ptr<HttpTransaction> trans(
13736 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13737 // Send headers successfully, but get an error while sending the body.
13738 MockWrite data_writes[] = {
13739 MockWrite("POST / HTTP/1.1\r\n"
13740 "Host: www.foo.com\r\n"
13741 "Connection: keep-alive\r\n"
13742 "Transfer-Encoding: chunked\r\n\r\n"),
13743 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13746 MockRead data_reads[] = {
13747 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13748 MockRead("hello world"),
13749 MockRead(SYNCHRONOUS, OK),
13751 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13752 arraysize(data_writes));
13753 session_deps_.socket_factory->AddSocketDataProvider(&data);
13755 TestCompletionCallback callback;
13757 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13758 EXPECT_EQ(ERR_IO_PENDING, rv);
13759 // Make sure the headers are sent before adding a chunk. This ensures that
13760 // they can't be merged with the body in a single send. Not currently
13761 // necessary since a chunked body is never merged with headers, but this makes
13762 // the test more future proof.
13763 base::RunLoop().RunUntilIdle();
13765 upload_data_stream.AppendData("last chunk", 10, true);
13767 rv = callback.WaitForResult();
13768 EXPECT_EQ(OK, rv);
13770 const HttpResponseInfo* response = trans->GetResponseInfo();
13771 ASSERT_TRUE(response != NULL);
13773 EXPECT_TRUE(response->headers.get() != NULL);
13774 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13776 std::string response_data;
13777 rv = ReadTransaction(trans.get(), &response_data);
13778 EXPECT_EQ(OK, rv);
13779 EXPECT_EQ("hello world", response_data);
13782 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
13783 ScopedVector<UploadElementReader> element_readers;
13784 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13785 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13787 HttpRequestInfo request;
13788 request.method = "POST";
13789 request.url = GURL("http://www.foo.com/");
13790 request.upload_data_stream = &upload_data_stream;
13791 request.load_flags = 0;
13793 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13794 scoped_ptr<HttpTransaction> trans(
13795 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13797 MockWrite data_writes[] = {
13798 MockWrite("POST / HTTP/1.1\r\n"
13799 "Host: www.foo.com\r\n"
13800 "Connection: keep-alive\r\n"
13801 "Content-Length: 3\r\n\r\n"),
13802 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13805 MockRead data_reads[] = {
13806 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13807 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13808 MockRead("hello world"),
13809 MockRead(SYNCHRONOUS, OK),
13811 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13812 arraysize(data_writes));
13813 session_deps_.socket_factory->AddSocketDataProvider(&data);
13815 TestCompletionCallback callback;
13817 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13818 EXPECT_EQ(ERR_IO_PENDING, rv);
13820 rv = callback.WaitForResult();
13821 EXPECT_EQ(OK, rv);
13823 const HttpResponseInfo* response = trans->GetResponseInfo();
13824 ASSERT_TRUE(response != NULL);
13826 EXPECT_TRUE(response->headers.get() != NULL);
13827 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13829 std::string response_data;
13830 rv = ReadTransaction(trans.get(), &response_data);
13831 EXPECT_EQ(OK, rv);
13832 EXPECT_EQ("hello world", response_data);
13835 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
13836 ScopedVector<UploadElementReader> element_readers;
13837 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13838 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13840 HttpRequestInfo request;
13841 request.method = "POST";
13842 request.url = GURL("http://www.foo.com/");
13843 request.upload_data_stream = &upload_data_stream;
13844 request.load_flags = 0;
13846 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13847 scoped_ptr<HttpTransaction> trans(
13848 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13849 // Send headers successfully, but get an error while sending the body.
13850 MockWrite data_writes[] = {
13851 MockWrite("POST / HTTP/1.1\r\n"
13852 "Host: www.foo.com\r\n"
13853 "Connection: keep-alive\r\n"
13854 "Content-Length: 3\r\n\r\n"),
13855 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13858 MockRead data_reads[] = {
13859 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13860 MockRead("hello world"),
13861 MockRead(SYNCHRONOUS, OK),
13863 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13864 arraysize(data_writes));
13865 session_deps_.socket_factory->AddSocketDataProvider(&data);
13867 TestCompletionCallback callback;
13869 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13870 EXPECT_EQ(ERR_IO_PENDING, rv);
13872 rv = callback.WaitForResult();
13873 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13876 TEST_P(HttpNetworkTransactionTest,
13877 PostIgnoresNonErrorResponseAfterResetAnd100) {
13878 ScopedVector<UploadElementReader> element_readers;
13879 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13880 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13882 HttpRequestInfo request;
13883 request.method = "POST";
13884 request.url = GURL("http://www.foo.com/");
13885 request.upload_data_stream = &upload_data_stream;
13886 request.load_flags = 0;
13888 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13889 scoped_ptr<HttpTransaction> trans(
13890 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13891 // Send headers successfully, but get an error while sending the body.
13892 MockWrite data_writes[] = {
13893 MockWrite("POST / HTTP/1.1\r\n"
13894 "Host: www.foo.com\r\n"
13895 "Connection: keep-alive\r\n"
13896 "Content-Length: 3\r\n\r\n"),
13897 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13900 MockRead data_reads[] = {
13901 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13902 MockRead("HTTP/1.0 302 Redirect\r\n"),
13903 MockRead("Location: http://somewhere-else.com/\r\n"),
13904 MockRead("Content-Length: 0\r\n\r\n"),
13905 MockRead(SYNCHRONOUS, OK),
13907 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13908 arraysize(data_writes));
13909 session_deps_.socket_factory->AddSocketDataProvider(&data);
13911 TestCompletionCallback callback;
13913 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13914 EXPECT_EQ(ERR_IO_PENDING, rv);
13916 rv = callback.WaitForResult();
13917 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13920 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
13921 ScopedVector<UploadElementReader> element_readers;
13922 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13923 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13925 HttpRequestInfo request;
13926 request.method = "POST";
13927 request.url = GURL("http://www.foo.com/");
13928 request.upload_data_stream = &upload_data_stream;
13929 request.load_flags = 0;
13931 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13932 scoped_ptr<HttpTransaction> trans(
13933 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13934 // Send headers successfully, but get an error while sending the body.
13935 MockWrite data_writes[] = {
13936 MockWrite("POST / HTTP/1.1\r\n"
13937 "Host: www.foo.com\r\n"
13938 "Connection: keep-alive\r\n"
13939 "Content-Length: 3\r\n\r\n"),
13940 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13943 MockRead data_reads[] = {
13944 MockRead("HTTP 0.9 rocks!"),
13945 MockRead(SYNCHRONOUS, OK),
13947 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13948 arraysize(data_writes));
13949 session_deps_.socket_factory->AddSocketDataProvider(&data);
13951 TestCompletionCallback callback;
13953 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13954 EXPECT_EQ(ERR_IO_PENDING, rv);
13956 rv = callback.WaitForResult();
13957 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13960 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
13961 ScopedVector<UploadElementReader> element_readers;
13962 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13963 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13965 HttpRequestInfo request;
13966 request.method = "POST";
13967 request.url = GURL("http://www.foo.com/");
13968 request.upload_data_stream = &upload_data_stream;
13969 request.load_flags = 0;
13971 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13972 scoped_ptr<HttpTransaction> trans(
13973 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13974 // Send headers successfully, but get an error while sending the body.
13975 MockWrite data_writes[] = {
13976 MockWrite("POST / HTTP/1.1\r\n"
13977 "Host: www.foo.com\r\n"
13978 "Connection: keep-alive\r\n"
13979 "Content-Length: 3\r\n\r\n"),
13980 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13983 MockRead data_reads[] = {
13984 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13985 MockRead(SYNCHRONOUS, OK),
13987 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13988 arraysize(data_writes));
13989 session_deps_.socket_factory->AddSocketDataProvider(&data);
13991 TestCompletionCallback callback;
13993 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13994 EXPECT_EQ(ERR_IO_PENDING, rv);
13996 rv = callback.WaitForResult();
13997 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14000 // Verify that proxy headers are not sent to the destination server when
14001 // establishing a tunnel for a secure WebSocket connection.
14002 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
14003 HttpRequestInfo request;
14004 request.method = "GET";
14005 request.url = GURL("wss://www.example.org/");
14006 AddWebSocketHeaders(&request.extra_headers);
14008 // Configure against proxy server "myproxy:70".
14009 session_deps_.proxy_service.reset(
14010 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14012 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14014 // Since a proxy is configured, try to establish a tunnel.
14015 MockWrite data_writes[] = {
14016 MockWrite(
14017 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14018 "Host: www.example.org\r\n"
14019 "Proxy-Connection: keep-alive\r\n\r\n"),
14021 // After calling trans->RestartWithAuth(), this is the request we should
14022 // be issuing -- the final header line contains the credentials.
14023 MockWrite(
14024 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14025 "Host: www.example.org\r\n"
14026 "Proxy-Connection: keep-alive\r\n"
14027 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14029 MockWrite(
14030 "GET / HTTP/1.1\r\n"
14031 "Host: www.example.org\r\n"
14032 "Connection: Upgrade\r\n"
14033 "Upgrade: websocket\r\n"
14034 "Origin: http://www.example.org\r\n"
14035 "Sec-WebSocket-Version: 13\r\n"
14036 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14039 // The proxy responds to the connect with a 407, using a persistent
14040 // connection.
14041 MockRead data_reads[] = {
14042 // No credentials.
14043 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14044 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14045 MockRead("Proxy-Connection: close\r\n\r\n"),
14047 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14049 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14050 MockRead("Upgrade: websocket\r\n"),
14051 MockRead("Connection: Upgrade\r\n"),
14052 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14055 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14056 arraysize(data_writes));
14057 session_deps_.socket_factory->AddSocketDataProvider(&data);
14058 SSLSocketDataProvider ssl(ASYNC, OK);
14059 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14061 scoped_ptr<HttpTransaction> trans(
14062 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14063 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14064 trans->SetWebSocketHandshakeStreamCreateHelper(
14065 &websocket_stream_create_helper);
14068 TestCompletionCallback callback;
14070 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14071 EXPECT_EQ(ERR_IO_PENDING, rv);
14073 rv = callback.WaitForResult();
14074 EXPECT_EQ(OK, rv);
14077 const HttpResponseInfo* response = trans->GetResponseInfo();
14078 ASSERT_TRUE(response);
14079 ASSERT_TRUE(response->headers.get());
14080 EXPECT_EQ(407, response->headers->response_code());
14083 TestCompletionCallback callback;
14085 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
14086 callback.callback());
14087 EXPECT_EQ(ERR_IO_PENDING, rv);
14089 rv = callback.WaitForResult();
14090 EXPECT_EQ(OK, rv);
14093 response = trans->GetResponseInfo();
14094 ASSERT_TRUE(response);
14095 ASSERT_TRUE(response->headers.get());
14097 EXPECT_EQ(101, response->headers->response_code());
14099 trans.reset();
14100 session->CloseAllConnections();
14103 // Verify that proxy headers are not sent to the destination server when
14104 // establishing a tunnel for an insecure WebSocket connection.
14105 // This requires the authentication info to be injected into the auth cache
14106 // due to crbug.com/395064
14107 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14108 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
14109 HttpRequestInfo request;
14110 request.method = "GET";
14111 request.url = GURL("ws://www.example.org/");
14112 AddWebSocketHeaders(&request.extra_headers);
14114 // Configure against proxy server "myproxy:70".
14115 session_deps_.proxy_service.reset(
14116 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14118 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14120 MockWrite data_writes[] = {
14121 // Try to establish a tunnel for the WebSocket connection, with
14122 // credentials. Because WebSockets have a separate set of socket pools,
14123 // they cannot and will not use the same TCP/IP connection as the
14124 // preflight HTTP request.
14125 MockWrite(
14126 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14127 "Host: www.example.org:80\r\n"
14128 "Proxy-Connection: keep-alive\r\n"
14129 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14131 MockWrite(
14132 "GET / HTTP/1.1\r\n"
14133 "Host: www.example.org\r\n"
14134 "Connection: Upgrade\r\n"
14135 "Upgrade: websocket\r\n"
14136 "Origin: http://www.example.org\r\n"
14137 "Sec-WebSocket-Version: 13\r\n"
14138 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14141 MockRead data_reads[] = {
14142 // HTTP CONNECT with credentials.
14143 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14145 // WebSocket connection established inside tunnel.
14146 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14147 MockRead("Upgrade: websocket\r\n"),
14148 MockRead("Connection: Upgrade\r\n"),
14149 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14152 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14153 arraysize(data_writes));
14154 session_deps_.socket_factory->AddSocketDataProvider(&data);
14156 session->http_auth_cache()->Add(
14157 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
14158 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
14160 scoped_ptr<HttpTransaction> trans(
14161 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14162 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14163 trans->SetWebSocketHandshakeStreamCreateHelper(
14164 &websocket_stream_create_helper);
14166 TestCompletionCallback callback;
14168 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14169 EXPECT_EQ(ERR_IO_PENDING, rv);
14171 rv = callback.WaitForResult();
14172 EXPECT_EQ(OK, rv);
14174 const HttpResponseInfo* response = trans->GetResponseInfo();
14175 ASSERT_TRUE(response);
14176 ASSERT_TRUE(response->headers.get());
14178 EXPECT_EQ(101, response->headers->response_code());
14180 trans.reset();
14181 session->CloseAllConnections();
14184 } // namespace net