Update broken references to image assets
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blobf2637776848f8d70ff90d8ac41cef2bd15a14bf7
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 std::string GetAlternativeServiceHttpHeader() {
292 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
293 "=\"www.example.com:443\"\r\n";
296 std::string GetAlternateProtocolHttpHeader() {
297 return std::string("Alternate-Protocol: 443:") +
298 GetAlternateProtocolFromParam() + "\r\n";
301 // Either |write_failure| specifies a write failure or |read_failure|
302 // specifies a read failure when using a reused socket. In either case, the
303 // failure should cause the network transaction to resend the request, and the
304 // other argument should be NULL.
305 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
306 const MockRead* read_failure);
308 // Either |write_failure| specifies a write failure or |read_failure|
309 // specifies a read failure when using a reused socket. In either case, the
310 // failure should cause the network transaction to resend the request, and the
311 // other argument should be NULL.
312 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
313 const MockRead* read_failure,
314 bool use_spdy);
316 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
317 size_t data_count) {
318 SimpleGetHelperResult out;
320 HttpRequestInfo request;
321 request.method = "GET";
322 request.url = GURL("http://www.example.org/");
323 request.load_flags = 0;
325 BoundTestNetLog log;
326 session_deps_.net_log = log.bound().net_log();
327 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
328 scoped_ptr<HttpTransaction> trans(
329 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
331 for (size_t i = 0; i < data_count; ++i) {
332 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
335 TestCompletionCallback callback;
337 EXPECT_TRUE(log.bound().IsCapturing());
338 int rv = trans->Start(&request, callback.callback(), log.bound());
339 EXPECT_EQ(ERR_IO_PENDING, rv);
341 out.rv = callback.WaitForResult();
343 // Even in the failure cases that use this function, connections are always
344 // successfully established before the error.
345 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
346 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
348 if (out.rv != OK)
349 return out;
351 const HttpResponseInfo* response = trans->GetResponseInfo();
352 // Can't use ASSERT_* inside helper functions like this, so
353 // return an error.
354 if (response == NULL || response->headers.get() == NULL) {
355 out.rv = ERR_UNEXPECTED;
356 return out;
358 out.status_line = response->headers->GetStatusLine();
360 EXPECT_EQ("127.0.0.1", response->socket_address.host());
361 EXPECT_EQ(80, response->socket_address.port());
363 rv = ReadTransaction(trans.get(), &out.response_data);
364 EXPECT_EQ(OK, rv);
366 TestNetLogEntry::List entries;
367 log.GetEntries(&entries);
368 size_t pos = ExpectLogContainsSomewhere(
369 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
370 NetLog::PHASE_NONE);
371 ExpectLogContainsSomewhere(
372 entries, pos,
373 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
374 NetLog::PHASE_NONE);
376 std::string line;
377 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
378 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
380 HttpRequestHeaders request_headers;
381 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
382 std::string value;
383 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
384 EXPECT_EQ("www.example.org", value);
385 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
386 EXPECT_EQ("keep-alive", value);
388 std::string response_headers;
389 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
390 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
391 response_headers);
393 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
394 trans->GetConnectionAttempts(&out.connection_attempts);
395 return out;
398 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
399 size_t reads_count) {
400 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
401 StaticSocketDataProvider* data[] = { &reads };
402 return SimpleGetHelperForData(data, 1);
405 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
406 int64 size = 0;
407 for (size_t i = 0; i < reads_count; ++i)
408 size += data_reads[i].data_len;
409 return size;
412 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
413 int expected_status);
415 void ConnectStatusHelper(const MockRead& status);
417 void BypassHostCacheOnRefreshHelper(int load_flags);
419 void CheckErrorIsPassedBack(int error, IoMode mode);
421 SpdyTestUtil spdy_util_;
422 SpdySessionDependencies session_deps_;
424 // Original socket limits. Some tests set these. Safest to always restore
425 // them once each test has been run.
426 int old_max_group_sockets_;
427 int old_max_pool_sockets_;
430 INSTANTIATE_TEST_CASE_P(NextProto,
431 HttpNetworkTransactionTest,
432 testing::Values(kProtoSPDY31,
433 kProtoHTTP2_14,
434 kProtoHTTP2));
436 namespace {
438 class BeforeNetworkStartHandler {
439 public:
440 explicit BeforeNetworkStartHandler(bool defer)
441 : defer_on_before_network_start_(defer),
442 observed_before_network_start_(false) {}
444 void OnBeforeNetworkStart(bool* defer) {
445 *defer = defer_on_before_network_start_;
446 observed_before_network_start_ = true;
449 bool observed_before_network_start() const {
450 return observed_before_network_start_;
453 private:
454 const bool defer_on_before_network_start_;
455 bool observed_before_network_start_;
457 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
460 class BeforeProxyHeadersSentHandler {
461 public:
462 BeforeProxyHeadersSentHandler()
463 : observed_before_proxy_headers_sent_(false) {}
465 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
466 HttpRequestHeaders* request_headers) {
467 observed_before_proxy_headers_sent_ = true;
468 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
471 bool observed_before_proxy_headers_sent() const {
472 return observed_before_proxy_headers_sent_;
475 std::string observed_proxy_server_uri() const {
476 return observed_proxy_server_uri_;
479 private:
480 bool observed_before_proxy_headers_sent_;
481 std::string observed_proxy_server_uri_;
483 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
486 // Fill |str| with a long header list that consumes >= |size| bytes.
487 void FillLargeHeadersString(std::string* str, int size) {
488 const char row[] =
489 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
490 const int sizeof_row = strlen(row);
491 const int num_rows = static_cast<int>(
492 ceil(static_cast<float>(size) / sizeof_row));
493 const int sizeof_data = num_rows * sizeof_row;
494 DCHECK(sizeof_data >= size);
495 str->reserve(sizeof_data);
497 for (int i = 0; i < num_rows; ++i)
498 str->append(row, sizeof_row);
501 #if defined(NTLM_PORTABLE)
502 // Alternative functions that eliminate randomness and dependency on the local
503 // host name so that the generated NTLM messages are reproducible.
504 void MockGenerateRandom1(uint8* output, size_t n) {
505 static const uint8 bytes[] = {
506 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
508 static size_t current_byte = 0;
509 for (size_t i = 0; i < n; ++i) {
510 output[i] = bytes[current_byte++];
511 current_byte %= arraysize(bytes);
515 void MockGenerateRandom2(uint8* output, size_t n) {
516 static const uint8 bytes[] = {
517 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
518 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
520 static size_t current_byte = 0;
521 for (size_t i = 0; i < n; ++i) {
522 output[i] = bytes[current_byte++];
523 current_byte %= arraysize(bytes);
527 std::string MockGetHostName() {
528 return "WTC-WIN7";
530 #endif // defined(NTLM_PORTABLE)
532 template<typename ParentPool>
533 class CaptureGroupNameSocketPool : public ParentPool {
534 public:
535 CaptureGroupNameSocketPool(HostResolver* host_resolver,
536 CertVerifier* cert_verifier);
538 const std::string last_group_name_received() const {
539 return last_group_name_;
542 int RequestSocket(const std::string& group_name,
543 const void* socket_params,
544 RequestPriority priority,
545 ClientSocketHandle* handle,
546 const CompletionCallback& callback,
547 const BoundNetLog& net_log) override {
548 last_group_name_ = group_name;
549 return ERR_IO_PENDING;
551 void CancelRequest(const std::string& group_name,
552 ClientSocketHandle* handle) override {}
553 void ReleaseSocket(const std::string& group_name,
554 scoped_ptr<StreamSocket> socket,
555 int id) override {}
556 void CloseIdleSockets() override {}
557 int IdleSocketCount() const override { return 0; }
558 int IdleSocketCountInGroup(const std::string& group_name) const override {
559 return 0;
561 LoadState GetLoadState(const std::string& group_name,
562 const ClientSocketHandle* handle) const override {
563 return LOAD_STATE_IDLE;
565 base::TimeDelta ConnectionTimeout() const override {
566 return base::TimeDelta();
569 private:
570 std::string last_group_name_;
573 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
574 CaptureGroupNameTransportSocketPool;
575 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
576 CaptureGroupNameHttpProxySocketPool;
577 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
578 CaptureGroupNameSOCKSSocketPool;
579 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
580 CaptureGroupNameSSLSocketPool;
582 template <typename ParentPool>
583 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
584 HostResolver* host_resolver,
585 CertVerifier* /* cert_verifier */)
586 : ParentPool(0, 0, host_resolver, NULL, NULL) {
589 template <>
590 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
591 HostResolver* /* host_resolver */,
592 CertVerifier* /* cert_verifier */)
593 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
596 template <>
597 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
598 HostResolver* /* host_resolver */,
599 CertVerifier* cert_verifier)
600 : SSLClientSocketPool(0,
602 cert_verifier,
603 NULL,
604 NULL,
605 NULL,
606 NULL,
607 std::string(),
608 NULL,
609 NULL,
610 NULL,
611 NULL,
612 NULL,
613 NULL) {
616 //-----------------------------------------------------------------------------
618 // Helper functions for validating that AuthChallengeInfo's are correctly
619 // configured for common cases.
620 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
621 if (!auth_challenge)
622 return false;
623 EXPECT_FALSE(auth_challenge->is_proxy);
624 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
625 EXPECT_EQ("MyRealm1", auth_challenge->realm);
626 EXPECT_EQ("basic", auth_challenge->scheme);
627 return true;
630 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
631 if (!auth_challenge)
632 return false;
633 EXPECT_TRUE(auth_challenge->is_proxy);
634 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
635 EXPECT_EQ("MyRealm1", auth_challenge->realm);
636 EXPECT_EQ("basic", auth_challenge->scheme);
637 return true;
640 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
641 if (!auth_challenge)
642 return false;
643 EXPECT_FALSE(auth_challenge->is_proxy);
644 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
645 EXPECT_EQ("digestive", auth_challenge->realm);
646 EXPECT_EQ("digest", auth_challenge->scheme);
647 return true;
650 #if defined(NTLM_PORTABLE)
651 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
652 if (!auth_challenge)
653 return false;
654 EXPECT_FALSE(auth_challenge->is_proxy);
655 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
656 EXPECT_EQ(std::string(), auth_challenge->realm);
657 EXPECT_EQ("ntlm", auth_challenge->scheme);
658 return true;
660 #endif // defined(NTLM_PORTABLE)
662 } // namespace
664 TEST_P(HttpNetworkTransactionTest, Basic) {
665 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
666 scoped_ptr<HttpTransaction> trans(
667 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
670 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
671 MockRead data_reads[] = {
672 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
673 MockRead("hello world"),
674 MockRead(SYNCHRONOUS, OK),
676 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
677 arraysize(data_reads));
678 EXPECT_EQ(OK, out.rv);
679 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
680 EXPECT_EQ("hello world", out.response_data);
681 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
682 EXPECT_EQ(reads_size, out.totalReceivedBytes);
683 EXPECT_EQ(0u, out.connection_attempts.size());
686 // Response with no status line.
687 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
688 MockRead data_reads[] = {
689 MockRead("hello world"),
690 MockRead(SYNCHRONOUS, OK),
692 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
693 arraysize(data_reads));
694 EXPECT_EQ(OK, out.rv);
695 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
696 EXPECT_EQ("hello world", out.response_data);
697 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
698 EXPECT_EQ(reads_size, out.totalReceivedBytes);
701 // Allow up to 4 bytes of junk to precede status line.
702 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
703 MockRead data_reads[] = {
704 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
705 MockRead(SYNCHRONOUS, OK),
707 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
708 arraysize(data_reads));
709 EXPECT_EQ(OK, out.rv);
710 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
711 EXPECT_EQ("DATA", out.response_data);
712 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
713 EXPECT_EQ(reads_size, out.totalReceivedBytes);
716 // Allow up to 4 bytes of junk to precede status line.
717 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
718 MockRead data_reads[] = {
719 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
720 MockRead(SYNCHRONOUS, OK),
722 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
723 arraysize(data_reads));
724 EXPECT_EQ(OK, out.rv);
725 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
726 EXPECT_EQ("DATA", out.response_data);
727 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
728 EXPECT_EQ(reads_size, out.totalReceivedBytes);
731 // Beyond 4 bytes of slop and it should fail to find a status line.
732 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
733 MockRead data_reads[] = {
734 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
735 MockRead(SYNCHRONOUS, OK),
737 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
738 arraysize(data_reads));
739 EXPECT_EQ(OK, out.rv);
740 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
741 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
742 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
743 EXPECT_EQ(reads_size, out.totalReceivedBytes);
746 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
747 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
748 MockRead data_reads[] = {
749 MockRead("\n"),
750 MockRead("\n"),
751 MockRead("Q"),
752 MockRead("J"),
753 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
754 MockRead(SYNCHRONOUS, OK),
756 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
757 arraysize(data_reads));
758 EXPECT_EQ(OK, out.rv);
759 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
760 EXPECT_EQ("DATA", out.response_data);
761 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
762 EXPECT_EQ(reads_size, out.totalReceivedBytes);
765 // Close the connection before enough bytes to have a status line.
766 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
767 MockRead data_reads[] = {
768 MockRead("HTT"),
769 MockRead(SYNCHRONOUS, OK),
771 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
772 arraysize(data_reads));
773 EXPECT_EQ(OK, out.rv);
774 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
775 EXPECT_EQ("HTT", out.response_data);
776 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
777 EXPECT_EQ(reads_size, out.totalReceivedBytes);
780 // Simulate a 204 response, lacking a Content-Length header, sent over a
781 // persistent connection. The response should still terminate since a 204
782 // cannot have a response body.
783 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
784 char junk[] = "junk";
785 MockRead data_reads[] = {
786 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
787 MockRead(junk), // Should not be read!!
788 MockRead(SYNCHRONOUS, OK),
790 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
791 arraysize(data_reads));
792 EXPECT_EQ(OK, out.rv);
793 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
794 EXPECT_EQ("", out.response_data);
795 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
796 int64 response_size = reads_size - strlen(junk);
797 EXPECT_EQ(response_size, out.totalReceivedBytes);
800 // A simple request using chunked encoding with some extra data after.
801 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
802 std::string final_chunk = "0\r\n\r\n";
803 std::string extra_data = "HTTP/1.1 200 OK\r\n";
804 std::string last_read = final_chunk + extra_data;
805 MockRead data_reads[] = {
806 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
807 MockRead("5\r\nHello\r\n"),
808 MockRead("1\r\n"),
809 MockRead(" \r\n"),
810 MockRead("5\r\nworld\r\n"),
811 MockRead(last_read.data()),
812 MockRead(SYNCHRONOUS, OK),
814 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
815 arraysize(data_reads));
816 EXPECT_EQ(OK, out.rv);
817 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
818 EXPECT_EQ("Hello world", out.response_data);
819 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
820 int64 response_size = reads_size - extra_data.size();
821 EXPECT_EQ(response_size, out.totalReceivedBytes);
824 // Next tests deal with http://crbug.com/56344.
826 TEST_P(HttpNetworkTransactionTest,
827 MultipleContentLengthHeadersNoTransferEncoding) {
828 MockRead data_reads[] = {
829 MockRead("HTTP/1.1 200 OK\r\n"),
830 MockRead("Content-Length: 10\r\n"),
831 MockRead("Content-Length: 5\r\n\r\n"),
833 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
834 arraysize(data_reads));
835 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
838 TEST_P(HttpNetworkTransactionTest,
839 DuplicateContentLengthHeadersNoTransferEncoding) {
840 MockRead data_reads[] = {
841 MockRead("HTTP/1.1 200 OK\r\n"),
842 MockRead("Content-Length: 5\r\n"),
843 MockRead("Content-Length: 5\r\n\r\n"),
844 MockRead("Hello"),
846 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
847 arraysize(data_reads));
848 EXPECT_EQ(OK, out.rv);
849 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
850 EXPECT_EQ("Hello", out.response_data);
853 TEST_P(HttpNetworkTransactionTest,
854 ComplexContentLengthHeadersNoTransferEncoding) {
855 // More than 2 dupes.
857 MockRead data_reads[] = {
858 MockRead("HTTP/1.1 200 OK\r\n"),
859 MockRead("Content-Length: 5\r\n"),
860 MockRead("Content-Length: 5\r\n"),
861 MockRead("Content-Length: 5\r\n\r\n"),
862 MockRead("Hello"),
864 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
865 arraysize(data_reads));
866 EXPECT_EQ(OK, out.rv);
867 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
868 EXPECT_EQ("Hello", out.response_data);
870 // HTTP/1.0
872 MockRead data_reads[] = {
873 MockRead("HTTP/1.0 200 OK\r\n"),
874 MockRead("Content-Length: 5\r\n"),
875 MockRead("Content-Length: 5\r\n"),
876 MockRead("Content-Length: 5\r\n\r\n"),
877 MockRead("Hello"),
879 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
880 arraysize(data_reads));
881 EXPECT_EQ(OK, out.rv);
882 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
883 EXPECT_EQ("Hello", out.response_data);
885 // 2 dupes and one mismatched.
887 MockRead data_reads[] = {
888 MockRead("HTTP/1.1 200 OK\r\n"),
889 MockRead("Content-Length: 10\r\n"),
890 MockRead("Content-Length: 10\r\n"),
891 MockRead("Content-Length: 5\r\n\r\n"),
893 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
894 arraysize(data_reads));
895 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
899 TEST_P(HttpNetworkTransactionTest,
900 MultipleContentLengthHeadersTransferEncoding) {
901 MockRead data_reads[] = {
902 MockRead("HTTP/1.1 200 OK\r\n"),
903 MockRead("Content-Length: 666\r\n"),
904 MockRead("Content-Length: 1337\r\n"),
905 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
906 MockRead("5\r\nHello\r\n"),
907 MockRead("1\r\n"),
908 MockRead(" \r\n"),
909 MockRead("5\r\nworld\r\n"),
910 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
911 MockRead(SYNCHRONOUS, OK),
913 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
914 arraysize(data_reads));
915 EXPECT_EQ(OK, out.rv);
916 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
917 EXPECT_EQ("Hello world", out.response_data);
920 // Next tests deal with http://crbug.com/98895.
922 // Checks that a single Content-Disposition header results in no error.
923 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
924 MockRead data_reads[] = {
925 MockRead("HTTP/1.1 200 OK\r\n"),
926 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
927 MockRead("Content-Length: 5\r\n\r\n"),
928 MockRead("Hello"),
930 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
931 arraysize(data_reads));
932 EXPECT_EQ(OK, out.rv);
933 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
934 EXPECT_EQ("Hello", out.response_data);
937 // Checks that two identical Content-Disposition headers result in no error.
938 TEST_P(HttpNetworkTransactionTest,
939 TwoIdenticalContentDispositionHeaders) {
940 MockRead data_reads[] = {
941 MockRead("HTTP/1.1 200 OK\r\n"),
942 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
943 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
944 MockRead("Content-Length: 5\r\n\r\n"),
945 MockRead("Hello"),
947 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
948 arraysize(data_reads));
949 EXPECT_EQ(OK, out.rv);
950 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
951 EXPECT_EQ("Hello", out.response_data);
954 // Checks that two distinct Content-Disposition headers result in an error.
955 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
956 MockRead data_reads[] = {
957 MockRead("HTTP/1.1 200 OK\r\n"),
958 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
959 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
960 MockRead("Content-Length: 5\r\n\r\n"),
961 MockRead("Hello"),
963 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
964 arraysize(data_reads));
965 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
968 // Checks that two identical Location headers result in no error.
969 // Also tests Location header behavior.
970 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
971 MockRead data_reads[] = {
972 MockRead("HTTP/1.1 302 Redirect\r\n"),
973 MockRead("Location: http://good.com/\r\n"),
974 MockRead("Location: http://good.com/\r\n"),
975 MockRead("Content-Length: 0\r\n\r\n"),
976 MockRead(SYNCHRONOUS, OK),
979 HttpRequestInfo request;
980 request.method = "GET";
981 request.url = GURL("http://redirect.com/");
982 request.load_flags = 0;
984 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
985 scoped_ptr<HttpTransaction> trans(
986 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
988 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
989 session_deps_.socket_factory->AddSocketDataProvider(&data);
991 TestCompletionCallback callback;
993 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
994 EXPECT_EQ(ERR_IO_PENDING, rv);
996 EXPECT_EQ(OK, callback.WaitForResult());
998 const HttpResponseInfo* response = trans->GetResponseInfo();
999 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
1000 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1001 std::string url;
1002 EXPECT_TRUE(response->headers->IsRedirect(&url));
1003 EXPECT_EQ("http://good.com/", url);
1004 EXPECT_TRUE(response->proxy_server.IsEmpty());
1007 // Checks that two distinct Location headers result in an error.
1008 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
1009 MockRead data_reads[] = {
1010 MockRead("HTTP/1.1 302 Redirect\r\n"),
1011 MockRead("Location: http://good.com/\r\n"),
1012 MockRead("Location: http://evil.com/\r\n"),
1013 MockRead("Content-Length: 0\r\n\r\n"),
1014 MockRead(SYNCHRONOUS, OK),
1016 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1017 arraysize(data_reads));
1018 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1021 // Do a request using the HEAD method. Verify that we don't try to read the
1022 // message body (since HEAD has none).
1023 TEST_P(HttpNetworkTransactionTest, Head) {
1024 HttpRequestInfo request;
1025 request.method = "HEAD";
1026 request.url = GURL("http://www.example.org/");
1027 request.load_flags = 0;
1029 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1030 scoped_ptr<HttpTransaction> trans(
1031 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1032 BeforeProxyHeadersSentHandler proxy_headers_handler;
1033 trans->SetBeforeProxyHeadersSentCallback(
1034 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1035 base::Unretained(&proxy_headers_handler)));
1037 MockWrite data_writes1[] = {
1038 MockWrite("HEAD / HTTP/1.1\r\n"
1039 "Host: www.example.org\r\n"
1040 "Connection: keep-alive\r\n\r\n"),
1042 MockRead data_reads1[] = {
1043 MockRead("HTTP/1.1 404 Not Found\r\n"),
1044 MockRead("Server: Blah\r\n"),
1045 MockRead("Content-Length: 1234\r\n\r\n"),
1047 // No response body because the test stops reading here.
1048 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1051 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1052 data_writes1, arraysize(data_writes1));
1053 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1055 TestCompletionCallback callback1;
1057 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1058 EXPECT_EQ(ERR_IO_PENDING, rv);
1060 rv = callback1.WaitForResult();
1061 EXPECT_EQ(OK, rv);
1063 const HttpResponseInfo* response = trans->GetResponseInfo();
1064 ASSERT_TRUE(response != NULL);
1066 // Check that the headers got parsed.
1067 EXPECT_TRUE(response->headers.get() != NULL);
1068 EXPECT_EQ(1234, response->headers->GetContentLength());
1069 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1070 EXPECT_TRUE(response->proxy_server.IsEmpty());
1071 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1073 std::string server_header;
1074 void* iter = NULL;
1075 bool has_server_header = response->headers->EnumerateHeader(
1076 &iter, "Server", &server_header);
1077 EXPECT_TRUE(has_server_header);
1078 EXPECT_EQ("Blah", server_header);
1080 // Reading should give EOF right away, since there is no message body
1081 // (despite non-zero content-length).
1082 std::string response_data;
1083 rv = ReadTransaction(trans.get(), &response_data);
1084 EXPECT_EQ(OK, rv);
1085 EXPECT_EQ("", response_data);
1088 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1089 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1091 MockRead data_reads[] = {
1092 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1093 MockRead("hello"),
1094 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1095 MockRead("world"),
1096 MockRead(SYNCHRONOUS, OK),
1098 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1099 session_deps_.socket_factory->AddSocketDataProvider(&data);
1101 const char* const kExpectedResponseData[] = {
1102 "hello", "world"
1105 for (int i = 0; i < 2; ++i) {
1106 HttpRequestInfo request;
1107 request.method = "GET";
1108 request.url = GURL("http://www.example.org/");
1109 request.load_flags = 0;
1111 scoped_ptr<HttpTransaction> trans(
1112 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1114 TestCompletionCallback callback;
1116 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1117 EXPECT_EQ(ERR_IO_PENDING, rv);
1119 rv = callback.WaitForResult();
1120 EXPECT_EQ(OK, rv);
1122 const HttpResponseInfo* response = trans->GetResponseInfo();
1123 ASSERT_TRUE(response != NULL);
1125 EXPECT_TRUE(response->headers.get() != NULL);
1126 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1127 EXPECT_TRUE(response->proxy_server.IsEmpty());
1129 std::string response_data;
1130 rv = ReadTransaction(trans.get(), &response_data);
1131 EXPECT_EQ(OK, rv);
1132 EXPECT_EQ(kExpectedResponseData[i], response_data);
1136 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1137 ScopedVector<UploadElementReader> element_readers;
1138 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1139 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
1141 HttpRequestInfo request;
1142 request.method = "POST";
1143 request.url = GURL("http://www.foo.com/");
1144 request.upload_data_stream = &upload_data_stream;
1145 request.load_flags = 0;
1147 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1148 scoped_ptr<HttpTransaction> trans(
1149 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1151 MockRead data_reads[] = {
1152 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1153 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1154 MockRead("hello world"),
1155 MockRead(SYNCHRONOUS, OK),
1157 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1158 session_deps_.socket_factory->AddSocketDataProvider(&data);
1160 TestCompletionCallback callback;
1162 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1163 EXPECT_EQ(ERR_IO_PENDING, rv);
1165 rv = callback.WaitForResult();
1166 EXPECT_EQ(OK, rv);
1168 const HttpResponseInfo* response = trans->GetResponseInfo();
1169 ASSERT_TRUE(response != NULL);
1171 EXPECT_TRUE(response->headers.get() != NULL);
1172 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1174 std::string response_data;
1175 rv = ReadTransaction(trans.get(), &response_data);
1176 EXPECT_EQ(OK, rv);
1177 EXPECT_EQ("hello world", response_data);
1180 // This test is almost the same as Ignores100 above, but the response contains
1181 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1182 // HTTP/1.1 and the two status headers are read in one read.
1183 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1184 HttpRequestInfo request;
1185 request.method = "GET";
1186 request.url = GURL("http://www.foo.com/");
1187 request.load_flags = 0;
1189 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1190 scoped_ptr<HttpTransaction> trans(
1191 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1193 MockRead data_reads[] = {
1194 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1195 "HTTP/1.1 200 OK\r\n\r\n"),
1196 MockRead("hello world"),
1197 MockRead(SYNCHRONOUS, OK),
1199 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1200 session_deps_.socket_factory->AddSocketDataProvider(&data);
1202 TestCompletionCallback callback;
1204 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1205 EXPECT_EQ(ERR_IO_PENDING, rv);
1207 rv = callback.WaitForResult();
1208 EXPECT_EQ(OK, rv);
1210 const HttpResponseInfo* response = trans->GetResponseInfo();
1211 ASSERT_TRUE(response != NULL);
1213 EXPECT_TRUE(response->headers.get() != NULL);
1214 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1216 std::string response_data;
1217 rv = ReadTransaction(trans.get(), &response_data);
1218 EXPECT_EQ(OK, rv);
1219 EXPECT_EQ("hello world", response_data);
1222 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1223 HttpRequestInfo request;
1224 request.method = "POST";
1225 request.url = GURL("http://www.foo.com/");
1226 request.load_flags = 0;
1228 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1229 scoped_ptr<HttpTransaction> trans(
1230 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1232 MockRead data_reads[] = {
1233 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1234 MockRead(ASYNC, 0),
1236 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1237 session_deps_.socket_factory->AddSocketDataProvider(&data);
1239 TestCompletionCallback callback;
1241 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1242 EXPECT_EQ(ERR_IO_PENDING, rv);
1244 rv = callback.WaitForResult();
1245 EXPECT_EQ(OK, rv);
1247 std::string response_data;
1248 rv = ReadTransaction(trans.get(), &response_data);
1249 EXPECT_EQ(OK, rv);
1250 EXPECT_EQ("", response_data);
1253 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1254 HttpRequestInfo request;
1255 request.method = "POST";
1256 request.url = GURL("http://www.foo.com/");
1257 request.load_flags = 0;
1259 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1260 scoped_ptr<HttpTransaction> trans(
1261 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1263 MockRead data_reads[] = {
1264 MockRead(ASYNC, 0),
1266 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1267 session_deps_.socket_factory->AddSocketDataProvider(&data);
1269 TestCompletionCallback callback;
1271 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1272 EXPECT_EQ(ERR_IO_PENDING, rv);
1274 rv = callback.WaitForResult();
1275 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1278 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1279 const MockWrite* write_failure,
1280 const MockRead* read_failure) {
1281 HttpRequestInfo request;
1282 request.method = "GET";
1283 request.url = GURL("http://www.foo.com/");
1284 request.load_flags = 0;
1286 TestNetLog net_log;
1287 session_deps_.net_log = &net_log;
1288 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1290 // Written data for successfully sending both requests.
1291 MockWrite data1_writes[] = {
1292 MockWrite("GET / HTTP/1.1\r\n"
1293 "Host: www.foo.com\r\n"
1294 "Connection: keep-alive\r\n\r\n"),
1295 MockWrite("GET / HTTP/1.1\r\n"
1296 "Host: www.foo.com\r\n"
1297 "Connection: keep-alive\r\n\r\n")
1300 // Read results for the first request.
1301 MockRead data1_reads[] = {
1302 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1303 MockRead("hello"),
1304 MockRead(ASYNC, OK),
1307 if (write_failure) {
1308 ASSERT_FALSE(read_failure);
1309 data1_writes[1] = *write_failure;
1310 } else {
1311 ASSERT_TRUE(read_failure);
1312 data1_reads[2] = *read_failure;
1315 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1316 data1_writes, arraysize(data1_writes));
1317 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1319 MockRead data2_reads[] = {
1320 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1321 MockRead("world"),
1322 MockRead(ASYNC, OK),
1324 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1325 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1327 const char* const kExpectedResponseData[] = {
1328 "hello", "world"
1331 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1332 for (int i = 0; i < 2; ++i) {
1333 TestCompletionCallback callback;
1335 scoped_ptr<HttpTransaction> trans(
1336 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1338 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1339 EXPECT_EQ(ERR_IO_PENDING, rv);
1341 rv = callback.WaitForResult();
1342 EXPECT_EQ(OK, rv);
1344 LoadTimingInfo load_timing_info;
1345 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1346 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1347 if (i == 0) {
1348 first_socket_log_id = load_timing_info.socket_log_id;
1349 } else {
1350 // The second request should be using a new socket.
1351 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1354 const HttpResponseInfo* response = trans->GetResponseInfo();
1355 ASSERT_TRUE(response != NULL);
1357 EXPECT_TRUE(response->headers.get() != NULL);
1358 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1360 std::string response_data;
1361 rv = ReadTransaction(trans.get(), &response_data);
1362 EXPECT_EQ(OK, rv);
1363 EXPECT_EQ(kExpectedResponseData[i], response_data);
1367 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1368 const MockWrite* write_failure,
1369 const MockRead* read_failure,
1370 bool use_spdy) {
1371 HttpRequestInfo request;
1372 request.method = "GET";
1373 request.url = GURL("https://www.foo.com/");
1374 request.load_flags = 0;
1376 TestNetLog net_log;
1377 session_deps_.net_log = &net_log;
1378 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1380 SSLSocketDataProvider ssl1(ASYNC, OK);
1381 SSLSocketDataProvider ssl2(ASYNC, OK);
1382 if (use_spdy) {
1383 ssl1.SetNextProto(GetParam());
1384 ssl2.SetNextProto(GetParam());
1386 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1387 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1389 // SPDY versions of the request and response.
1390 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1391 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1392 scoped_ptr<SpdyFrame> spdy_response(
1393 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1394 scoped_ptr<SpdyFrame> spdy_data(
1395 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1397 // HTTP/1.1 versions of the request and response.
1398 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1399 "Host: www.foo.com\r\n"
1400 "Connection: keep-alive\r\n\r\n";
1401 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1402 const char kHttpData[] = "hello";
1404 std::vector<MockRead> data1_reads;
1405 std::vector<MockWrite> data1_writes;
1406 if (write_failure) {
1407 ASSERT_FALSE(read_failure);
1408 data1_writes.push_back(*write_failure);
1409 data1_reads.push_back(MockRead(ASYNC, OK));
1410 } else {
1411 ASSERT_TRUE(read_failure);
1412 if (use_spdy) {
1413 data1_writes.push_back(CreateMockWrite(*spdy_request));
1414 } else {
1415 data1_writes.push_back(MockWrite(kHttpRequest));
1417 data1_reads.push_back(*read_failure);
1420 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1421 &data1_writes[0], data1_writes.size());
1422 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1424 std::vector<MockRead> data2_reads;
1425 std::vector<MockWrite> data2_writes;
1427 if (use_spdy) {
1428 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1430 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1431 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1432 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1433 } else {
1434 data2_writes.push_back(
1435 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1437 data2_reads.push_back(
1438 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1439 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1440 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1442 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1443 &data2_writes[0], data2_writes.size());
1444 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1446 // Preconnect a socket.
1447 SSLConfig ssl_config;
1448 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1449 session->GetNextProtos(&ssl_config.next_protos);
1450 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1451 ssl_config);
1452 // Wait for the preconnect to complete.
1453 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1454 base::RunLoop().RunUntilIdle();
1455 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1457 // Make the request.
1458 TestCompletionCallback callback;
1460 scoped_ptr<HttpTransaction> trans(
1461 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1463 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1464 EXPECT_EQ(ERR_IO_PENDING, rv);
1466 rv = callback.WaitForResult();
1467 EXPECT_EQ(OK, rv);
1469 LoadTimingInfo load_timing_info;
1470 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1471 TestLoadTimingNotReused(
1472 load_timing_info,
1473 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1475 const HttpResponseInfo* response = trans->GetResponseInfo();
1476 ASSERT_TRUE(response != NULL);
1478 EXPECT_TRUE(response->headers.get() != NULL);
1479 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1481 std::string response_data;
1482 rv = ReadTransaction(trans.get(), &response_data);
1483 EXPECT_EQ(OK, rv);
1484 EXPECT_EQ(kHttpData, response_data);
1487 TEST_P(HttpNetworkTransactionTest,
1488 KeepAliveConnectionNotConnectedOnWrite) {
1489 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1490 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1493 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1494 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1495 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1498 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1499 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1500 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1503 // Make sure that on a 408 response (Request Timeout), the request is retried,
1504 // if the socket was a reused keep alive socket.
1505 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1506 MockRead read_failure(SYNCHRONOUS,
1507 "HTTP/1.1 408 Request Timeout\r\n"
1508 "Connection: Keep-Alive\r\n"
1509 "Content-Length: 6\r\n\r\n"
1510 "Pickle");
1511 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1514 TEST_P(HttpNetworkTransactionTest,
1515 PreconnectErrorNotConnectedOnWrite) {
1516 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1517 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1520 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1521 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1522 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1525 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1526 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1527 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1530 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1531 MockRead read_failure(ASYNC, OK); // EOF
1532 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1535 // Make sure that on a 408 response (Request Timeout), the request is retried,
1536 // if the socket was a preconnected (UNUSED_IDLE) socket.
1537 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1538 MockRead read_failure(SYNCHRONOUS,
1539 "HTTP/1.1 408 Request Timeout\r\n"
1540 "Connection: Keep-Alive\r\n"
1541 "Content-Length: 6\r\n\r\n"
1542 "Pickle");
1543 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1544 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1547 TEST_P(HttpNetworkTransactionTest,
1548 SpdyPreconnectErrorNotConnectedOnWrite) {
1549 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1550 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1553 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1554 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1555 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1558 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1559 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1560 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1563 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1564 MockRead read_failure(ASYNC, OK); // EOF
1565 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1568 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1569 HttpRequestInfo request;
1570 request.method = "GET";
1571 request.url = GURL("http://www.example.org/");
1572 request.load_flags = 0;
1574 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1575 scoped_ptr<HttpTransaction> trans(
1576 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1578 MockRead data_reads[] = {
1579 MockRead(ASYNC, ERR_CONNECTION_RESET),
1580 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1581 MockRead("hello world"),
1582 MockRead(SYNCHRONOUS, OK),
1584 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1585 session_deps_.socket_factory->AddSocketDataProvider(&data);
1587 TestCompletionCallback callback;
1589 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1590 EXPECT_EQ(ERR_IO_PENDING, rv);
1592 rv = callback.WaitForResult();
1593 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1596 // What do various browsers do when the server closes a non-keepalive
1597 // connection without sending any response header or body?
1599 // IE7: error page
1600 // Safari 3.1.2 (Windows): error page
1601 // Firefox 3.0.1: blank page
1602 // Opera 9.52: after five attempts, blank page
1603 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1604 // Us: error page (EMPTY_RESPONSE)
1605 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1606 MockRead data_reads[] = {
1607 MockRead(SYNCHRONOUS, OK), // EOF
1608 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1609 MockRead("hello world"),
1610 MockRead(SYNCHRONOUS, OK),
1612 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1613 arraysize(data_reads));
1614 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1617 // Test that network access can be deferred and resumed.
1618 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1619 HttpRequestInfo request;
1620 request.method = "GET";
1621 request.url = GURL("http://www.example.org/");
1622 request.load_flags = 0;
1624 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1625 scoped_ptr<HttpTransaction> trans(
1626 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1628 // Defer on OnBeforeNetworkStart.
1629 BeforeNetworkStartHandler net_start_handler(true); // defer
1630 trans->SetBeforeNetworkStartCallback(
1631 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1632 base::Unretained(&net_start_handler)));
1634 MockRead data_reads[] = {
1635 MockRead("HTTP/1.0 200 OK\r\n"),
1636 MockRead("Content-Length: 5\r\n\r\n"),
1637 MockRead("hello"),
1638 MockRead(SYNCHRONOUS, 0),
1640 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1641 session_deps_.socket_factory->AddSocketDataProvider(&data);
1643 TestCompletionCallback callback;
1645 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1646 EXPECT_EQ(ERR_IO_PENDING, rv);
1647 base::MessageLoop::current()->RunUntilIdle();
1649 // Should have deferred for network start.
1650 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1651 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1653 trans->ResumeNetworkStart();
1654 rv = callback.WaitForResult();
1655 EXPECT_EQ(OK, rv);
1656 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1658 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1659 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1660 if (rv == ERR_IO_PENDING)
1661 rv = callback.WaitForResult();
1662 EXPECT_EQ(5, rv);
1663 trans.reset();
1666 // Test that network use can be deferred and canceled.
1667 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1668 HttpRequestInfo request;
1669 request.method = "GET";
1670 request.url = GURL("http://www.example.org/");
1671 request.load_flags = 0;
1673 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1674 scoped_ptr<HttpTransaction> trans(
1675 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1677 // Defer on OnBeforeNetworkStart.
1678 BeforeNetworkStartHandler net_start_handler(true); // defer
1679 trans->SetBeforeNetworkStartCallback(
1680 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1681 base::Unretained(&net_start_handler)));
1683 TestCompletionCallback callback;
1685 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1686 EXPECT_EQ(ERR_IO_PENDING, rv);
1687 base::MessageLoop::current()->RunUntilIdle();
1689 // Should have deferred for network start.
1690 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1691 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1694 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1695 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1696 // destructor in such situations.
1697 // See http://crbug.com/154712 and http://crbug.com/156609.
1698 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1699 HttpRequestInfo request;
1700 request.method = "GET";
1701 request.url = GURL("http://www.example.org/");
1702 request.load_flags = 0;
1704 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1705 scoped_ptr<HttpTransaction> trans(
1706 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1708 MockRead data_reads[] = {
1709 MockRead("HTTP/1.0 200 OK\r\n"),
1710 MockRead("Connection: keep-alive\r\n"),
1711 MockRead("Content-Length: 100\r\n\r\n"),
1712 MockRead("hello"),
1713 MockRead(SYNCHRONOUS, 0),
1715 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1716 session_deps_.socket_factory->AddSocketDataProvider(&data);
1718 TestCompletionCallback callback;
1720 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1721 EXPECT_EQ(ERR_IO_PENDING, rv);
1723 rv = callback.WaitForResult();
1724 EXPECT_EQ(OK, rv);
1726 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1727 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1728 if (rv == ERR_IO_PENDING)
1729 rv = callback.WaitForResult();
1730 EXPECT_EQ(5, rv);
1731 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1732 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1734 trans.reset();
1735 base::MessageLoop::current()->RunUntilIdle();
1736 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1739 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1740 HttpRequestInfo request;
1741 request.method = "GET";
1742 request.url = GURL("http://www.example.org/");
1743 request.load_flags = 0;
1745 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1746 scoped_ptr<HttpTransaction> trans(
1747 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1749 MockRead data_reads[] = {
1750 MockRead("HTTP/1.0 200 OK\r\n"),
1751 MockRead("Connection: keep-alive\r\n"),
1752 MockRead("Content-Length: 100\r\n\r\n"),
1753 MockRead(SYNCHRONOUS, 0),
1755 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1756 session_deps_.socket_factory->AddSocketDataProvider(&data);
1758 TestCompletionCallback callback;
1760 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1761 EXPECT_EQ(ERR_IO_PENDING, rv);
1763 rv = callback.WaitForResult();
1764 EXPECT_EQ(OK, rv);
1766 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1767 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1768 if (rv == ERR_IO_PENDING)
1769 rv = callback.WaitForResult();
1770 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1772 trans.reset();
1773 base::MessageLoop::current()->RunUntilIdle();
1774 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1777 // Test that we correctly reuse a keep-alive connection after not explicitly
1778 // reading the body.
1779 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1780 HttpRequestInfo request;
1781 request.method = "GET";
1782 request.url = GURL("http://www.foo.com/");
1783 request.load_flags = 0;
1785 TestNetLog net_log;
1786 session_deps_.net_log = &net_log;
1787 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1789 // Note that because all these reads happen in the same
1790 // StaticSocketDataProvider, it shows that the same socket is being reused for
1791 // all transactions.
1792 MockRead data1_reads[] = {
1793 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1794 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1795 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1796 MockRead("HTTP/1.1 302 Found\r\n"
1797 "Content-Length: 0\r\n\r\n"),
1798 MockRead("HTTP/1.1 302 Found\r\n"
1799 "Content-Length: 5\r\n\r\n"
1800 "hello"),
1801 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1802 "Content-Length: 0\r\n\r\n"),
1803 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1804 "Content-Length: 5\r\n\r\n"
1805 "hello"),
1806 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1807 MockRead("hello"),
1809 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1810 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1812 MockRead data2_reads[] = {
1813 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1815 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1816 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1818 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1819 std::string response_lines[kNumUnreadBodies];
1821 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1822 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1823 TestCompletionCallback callback;
1825 scoped_ptr<HttpTransaction> trans(
1826 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1828 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1829 EXPECT_EQ(ERR_IO_PENDING, rv);
1831 rv = callback.WaitForResult();
1832 EXPECT_EQ(OK, rv);
1834 LoadTimingInfo load_timing_info;
1835 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1836 if (i == 0) {
1837 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1838 first_socket_log_id = load_timing_info.socket_log_id;
1839 } else {
1840 TestLoadTimingReused(load_timing_info);
1841 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1844 const HttpResponseInfo* response = trans->GetResponseInfo();
1845 ASSERT_TRUE(response != NULL);
1847 ASSERT_TRUE(response->headers.get() != NULL);
1848 response_lines[i] = response->headers->GetStatusLine();
1850 // We intentionally don't read the response bodies.
1853 const char* const kStatusLines[] = {
1854 "HTTP/1.1 204 No Content",
1855 "HTTP/1.1 205 Reset Content",
1856 "HTTP/1.1 304 Not Modified",
1857 "HTTP/1.1 302 Found",
1858 "HTTP/1.1 302 Found",
1859 "HTTP/1.1 301 Moved Permanently",
1860 "HTTP/1.1 301 Moved Permanently",
1863 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1864 "forgot to update kStatusLines");
1866 for (int i = 0; i < kNumUnreadBodies; ++i)
1867 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1869 TestCompletionCallback callback;
1870 scoped_ptr<HttpTransaction> trans(
1871 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1872 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1873 EXPECT_EQ(ERR_IO_PENDING, rv);
1874 rv = callback.WaitForResult();
1875 EXPECT_EQ(OK, rv);
1876 const HttpResponseInfo* response = trans->GetResponseInfo();
1877 ASSERT_TRUE(response != NULL);
1878 ASSERT_TRUE(response->headers.get() != NULL);
1879 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1880 std::string response_data;
1881 rv = ReadTransaction(trans.get(), &response_data);
1882 EXPECT_EQ(OK, rv);
1883 EXPECT_EQ("hello", response_data);
1886 // Test the request-challenge-retry sequence for basic auth.
1887 // (basic auth is the easiest to mock, because it has no randomness).
1888 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1889 HttpRequestInfo request;
1890 request.method = "GET";
1891 request.url = GURL("http://www.example.org/");
1892 request.load_flags = 0;
1894 TestNetLog log;
1895 session_deps_.net_log = &log;
1896 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1897 scoped_ptr<HttpTransaction> trans(
1898 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1900 MockWrite data_writes1[] = {
1901 MockWrite(
1902 "GET / HTTP/1.1\r\n"
1903 "Host: www.example.org\r\n"
1904 "Connection: keep-alive\r\n\r\n"),
1907 MockRead data_reads1[] = {
1908 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1909 // Give a couple authenticate options (only the middle one is actually
1910 // supported).
1911 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1912 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1913 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1914 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1915 // Large content-length -- won't matter, as connection will be reset.
1916 MockRead("Content-Length: 10000\r\n\r\n"),
1917 MockRead(SYNCHRONOUS, ERR_FAILED),
1920 // After calling trans->RestartWithAuth(), this is the request we should
1921 // be issuing -- the final header line contains the credentials.
1922 MockWrite data_writes2[] = {
1923 MockWrite(
1924 "GET / HTTP/1.1\r\n"
1925 "Host: www.example.org\r\n"
1926 "Connection: keep-alive\r\n"
1927 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1930 // Lastly, the server responds with the actual content.
1931 MockRead data_reads2[] = {
1932 MockRead("HTTP/1.0 200 OK\r\n"),
1933 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1934 MockRead("Content-Length: 100\r\n\r\n"),
1935 MockRead(SYNCHRONOUS, OK),
1938 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1939 data_writes1, arraysize(data_writes1));
1940 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1941 data_writes2, arraysize(data_writes2));
1942 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1943 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1945 TestCompletionCallback callback1;
1947 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1948 EXPECT_EQ(ERR_IO_PENDING, rv);
1950 rv = callback1.WaitForResult();
1951 EXPECT_EQ(OK, rv);
1953 LoadTimingInfo load_timing_info1;
1954 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1955 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1957 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1958 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1960 const HttpResponseInfo* response = trans->GetResponseInfo();
1961 ASSERT_TRUE(response != NULL);
1962 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1964 TestCompletionCallback callback2;
1966 rv = trans->RestartWithAuth(
1967 AuthCredentials(kFoo, kBar), callback2.callback());
1968 EXPECT_EQ(ERR_IO_PENDING, rv);
1970 rv = callback2.WaitForResult();
1971 EXPECT_EQ(OK, rv);
1973 LoadTimingInfo load_timing_info2;
1974 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1975 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1976 // The load timing after restart should have a new socket ID, and times after
1977 // those of the first load timing.
1978 EXPECT_LE(load_timing_info1.receive_headers_end,
1979 load_timing_info2.connect_timing.connect_start);
1980 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1982 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1983 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1985 response = trans->GetResponseInfo();
1986 ASSERT_TRUE(response != NULL);
1987 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1988 EXPECT_EQ(100, response->headers->GetContentLength());
1991 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1992 HttpRequestInfo request;
1993 request.method = "GET";
1994 request.url = GURL("http://www.example.org/");
1995 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
1997 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1998 scoped_ptr<HttpTransaction> trans(
1999 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2001 MockWrite data_writes[] = {
2002 MockWrite(
2003 "GET / HTTP/1.1\r\n"
2004 "Host: www.example.org\r\n"
2005 "Connection: keep-alive\r\n\r\n"),
2008 MockRead data_reads[] = {
2009 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2010 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2011 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2012 // Large content-length -- won't matter, as connection will be reset.
2013 MockRead("Content-Length: 10000\r\n\r\n"),
2014 MockRead(SYNCHRONOUS, ERR_FAILED),
2017 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2018 data_writes, arraysize(data_writes));
2019 session_deps_.socket_factory->AddSocketDataProvider(&data);
2020 TestCompletionCallback callback;
2022 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2023 EXPECT_EQ(ERR_IO_PENDING, rv);
2025 rv = callback.WaitForResult();
2026 EXPECT_EQ(0, rv);
2028 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2029 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2031 const HttpResponseInfo* response = trans->GetResponseInfo();
2032 ASSERT_TRUE(response != NULL);
2033 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2036 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2037 // connection.
2038 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2039 HttpRequestInfo request;
2040 request.method = "GET";
2041 request.url = GURL("http://www.example.org/");
2042 request.load_flags = 0;
2044 TestNetLog log;
2045 session_deps_.net_log = &log;
2046 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2048 MockWrite data_writes1[] = {
2049 MockWrite(
2050 "GET / HTTP/1.1\r\n"
2051 "Host: www.example.org\r\n"
2052 "Connection: keep-alive\r\n\r\n"),
2054 // After calling trans->RestartWithAuth(), this is the request we should
2055 // be issuing -- the final header line contains the credentials.
2056 MockWrite(
2057 "GET / HTTP/1.1\r\n"
2058 "Host: www.example.org\r\n"
2059 "Connection: keep-alive\r\n"
2060 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2063 MockRead data_reads1[] = {
2064 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2065 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2066 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2067 MockRead("Content-Length: 14\r\n\r\n"),
2068 MockRead("Unauthorized\r\n"),
2070 // Lastly, the server responds with the actual content.
2071 MockRead("HTTP/1.1 200 OK\r\n"),
2072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2073 MockRead("Content-Length: 5\r\n\r\n"),
2074 MockRead("Hello"),
2077 // If there is a regression where we disconnect a Keep-Alive
2078 // connection during an auth roundtrip, we'll end up reading this.
2079 MockRead data_reads2[] = {
2080 MockRead(SYNCHRONOUS, ERR_FAILED),
2083 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2084 data_writes1, arraysize(data_writes1));
2085 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2086 NULL, 0);
2087 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2088 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2090 TestCompletionCallback callback1;
2092 scoped_ptr<HttpTransaction> trans(
2093 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2094 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2095 EXPECT_EQ(ERR_IO_PENDING, rv);
2097 rv = callback1.WaitForResult();
2098 EXPECT_EQ(OK, rv);
2100 LoadTimingInfo load_timing_info1;
2101 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2102 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2104 const HttpResponseInfo* response = trans->GetResponseInfo();
2105 ASSERT_TRUE(response != NULL);
2106 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2108 TestCompletionCallback callback2;
2110 rv = trans->RestartWithAuth(
2111 AuthCredentials(kFoo, kBar), callback2.callback());
2112 EXPECT_EQ(ERR_IO_PENDING, rv);
2114 rv = callback2.WaitForResult();
2115 EXPECT_EQ(OK, rv);
2117 LoadTimingInfo load_timing_info2;
2118 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2119 TestLoadTimingReused(load_timing_info2);
2120 // The load timing after restart should have the same socket ID, and times
2121 // those of the first load timing.
2122 EXPECT_LE(load_timing_info1.receive_headers_end,
2123 load_timing_info2.send_start);
2124 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2126 response = trans->GetResponseInfo();
2127 ASSERT_TRUE(response != NULL);
2128 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2129 EXPECT_EQ(5, response->headers->GetContentLength());
2131 std::string response_data;
2132 rv = ReadTransaction(trans.get(), &response_data);
2133 EXPECT_EQ(OK, rv);
2134 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2135 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2138 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2139 // connection and with no response body to drain.
2140 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2141 HttpRequestInfo request;
2142 request.method = "GET";
2143 request.url = GURL("http://www.example.org/");
2144 request.load_flags = 0;
2146 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2148 MockWrite data_writes1[] = {
2149 MockWrite(
2150 "GET / HTTP/1.1\r\n"
2151 "Host: www.example.org\r\n"
2152 "Connection: keep-alive\r\n\r\n"),
2154 // After calling trans->RestartWithAuth(), this is the request we should
2155 // be issuing -- the final header line contains the credentials.
2156 MockWrite(
2157 "GET / HTTP/1.1\r\n"
2158 "Host: www.example.org\r\n"
2159 "Connection: keep-alive\r\n"
2160 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2163 MockRead data_reads1[] = {
2164 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2165 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2166 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2168 // Lastly, the server responds with the actual content.
2169 MockRead("HTTP/1.1 200 OK\r\n"),
2170 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2171 MockRead("Content-Length: 5\r\n\r\n"),
2172 MockRead("hello"),
2175 // An incorrect reconnect would cause this to be read.
2176 MockRead data_reads2[] = {
2177 MockRead(SYNCHRONOUS, ERR_FAILED),
2180 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2181 data_writes1, arraysize(data_writes1));
2182 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2183 NULL, 0);
2184 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2185 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2187 TestCompletionCallback callback1;
2189 scoped_ptr<HttpTransaction> trans(
2190 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2191 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2192 EXPECT_EQ(ERR_IO_PENDING, rv);
2194 rv = callback1.WaitForResult();
2195 EXPECT_EQ(OK, rv);
2197 const HttpResponseInfo* response = trans->GetResponseInfo();
2198 ASSERT_TRUE(response != NULL);
2199 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2201 TestCompletionCallback callback2;
2203 rv = trans->RestartWithAuth(
2204 AuthCredentials(kFoo, kBar), callback2.callback());
2205 EXPECT_EQ(ERR_IO_PENDING, rv);
2207 rv = callback2.WaitForResult();
2208 EXPECT_EQ(OK, rv);
2210 response = trans->GetResponseInfo();
2211 ASSERT_TRUE(response != NULL);
2212 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2213 EXPECT_EQ(5, response->headers->GetContentLength());
2216 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2217 // connection and with a large response body to drain.
2218 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2219 HttpRequestInfo request;
2220 request.method = "GET";
2221 request.url = GURL("http://www.example.org/");
2222 request.load_flags = 0;
2224 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2226 MockWrite data_writes1[] = {
2227 MockWrite(
2228 "GET / HTTP/1.1\r\n"
2229 "Host: www.example.org\r\n"
2230 "Connection: keep-alive\r\n\r\n"),
2232 // After calling trans->RestartWithAuth(), this is the request we should
2233 // be issuing -- the final header line contains the credentials.
2234 MockWrite(
2235 "GET / HTTP/1.1\r\n"
2236 "Host: www.example.org\r\n"
2237 "Connection: keep-alive\r\n"
2238 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2241 // Respond with 5 kb of response body.
2242 std::string large_body_string("Unauthorized");
2243 large_body_string.append(5 * 1024, ' ');
2244 large_body_string.append("\r\n");
2246 MockRead data_reads1[] = {
2247 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2248 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2250 // 5134 = 12 + 5 * 1024 + 2
2251 MockRead("Content-Length: 5134\r\n\r\n"),
2252 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2254 // Lastly, the server responds with the actual content.
2255 MockRead("HTTP/1.1 200 OK\r\n"),
2256 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2257 MockRead("Content-Length: 5\r\n\r\n"),
2258 MockRead("hello"),
2261 // An incorrect reconnect would cause this to be read.
2262 MockRead data_reads2[] = {
2263 MockRead(SYNCHRONOUS, ERR_FAILED),
2266 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2267 data_writes1, arraysize(data_writes1));
2268 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2269 NULL, 0);
2270 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2271 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2273 TestCompletionCallback callback1;
2275 scoped_ptr<HttpTransaction> trans(
2276 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2277 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2278 EXPECT_EQ(ERR_IO_PENDING, rv);
2280 rv = callback1.WaitForResult();
2281 EXPECT_EQ(OK, rv);
2283 const HttpResponseInfo* response = trans->GetResponseInfo();
2284 ASSERT_TRUE(response != NULL);
2285 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2287 TestCompletionCallback callback2;
2289 rv = trans->RestartWithAuth(
2290 AuthCredentials(kFoo, kBar), callback2.callback());
2291 EXPECT_EQ(ERR_IO_PENDING, rv);
2293 rv = callback2.WaitForResult();
2294 EXPECT_EQ(OK, rv);
2296 response = trans->GetResponseInfo();
2297 ASSERT_TRUE(response != NULL);
2298 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2299 EXPECT_EQ(5, response->headers->GetContentLength());
2302 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2303 // connection, but the server gets impatient and closes the connection.
2304 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2305 HttpRequestInfo request;
2306 request.method = "GET";
2307 request.url = GURL("http://www.example.org/");
2308 request.load_flags = 0;
2310 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2312 MockWrite data_writes1[] = {
2313 MockWrite(
2314 "GET / HTTP/1.1\r\n"
2315 "Host: www.example.org\r\n"
2316 "Connection: keep-alive\r\n\r\n"),
2317 // This simulates the seemingly successful write to a closed connection
2318 // if the bug is not fixed.
2319 MockWrite(
2320 "GET / HTTP/1.1\r\n"
2321 "Host: www.example.org\r\n"
2322 "Connection: keep-alive\r\n"
2323 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2326 MockRead data_reads1[] = {
2327 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2328 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2329 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2330 MockRead("Content-Length: 14\r\n\r\n"),
2331 // Tell MockTCPClientSocket to simulate the server closing the connection.
2332 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2333 MockRead("Unauthorized\r\n"),
2334 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2337 // After calling trans->RestartWithAuth(), this is the request we should
2338 // be issuing -- the final header line contains the credentials.
2339 MockWrite data_writes2[] = {
2340 MockWrite(
2341 "GET / HTTP/1.1\r\n"
2342 "Host: www.example.org\r\n"
2343 "Connection: keep-alive\r\n"
2344 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2347 // Lastly, the server responds with the actual content.
2348 MockRead data_reads2[] = {
2349 MockRead("HTTP/1.1 200 OK\r\n"),
2350 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2351 MockRead("Content-Length: 5\r\n\r\n"),
2352 MockRead("hello"),
2355 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2356 data_writes1, arraysize(data_writes1));
2357 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2358 data_writes2, arraysize(data_writes2));
2359 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2360 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2362 TestCompletionCallback callback1;
2364 scoped_ptr<HttpTransaction> trans(
2365 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2366 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2367 EXPECT_EQ(ERR_IO_PENDING, rv);
2369 rv = callback1.WaitForResult();
2370 EXPECT_EQ(OK, rv);
2372 const HttpResponseInfo* response = trans->GetResponseInfo();
2373 ASSERT_TRUE(response != NULL);
2374 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2376 TestCompletionCallback callback2;
2378 rv = trans->RestartWithAuth(
2379 AuthCredentials(kFoo, kBar), callback2.callback());
2380 EXPECT_EQ(ERR_IO_PENDING, rv);
2382 rv = callback2.WaitForResult();
2383 EXPECT_EQ(OK, rv);
2385 response = trans->GetResponseInfo();
2386 ASSERT_TRUE(response != NULL);
2387 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2388 EXPECT_EQ(5, response->headers->GetContentLength());
2391 // Test the request-challenge-retry sequence for basic auth, over a connection
2392 // that requires a restart when setting up an SSL tunnel.
2393 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2394 HttpRequestInfo request;
2395 request.method = "GET";
2396 request.url = GURL("https://www.example.org/");
2397 // when the no authentication data flag is set.
2398 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2400 // Configure against proxy server "myproxy:70".
2401 session_deps_.proxy_service.reset(
2402 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2403 BoundTestNetLog log;
2404 session_deps_.net_log = log.bound().net_log();
2405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2407 // Since we have proxy, should try to establish tunnel.
2408 MockWrite data_writes1[] = {
2409 MockWrite(
2410 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2411 "Host: www.example.org\r\n"
2412 "Proxy-Connection: keep-alive\r\n\r\n"),
2414 // After calling trans->RestartWithAuth(), this is the request we should
2415 // be issuing -- the final header line contains the credentials.
2416 MockWrite(
2417 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2418 "Host: www.example.org\r\n"
2419 "Proxy-Connection: keep-alive\r\n"
2420 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2422 MockWrite(
2423 "GET / HTTP/1.1\r\n"
2424 "Host: www.example.org\r\n"
2425 "Connection: keep-alive\r\n\r\n"),
2428 // The proxy responds to the connect with a 407, using a persistent
2429 // connection.
2430 MockRead data_reads1[] = {
2431 // No credentials.
2432 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2433 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2435 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2437 MockRead("HTTP/1.1 200 OK\r\n"),
2438 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2439 MockRead("Content-Length: 5\r\n\r\n"),
2440 MockRead(SYNCHRONOUS, "hello"),
2443 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2444 data_writes1, arraysize(data_writes1));
2445 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2446 SSLSocketDataProvider ssl(ASYNC, OK);
2447 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2449 TestCompletionCallback callback1;
2451 scoped_ptr<HttpTransaction> trans(
2452 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2454 int rv = trans->Start(&request, callback1.callback(), log.bound());
2455 EXPECT_EQ(ERR_IO_PENDING, rv);
2457 rv = callback1.WaitForResult();
2458 EXPECT_EQ(OK, rv);
2459 TestNetLogEntry::List entries;
2460 log.GetEntries(&entries);
2461 size_t pos = ExpectLogContainsSomewhere(
2462 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2463 NetLog::PHASE_NONE);
2464 ExpectLogContainsSomewhere(
2465 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2466 NetLog::PHASE_NONE);
2468 const HttpResponseInfo* response = trans->GetResponseInfo();
2469 ASSERT_TRUE(response != NULL);
2470 EXPECT_FALSE(response->headers->IsKeepAlive());
2471 ASSERT_FALSE(response->headers.get() == NULL);
2472 EXPECT_EQ(407, response->headers->response_code());
2473 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2474 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2476 LoadTimingInfo load_timing_info;
2477 // CONNECT requests and responses are handled at the connect job level, so
2478 // the transaction does not yet have a connection.
2479 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2481 TestCompletionCallback callback2;
2483 rv =
2484 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2485 EXPECT_EQ(ERR_IO_PENDING, rv);
2487 rv = callback2.WaitForResult();
2488 EXPECT_EQ(OK, rv);
2490 response = trans->GetResponseInfo();
2491 ASSERT_TRUE(response != NULL);
2493 EXPECT_TRUE(response->headers->IsKeepAlive());
2494 EXPECT_EQ(200, response->headers->response_code());
2495 EXPECT_EQ(5, response->headers->GetContentLength());
2496 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2498 // The password prompt info should not be set.
2499 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2501 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2502 TestLoadTimingNotReusedWithPac(load_timing_info,
2503 CONNECT_TIMING_HAS_SSL_TIMES);
2505 trans.reset();
2506 session->CloseAllConnections();
2509 // Test the request-challenge-retry sequence for basic auth, over a connection
2510 // that requires a restart when setting up an SSL tunnel.
2511 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
2512 HttpRequestInfo request;
2513 request.method = "GET";
2514 request.url = GURL("https://www.example.org/");
2515 // when the no authentication data flag is set.
2516 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2518 // Configure against proxy server "myproxy:70".
2519 session_deps_.proxy_service.reset(
2520 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2521 BoundTestNetLog log;
2522 session_deps_.net_log = log.bound().net_log();
2523 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2525 // Since we have proxy, should try to establish tunnel.
2526 MockWrite data_writes1[] = {
2527 MockWrite(
2528 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2529 "Host: www.example.org\r\n"
2530 "Proxy-Connection: keep-alive\r\n\r\n"),
2532 // After calling trans->RestartWithAuth(), this is the request we should
2533 // be issuing -- the final header line contains the credentials.
2534 MockWrite(
2535 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2536 "Host: www.example.org\r\n"
2537 "Proxy-Connection: keep-alive\r\n"
2538 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2540 MockWrite(
2541 "GET / HTTP/1.1\r\n"
2542 "Host: www.example.org\r\n"
2543 "Connection: keep-alive\r\n\r\n"),
2546 // The proxy responds to the connect with a 407, using a persistent
2547 // connection.
2548 MockRead data_reads1[] = {
2549 // No credentials.
2550 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2551 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2552 MockRead("Proxy-Connection: close\r\n\r\n"),
2554 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2556 MockRead("HTTP/1.1 200 OK\r\n"),
2557 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2558 MockRead("Content-Length: 5\r\n\r\n"),
2559 MockRead(SYNCHRONOUS, "hello"),
2562 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2563 data_writes1, arraysize(data_writes1));
2564 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2565 SSLSocketDataProvider ssl(ASYNC, OK);
2566 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2568 TestCompletionCallback callback1;
2570 scoped_ptr<HttpTransaction> trans(
2571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2573 int rv = trans->Start(&request, callback1.callback(), log.bound());
2574 EXPECT_EQ(ERR_IO_PENDING, rv);
2576 rv = callback1.WaitForResult();
2577 EXPECT_EQ(OK, rv);
2578 TestNetLogEntry::List entries;
2579 log.GetEntries(&entries);
2580 size_t pos = ExpectLogContainsSomewhere(
2581 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2582 NetLog::PHASE_NONE);
2583 ExpectLogContainsSomewhere(
2584 entries, pos,
2585 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2586 NetLog::PHASE_NONE);
2588 const HttpResponseInfo* response = trans->GetResponseInfo();
2589 ASSERT_TRUE(response != NULL);
2590 EXPECT_FALSE(response->headers->IsKeepAlive());
2591 ASSERT_FALSE(response->headers.get() == NULL);
2592 EXPECT_EQ(407, response->headers->response_code());
2593 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2594 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2596 LoadTimingInfo load_timing_info;
2597 // CONNECT requests and responses are handled at the connect job level, so
2598 // the transaction does not yet have a connection.
2599 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2601 TestCompletionCallback callback2;
2603 rv = trans->RestartWithAuth(
2604 AuthCredentials(kFoo, kBar), callback2.callback());
2605 EXPECT_EQ(ERR_IO_PENDING, rv);
2607 rv = callback2.WaitForResult();
2608 EXPECT_EQ(OK, rv);
2610 response = trans->GetResponseInfo();
2611 ASSERT_TRUE(response != NULL);
2613 EXPECT_TRUE(response->headers->IsKeepAlive());
2614 EXPECT_EQ(200, response->headers->response_code());
2615 EXPECT_EQ(5, response->headers->GetContentLength());
2616 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2618 // The password prompt info should not be set.
2619 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2621 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2622 TestLoadTimingNotReusedWithPac(load_timing_info,
2623 CONNECT_TIMING_HAS_SSL_TIMES);
2625 trans.reset();
2626 session->CloseAllConnections();
2629 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2630 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2631 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2632 HttpRequestInfo request;
2633 request.method = "GET";
2634 request.url = GURL("https://www.example.org/");
2635 // Ensure that proxy authentication is attempted even
2636 // when the no authentication data flag is set.
2637 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2639 // Configure against proxy server "myproxy:70".
2640 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2641 BoundTestNetLog log;
2642 session_deps_.net_log = log.bound().net_log();
2643 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2645 scoped_ptr<HttpTransaction> trans(
2646 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2648 // Since we have proxy, should try to establish tunnel.
2649 MockWrite data_writes1[] = {
2650 MockWrite(
2651 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2652 "Host: www.example.org\r\n"
2653 "Proxy-Connection: keep-alive\r\n\r\n"),
2655 // After calling trans->RestartWithAuth(), this is the request we should
2656 // be issuing -- the final header line contains the credentials.
2657 MockWrite(
2658 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2659 "Host: www.example.org\r\n"
2660 "Proxy-Connection: keep-alive\r\n"
2661 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2664 // The proxy responds to the connect with a 407, using a persistent
2665 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2666 MockRead data_reads1[] = {
2667 // No credentials.
2668 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2669 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2670 MockRead("Proxy-Connection: keep-alive\r\n"),
2671 MockRead("Content-Length: 10\r\n\r\n"),
2672 MockRead("0123456789"),
2674 // Wrong credentials (wrong password).
2675 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2676 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2677 MockRead("Proxy-Connection: keep-alive\r\n"),
2678 MockRead("Content-Length: 10\r\n\r\n"),
2679 // No response body because the test stops reading here.
2680 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2683 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2684 data_writes1, arraysize(data_writes1));
2685 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2687 TestCompletionCallback callback1;
2689 int rv = trans->Start(&request, callback1.callback(), log.bound());
2690 EXPECT_EQ(ERR_IO_PENDING, rv);
2692 rv = callback1.WaitForResult();
2693 EXPECT_EQ(OK, rv);
2694 TestNetLogEntry::List entries;
2695 log.GetEntries(&entries);
2696 size_t pos = ExpectLogContainsSomewhere(
2697 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2698 NetLog::PHASE_NONE);
2699 ExpectLogContainsSomewhere(
2700 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2701 NetLog::PHASE_NONE);
2703 const HttpResponseInfo* response = trans->GetResponseInfo();
2704 ASSERT_TRUE(response);
2705 ASSERT_TRUE(response->headers);
2706 EXPECT_TRUE(response->headers->IsKeepAlive());
2707 EXPECT_EQ(407, response->headers->response_code());
2708 EXPECT_EQ(10, response->headers->GetContentLength());
2709 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2710 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2712 TestCompletionCallback callback2;
2714 // Wrong password (should be "bar").
2715 rv =
2716 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2717 EXPECT_EQ(ERR_IO_PENDING, rv);
2719 rv = callback2.WaitForResult();
2720 EXPECT_EQ(OK, rv);
2722 response = trans->GetResponseInfo();
2723 ASSERT_TRUE(response);
2724 ASSERT_TRUE(response->headers);
2725 EXPECT_TRUE(response->headers->IsKeepAlive());
2726 EXPECT_EQ(407, response->headers->response_code());
2727 EXPECT_EQ(10, response->headers->GetContentLength());
2728 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2729 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2731 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2732 // out of scope.
2733 session->CloseAllConnections();
2736 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2737 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2738 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
2739 HttpRequestInfo request;
2740 request.method = "GET";
2741 request.url = GURL("https://www.example.org/");
2742 // Ensure that proxy authentication is attempted even
2743 // when the no authentication data flag is set.
2744 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2746 // Configure against proxy server "myproxy:70".
2747 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2748 BoundTestNetLog log;
2749 session_deps_.net_log = log.bound().net_log();
2750 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2752 scoped_ptr<HttpTransaction> trans(
2753 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2755 // Since we have proxy, should try to establish tunnel.
2756 MockWrite data_writes1[] = {
2757 MockWrite(
2758 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2759 "Host: www.example.org\r\n"
2760 "Proxy-Connection: keep-alive\r\n\r\n"),
2762 // After calling trans->RestartWithAuth(), this is the request we should
2763 // be issuing -- the final header line contains the credentials.
2764 MockWrite(
2765 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2766 "Host: www.example.org\r\n"
2767 "Proxy-Connection: keep-alive\r\n"
2768 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2771 // The proxy responds to the connect with a 407, using a persistent
2772 // connection.
2773 MockRead data_reads1[] = {
2774 // No credentials.
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 MockRead("0123456789"),
2780 // Wrong credentials (wrong password).
2781 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2782 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2783 MockRead("Content-Length: 10\r\n\r\n"),
2784 // No response body because the test stops reading here.
2785 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2788 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2789 data_writes1, arraysize(data_writes1));
2790 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2792 TestCompletionCallback callback1;
2794 int rv = trans->Start(&request, callback1.callback(), log.bound());
2795 EXPECT_EQ(ERR_IO_PENDING, rv);
2797 rv = callback1.WaitForResult();
2798 EXPECT_EQ(OK, rv);
2799 TestNetLogEntry::List entries;
2800 log.GetEntries(&entries);
2801 size_t pos = ExpectLogContainsSomewhere(
2802 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2803 NetLog::PHASE_NONE);
2804 ExpectLogContainsSomewhere(
2805 entries, pos,
2806 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2807 NetLog::PHASE_NONE);
2809 const HttpResponseInfo* response = trans->GetResponseInfo();
2810 ASSERT_TRUE(response);
2811 ASSERT_TRUE(response->headers);
2812 EXPECT_TRUE(response->headers->IsKeepAlive());
2813 EXPECT_EQ(407, response->headers->response_code());
2814 EXPECT_EQ(10, response->headers->GetContentLength());
2815 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2816 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2818 TestCompletionCallback callback2;
2820 // Wrong password (should be "bar").
2821 rv = trans->RestartWithAuth(
2822 AuthCredentials(kFoo, kBaz), callback2.callback());
2823 EXPECT_EQ(ERR_IO_PENDING, rv);
2825 rv = callback2.WaitForResult();
2826 EXPECT_EQ(OK, rv);
2828 response = trans->GetResponseInfo();
2829 ASSERT_TRUE(response);
2830 ASSERT_TRUE(response->headers);
2831 EXPECT_TRUE(response->headers->IsKeepAlive());
2832 EXPECT_EQ(407, response->headers->response_code());
2833 EXPECT_EQ(10, response->headers->GetContentLength());
2834 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2835 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2837 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2838 // out of scope.
2839 session->CloseAllConnections();
2842 // Test that we don't read the response body when we fail to establish a tunnel,
2843 // even if the user cancels the proxy's auth attempt.
2844 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2845 HttpRequestInfo request;
2846 request.method = "GET";
2847 request.url = GURL("https://www.example.org/");
2848 request.load_flags = 0;
2850 // Configure against proxy server "myproxy:70".
2851 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2853 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2855 scoped_ptr<HttpTransaction> trans(
2856 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2858 // Since we have proxy, should try to establish tunnel.
2859 MockWrite data_writes[] = {
2860 MockWrite(
2861 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2862 "Host: www.example.org\r\n"
2863 "Proxy-Connection: keep-alive\r\n\r\n"),
2866 // The proxy responds to the connect with a 407.
2867 MockRead data_reads[] = {
2868 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2869 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2870 MockRead("Content-Length: 10\r\n\r\n"),
2871 MockRead("0123456789"), // Should not be reached.
2872 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
2875 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2876 data_writes, arraysize(data_writes));
2877 session_deps_.socket_factory->AddSocketDataProvider(&data);
2879 TestCompletionCallback callback;
2881 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2882 EXPECT_EQ(ERR_IO_PENDING, rv);
2884 rv = callback.WaitForResult();
2885 EXPECT_EQ(OK, rv);
2887 const HttpResponseInfo* response = trans->GetResponseInfo();
2888 ASSERT_TRUE(response);
2889 ASSERT_TRUE(response->headers);
2890 EXPECT_TRUE(response->headers->IsKeepAlive());
2891 EXPECT_EQ(407, response->headers->response_code());
2892 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2894 std::string response_data;
2895 rv = ReadTransaction(trans.get(), &response_data);
2896 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2898 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2899 session->CloseAllConnections();
2902 // Test that we don't pass extraneous headers from the proxy's response to the
2903 // caller when the proxy responds to CONNECT with 407.
2904 TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
2905 HttpRequestInfo request;
2906 request.method = "GET";
2907 request.url = GURL("https://www.example.org/");
2908 request.load_flags = 0;
2910 // Configure against proxy server "myproxy:70".
2911 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2913 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2915 scoped_ptr<HttpTransaction> trans(
2916 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2918 // Since we have proxy, should try to establish tunnel.
2919 MockWrite data_writes[] = {
2920 MockWrite(
2921 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2922 "Host: www.example.org\r\n"
2923 "Proxy-Connection: keep-alive\r\n\r\n"),
2926 // The proxy responds to the connect with a 407.
2927 MockRead data_reads[] = {
2928 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2929 MockRead("X-Foo: bar\r\n"),
2930 MockRead("Set-Cookie: foo=bar\r\n"),
2931 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2932 MockRead("Content-Length: 10\r\n\r\n"),
2933 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2936 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
2937 arraysize(data_writes));
2938 session_deps_.socket_factory->AddSocketDataProvider(&data);
2940 TestCompletionCallback callback;
2942 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2943 EXPECT_EQ(ERR_IO_PENDING, rv);
2945 rv = callback.WaitForResult();
2946 EXPECT_EQ(OK, rv);
2948 const HttpResponseInfo* response = trans->GetResponseInfo();
2949 ASSERT_TRUE(response);
2950 ASSERT_TRUE(response->headers);
2951 EXPECT_TRUE(response->headers->IsKeepAlive());
2952 EXPECT_EQ(407, response->headers->response_code());
2953 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2954 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
2955 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
2957 std::string response_data;
2958 rv = ReadTransaction(trans.get(), &response_data);
2959 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2961 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2962 session->CloseAllConnections();
2965 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2966 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2967 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2968 HttpRequestInfo request;
2969 request.method = "GET";
2970 request.url = GURL("http://www.example.org/");
2971 request.load_flags = 0;
2973 // We are using a DIRECT connection (i.e. no proxy) for this session.
2974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2975 scoped_ptr<HttpTransaction> trans(
2976 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2978 MockWrite data_writes1[] = {
2979 MockWrite(
2980 "GET / HTTP/1.1\r\n"
2981 "Host: www.example.org\r\n"
2982 "Connection: keep-alive\r\n\r\n"),
2985 MockRead data_reads1[] = {
2986 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2987 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2988 // Large content-length -- won't matter, as connection will be reset.
2989 MockRead("Content-Length: 10000\r\n\r\n"),
2990 MockRead(SYNCHRONOUS, ERR_FAILED),
2993 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2994 data_writes1, arraysize(data_writes1));
2995 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2997 TestCompletionCallback callback;
2999 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3000 EXPECT_EQ(ERR_IO_PENDING, rv);
3002 rv = callback.WaitForResult();
3003 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3006 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3007 // through a non-authenticating proxy. The request should fail with
3008 // ERR_UNEXPECTED_PROXY_AUTH.
3009 // Note that it is impossible to detect if an HTTP server returns a 407 through
3010 // a non-authenticating proxy - there is nothing to indicate whether the
3011 // response came from the proxy or the server, so it is treated as if the proxy
3012 // issued the challenge.
3013 TEST_P(HttpNetworkTransactionTest,
3014 HttpsServerRequestsProxyAuthThroughProxy) {
3015 HttpRequestInfo request;
3016 request.method = "GET";
3017 request.url = GURL("https://www.example.org/");
3019 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3020 BoundTestNetLog log;
3021 session_deps_.net_log = log.bound().net_log();
3022 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3024 // Since we have proxy, should try to establish tunnel.
3025 MockWrite data_writes1[] = {
3026 MockWrite(
3027 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3028 "Host: www.example.org\r\n"
3029 "Proxy-Connection: keep-alive\r\n\r\n"),
3031 MockWrite(
3032 "GET / HTTP/1.1\r\n"
3033 "Host: www.example.org\r\n"
3034 "Connection: keep-alive\r\n\r\n"),
3037 MockRead data_reads1[] = {
3038 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3040 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3041 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3042 MockRead("\r\n"),
3043 MockRead(SYNCHRONOUS, OK),
3046 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3047 data_writes1, arraysize(data_writes1));
3048 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3049 SSLSocketDataProvider ssl(ASYNC, OK);
3050 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3052 TestCompletionCallback callback1;
3054 scoped_ptr<HttpTransaction> trans(
3055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3057 int rv = trans->Start(&request, callback1.callback(), log.bound());
3058 EXPECT_EQ(ERR_IO_PENDING, rv);
3060 rv = callback1.WaitForResult();
3061 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3062 TestNetLogEntry::List entries;
3063 log.GetEntries(&entries);
3064 size_t pos = ExpectLogContainsSomewhere(
3065 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3066 NetLog::PHASE_NONE);
3067 ExpectLogContainsSomewhere(
3068 entries, pos,
3069 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3070 NetLog::PHASE_NONE);
3073 // Test the load timing for HTTPS requests with an HTTP proxy.
3074 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
3075 HttpRequestInfo request1;
3076 request1.method = "GET";
3077 request1.url = GURL("https://www.example.org/1");
3079 HttpRequestInfo request2;
3080 request2.method = "GET";
3081 request2.url = GURL("https://www.example.org/2");
3083 // Configure against proxy server "myproxy:70".
3084 session_deps_.proxy_service.reset(
3085 ProxyService::CreateFixed("PROXY myproxy:70"));
3086 BoundTestNetLog log;
3087 session_deps_.net_log = log.bound().net_log();
3088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3090 // Since we have proxy, should try to establish tunnel.
3091 MockWrite data_writes1[] = {
3092 MockWrite(
3093 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3094 "Host: www.example.org\r\n"
3095 "Proxy-Connection: keep-alive\r\n\r\n"),
3097 MockWrite(
3098 "GET /1 HTTP/1.1\r\n"
3099 "Host: www.example.org\r\n"
3100 "Connection: keep-alive\r\n\r\n"),
3102 MockWrite(
3103 "GET /2 HTTP/1.1\r\n"
3104 "Host: www.example.org\r\n"
3105 "Connection: keep-alive\r\n\r\n"),
3108 // The proxy responds to the connect with a 407, using a persistent
3109 // connection.
3110 MockRead data_reads1[] = {
3111 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3113 MockRead("HTTP/1.1 200 OK\r\n"),
3114 MockRead("Content-Length: 1\r\n\r\n"),
3115 MockRead(SYNCHRONOUS, "1"),
3117 MockRead("HTTP/1.1 200 OK\r\n"),
3118 MockRead("Content-Length: 2\r\n\r\n"),
3119 MockRead(SYNCHRONOUS, "22"),
3122 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3123 data_writes1, arraysize(data_writes1));
3124 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3125 SSLSocketDataProvider ssl(ASYNC, OK);
3126 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3128 TestCompletionCallback callback1;
3129 scoped_ptr<HttpTransaction> trans1(
3130 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3132 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3133 EXPECT_EQ(ERR_IO_PENDING, rv);
3135 rv = callback1.WaitForResult();
3136 EXPECT_EQ(OK, rv);
3138 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3139 ASSERT_TRUE(response1 != NULL);
3140 ASSERT_TRUE(response1->headers.get() != NULL);
3141 EXPECT_EQ(1, response1->headers->GetContentLength());
3143 LoadTimingInfo load_timing_info1;
3144 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3145 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3147 trans1.reset();
3149 TestCompletionCallback callback2;
3150 scoped_ptr<HttpTransaction> trans2(
3151 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3153 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3154 EXPECT_EQ(ERR_IO_PENDING, rv);
3156 rv = callback2.WaitForResult();
3157 EXPECT_EQ(OK, rv);
3159 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3160 ASSERT_TRUE(response2 != NULL);
3161 ASSERT_TRUE(response2->headers.get() != NULL);
3162 EXPECT_EQ(2, response2->headers->GetContentLength());
3164 LoadTimingInfo load_timing_info2;
3165 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3166 TestLoadTimingReused(load_timing_info2);
3168 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3170 trans2.reset();
3171 session->CloseAllConnections();
3174 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3175 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
3176 HttpRequestInfo request1;
3177 request1.method = "GET";
3178 request1.url = GURL("https://www.example.org/1");
3180 HttpRequestInfo request2;
3181 request2.method = "GET";
3182 request2.url = GURL("https://www.example.org/2");
3184 // Configure against proxy server "myproxy:70".
3185 session_deps_.proxy_service.reset(
3186 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3187 BoundTestNetLog log;
3188 session_deps_.net_log = log.bound().net_log();
3189 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3191 // Since we have proxy, should try to establish tunnel.
3192 MockWrite data_writes1[] = {
3193 MockWrite(
3194 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3195 "Host: www.example.org\r\n"
3196 "Proxy-Connection: keep-alive\r\n\r\n"),
3198 MockWrite(
3199 "GET /1 HTTP/1.1\r\n"
3200 "Host: www.example.org\r\n"
3201 "Connection: keep-alive\r\n\r\n"),
3203 MockWrite(
3204 "GET /2 HTTP/1.1\r\n"
3205 "Host: www.example.org\r\n"
3206 "Connection: keep-alive\r\n\r\n"),
3209 // The proxy responds to the connect with a 407, using a persistent
3210 // connection.
3211 MockRead data_reads1[] = {
3212 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3214 MockRead("HTTP/1.1 200 OK\r\n"),
3215 MockRead("Content-Length: 1\r\n\r\n"),
3216 MockRead(SYNCHRONOUS, "1"),
3218 MockRead("HTTP/1.1 200 OK\r\n"),
3219 MockRead("Content-Length: 2\r\n\r\n"),
3220 MockRead(SYNCHRONOUS, "22"),
3223 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3224 data_writes1, arraysize(data_writes1));
3225 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3226 SSLSocketDataProvider ssl(ASYNC, OK);
3227 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3229 TestCompletionCallback callback1;
3230 scoped_ptr<HttpTransaction> trans1(
3231 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3233 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3234 EXPECT_EQ(ERR_IO_PENDING, rv);
3236 rv = callback1.WaitForResult();
3237 EXPECT_EQ(OK, rv);
3239 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3240 ASSERT_TRUE(response1 != NULL);
3241 ASSERT_TRUE(response1->headers.get() != NULL);
3242 EXPECT_EQ(1, response1->headers->GetContentLength());
3244 LoadTimingInfo load_timing_info1;
3245 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3246 TestLoadTimingNotReusedWithPac(load_timing_info1,
3247 CONNECT_TIMING_HAS_SSL_TIMES);
3249 trans1.reset();
3251 TestCompletionCallback callback2;
3252 scoped_ptr<HttpTransaction> trans2(
3253 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3255 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3256 EXPECT_EQ(ERR_IO_PENDING, rv);
3258 rv = callback2.WaitForResult();
3259 EXPECT_EQ(OK, rv);
3261 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3262 ASSERT_TRUE(response2 != NULL);
3263 ASSERT_TRUE(response2->headers.get() != NULL);
3264 EXPECT_EQ(2, response2->headers->GetContentLength());
3266 LoadTimingInfo load_timing_info2;
3267 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3268 TestLoadTimingReusedWithPac(load_timing_info2);
3270 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3272 trans2.reset();
3273 session->CloseAllConnections();
3276 // Test a simple get through an HTTPS Proxy.
3277 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
3278 HttpRequestInfo request;
3279 request.method = "GET";
3280 request.url = GURL("http://www.example.org/");
3282 // Configure against https proxy server "proxy:70".
3283 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3284 "https://proxy:70"));
3285 BoundTestNetLog log;
3286 session_deps_.net_log = log.bound().net_log();
3287 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3289 // Since we have proxy, should use full url
3290 MockWrite data_writes1[] = {
3291 MockWrite(
3292 "GET http://www.example.org/ HTTP/1.1\r\n"
3293 "Host: www.example.org\r\n"
3294 "Proxy-Connection: keep-alive\r\n\r\n"),
3297 MockRead data_reads1[] = {
3298 MockRead("HTTP/1.1 200 OK\r\n"),
3299 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3300 MockRead("Content-Length: 100\r\n\r\n"),
3301 MockRead(SYNCHRONOUS, OK),
3304 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3305 data_writes1, arraysize(data_writes1));
3306 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3307 SSLSocketDataProvider ssl(ASYNC, OK);
3308 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3310 TestCompletionCallback callback1;
3312 scoped_ptr<HttpTransaction> trans(
3313 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3315 int rv = trans->Start(&request, callback1.callback(), log.bound());
3316 EXPECT_EQ(ERR_IO_PENDING, rv);
3318 rv = callback1.WaitForResult();
3319 EXPECT_EQ(OK, rv);
3321 LoadTimingInfo load_timing_info;
3322 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3323 TestLoadTimingNotReused(load_timing_info,
3324 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3326 const HttpResponseInfo* response = trans->GetResponseInfo();
3327 ASSERT_TRUE(response != NULL);
3329 EXPECT_TRUE(response->headers->IsKeepAlive());
3330 EXPECT_EQ(200, response->headers->response_code());
3331 EXPECT_EQ(100, response->headers->GetContentLength());
3332 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3334 // The password prompt info should not be set.
3335 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3338 // Test a SPDY get through an HTTPS Proxy.
3339 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3340 HttpRequestInfo request;
3341 request.method = "GET";
3342 request.url = GURL("http://www.example.org/");
3343 request.load_flags = 0;
3345 // Configure against https proxy server "proxy:70".
3346 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3347 "https://proxy:70"));
3348 BoundTestNetLog log;
3349 session_deps_.net_log = log.bound().net_log();
3350 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3352 // fetch http://www.example.org/ via SPDY
3353 scoped_ptr<SpdyFrame> req(
3354 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3355 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3357 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3358 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3359 MockRead spdy_reads[] = {
3360 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3363 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3364 arraysize(spdy_writes));
3365 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3367 SSLSocketDataProvider ssl(ASYNC, OK);
3368 ssl.SetNextProto(GetParam());
3369 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3371 TestCompletionCallback callback1;
3373 scoped_ptr<HttpTransaction> trans(
3374 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3376 int rv = trans->Start(&request, callback1.callback(), log.bound());
3377 EXPECT_EQ(ERR_IO_PENDING, rv);
3379 rv = callback1.WaitForResult();
3380 EXPECT_EQ(OK, rv);
3382 LoadTimingInfo load_timing_info;
3383 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3384 TestLoadTimingNotReused(load_timing_info,
3385 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3387 const HttpResponseInfo* response = trans->GetResponseInfo();
3388 ASSERT_TRUE(response != NULL);
3389 ASSERT_TRUE(response->headers.get() != NULL);
3390 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3392 std::string response_data;
3393 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3394 EXPECT_EQ(kUploadData, response_data);
3397 // Verifies that a session which races and wins against the owning transaction
3398 // (completing prior to host resolution), doesn't fail the transaction.
3399 // Regression test for crbug.com/334413.
3400 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3401 HttpRequestInfo request;
3402 request.method = "GET";
3403 request.url = GURL("http://www.example.org/");
3404 request.load_flags = 0;
3406 // Configure SPDY proxy server "proxy:70".
3407 session_deps_.proxy_service.reset(
3408 ProxyService::CreateFixed("https://proxy:70"));
3409 BoundTestNetLog log;
3410 session_deps_.net_log = log.bound().net_log();
3411 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3413 // Fetch http://www.example.org/ through the SPDY proxy.
3414 scoped_ptr<SpdyFrame> req(
3415 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3416 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3418 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3419 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3420 MockRead spdy_reads[] = {
3421 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3424 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3425 arraysize(spdy_writes));
3426 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3428 SSLSocketDataProvider ssl(ASYNC, OK);
3429 ssl.SetNextProto(GetParam());
3430 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3432 TestCompletionCallback callback1;
3434 scoped_ptr<HttpTransaction> trans(
3435 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3437 // Stall the hostname resolution begun by the transaction.
3438 session_deps_.host_resolver->set_synchronous_mode(false);
3439 session_deps_.host_resolver->set_ondemand_mode(true);
3441 int rv = trans->Start(&request, callback1.callback(), log.bound());
3442 EXPECT_EQ(ERR_IO_PENDING, rv);
3444 // Race a session to the proxy, which completes first.
3445 session_deps_.host_resolver->set_ondemand_mode(false);
3446 SpdySessionKey key(
3447 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3448 base::WeakPtr<SpdySession> spdy_session =
3449 CreateSecureSpdySession(session, key, log.bound());
3451 // Unstall the resolution begun by the transaction.
3452 session_deps_.host_resolver->set_ondemand_mode(true);
3453 session_deps_.host_resolver->ResolveAllPending();
3455 EXPECT_FALSE(callback1.have_result());
3456 rv = callback1.WaitForResult();
3457 EXPECT_EQ(OK, rv);
3459 const HttpResponseInfo* response = trans->GetResponseInfo();
3460 ASSERT_TRUE(response != NULL);
3461 ASSERT_TRUE(response->headers.get() != NULL);
3462 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3464 std::string response_data;
3465 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3466 EXPECT_EQ(kUploadData, response_data);
3469 // Test a SPDY get through an HTTPS Proxy.
3470 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3471 HttpRequestInfo request;
3472 request.method = "GET";
3473 request.url = GURL("http://www.example.org/");
3474 request.load_flags = 0;
3476 // Configure against https proxy server "myproxy:70".
3477 session_deps_.proxy_service.reset(
3478 ProxyService::CreateFixed("https://myproxy:70"));
3479 BoundTestNetLog log;
3480 session_deps_.net_log = log.bound().net_log();
3481 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3483 // The first request will be a bare GET, the second request will be a
3484 // GET with a Proxy-Authorization header.
3485 scoped_ptr<SpdyFrame> req_get(
3486 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3487 const char* const kExtraAuthorizationHeaders[] = {
3488 "proxy-authorization", "Basic Zm9vOmJhcg=="
3490 scoped_ptr<SpdyFrame> req_get_authorization(
3491 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3492 arraysize(kExtraAuthorizationHeaders) / 2,
3493 false,
3495 LOWEST,
3496 false));
3497 MockWrite spdy_writes[] = {
3498 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
3501 // The first response is a 407 proxy authentication challenge, and the second
3502 // response will be a 200 response since the second request includes a valid
3503 // Authorization header.
3504 const char* const kExtraAuthenticationHeaders[] = {
3505 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3507 scoped_ptr<SpdyFrame> resp_authentication(
3508 spdy_util_.ConstructSpdySynReplyError(
3509 "407 Proxy Authentication Required",
3510 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3511 1));
3512 scoped_ptr<SpdyFrame> body_authentication(
3513 spdy_util_.ConstructSpdyBodyFrame(1, true));
3514 scoped_ptr<SpdyFrame> resp_data(
3515 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3516 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3517 MockRead spdy_reads[] = {
3518 CreateMockRead(*resp_authentication, 1),
3519 CreateMockRead(*body_authentication, 2),
3520 CreateMockRead(*resp_data, 4),
3521 CreateMockRead(*body_data, 5),
3522 MockRead(ASYNC, 0, 6),
3525 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3526 arraysize(spdy_writes));
3527 session_deps_.socket_factory->AddSocketDataProvider(&data);
3529 SSLSocketDataProvider ssl(ASYNC, OK);
3530 ssl.SetNextProto(GetParam());
3531 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3533 TestCompletionCallback callback1;
3535 scoped_ptr<HttpTransaction> trans(
3536 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3538 int rv = trans->Start(&request, callback1.callback(), log.bound());
3539 EXPECT_EQ(ERR_IO_PENDING, rv);
3541 rv = callback1.WaitForResult();
3542 EXPECT_EQ(OK, rv);
3544 const HttpResponseInfo* const response = trans->GetResponseInfo();
3546 ASSERT_TRUE(response != NULL);
3547 ASSERT_TRUE(response->headers.get() != NULL);
3548 EXPECT_EQ(407, response->headers->response_code());
3549 EXPECT_TRUE(response->was_fetched_via_spdy);
3550 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3552 TestCompletionCallback callback2;
3554 rv = trans->RestartWithAuth(
3555 AuthCredentials(kFoo, kBar), callback2.callback());
3556 EXPECT_EQ(ERR_IO_PENDING, rv);
3558 rv = callback2.WaitForResult();
3559 EXPECT_EQ(OK, rv);
3561 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3563 ASSERT_TRUE(response_restart != NULL);
3564 ASSERT_TRUE(response_restart->headers.get() != NULL);
3565 EXPECT_EQ(200, response_restart->headers->response_code());
3566 // The password prompt info should not be set.
3567 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3570 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3571 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3572 HttpRequestInfo request;
3573 request.method = "GET";
3574 request.url = GURL("https://www.example.org/");
3575 request.load_flags = 0;
3577 // Configure against https proxy server "proxy:70".
3578 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3579 "https://proxy:70"));
3580 BoundTestNetLog log;
3581 session_deps_.net_log = log.bound().net_log();
3582 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3584 scoped_ptr<HttpTransaction> trans(
3585 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3587 // CONNECT to www.example.org:443 via SPDY
3588 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3589 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3590 // fetch https://www.example.org/ via HTTP
3592 const char get[] =
3593 "GET / HTTP/1.1\r\n"
3594 "Host: www.example.org\r\n"
3595 "Connection: keep-alive\r\n\r\n";
3596 scoped_ptr<SpdyFrame> wrapped_get(
3597 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3598 scoped_ptr<SpdyFrame> conn_resp(
3599 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3600 const char resp[] = "HTTP/1.1 200 OK\r\n"
3601 "Content-Length: 10\r\n\r\n";
3602 scoped_ptr<SpdyFrame> wrapped_get_resp(
3603 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3604 scoped_ptr<SpdyFrame> wrapped_body(
3605 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3606 scoped_ptr<SpdyFrame> window_update(
3607 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3609 MockWrite spdy_writes[] = {
3610 CreateMockWrite(*connect, 0),
3611 CreateMockWrite(*wrapped_get, 2),
3612 CreateMockWrite(*window_update, 6),
3615 MockRead spdy_reads[] = {
3616 CreateMockRead(*conn_resp, 1, ASYNC),
3617 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
3618 CreateMockRead(*wrapped_body, 4, ASYNC),
3619 CreateMockRead(*wrapped_body, 5, ASYNC),
3620 MockRead(ASYNC, 0, 7),
3623 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3624 arraysize(spdy_writes));
3625 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3627 SSLSocketDataProvider ssl(ASYNC, OK);
3628 ssl.SetNextProto(GetParam());
3629 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3630 SSLSocketDataProvider ssl2(ASYNC, OK);
3631 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3633 TestCompletionCallback callback1;
3635 int rv = trans->Start(&request, callback1.callback(), log.bound());
3636 EXPECT_EQ(ERR_IO_PENDING, rv);
3638 rv = callback1.WaitForResult();
3639 ASSERT_EQ(OK, rv);
3641 LoadTimingInfo load_timing_info;
3642 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3643 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3645 const HttpResponseInfo* response = trans->GetResponseInfo();
3646 ASSERT_TRUE(response != NULL);
3647 ASSERT_TRUE(response->headers.get() != NULL);
3648 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3650 std::string response_data;
3651 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3652 EXPECT_EQ("1234567890", response_data);
3655 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3656 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3657 HttpRequestInfo request;
3658 request.method = "GET";
3659 request.url = GURL("https://www.example.org/");
3660 request.load_flags = 0;
3662 // Configure against https proxy server "proxy:70".
3663 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3664 "https://proxy:70"));
3665 BoundTestNetLog log;
3666 session_deps_.net_log = log.bound().net_log();
3667 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3669 scoped_ptr<HttpTransaction> trans(
3670 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3672 // CONNECT to www.example.org:443 via SPDY
3673 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3674 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3675 // fetch https://www.example.org/ via SPDY
3676 const char kMyUrl[] = "https://www.example.org/";
3677 scoped_ptr<SpdyFrame> get(
3678 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3679 scoped_ptr<SpdyFrame> wrapped_get(
3680 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3681 scoped_ptr<SpdyFrame> conn_resp(
3682 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3683 scoped_ptr<SpdyFrame> get_resp(
3684 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3685 scoped_ptr<SpdyFrame> wrapped_get_resp(
3686 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3687 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3688 scoped_ptr<SpdyFrame> wrapped_body(
3689 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3690 scoped_ptr<SpdyFrame> window_update_get_resp(
3691 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3692 scoped_ptr<SpdyFrame> window_update_body(
3693 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3695 MockWrite spdy_writes[] = {
3696 CreateMockWrite(*connect, 0),
3697 CreateMockWrite(*wrapped_get, 2),
3698 CreateMockWrite(*window_update_get_resp, 6),
3699 CreateMockWrite(*window_update_body, 7),
3702 MockRead spdy_reads[] = {
3703 CreateMockRead(*conn_resp, 1, ASYNC),
3704 MockRead(ASYNC, ERR_IO_PENDING, 3),
3705 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3706 CreateMockRead(*wrapped_body, 5, ASYNC),
3707 MockRead(ASYNC, 0, 8),
3710 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3711 arraysize(spdy_writes));
3712 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3714 SSLSocketDataProvider ssl(ASYNC, OK);
3715 ssl.SetNextProto(GetParam());
3716 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3717 SSLSocketDataProvider ssl2(ASYNC, OK);
3718 ssl2.SetNextProto(GetParam());
3719 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3721 TestCompletionCallback callback1;
3723 int rv = trans->Start(&request, callback1.callback(), log.bound());
3724 EXPECT_EQ(ERR_IO_PENDING, rv);
3726 // Allow the SpdyProxyClientSocket's write callback to complete.
3727 base::MessageLoop::current()->RunUntilIdle();
3728 // Now allow the read of the response to complete.
3729 spdy_data.CompleteRead();
3730 rv = callback1.WaitForResult();
3731 EXPECT_EQ(OK, rv);
3733 LoadTimingInfo load_timing_info;
3734 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3735 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3737 const HttpResponseInfo* response = trans->GetResponseInfo();
3738 ASSERT_TRUE(response != NULL);
3739 ASSERT_TRUE(response->headers.get() != NULL);
3740 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3742 std::string response_data;
3743 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3744 EXPECT_EQ(kUploadData, response_data);
3747 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3748 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3749 HttpRequestInfo request;
3750 request.method = "GET";
3751 request.url = GURL("https://www.example.org/");
3752 request.load_flags = 0;
3754 // Configure against https proxy server "proxy:70".
3755 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3756 "https://proxy:70"));
3757 BoundTestNetLog log;
3758 session_deps_.net_log = log.bound().net_log();
3759 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3761 scoped_ptr<HttpTransaction> trans(
3762 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3764 // CONNECT to www.example.org:443 via SPDY
3765 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3766 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3767 scoped_ptr<SpdyFrame> get(
3768 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3770 MockWrite spdy_writes[] = {
3771 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
3774 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3775 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3776 MockRead spdy_reads[] = {
3777 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
3780 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3781 arraysize(spdy_writes));
3782 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3784 SSLSocketDataProvider ssl(ASYNC, OK);
3785 ssl.SetNextProto(GetParam());
3786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3787 SSLSocketDataProvider ssl2(ASYNC, OK);
3788 ssl2.SetNextProto(GetParam());
3789 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3791 TestCompletionCallback callback1;
3793 int rv = trans->Start(&request, callback1.callback(), log.bound());
3794 EXPECT_EQ(ERR_IO_PENDING, rv);
3796 rv = callback1.WaitForResult();
3797 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3799 // TODO(ttuttle): Anything else to check here?
3802 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3803 // HTTPS Proxy to different servers.
3804 TEST_P(HttpNetworkTransactionTest,
3805 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3806 // Configure against https proxy server "proxy:70".
3807 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3808 "https://proxy:70"));
3809 BoundTestNetLog log;
3810 session_deps_.net_log = log.bound().net_log();
3811 scoped_refptr<HttpNetworkSession> session(
3812 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
3814 HttpRequestInfo request1;
3815 request1.method = "GET";
3816 request1.url = GURL("https://www.example.org/");
3817 request1.load_flags = 0;
3819 HttpRequestInfo request2;
3820 request2.method = "GET";
3821 request2.url = GURL("https://mail.example.org/");
3822 request2.load_flags = 0;
3824 // CONNECT to www.example.org:443 via SPDY.
3825 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3826 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3827 scoped_ptr<SpdyFrame> conn_resp1(
3828 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3830 // Fetch https://www.example.org/ via HTTP.
3831 const char get1[] =
3832 "GET / HTTP/1.1\r\n"
3833 "Host: www.example.org\r\n"
3834 "Connection: keep-alive\r\n\r\n";
3835 scoped_ptr<SpdyFrame> wrapped_get1(
3836 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3837 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3838 "Content-Length: 1\r\n\r\n";
3839 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3840 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3841 scoped_ptr<SpdyFrame> wrapped_body1(
3842 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3843 scoped_ptr<SpdyFrame> window_update(
3844 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3846 // CONNECT to mail.example.org:443 via SPDY.
3847 SpdyHeaderBlock connect2_block;
3848 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3849 if (GetParam() >= kProtoHTTP2MinimumVersion) {
3850 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
3851 } else {
3852 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
3853 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
3855 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3856 scoped_ptr<SpdyFrame> connect2(
3857 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3859 scoped_ptr<SpdyFrame> conn_resp2(
3860 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3862 // Fetch https://mail.example.org/ via HTTP.
3863 const char get2[] =
3864 "GET / HTTP/1.1\r\n"
3865 "Host: mail.example.org\r\n"
3866 "Connection: keep-alive\r\n\r\n";
3867 scoped_ptr<SpdyFrame> wrapped_get2(
3868 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3869 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3870 "Content-Length: 2\r\n\r\n";
3871 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3872 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3873 scoped_ptr<SpdyFrame> wrapped_body2(
3874 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3876 MockWrite spdy_writes[] = {
3877 CreateMockWrite(*connect1, 0),
3878 CreateMockWrite(*wrapped_get1, 2),
3879 CreateMockWrite(*connect2, 5),
3880 CreateMockWrite(*wrapped_get2, 7),
3883 MockRead spdy_reads[] = {
3884 CreateMockRead(*conn_resp1, 1, ASYNC),
3885 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3886 CreateMockRead(*wrapped_body1, 4, ASYNC),
3887 CreateMockRead(*conn_resp2, 6, ASYNC),
3888 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3889 CreateMockRead(*wrapped_body2, 9, ASYNC),
3890 MockRead(ASYNC, 0, 10),
3893 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3894 arraysize(spdy_writes));
3895 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3897 SSLSocketDataProvider ssl(ASYNC, OK);
3898 ssl.SetNextProto(GetParam());
3899 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3900 SSLSocketDataProvider ssl2(ASYNC, OK);
3901 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3902 SSLSocketDataProvider ssl3(ASYNC, OK);
3903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
3905 TestCompletionCallback callback;
3907 scoped_ptr<HttpTransaction> trans(
3908 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3909 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3910 EXPECT_EQ(OK, callback.GetResult(rv));
3912 LoadTimingInfo load_timing_info;
3913 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3914 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3916 const HttpResponseInfo* response = trans->GetResponseInfo();
3917 ASSERT_TRUE(response != NULL);
3918 ASSERT_TRUE(response->headers.get() != NULL);
3919 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3921 std::string response_data;
3922 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
3923 rv = trans->Read(buf.get(), 256, callback.callback());
3924 EXPECT_EQ(1, callback.GetResult(rv));
3926 scoped_ptr<HttpTransaction> trans2(
3927 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3928 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3929 EXPECT_EQ(OK, callback.GetResult(rv));
3931 LoadTimingInfo load_timing_info2;
3932 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3933 // Even though the SPDY connection is reused, a new tunnelled connection has
3934 // to be created, so the socket's load timing looks like a fresh connection.
3935 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3937 // The requests should have different IDs, since they each are using their own
3938 // separate stream.
3939 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3941 rv = trans2->Read(buf.get(), 256, callback.callback());
3942 EXPECT_EQ(2, callback.GetResult(rv));
3945 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3946 // HTTPS Proxy to the same server.
3947 TEST_P(HttpNetworkTransactionTest,
3948 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3949 // Configure against https proxy server "proxy:70".
3950 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3951 "https://proxy:70"));
3952 BoundTestNetLog log;
3953 session_deps_.net_log = log.bound().net_log();
3954 scoped_refptr<HttpNetworkSession> session(
3955 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
3957 HttpRequestInfo request1;
3958 request1.method = "GET";
3959 request1.url = GURL("https://www.example.org/");
3960 request1.load_flags = 0;
3962 HttpRequestInfo request2;
3963 request2.method = "GET";
3964 request2.url = GURL("https://www.example.org/2");
3965 request2.load_flags = 0;
3967 // CONNECT to www.example.org:443 via SPDY.
3968 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3969 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3970 scoped_ptr<SpdyFrame> conn_resp1(
3971 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3973 // Fetch https://www.example.org/ via HTTP.
3974 const char get1[] =
3975 "GET / HTTP/1.1\r\n"
3976 "Host: www.example.org\r\n"
3977 "Connection: keep-alive\r\n\r\n";
3978 scoped_ptr<SpdyFrame> wrapped_get1(
3979 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3980 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3981 "Content-Length: 1\r\n\r\n";
3982 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3983 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3984 scoped_ptr<SpdyFrame> wrapped_body1(
3985 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3986 scoped_ptr<SpdyFrame> window_update(
3987 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3989 // Fetch https://www.example.org/2 via HTTP.
3990 const char get2[] =
3991 "GET /2 HTTP/1.1\r\n"
3992 "Host: www.example.org\r\n"
3993 "Connection: keep-alive\r\n\r\n";
3994 scoped_ptr<SpdyFrame> wrapped_get2(
3995 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3996 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3997 "Content-Length: 2\r\n\r\n";
3998 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3999 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
4000 scoped_ptr<SpdyFrame> wrapped_body2(
4001 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
4003 MockWrite spdy_writes[] = {
4004 CreateMockWrite(*connect1, 0),
4005 CreateMockWrite(*wrapped_get1, 2),
4006 CreateMockWrite(*wrapped_get2, 5),
4009 MockRead spdy_reads[] = {
4010 CreateMockRead(*conn_resp1, 1, ASYNC),
4011 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4012 CreateMockRead(*wrapped_body1, 4, ASYNC),
4013 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4014 CreateMockRead(*wrapped_body2, 7, ASYNC),
4015 MockRead(ASYNC, 0, 8),
4018 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4019 arraysize(spdy_writes));
4020 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4022 SSLSocketDataProvider ssl(ASYNC, OK);
4023 ssl.SetNextProto(GetParam());
4024 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4025 SSLSocketDataProvider ssl2(ASYNC, OK);
4026 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4028 TestCompletionCallback callback;
4030 scoped_ptr<HttpTransaction> trans(
4031 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4032 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4033 EXPECT_EQ(ERR_IO_PENDING, rv);
4035 rv = callback.WaitForResult();
4036 EXPECT_EQ(OK, rv);
4038 LoadTimingInfo load_timing_info;
4039 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4040 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4042 const HttpResponseInfo* response = trans->GetResponseInfo();
4043 ASSERT_TRUE(response != NULL);
4044 ASSERT_TRUE(response->headers.get() != NULL);
4045 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4047 std::string response_data;
4048 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4049 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
4050 trans.reset();
4052 scoped_ptr<HttpTransaction> trans2(
4053 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4054 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4055 EXPECT_EQ(ERR_IO_PENDING, rv);
4057 rv = callback.WaitForResult();
4058 EXPECT_EQ(OK, rv);
4060 LoadTimingInfo load_timing_info2;
4061 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4062 TestLoadTimingReused(load_timing_info2);
4064 // The requests should have the same ID.
4065 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4067 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
4070 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4071 // Proxy to different servers.
4072 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
4073 // Configure against https proxy server "proxy:70".
4074 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
4075 "https://proxy:70"));
4076 BoundTestNetLog log;
4077 session_deps_.net_log = log.bound().net_log();
4078 scoped_refptr<HttpNetworkSession> session(
4079 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
4081 HttpRequestInfo request1;
4082 request1.method = "GET";
4083 request1.url = GURL("http://www.example.org/");
4084 request1.load_flags = 0;
4086 HttpRequestInfo request2;
4087 request2.method = "GET";
4088 request2.url = GURL("http://mail.example.org/");
4089 request2.load_flags = 0;
4091 // http://www.example.org/
4092 scoped_ptr<SpdyHeaderBlock> headers(
4093 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4094 scoped_ptr<SpdyFrame> get1(
4095 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4096 scoped_ptr<SpdyFrame> get_resp1(
4097 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4098 scoped_ptr<SpdyFrame> body1(
4099 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
4101 // http://mail.example.org/
4102 scoped_ptr<SpdyHeaderBlock> headers2(
4103 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4104 scoped_ptr<SpdyFrame> get2(
4105 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
4106 scoped_ptr<SpdyFrame> get_resp2(
4107 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4108 scoped_ptr<SpdyFrame> body2(
4109 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
4111 MockWrite spdy_writes[] = {
4112 CreateMockWrite(*get1, 0),
4113 CreateMockWrite(*get2, 3),
4116 MockRead spdy_reads[] = {
4117 CreateMockRead(*get_resp1, 1, ASYNC),
4118 CreateMockRead(*body1, 2, ASYNC),
4119 CreateMockRead(*get_resp2, 4, ASYNC),
4120 CreateMockRead(*body2, 5, ASYNC),
4121 MockRead(ASYNC, 0, 6),
4124 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4125 arraysize(spdy_writes));
4126 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4128 SSLSocketDataProvider ssl(ASYNC, OK);
4129 ssl.SetNextProto(GetParam());
4130 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4132 TestCompletionCallback callback;
4134 scoped_ptr<HttpTransaction> trans(
4135 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4136 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4137 EXPECT_EQ(OK, callback.GetResult(rv));
4139 LoadTimingInfo load_timing_info;
4140 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4141 TestLoadTimingNotReused(load_timing_info,
4142 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4144 const HttpResponseInfo* response = trans->GetResponseInfo();
4145 ASSERT_TRUE(response != NULL);
4146 ASSERT_TRUE(response->headers.get() != NULL);
4147 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4149 std::string response_data;
4150 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4151 rv = trans->Read(buf.get(), 256, callback.callback());
4152 EXPECT_EQ(1, callback.GetResult(rv));
4153 // Delete the first request, so the second one can reuse the socket.
4154 trans.reset();
4156 scoped_ptr<HttpTransaction> trans2(
4157 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4158 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4159 EXPECT_EQ(OK, callback.GetResult(rv));
4161 LoadTimingInfo load_timing_info2;
4162 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4163 TestLoadTimingReused(load_timing_info2);
4165 // The requests should have the same ID.
4166 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4168 rv = trans2->Read(buf.get(), 256, callback.callback());
4169 EXPECT_EQ(2, callback.GetResult(rv));
4172 // Test the challenge-response-retry sequence through an HTTPS Proxy
4173 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
4174 HttpRequestInfo request;
4175 request.method = "GET";
4176 request.url = GURL("http://www.example.org/");
4177 // when the no authentication data flag is set.
4178 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
4180 // Configure against https proxy server "myproxy:70".
4181 session_deps_.proxy_service.reset(
4182 ProxyService::CreateFixed("https://myproxy:70"));
4183 BoundTestNetLog log;
4184 session_deps_.net_log = log.bound().net_log();
4185 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4187 // Since we have proxy, should use full url
4188 MockWrite data_writes1[] = {
4189 MockWrite(
4190 "GET http://www.example.org/ HTTP/1.1\r\n"
4191 "Host: www.example.org\r\n"
4192 "Proxy-Connection: keep-alive\r\n\r\n"),
4194 // After calling trans->RestartWithAuth(), this is the request we should
4195 // be issuing -- the final header line contains the credentials.
4196 MockWrite(
4197 "GET http://www.example.org/ HTTP/1.1\r\n"
4198 "Host: www.example.org\r\n"
4199 "Proxy-Connection: keep-alive\r\n"
4200 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4203 // The proxy responds to the GET with a 407, using a persistent
4204 // connection.
4205 MockRead data_reads1[] = {
4206 // No credentials.
4207 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4208 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4209 MockRead("Proxy-Connection: keep-alive\r\n"),
4210 MockRead("Content-Length: 0\r\n\r\n"),
4212 MockRead("HTTP/1.1 200 OK\r\n"),
4213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4214 MockRead("Content-Length: 100\r\n\r\n"),
4215 MockRead(SYNCHRONOUS, OK),
4218 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4219 data_writes1, arraysize(data_writes1));
4220 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4221 SSLSocketDataProvider ssl(ASYNC, OK);
4222 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4224 TestCompletionCallback callback1;
4226 scoped_ptr<HttpTransaction> trans(
4227 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4229 int rv = trans->Start(&request, callback1.callback(), log.bound());
4230 EXPECT_EQ(ERR_IO_PENDING, rv);
4232 rv = callback1.WaitForResult();
4233 EXPECT_EQ(OK, rv);
4235 LoadTimingInfo load_timing_info;
4236 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4237 TestLoadTimingNotReused(load_timing_info,
4238 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4240 const HttpResponseInfo* response = trans->GetResponseInfo();
4241 ASSERT_TRUE(response != NULL);
4242 ASSERT_FALSE(response->headers.get() == NULL);
4243 EXPECT_EQ(407, response->headers->response_code());
4244 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4245 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4247 TestCompletionCallback callback2;
4249 rv = trans->RestartWithAuth(
4250 AuthCredentials(kFoo, kBar), callback2.callback());
4251 EXPECT_EQ(ERR_IO_PENDING, rv);
4253 rv = callback2.WaitForResult();
4254 EXPECT_EQ(OK, rv);
4256 load_timing_info = LoadTimingInfo();
4257 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4258 // Retrying with HTTP AUTH is considered to be reusing a socket.
4259 TestLoadTimingReused(load_timing_info);
4261 response = trans->GetResponseInfo();
4262 ASSERT_TRUE(response != NULL);
4264 EXPECT_TRUE(response->headers->IsKeepAlive());
4265 EXPECT_EQ(200, response->headers->response_code());
4266 EXPECT_EQ(100, response->headers->GetContentLength());
4267 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4269 // The password prompt info should not be set.
4270 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4273 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4274 const MockRead& status, int expected_status) {
4275 HttpRequestInfo request;
4276 request.method = "GET";
4277 request.url = GURL("https://www.example.org/");
4278 request.load_flags = 0;
4280 // Configure against proxy server "myproxy:70".
4281 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4282 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4284 // Since we have proxy, should try to establish tunnel.
4285 MockWrite data_writes[] = {
4286 MockWrite(
4287 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4288 "Host: www.example.org\r\n"
4289 "Proxy-Connection: keep-alive\r\n\r\n"),
4292 MockRead data_reads[] = {
4293 status,
4294 MockRead("Content-Length: 10\r\n\r\n"),
4295 // No response body because the test stops reading here.
4296 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4299 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4300 data_writes, arraysize(data_writes));
4301 session_deps_.socket_factory->AddSocketDataProvider(&data);
4303 TestCompletionCallback callback;
4305 scoped_ptr<HttpTransaction> trans(
4306 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4308 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4309 EXPECT_EQ(ERR_IO_PENDING, rv);
4311 rv = callback.WaitForResult();
4312 EXPECT_EQ(expected_status, rv);
4315 void HttpNetworkTransactionTest::ConnectStatusHelper(
4316 const MockRead& status) {
4317 ConnectStatusHelperWithExpectedStatus(
4318 status, ERR_TUNNEL_CONNECTION_FAILED);
4321 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4322 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4325 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4326 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4329 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4330 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4333 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4334 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4337 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4338 ConnectStatusHelper(
4339 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4342 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4343 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4346 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4347 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4350 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4351 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4354 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4355 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4358 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4359 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4362 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4363 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4366 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4367 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4370 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4371 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4374 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4375 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4378 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4379 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4382 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4383 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4386 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4387 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4390 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4391 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4394 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4395 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4398 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4399 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4402 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4403 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4406 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4407 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4410 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4411 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4414 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4415 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4418 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4419 ConnectStatusHelperWithExpectedStatus(
4420 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4421 ERR_PROXY_AUTH_UNSUPPORTED);
4424 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4425 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4428 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4429 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4432 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4433 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4436 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4437 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4440 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4441 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4444 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4445 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4448 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4449 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4452 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4453 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4456 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4457 ConnectStatusHelper(
4458 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4461 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4462 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4465 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4466 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4469 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4470 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4473 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4474 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4477 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4478 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4481 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4482 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4485 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4486 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4489 // Test the flow when both the proxy server AND origin server require
4490 // authentication. Again, this uses basic auth for both since that is
4491 // the simplest to mock.
4492 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4493 HttpRequestInfo request;
4494 request.method = "GET";
4495 request.url = GURL("http://www.example.org/");
4496 request.load_flags = 0;
4498 // Configure against proxy server "myproxy:70".
4499 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4500 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4502 scoped_ptr<HttpTransaction> trans(
4503 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4505 MockWrite data_writes1[] = {
4506 MockWrite(
4507 "GET http://www.example.org/ HTTP/1.1\r\n"
4508 "Host: www.example.org\r\n"
4509 "Proxy-Connection: keep-alive\r\n\r\n"),
4512 MockRead data_reads1[] = {
4513 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4514 // Give a couple authenticate options (only the middle one is actually
4515 // supported).
4516 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4517 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4518 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4519 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4520 // Large content-length -- won't matter, as connection will be reset.
4521 MockRead("Content-Length: 10000\r\n\r\n"),
4522 MockRead(SYNCHRONOUS, ERR_FAILED),
4525 // After calling trans->RestartWithAuth() the first time, this is the
4526 // request we should be issuing -- the final header line contains the
4527 // proxy's credentials.
4528 MockWrite data_writes2[] = {
4529 MockWrite(
4530 "GET http://www.example.org/ HTTP/1.1\r\n"
4531 "Host: www.example.org\r\n"
4532 "Proxy-Connection: keep-alive\r\n"
4533 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4536 // Now the proxy server lets the request pass through to origin server.
4537 // The origin server responds with a 401.
4538 MockRead data_reads2[] = {
4539 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4540 // Note: We are using the same realm-name as the proxy server. This is
4541 // completely valid, as realms are unique across hosts.
4542 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4543 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4544 MockRead("Content-Length: 2000\r\n\r\n"),
4545 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4548 // After calling trans->RestartWithAuth() the second time, we should send
4549 // the credentials for both the proxy and origin server.
4550 MockWrite data_writes3[] = {
4551 MockWrite(
4552 "GET http://www.example.org/ HTTP/1.1\r\n"
4553 "Host: www.example.org\r\n"
4554 "Proxy-Connection: keep-alive\r\n"
4555 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4556 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4559 // Lastly we get the desired content.
4560 MockRead data_reads3[] = {
4561 MockRead("HTTP/1.0 200 OK\r\n"),
4562 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4563 MockRead("Content-Length: 100\r\n\r\n"),
4564 MockRead(SYNCHRONOUS, OK),
4567 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4568 data_writes1, arraysize(data_writes1));
4569 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4570 data_writes2, arraysize(data_writes2));
4571 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4572 data_writes3, arraysize(data_writes3));
4573 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4574 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4575 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4577 TestCompletionCallback callback1;
4579 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4580 EXPECT_EQ(ERR_IO_PENDING, rv);
4582 rv = callback1.WaitForResult();
4583 EXPECT_EQ(OK, rv);
4585 const HttpResponseInfo* response = trans->GetResponseInfo();
4586 ASSERT_TRUE(response != NULL);
4587 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4589 TestCompletionCallback callback2;
4591 rv = trans->RestartWithAuth(
4592 AuthCredentials(kFoo, kBar), callback2.callback());
4593 EXPECT_EQ(ERR_IO_PENDING, rv);
4595 rv = callback2.WaitForResult();
4596 EXPECT_EQ(OK, rv);
4598 response = trans->GetResponseInfo();
4599 ASSERT_TRUE(response != NULL);
4600 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4602 TestCompletionCallback callback3;
4604 rv = trans->RestartWithAuth(
4605 AuthCredentials(kFoo2, kBar2), callback3.callback());
4606 EXPECT_EQ(ERR_IO_PENDING, rv);
4608 rv = callback3.WaitForResult();
4609 EXPECT_EQ(OK, rv);
4611 response = trans->GetResponseInfo();
4612 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4613 EXPECT_EQ(100, response->headers->GetContentLength());
4616 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4617 // can't hook into its internals to cause it to generate predictable NTLM
4618 // authorization headers.
4619 #if defined(NTLM_PORTABLE)
4620 // The NTLM authentication unit tests were generated by capturing the HTTP
4621 // requests and responses using Fiddler 2 and inspecting the generated random
4622 // bytes in the debugger.
4624 // Enter the correct password and authenticate successfully.
4625 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4626 HttpRequestInfo request;
4627 request.method = "GET";
4628 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4630 // Ensure load is not disrupted by flags which suppress behaviour specific
4631 // to other auth schemes.
4632 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4634 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4635 MockGetHostName);
4636 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4638 MockWrite data_writes1[] = {
4639 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4640 "Host: 172.22.68.17\r\n"
4641 "Connection: keep-alive\r\n\r\n"),
4644 MockRead data_reads1[] = {
4645 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4646 // Negotiate and NTLM are often requested together. However, we only want
4647 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4648 // the header that requests Negotiate for this test.
4649 MockRead("WWW-Authenticate: NTLM\r\n"),
4650 MockRead("Connection: close\r\n"),
4651 MockRead("Content-Length: 42\r\n"),
4652 MockRead("Content-Type: text/html\r\n\r\n"),
4653 // Missing content -- won't matter, as connection will be reset.
4654 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4657 MockWrite data_writes2[] = {
4658 // After restarting with a null identity, this is the
4659 // request we should be issuing -- the final header line contains a Type
4660 // 1 message.
4661 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4662 "Host: 172.22.68.17\r\n"
4663 "Connection: keep-alive\r\n"
4664 "Authorization: NTLM "
4665 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4667 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4668 // (the credentials for the origin server). The second request continues
4669 // on the same connection.
4670 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4671 "Host: 172.22.68.17\r\n"
4672 "Connection: keep-alive\r\n"
4673 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4674 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4675 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4676 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4677 "ahlhx5I=\r\n\r\n"),
4680 MockRead data_reads2[] = {
4681 // The origin server responds with a Type 2 message.
4682 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4683 MockRead("WWW-Authenticate: NTLM "
4684 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4685 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4686 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4687 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4688 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4689 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4690 "BtAAAAAAA=\r\n"),
4691 MockRead("Content-Length: 42\r\n"),
4692 MockRead("Content-Type: text/html\r\n\r\n"),
4693 MockRead("You are not authorized to view this page\r\n"),
4695 // Lastly we get the desired content.
4696 MockRead("HTTP/1.1 200 OK\r\n"),
4697 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4698 MockRead("Content-Length: 13\r\n\r\n"),
4699 MockRead("Please Login\r\n"),
4700 MockRead(SYNCHRONOUS, OK),
4703 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4704 data_writes1, arraysize(data_writes1));
4705 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4706 data_writes2, arraysize(data_writes2));
4707 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4708 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4710 TestCompletionCallback callback1;
4712 scoped_ptr<HttpTransaction> trans(
4713 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4715 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4716 EXPECT_EQ(ERR_IO_PENDING, rv);
4718 rv = callback1.WaitForResult();
4719 EXPECT_EQ(OK, rv);
4721 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4723 const HttpResponseInfo* response = trans->GetResponseInfo();
4724 ASSERT_FALSE(response == NULL);
4725 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4727 TestCompletionCallback callback2;
4729 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4730 callback2.callback());
4731 EXPECT_EQ(ERR_IO_PENDING, rv);
4733 rv = callback2.WaitForResult();
4734 EXPECT_EQ(OK, rv);
4736 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4738 response = trans->GetResponseInfo();
4739 ASSERT_TRUE(response != NULL);
4740 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4742 TestCompletionCallback callback3;
4744 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4745 EXPECT_EQ(ERR_IO_PENDING, rv);
4747 rv = callback3.WaitForResult();
4748 EXPECT_EQ(OK, rv);
4750 response = trans->GetResponseInfo();
4751 ASSERT_TRUE(response != NULL);
4752 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4753 EXPECT_EQ(13, response->headers->GetContentLength());
4756 // Enter a wrong password, and then the correct one.
4757 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4758 HttpRequestInfo request;
4759 request.method = "GET";
4760 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4761 request.load_flags = 0;
4763 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4764 MockGetHostName);
4765 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4767 MockWrite data_writes1[] = {
4768 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4769 "Host: 172.22.68.17\r\n"
4770 "Connection: keep-alive\r\n\r\n"),
4773 MockRead data_reads1[] = {
4774 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4775 // Negotiate and NTLM are often requested together. However, we only want
4776 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4777 // the header that requests Negotiate for this test.
4778 MockRead("WWW-Authenticate: NTLM\r\n"),
4779 MockRead("Connection: close\r\n"),
4780 MockRead("Content-Length: 42\r\n"),
4781 MockRead("Content-Type: text/html\r\n\r\n"),
4782 // Missing content -- won't matter, as connection will be reset.
4783 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4786 MockWrite data_writes2[] = {
4787 // After restarting with a null identity, this is the
4788 // request we should be issuing -- the final header line contains a Type
4789 // 1 message.
4790 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4791 "Host: 172.22.68.17\r\n"
4792 "Connection: keep-alive\r\n"
4793 "Authorization: NTLM "
4794 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4796 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4797 // (the credentials for the origin server). The second request continues
4798 // on the same connection.
4799 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4800 "Host: 172.22.68.17\r\n"
4801 "Connection: keep-alive\r\n"
4802 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4803 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4804 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4805 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4806 "4Ww7b7E=\r\n\r\n"),
4809 MockRead data_reads2[] = {
4810 // The origin server responds with a Type 2 message.
4811 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4812 MockRead("WWW-Authenticate: NTLM "
4813 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4814 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4815 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4816 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4817 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4818 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4819 "BtAAAAAAA=\r\n"),
4820 MockRead("Content-Length: 42\r\n"),
4821 MockRead("Content-Type: text/html\r\n\r\n"),
4822 MockRead("You are not authorized to view this page\r\n"),
4824 // Wrong password.
4825 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4826 MockRead("WWW-Authenticate: NTLM\r\n"),
4827 MockRead("Connection: close\r\n"),
4828 MockRead("Content-Length: 42\r\n"),
4829 MockRead("Content-Type: text/html\r\n\r\n"),
4830 // Missing content -- won't matter, as connection will be reset.
4831 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4834 MockWrite data_writes3[] = {
4835 // After restarting with a null identity, this is the
4836 // request we should be issuing -- the final header line contains a Type
4837 // 1 message.
4838 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4839 "Host: 172.22.68.17\r\n"
4840 "Connection: keep-alive\r\n"
4841 "Authorization: NTLM "
4842 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4844 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4845 // (the credentials for the origin server). The second request continues
4846 // on the same connection.
4847 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4848 "Host: 172.22.68.17\r\n"
4849 "Connection: keep-alive\r\n"
4850 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4851 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4852 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4853 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4854 "+4MUm7c=\r\n\r\n"),
4857 MockRead data_reads3[] = {
4858 // The origin server responds with a Type 2 message.
4859 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4860 MockRead("WWW-Authenticate: NTLM "
4861 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4862 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4863 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4864 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4865 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4866 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4867 "BtAAAAAAA=\r\n"),
4868 MockRead("Content-Length: 42\r\n"),
4869 MockRead("Content-Type: text/html\r\n\r\n"),
4870 MockRead("You are not authorized to view this page\r\n"),
4872 // Lastly we get the desired content.
4873 MockRead("HTTP/1.1 200 OK\r\n"),
4874 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4875 MockRead("Content-Length: 13\r\n\r\n"),
4876 MockRead("Please Login\r\n"),
4877 MockRead(SYNCHRONOUS, OK),
4880 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4881 data_writes1, arraysize(data_writes1));
4882 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4883 data_writes2, arraysize(data_writes2));
4884 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4885 data_writes3, arraysize(data_writes3));
4886 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4887 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4888 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4890 TestCompletionCallback callback1;
4892 scoped_ptr<HttpTransaction> trans(
4893 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4895 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4896 EXPECT_EQ(ERR_IO_PENDING, rv);
4898 rv = callback1.WaitForResult();
4899 EXPECT_EQ(OK, rv);
4901 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4903 const HttpResponseInfo* response = trans->GetResponseInfo();
4904 ASSERT_TRUE(response != NULL);
4905 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4907 TestCompletionCallback callback2;
4909 // Enter the wrong password.
4910 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4911 callback2.callback());
4912 EXPECT_EQ(ERR_IO_PENDING, rv);
4914 rv = callback2.WaitForResult();
4915 EXPECT_EQ(OK, rv);
4917 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4918 TestCompletionCallback callback3;
4919 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4920 EXPECT_EQ(ERR_IO_PENDING, rv);
4921 rv = callback3.WaitForResult();
4922 EXPECT_EQ(OK, rv);
4923 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4925 response = trans->GetResponseInfo();
4926 ASSERT_FALSE(response == NULL);
4927 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4929 TestCompletionCallback callback4;
4931 // Now enter the right password.
4932 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4933 callback4.callback());
4934 EXPECT_EQ(ERR_IO_PENDING, rv);
4936 rv = callback4.WaitForResult();
4937 EXPECT_EQ(OK, rv);
4939 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4941 TestCompletionCallback callback5;
4943 // One more roundtrip
4944 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4945 EXPECT_EQ(ERR_IO_PENDING, rv);
4947 rv = callback5.WaitForResult();
4948 EXPECT_EQ(OK, rv);
4950 response = trans->GetResponseInfo();
4951 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4952 EXPECT_EQ(13, response->headers->GetContentLength());
4954 #endif // NTLM_PORTABLE
4956 // Test reading a server response which has only headers, and no body.
4957 // After some maximum number of bytes is consumed, the transaction should
4958 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4959 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4960 HttpRequestInfo request;
4961 request.method = "GET";
4962 request.url = GURL("http://www.example.org/");
4963 request.load_flags = 0;
4965 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4966 scoped_ptr<HttpTransaction> trans(
4967 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4969 // Respond with 300 kb of headers (we should fail after 256 kb).
4970 std::string large_headers_string;
4971 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4973 MockRead data_reads[] = {
4974 MockRead("HTTP/1.0 200 OK\r\n"),
4975 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4976 MockRead("\r\nBODY"),
4977 MockRead(SYNCHRONOUS, OK),
4979 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4980 session_deps_.socket_factory->AddSocketDataProvider(&data);
4982 TestCompletionCallback callback;
4984 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4985 EXPECT_EQ(ERR_IO_PENDING, rv);
4987 rv = callback.WaitForResult();
4988 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4991 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4992 // establish tunnel.
4993 // http://code.google.com/p/chromium/issues/detail?id=3772
4994 TEST_P(HttpNetworkTransactionTest,
4995 DontRecycleTransportSocketForSSLTunnel) {
4996 HttpRequestInfo request;
4997 request.method = "GET";
4998 request.url = GURL("https://www.example.org/");
4999 request.load_flags = 0;
5001 // Configure against proxy server "myproxy:70".
5002 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5004 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5006 scoped_ptr<HttpTransaction> trans(
5007 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5009 // Since we have proxy, should try to establish tunnel.
5010 MockWrite data_writes1[] = {
5011 MockWrite(
5012 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5013 "Host: www.example.org\r\n"
5014 "Proxy-Connection: keep-alive\r\n\r\n"),
5017 // The proxy responds to the connect with a 404, using a persistent
5018 // connection. Usually a proxy would return 501 (not implemented),
5019 // or 200 (tunnel established).
5020 MockRead data_reads1[] = {
5021 MockRead("HTTP/1.1 404 Not Found\r\n"),
5022 MockRead("Content-Length: 10\r\n\r\n"),
5023 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
5026 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5027 data_writes1, arraysize(data_writes1));
5028 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5030 TestCompletionCallback callback1;
5032 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5033 EXPECT_EQ(ERR_IO_PENDING, rv);
5035 rv = callback1.WaitForResult();
5036 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5038 // Empty the current queue. This is necessary because idle sockets are
5039 // added to the connection pool asynchronously with a PostTask.
5040 base::MessageLoop::current()->RunUntilIdle();
5042 // We now check to make sure the TCPClientSocket was not added back to
5043 // the pool.
5044 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5045 trans.reset();
5046 base::MessageLoop::current()->RunUntilIdle();
5047 // Make sure that the socket didn't get recycled after calling the destructor.
5048 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5051 // Make sure that we recycle a socket after reading all of the response body.
5052 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
5053 HttpRequestInfo request;
5054 request.method = "GET";
5055 request.url = GURL("http://www.example.org/");
5056 request.load_flags = 0;
5058 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5060 scoped_ptr<HttpTransaction> trans(
5061 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5063 MockRead data_reads[] = {
5064 // A part of the response body is received with the response headers.
5065 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5066 // The rest of the response body is received in two parts.
5067 MockRead("lo"),
5068 MockRead(" world"),
5069 MockRead("junk"), // Should not be read!!
5070 MockRead(SYNCHRONOUS, OK),
5073 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5074 session_deps_.socket_factory->AddSocketDataProvider(&data);
5076 TestCompletionCallback callback;
5078 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5079 EXPECT_EQ(ERR_IO_PENDING, rv);
5081 rv = callback.WaitForResult();
5082 EXPECT_EQ(OK, rv);
5084 const HttpResponseInfo* response = trans->GetResponseInfo();
5085 ASSERT_TRUE(response != NULL);
5087 EXPECT_TRUE(response->headers.get() != NULL);
5088 std::string status_line = response->headers->GetStatusLine();
5089 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5091 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5093 std::string response_data;
5094 rv = ReadTransaction(trans.get(), &response_data);
5095 EXPECT_EQ(OK, rv);
5096 EXPECT_EQ("hello world", response_data);
5098 // Empty the current queue. This is necessary because idle sockets are
5099 // added to the connection pool asynchronously with a PostTask.
5100 base::MessageLoop::current()->RunUntilIdle();
5102 // We now check to make sure the socket was added back to the pool.
5103 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5106 // Make sure that we recycle a SSL socket after reading all of the response
5107 // body.
5108 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
5109 HttpRequestInfo request;
5110 request.method = "GET";
5111 request.url = GURL("https://www.example.org/");
5112 request.load_flags = 0;
5114 MockWrite data_writes[] = {
5115 MockWrite(
5116 "GET / HTTP/1.1\r\n"
5117 "Host: www.example.org\r\n"
5118 "Connection: keep-alive\r\n\r\n"),
5121 MockRead data_reads[] = {
5122 MockRead("HTTP/1.1 200 OK\r\n"),
5123 MockRead("Content-Length: 11\r\n\r\n"),
5124 MockRead("hello world"),
5125 MockRead(SYNCHRONOUS, OK),
5128 SSLSocketDataProvider ssl(ASYNC, OK);
5129 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5131 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5132 data_writes, arraysize(data_writes));
5133 session_deps_.socket_factory->AddSocketDataProvider(&data);
5135 TestCompletionCallback callback;
5137 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5138 scoped_ptr<HttpTransaction> trans(
5139 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5141 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5143 EXPECT_EQ(ERR_IO_PENDING, rv);
5144 EXPECT_EQ(OK, callback.WaitForResult());
5146 const HttpResponseInfo* response = trans->GetResponseInfo();
5147 ASSERT_TRUE(response != NULL);
5148 ASSERT_TRUE(response->headers.get() != NULL);
5149 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5151 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5153 std::string response_data;
5154 rv = ReadTransaction(trans.get(), &response_data);
5155 EXPECT_EQ(OK, rv);
5156 EXPECT_EQ("hello world", response_data);
5158 // Empty the current queue. This is necessary because idle sockets are
5159 // added to the connection pool asynchronously with a PostTask.
5160 base::MessageLoop::current()->RunUntilIdle();
5162 // We now check to make sure the socket was added back to the pool.
5163 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5166 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5167 // from the pool and make sure that we recover okay.
5168 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
5169 HttpRequestInfo request;
5170 request.method = "GET";
5171 request.url = GURL("https://www.example.org/");
5172 request.load_flags = 0;
5174 MockWrite data_writes[] = {
5175 MockWrite(
5176 "GET / HTTP/1.1\r\n"
5177 "Host: www.example.org\r\n"
5178 "Connection: keep-alive\r\n\r\n"),
5179 MockWrite(
5180 "GET / HTTP/1.1\r\n"
5181 "Host: www.example.org\r\n"
5182 "Connection: keep-alive\r\n\r\n"),
5185 MockRead data_reads[] = {
5186 MockRead("HTTP/1.1 200 OK\r\n"),
5187 MockRead("Content-Length: 11\r\n\r\n"),
5188 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
5189 MockRead("hello world"),
5190 MockRead(ASYNC, 0, 0) // EOF
5193 SSLSocketDataProvider ssl(ASYNC, OK);
5194 SSLSocketDataProvider ssl2(ASYNC, OK);
5195 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5196 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5198 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5199 data_writes, arraysize(data_writes));
5200 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5201 data_writes, arraysize(data_writes));
5202 session_deps_.socket_factory->AddSocketDataProvider(&data);
5203 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5205 TestCompletionCallback callback;
5207 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5208 scoped_ptr<HttpTransaction> trans(
5209 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5211 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5213 EXPECT_EQ(ERR_IO_PENDING, rv);
5214 EXPECT_EQ(OK, callback.WaitForResult());
5216 const HttpResponseInfo* response = trans->GetResponseInfo();
5217 ASSERT_TRUE(response != NULL);
5218 ASSERT_TRUE(response->headers.get() != NULL);
5219 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5221 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5223 std::string response_data;
5224 rv = ReadTransaction(trans.get(), &response_data);
5225 EXPECT_EQ(OK, rv);
5226 EXPECT_EQ("hello world", response_data);
5228 // Empty the current queue. This is necessary because idle sockets are
5229 // added to the connection pool asynchronously with a PostTask.
5230 base::MessageLoop::current()->RunUntilIdle();
5232 // We now check to make sure the socket was added back to the pool.
5233 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5235 // Now start the second transaction, which should reuse the previous socket.
5237 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5239 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5241 EXPECT_EQ(ERR_IO_PENDING, rv);
5242 EXPECT_EQ(OK, callback.WaitForResult());
5244 response = trans->GetResponseInfo();
5245 ASSERT_TRUE(response != NULL);
5246 ASSERT_TRUE(response->headers.get() != NULL);
5247 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5249 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5251 rv = ReadTransaction(trans.get(), &response_data);
5252 EXPECT_EQ(OK, rv);
5253 EXPECT_EQ("hello world", response_data);
5255 // Empty the current queue. This is necessary because idle sockets are
5256 // added to the connection pool asynchronously with a PostTask.
5257 base::MessageLoop::current()->RunUntilIdle();
5259 // We now check to make sure the socket was added back to the pool.
5260 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5263 // Make sure that we recycle a socket after a zero-length response.
5264 // http://crbug.com/9880
5265 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
5266 HttpRequestInfo request;
5267 request.method = "GET";
5268 request.url = GURL(
5269 "http://www.example.org/csi?v=3&s=web&action=&"
5270 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5271 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5272 "rt=prt.2642,ol.2649,xjs.2951");
5273 request.load_flags = 0;
5275 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5277 scoped_ptr<HttpTransaction> trans(
5278 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5280 MockRead data_reads[] = {
5281 MockRead("HTTP/1.1 204 No Content\r\n"
5282 "Content-Length: 0\r\n"
5283 "Content-Type: text/html\r\n\r\n"),
5284 MockRead("junk"), // Should not be read!!
5285 MockRead(SYNCHRONOUS, OK),
5288 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5289 session_deps_.socket_factory->AddSocketDataProvider(&data);
5291 TestCompletionCallback callback;
5293 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5294 EXPECT_EQ(ERR_IO_PENDING, rv);
5296 rv = callback.WaitForResult();
5297 EXPECT_EQ(OK, rv);
5299 const HttpResponseInfo* response = trans->GetResponseInfo();
5300 ASSERT_TRUE(response != NULL);
5302 EXPECT_TRUE(response->headers.get() != NULL);
5303 std::string status_line = response->headers->GetStatusLine();
5304 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5306 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5308 std::string response_data;
5309 rv = ReadTransaction(trans.get(), &response_data);
5310 EXPECT_EQ(OK, rv);
5311 EXPECT_EQ("", response_data);
5313 // Empty the current queue. This is necessary because idle sockets are
5314 // added to the connection pool asynchronously with a PostTask.
5315 base::MessageLoop::current()->RunUntilIdle();
5317 // We now check to make sure the socket was added back to the pool.
5318 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5321 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5322 ScopedVector<UploadElementReader> element_readers;
5323 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5324 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
5326 HttpRequestInfo request[2];
5327 // Transaction 1: a GET request that succeeds. The socket is recycled
5328 // after use.
5329 request[0].method = "GET";
5330 request[0].url = GURL("http://www.google.com/");
5331 request[0].load_flags = 0;
5332 // Transaction 2: a POST request. Reuses the socket kept alive from
5333 // transaction 1. The first attempts fails when writing the POST data.
5334 // This causes the transaction to retry with a new socket. The second
5335 // attempt succeeds.
5336 request[1].method = "POST";
5337 request[1].url = GURL("http://www.google.com/login.cgi");
5338 request[1].upload_data_stream = &upload_data_stream;
5339 request[1].load_flags = 0;
5341 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5343 // The first socket is used for transaction 1 and the first attempt of
5344 // transaction 2.
5346 // The response of transaction 1.
5347 MockRead data_reads1[] = {
5348 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5349 MockRead("hello world"),
5350 MockRead(SYNCHRONOUS, OK),
5352 // The mock write results of transaction 1 and the first attempt of
5353 // transaction 2.
5354 MockWrite data_writes1[] = {
5355 MockWrite(SYNCHRONOUS, 64), // GET
5356 MockWrite(SYNCHRONOUS, 93), // POST
5357 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5359 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5360 data_writes1, arraysize(data_writes1));
5362 // The second socket is used for the second attempt of transaction 2.
5364 // The response of transaction 2.
5365 MockRead data_reads2[] = {
5366 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5367 MockRead("welcome"),
5368 MockRead(SYNCHRONOUS, OK),
5370 // The mock write results of the second attempt of transaction 2.
5371 MockWrite data_writes2[] = {
5372 MockWrite(SYNCHRONOUS, 93), // POST
5373 MockWrite(SYNCHRONOUS, 3), // POST data
5375 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5376 data_writes2, arraysize(data_writes2));
5378 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5379 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5381 const char* const kExpectedResponseData[] = {
5382 "hello world", "welcome"
5385 for (int i = 0; i < 2; ++i) {
5386 scoped_ptr<HttpTransaction> trans(
5387 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5389 TestCompletionCallback callback;
5391 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5392 EXPECT_EQ(ERR_IO_PENDING, rv);
5394 rv = callback.WaitForResult();
5395 EXPECT_EQ(OK, rv);
5397 const HttpResponseInfo* response = trans->GetResponseInfo();
5398 ASSERT_TRUE(response != NULL);
5400 EXPECT_TRUE(response->headers.get() != NULL);
5401 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5403 std::string response_data;
5404 rv = ReadTransaction(trans.get(), &response_data);
5405 EXPECT_EQ(OK, rv);
5406 EXPECT_EQ(kExpectedResponseData[i], response_data);
5410 // Test the request-challenge-retry sequence for basic auth when there is
5411 // an identity in the URL. The request should be sent as normal, but when
5412 // it fails the identity from the URL is used to answer the challenge.
5413 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5414 HttpRequestInfo request;
5415 request.method = "GET";
5416 request.url = GURL("http://foo:b@r@www.example.org/");
5417 request.load_flags = LOAD_NORMAL;
5419 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5420 scoped_ptr<HttpTransaction> trans(
5421 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5423 // The password contains an escaped character -- for this test to pass it
5424 // will need to be unescaped by HttpNetworkTransaction.
5425 EXPECT_EQ("b%40r", request.url.password());
5427 MockWrite data_writes1[] = {
5428 MockWrite(
5429 "GET / HTTP/1.1\r\n"
5430 "Host: www.example.org\r\n"
5431 "Connection: keep-alive\r\n\r\n"),
5434 MockRead data_reads1[] = {
5435 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5436 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5437 MockRead("Content-Length: 10\r\n\r\n"),
5438 MockRead(SYNCHRONOUS, ERR_FAILED),
5441 // After the challenge above, the transaction will be restarted using the
5442 // identity from the url (foo, b@r) to answer the challenge.
5443 MockWrite data_writes2[] = {
5444 MockWrite(
5445 "GET / HTTP/1.1\r\n"
5446 "Host: www.example.org\r\n"
5447 "Connection: keep-alive\r\n"
5448 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5451 MockRead data_reads2[] = {
5452 MockRead("HTTP/1.0 200 OK\r\n"),
5453 MockRead("Content-Length: 100\r\n\r\n"),
5454 MockRead(SYNCHRONOUS, OK),
5457 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5458 data_writes1, arraysize(data_writes1));
5459 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5460 data_writes2, arraysize(data_writes2));
5461 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5462 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5464 TestCompletionCallback callback1;
5465 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5466 EXPECT_EQ(ERR_IO_PENDING, rv);
5467 rv = callback1.WaitForResult();
5468 EXPECT_EQ(OK, rv);
5469 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5471 TestCompletionCallback callback2;
5472 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5473 EXPECT_EQ(ERR_IO_PENDING, rv);
5474 rv = callback2.WaitForResult();
5475 EXPECT_EQ(OK, rv);
5476 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5478 const HttpResponseInfo* response = trans->GetResponseInfo();
5479 ASSERT_TRUE(response != NULL);
5481 // There is no challenge info, since the identity in URL worked.
5482 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5484 EXPECT_EQ(100, response->headers->GetContentLength());
5486 // Empty the current queue.
5487 base::MessageLoop::current()->RunUntilIdle();
5490 // Test the request-challenge-retry sequence for basic auth when there is an
5491 // incorrect identity in the URL. The identity from the URL should be used only
5492 // once.
5493 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5494 HttpRequestInfo request;
5495 request.method = "GET";
5496 // Note: the URL has a username:password in it. The password "baz" is
5497 // wrong (should be "bar").
5498 request.url = GURL("http://foo:baz@www.example.org/");
5500 request.load_flags = LOAD_NORMAL;
5502 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5503 scoped_ptr<HttpTransaction> trans(
5504 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5506 MockWrite data_writes1[] = {
5507 MockWrite(
5508 "GET / HTTP/1.1\r\n"
5509 "Host: www.example.org\r\n"
5510 "Connection: keep-alive\r\n\r\n"),
5513 MockRead data_reads1[] = {
5514 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5515 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5516 MockRead("Content-Length: 10\r\n\r\n"),
5517 MockRead(SYNCHRONOUS, ERR_FAILED),
5520 // After the challenge above, the transaction will be restarted using the
5521 // identity from the url (foo, baz) to answer the challenge.
5522 MockWrite data_writes2[] = {
5523 MockWrite(
5524 "GET / HTTP/1.1\r\n"
5525 "Host: www.example.org\r\n"
5526 "Connection: keep-alive\r\n"
5527 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5530 MockRead data_reads2[] = {
5531 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5532 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5533 MockRead("Content-Length: 10\r\n\r\n"),
5534 MockRead(SYNCHRONOUS, ERR_FAILED),
5537 // After the challenge above, the transaction will be restarted using the
5538 // identity supplied by the user (foo, bar) to answer the challenge.
5539 MockWrite data_writes3[] = {
5540 MockWrite(
5541 "GET / HTTP/1.1\r\n"
5542 "Host: www.example.org\r\n"
5543 "Connection: keep-alive\r\n"
5544 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5547 MockRead data_reads3[] = {
5548 MockRead("HTTP/1.0 200 OK\r\n"),
5549 MockRead("Content-Length: 100\r\n\r\n"),
5550 MockRead(SYNCHRONOUS, OK),
5553 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5554 data_writes1, arraysize(data_writes1));
5555 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5556 data_writes2, arraysize(data_writes2));
5557 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5558 data_writes3, arraysize(data_writes3));
5559 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5560 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5561 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5563 TestCompletionCallback callback1;
5565 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5566 EXPECT_EQ(ERR_IO_PENDING, rv);
5568 rv = callback1.WaitForResult();
5569 EXPECT_EQ(OK, rv);
5571 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5572 TestCompletionCallback callback2;
5573 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5574 EXPECT_EQ(ERR_IO_PENDING, rv);
5575 rv = callback2.WaitForResult();
5576 EXPECT_EQ(OK, rv);
5577 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5579 const HttpResponseInfo* response = trans->GetResponseInfo();
5580 ASSERT_TRUE(response != NULL);
5581 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5583 TestCompletionCallback callback3;
5584 rv = trans->RestartWithAuth(
5585 AuthCredentials(kFoo, kBar), callback3.callback());
5586 EXPECT_EQ(ERR_IO_PENDING, rv);
5587 rv = callback3.WaitForResult();
5588 EXPECT_EQ(OK, rv);
5589 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5591 response = trans->GetResponseInfo();
5592 ASSERT_TRUE(response != NULL);
5594 // There is no challenge info, since the identity worked.
5595 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5597 EXPECT_EQ(100, response->headers->GetContentLength());
5599 // Empty the current queue.
5600 base::MessageLoop::current()->RunUntilIdle();
5604 // Test the request-challenge-retry sequence for basic auth when there is a
5605 // correct identity in the URL, but its use is being suppressed. The identity
5606 // from the URL should never be used.
5607 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5608 HttpRequestInfo request;
5609 request.method = "GET";
5610 request.url = GURL("http://foo:bar@www.example.org/");
5611 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5613 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5614 scoped_ptr<HttpTransaction> trans(
5615 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5617 MockWrite data_writes1[] = {
5618 MockWrite(
5619 "GET / HTTP/1.1\r\n"
5620 "Host: www.example.org\r\n"
5621 "Connection: keep-alive\r\n\r\n"),
5624 MockRead data_reads1[] = {
5625 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5626 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5627 MockRead("Content-Length: 10\r\n\r\n"),
5628 MockRead(SYNCHRONOUS, ERR_FAILED),
5631 // After the challenge above, the transaction will be restarted using the
5632 // identity supplied by the user, not the one in the URL, to answer the
5633 // challenge.
5634 MockWrite data_writes3[] = {
5635 MockWrite(
5636 "GET / HTTP/1.1\r\n"
5637 "Host: www.example.org\r\n"
5638 "Connection: keep-alive\r\n"
5639 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5642 MockRead data_reads3[] = {
5643 MockRead("HTTP/1.0 200 OK\r\n"),
5644 MockRead("Content-Length: 100\r\n\r\n"),
5645 MockRead(SYNCHRONOUS, OK),
5648 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5649 data_writes1, arraysize(data_writes1));
5650 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5651 data_writes3, arraysize(data_writes3));
5652 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5653 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5655 TestCompletionCallback callback1;
5656 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5657 EXPECT_EQ(ERR_IO_PENDING, rv);
5658 rv = callback1.WaitForResult();
5659 EXPECT_EQ(OK, rv);
5660 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5662 const HttpResponseInfo* response = trans->GetResponseInfo();
5663 ASSERT_TRUE(response != NULL);
5664 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5666 TestCompletionCallback callback3;
5667 rv = trans->RestartWithAuth(
5668 AuthCredentials(kFoo, kBar), callback3.callback());
5669 EXPECT_EQ(ERR_IO_PENDING, rv);
5670 rv = callback3.WaitForResult();
5671 EXPECT_EQ(OK, rv);
5672 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5674 response = trans->GetResponseInfo();
5675 ASSERT_TRUE(response != NULL);
5677 // There is no challenge info, since the identity worked.
5678 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5679 EXPECT_EQ(100, response->headers->GetContentLength());
5681 // Empty the current queue.
5682 base::MessageLoop::current()->RunUntilIdle();
5685 // Test that previously tried username/passwords for a realm get re-used.
5686 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5687 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5689 // Transaction 1: authenticate (foo, bar) on MyRealm1
5691 HttpRequestInfo request;
5692 request.method = "GET";
5693 request.url = GURL("http://www.example.org/x/y/z");
5694 request.load_flags = 0;
5696 scoped_ptr<HttpTransaction> trans(
5697 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5699 MockWrite data_writes1[] = {
5700 MockWrite(
5701 "GET /x/y/z HTTP/1.1\r\n"
5702 "Host: www.example.org\r\n"
5703 "Connection: keep-alive\r\n\r\n"),
5706 MockRead data_reads1[] = {
5707 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5708 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5709 MockRead("Content-Length: 10000\r\n\r\n"),
5710 MockRead(SYNCHRONOUS, ERR_FAILED),
5713 // Resend with authorization (username=foo, password=bar)
5714 MockWrite data_writes2[] = {
5715 MockWrite(
5716 "GET /x/y/z HTTP/1.1\r\n"
5717 "Host: www.example.org\r\n"
5718 "Connection: keep-alive\r\n"
5719 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5722 // Sever accepts the authorization.
5723 MockRead data_reads2[] = {
5724 MockRead("HTTP/1.0 200 OK\r\n"),
5725 MockRead("Content-Length: 100\r\n\r\n"),
5726 MockRead(SYNCHRONOUS, OK),
5729 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5730 data_writes1, arraysize(data_writes1));
5731 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5732 data_writes2, arraysize(data_writes2));
5733 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5734 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5736 TestCompletionCallback callback1;
5738 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5739 EXPECT_EQ(ERR_IO_PENDING, rv);
5741 rv = callback1.WaitForResult();
5742 EXPECT_EQ(OK, rv);
5744 const HttpResponseInfo* response = trans->GetResponseInfo();
5745 ASSERT_TRUE(response != NULL);
5746 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5748 TestCompletionCallback callback2;
5750 rv = trans->RestartWithAuth(
5751 AuthCredentials(kFoo, kBar), callback2.callback());
5752 EXPECT_EQ(ERR_IO_PENDING, rv);
5754 rv = callback2.WaitForResult();
5755 EXPECT_EQ(OK, rv);
5757 response = trans->GetResponseInfo();
5758 ASSERT_TRUE(response != NULL);
5759 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5760 EXPECT_EQ(100, response->headers->GetContentLength());
5763 // ------------------------------------------------------------------------
5765 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5767 HttpRequestInfo request;
5768 request.method = "GET";
5769 // Note that Transaction 1 was at /x/y/z, so this is in the same
5770 // protection space as MyRealm1.
5771 request.url = GURL("http://www.example.org/x/y/a/b");
5772 request.load_flags = 0;
5774 scoped_ptr<HttpTransaction> trans(
5775 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5777 MockWrite data_writes1[] = {
5778 MockWrite(
5779 "GET /x/y/a/b HTTP/1.1\r\n"
5780 "Host: www.example.org\r\n"
5781 "Connection: keep-alive\r\n"
5782 // Send preemptive authorization for MyRealm1
5783 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5786 // The server didn't like the preemptive authorization, and
5787 // challenges us for a different realm (MyRealm2).
5788 MockRead data_reads1[] = {
5789 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5790 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5791 MockRead("Content-Length: 10000\r\n\r\n"),
5792 MockRead(SYNCHRONOUS, ERR_FAILED),
5795 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5796 MockWrite data_writes2[] = {
5797 MockWrite(
5798 "GET /x/y/a/b HTTP/1.1\r\n"
5799 "Host: www.example.org\r\n"
5800 "Connection: keep-alive\r\n"
5801 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5804 // Sever accepts the authorization.
5805 MockRead data_reads2[] = {
5806 MockRead("HTTP/1.0 200 OK\r\n"),
5807 MockRead("Content-Length: 100\r\n\r\n"),
5808 MockRead(SYNCHRONOUS, OK),
5811 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5812 data_writes1, arraysize(data_writes1));
5813 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5814 data_writes2, arraysize(data_writes2));
5815 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5816 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5818 TestCompletionCallback callback1;
5820 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5821 EXPECT_EQ(ERR_IO_PENDING, rv);
5823 rv = callback1.WaitForResult();
5824 EXPECT_EQ(OK, rv);
5826 const HttpResponseInfo* response = trans->GetResponseInfo();
5827 ASSERT_TRUE(response != NULL);
5828 ASSERT_TRUE(response->auth_challenge.get());
5829 EXPECT_FALSE(response->auth_challenge->is_proxy);
5830 EXPECT_EQ("www.example.org:80",
5831 response->auth_challenge->challenger.ToString());
5832 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5833 EXPECT_EQ("basic", response->auth_challenge->scheme);
5835 TestCompletionCallback callback2;
5837 rv = trans->RestartWithAuth(
5838 AuthCredentials(kFoo2, kBar2), callback2.callback());
5839 EXPECT_EQ(ERR_IO_PENDING, rv);
5841 rv = callback2.WaitForResult();
5842 EXPECT_EQ(OK, rv);
5844 response = trans->GetResponseInfo();
5845 ASSERT_TRUE(response != NULL);
5846 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5847 EXPECT_EQ(100, response->headers->GetContentLength());
5850 // ------------------------------------------------------------------------
5852 // Transaction 3: Resend a request in MyRealm's protection space --
5853 // succeed with preemptive authorization.
5855 HttpRequestInfo request;
5856 request.method = "GET";
5857 request.url = GURL("http://www.example.org/x/y/z2");
5858 request.load_flags = 0;
5860 scoped_ptr<HttpTransaction> trans(
5861 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5863 MockWrite data_writes1[] = {
5864 MockWrite(
5865 "GET /x/y/z2 HTTP/1.1\r\n"
5866 "Host: www.example.org\r\n"
5867 "Connection: keep-alive\r\n"
5868 // The authorization for MyRealm1 gets sent preemptively
5869 // (since the url is in the same protection space)
5870 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5873 // Sever accepts the preemptive authorization
5874 MockRead data_reads1[] = {
5875 MockRead("HTTP/1.0 200 OK\r\n"),
5876 MockRead("Content-Length: 100\r\n\r\n"),
5877 MockRead(SYNCHRONOUS, OK),
5880 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5881 data_writes1, arraysize(data_writes1));
5882 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5884 TestCompletionCallback callback1;
5886 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5887 EXPECT_EQ(ERR_IO_PENDING, rv);
5889 rv = callback1.WaitForResult();
5890 EXPECT_EQ(OK, rv);
5892 const HttpResponseInfo* response = trans->GetResponseInfo();
5893 ASSERT_TRUE(response != NULL);
5895 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5896 EXPECT_EQ(100, response->headers->GetContentLength());
5899 // ------------------------------------------------------------------------
5901 // Transaction 4: request another URL in MyRealm (however the
5902 // url is not known to belong to the protection space, so no pre-auth).
5904 HttpRequestInfo request;
5905 request.method = "GET";
5906 request.url = GURL("http://www.example.org/x/1");
5907 request.load_flags = 0;
5909 scoped_ptr<HttpTransaction> trans(
5910 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5912 MockWrite data_writes1[] = {
5913 MockWrite(
5914 "GET /x/1 HTTP/1.1\r\n"
5915 "Host: www.example.org\r\n"
5916 "Connection: keep-alive\r\n\r\n"),
5919 MockRead data_reads1[] = {
5920 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5921 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5922 MockRead("Content-Length: 10000\r\n\r\n"),
5923 MockRead(SYNCHRONOUS, ERR_FAILED),
5926 // Resend with authorization from MyRealm's cache.
5927 MockWrite data_writes2[] = {
5928 MockWrite(
5929 "GET /x/1 HTTP/1.1\r\n"
5930 "Host: www.example.org\r\n"
5931 "Connection: keep-alive\r\n"
5932 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5935 // Sever accepts the authorization.
5936 MockRead data_reads2[] = {
5937 MockRead("HTTP/1.0 200 OK\r\n"),
5938 MockRead("Content-Length: 100\r\n\r\n"),
5939 MockRead(SYNCHRONOUS, OK),
5942 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5943 data_writes1, arraysize(data_writes1));
5944 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5945 data_writes2, arraysize(data_writes2));
5946 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5947 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5949 TestCompletionCallback callback1;
5951 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5952 EXPECT_EQ(ERR_IO_PENDING, rv);
5954 rv = callback1.WaitForResult();
5955 EXPECT_EQ(OK, rv);
5957 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5958 TestCompletionCallback callback2;
5959 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5960 EXPECT_EQ(ERR_IO_PENDING, rv);
5961 rv = callback2.WaitForResult();
5962 EXPECT_EQ(OK, rv);
5963 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5965 const HttpResponseInfo* response = trans->GetResponseInfo();
5966 ASSERT_TRUE(response != NULL);
5967 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5968 EXPECT_EQ(100, response->headers->GetContentLength());
5971 // ------------------------------------------------------------------------
5973 // Transaction 5: request a URL in MyRealm, but the server rejects the
5974 // cached identity. Should invalidate and re-prompt.
5976 HttpRequestInfo request;
5977 request.method = "GET";
5978 request.url = GURL("http://www.example.org/p/q/t");
5979 request.load_flags = 0;
5981 scoped_ptr<HttpTransaction> trans(
5982 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5984 MockWrite data_writes1[] = {
5985 MockWrite(
5986 "GET /p/q/t HTTP/1.1\r\n"
5987 "Host: www.example.org\r\n"
5988 "Connection: keep-alive\r\n\r\n"),
5991 MockRead data_reads1[] = {
5992 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5993 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5994 MockRead("Content-Length: 10000\r\n\r\n"),
5995 MockRead(SYNCHRONOUS, ERR_FAILED),
5998 // Resend with authorization from cache for MyRealm.
5999 MockWrite data_writes2[] = {
6000 MockWrite(
6001 "GET /p/q/t HTTP/1.1\r\n"
6002 "Host: www.example.org\r\n"
6003 "Connection: keep-alive\r\n"
6004 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6007 // Sever rejects the authorization.
6008 MockRead data_reads2[] = {
6009 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6010 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6011 MockRead("Content-Length: 10000\r\n\r\n"),
6012 MockRead(SYNCHRONOUS, ERR_FAILED),
6015 // At this point we should prompt for new credentials for MyRealm.
6016 // Restart with username=foo3, password=foo4.
6017 MockWrite data_writes3[] = {
6018 MockWrite(
6019 "GET /p/q/t HTTP/1.1\r\n"
6020 "Host: www.example.org\r\n"
6021 "Connection: keep-alive\r\n"
6022 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6025 // Sever accepts the authorization.
6026 MockRead data_reads3[] = {
6027 MockRead("HTTP/1.0 200 OK\r\n"),
6028 MockRead("Content-Length: 100\r\n\r\n"),
6029 MockRead(SYNCHRONOUS, OK),
6032 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6033 data_writes1, arraysize(data_writes1));
6034 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6035 data_writes2, arraysize(data_writes2));
6036 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6037 data_writes3, arraysize(data_writes3));
6038 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6039 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6040 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6042 TestCompletionCallback callback1;
6044 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6045 EXPECT_EQ(ERR_IO_PENDING, rv);
6047 rv = callback1.WaitForResult();
6048 EXPECT_EQ(OK, rv);
6050 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6051 TestCompletionCallback callback2;
6052 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6053 EXPECT_EQ(ERR_IO_PENDING, rv);
6054 rv = callback2.WaitForResult();
6055 EXPECT_EQ(OK, rv);
6056 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6058 const HttpResponseInfo* response = trans->GetResponseInfo();
6059 ASSERT_TRUE(response != NULL);
6060 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6062 TestCompletionCallback callback3;
6064 rv = trans->RestartWithAuth(
6065 AuthCredentials(kFoo3, kBar3), callback3.callback());
6066 EXPECT_EQ(ERR_IO_PENDING, rv);
6068 rv = callback3.WaitForResult();
6069 EXPECT_EQ(OK, rv);
6071 response = trans->GetResponseInfo();
6072 ASSERT_TRUE(response != NULL);
6073 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6074 EXPECT_EQ(100, response->headers->GetContentLength());
6078 // Tests that nonce count increments when multiple auth attempts
6079 // are started with the same nonce.
6080 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
6081 HttpAuthHandlerDigest::Factory* digest_factory =
6082 new HttpAuthHandlerDigest::Factory();
6083 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6084 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6085 digest_factory->set_nonce_generator(nonce_generator);
6086 session_deps_.http_auth_handler_factory.reset(digest_factory);
6087 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6089 // Transaction 1: authenticate (foo, bar) on MyRealm1
6091 HttpRequestInfo request;
6092 request.method = "GET";
6093 request.url = GURL("http://www.example.org/x/y/z");
6094 request.load_flags = 0;
6096 scoped_ptr<HttpTransaction> trans(
6097 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6099 MockWrite data_writes1[] = {
6100 MockWrite(
6101 "GET /x/y/z HTTP/1.1\r\n"
6102 "Host: www.example.org\r\n"
6103 "Connection: keep-alive\r\n\r\n"),
6106 MockRead data_reads1[] = {
6107 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6108 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6109 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6110 MockRead(SYNCHRONOUS, OK),
6113 // Resend with authorization (username=foo, password=bar)
6114 MockWrite data_writes2[] = {
6115 MockWrite(
6116 "GET /x/y/z HTTP/1.1\r\n"
6117 "Host: www.example.org\r\n"
6118 "Connection: keep-alive\r\n"
6119 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6120 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6121 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6122 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6125 // Sever accepts the authorization.
6126 MockRead data_reads2[] = {
6127 MockRead("HTTP/1.0 200 OK\r\n"),
6128 MockRead(SYNCHRONOUS, OK),
6131 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6132 data_writes1, arraysize(data_writes1));
6133 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6134 data_writes2, arraysize(data_writes2));
6135 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6136 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6138 TestCompletionCallback callback1;
6140 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6141 EXPECT_EQ(ERR_IO_PENDING, rv);
6143 rv = callback1.WaitForResult();
6144 EXPECT_EQ(OK, rv);
6146 const HttpResponseInfo* response = trans->GetResponseInfo();
6147 ASSERT_TRUE(response != NULL);
6148 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
6150 TestCompletionCallback callback2;
6152 rv = trans->RestartWithAuth(
6153 AuthCredentials(kFoo, kBar), callback2.callback());
6154 EXPECT_EQ(ERR_IO_PENDING, rv);
6156 rv = callback2.WaitForResult();
6157 EXPECT_EQ(OK, rv);
6159 response = trans->GetResponseInfo();
6160 ASSERT_TRUE(response != NULL);
6161 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6164 // ------------------------------------------------------------------------
6166 // Transaction 2: Request another resource in digestive's protection space.
6167 // This will preemptively add an Authorization header which should have an
6168 // "nc" value of 2 (as compared to 1 in the first use.
6170 HttpRequestInfo request;
6171 request.method = "GET";
6172 // Note that Transaction 1 was at /x/y/z, so this is in the same
6173 // protection space as digest.
6174 request.url = GURL("http://www.example.org/x/y/a/b");
6175 request.load_flags = 0;
6177 scoped_ptr<HttpTransaction> trans(
6178 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6180 MockWrite data_writes1[] = {
6181 MockWrite(
6182 "GET /x/y/a/b HTTP/1.1\r\n"
6183 "Host: www.example.org\r\n"
6184 "Connection: keep-alive\r\n"
6185 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6186 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6187 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6188 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6191 // Sever accepts the authorization.
6192 MockRead data_reads1[] = {
6193 MockRead("HTTP/1.0 200 OK\r\n"),
6194 MockRead("Content-Length: 100\r\n\r\n"),
6195 MockRead(SYNCHRONOUS, OK),
6198 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6199 data_writes1, arraysize(data_writes1));
6200 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6202 TestCompletionCallback callback1;
6204 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6205 EXPECT_EQ(ERR_IO_PENDING, rv);
6207 rv = callback1.WaitForResult();
6208 EXPECT_EQ(OK, rv);
6210 const HttpResponseInfo* response = trans->GetResponseInfo();
6211 ASSERT_TRUE(response != NULL);
6212 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6216 // Test the ResetStateForRestart() private method.
6217 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
6218 // Create a transaction (the dependencies aren't important).
6219 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6220 scoped_ptr<HttpNetworkTransaction> trans(
6221 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6223 // Setup some state (which we expect ResetStateForRestart() will clear).
6224 trans->read_buf_ = new IOBuffer(15);
6225 trans->read_buf_len_ = 15;
6226 trans->request_headers_.SetHeader("Authorization", "NTLM");
6228 // Setup state in response_
6229 HttpResponseInfo* response = &trans->response_;
6230 response->auth_challenge = new AuthChallengeInfo();
6231 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
6232 response->response_time = base::Time::Now();
6233 response->was_cached = true; // (Wouldn't ever actually be true...)
6235 { // Setup state for response_.vary_data
6236 HttpRequestInfo request;
6237 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6238 std::replace(temp.begin(), temp.end(), '\n', '\0');
6239 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
6240 request.extra_headers.SetHeader("Foo", "1");
6241 request.extra_headers.SetHeader("bar", "23");
6242 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
6245 // Cause the above state to be reset.
6246 trans->ResetStateForRestart();
6248 // Verify that the state that needed to be reset, has been reset.
6249 EXPECT_TRUE(trans->read_buf_.get() == NULL);
6250 EXPECT_EQ(0, trans->read_buf_len_);
6251 EXPECT_TRUE(trans->request_headers_.IsEmpty());
6252 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6253 EXPECT_TRUE(response->headers.get() == NULL);
6254 EXPECT_FALSE(response->was_cached);
6255 EXPECT_EQ(0U, response->ssl_info.cert_status);
6256 EXPECT_FALSE(response->vary_data.is_valid());
6259 // Test HTTPS connections to a site with a bad certificate
6260 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
6261 HttpRequestInfo request;
6262 request.method = "GET";
6263 request.url = GURL("https://www.example.org/");
6264 request.load_flags = 0;
6266 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6267 scoped_ptr<HttpTransaction> trans(
6268 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6270 MockWrite data_writes[] = {
6271 MockWrite(
6272 "GET / HTTP/1.1\r\n"
6273 "Host: www.example.org\r\n"
6274 "Connection: keep-alive\r\n\r\n"),
6277 MockRead data_reads[] = {
6278 MockRead("HTTP/1.0 200 OK\r\n"),
6279 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6280 MockRead("Content-Length: 100\r\n\r\n"),
6281 MockRead(SYNCHRONOUS, OK),
6284 StaticSocketDataProvider ssl_bad_certificate;
6285 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6286 data_writes, arraysize(data_writes));
6287 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6288 SSLSocketDataProvider ssl(ASYNC, OK);
6290 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6291 session_deps_.socket_factory->AddSocketDataProvider(&data);
6292 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6293 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6295 TestCompletionCallback callback;
6297 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6298 EXPECT_EQ(ERR_IO_PENDING, rv);
6300 rv = callback.WaitForResult();
6301 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6303 rv = trans->RestartIgnoringLastError(callback.callback());
6304 EXPECT_EQ(ERR_IO_PENDING, rv);
6306 rv = callback.WaitForResult();
6307 EXPECT_EQ(OK, rv);
6309 const HttpResponseInfo* response = trans->GetResponseInfo();
6311 ASSERT_TRUE(response != NULL);
6312 EXPECT_EQ(100, response->headers->GetContentLength());
6315 // Test HTTPS connections to a site with a bad certificate, going through a
6316 // proxy
6317 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
6318 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6320 HttpRequestInfo request;
6321 request.method = "GET";
6322 request.url = GURL("https://www.example.org/");
6323 request.load_flags = 0;
6325 MockWrite proxy_writes[] = {
6326 MockWrite(
6327 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6328 "Host: www.example.org\r\n"
6329 "Proxy-Connection: keep-alive\r\n\r\n"),
6332 MockRead proxy_reads[] = {
6333 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6334 MockRead(SYNCHRONOUS, OK)
6337 MockWrite data_writes[] = {
6338 MockWrite(
6339 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6340 "Host: www.example.org\r\n"
6341 "Proxy-Connection: keep-alive\r\n\r\n"),
6342 MockWrite(
6343 "GET / HTTP/1.1\r\n"
6344 "Host: www.example.org\r\n"
6345 "Connection: keep-alive\r\n\r\n"),
6348 MockRead data_reads[] = {
6349 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6350 MockRead("HTTP/1.0 200 OK\r\n"),
6351 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6352 MockRead("Content-Length: 100\r\n\r\n"),
6353 MockRead(SYNCHRONOUS, OK),
6356 StaticSocketDataProvider ssl_bad_certificate(
6357 proxy_reads, arraysize(proxy_reads),
6358 proxy_writes, arraysize(proxy_writes));
6359 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6360 data_writes, arraysize(data_writes));
6361 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6362 SSLSocketDataProvider ssl(ASYNC, OK);
6364 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6365 session_deps_.socket_factory->AddSocketDataProvider(&data);
6366 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6367 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6369 TestCompletionCallback callback;
6371 for (int i = 0; i < 2; i++) {
6372 session_deps_.socket_factory->ResetNextMockIndexes();
6374 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6375 scoped_ptr<HttpTransaction> trans(
6376 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6378 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6379 EXPECT_EQ(ERR_IO_PENDING, rv);
6381 rv = callback.WaitForResult();
6382 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6384 rv = trans->RestartIgnoringLastError(callback.callback());
6385 EXPECT_EQ(ERR_IO_PENDING, rv);
6387 rv = callback.WaitForResult();
6388 EXPECT_EQ(OK, rv);
6390 const HttpResponseInfo* response = trans->GetResponseInfo();
6392 ASSERT_TRUE(response != NULL);
6393 EXPECT_EQ(100, response->headers->GetContentLength());
6398 // Test HTTPS connections to a site, going through an HTTPS proxy
6399 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6400 session_deps_.proxy_service.reset(
6401 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6402 TestNetLog net_log;
6403 session_deps_.net_log = &net_log;
6405 HttpRequestInfo request;
6406 request.method = "GET";
6407 request.url = GURL("https://www.example.org/");
6408 request.load_flags = 0;
6410 MockWrite data_writes[] = {
6411 MockWrite(
6412 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6413 "Host: www.example.org\r\n"
6414 "Proxy-Connection: keep-alive\r\n\r\n"),
6415 MockWrite(
6416 "GET / HTTP/1.1\r\n"
6417 "Host: www.example.org\r\n"
6418 "Connection: keep-alive\r\n\r\n"),
6421 MockRead data_reads[] = {
6422 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6423 MockRead("HTTP/1.1 200 OK\r\n"),
6424 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6425 MockRead("Content-Length: 100\r\n\r\n"),
6426 MockRead(SYNCHRONOUS, OK),
6429 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6430 data_writes, arraysize(data_writes));
6431 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6432 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6434 session_deps_.socket_factory->AddSocketDataProvider(&data);
6435 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6436 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6438 TestCompletionCallback callback;
6440 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6441 scoped_ptr<HttpTransaction> trans(
6442 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6444 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6445 EXPECT_EQ(ERR_IO_PENDING, rv);
6447 rv = callback.WaitForResult();
6448 EXPECT_EQ(OK, rv);
6449 const HttpResponseInfo* response = trans->GetResponseInfo();
6451 ASSERT_TRUE(response != NULL);
6453 EXPECT_TRUE(response->headers->IsKeepAlive());
6454 EXPECT_EQ(200, response->headers->response_code());
6455 EXPECT_EQ(100, response->headers->GetContentLength());
6456 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6458 LoadTimingInfo load_timing_info;
6459 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6460 TestLoadTimingNotReusedWithPac(load_timing_info,
6461 CONNECT_TIMING_HAS_SSL_TIMES);
6464 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6465 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6466 session_deps_.proxy_service.reset(
6467 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6468 TestNetLog net_log;
6469 session_deps_.net_log = &net_log;
6471 HttpRequestInfo request;
6472 request.method = "GET";
6473 request.url = GURL("https://www.example.org/");
6474 request.load_flags = 0;
6476 MockWrite data_writes[] = {
6477 MockWrite(
6478 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6479 "Host: www.example.org\r\n"
6480 "Proxy-Connection: keep-alive\r\n\r\n"),
6483 MockRead data_reads[] = {
6484 MockRead("HTTP/1.1 302 Redirect\r\n"),
6485 MockRead("Location: http://login.example.com/\r\n"),
6486 MockRead("Content-Length: 0\r\n\r\n"),
6487 MockRead(SYNCHRONOUS, OK),
6490 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6491 data_writes, arraysize(data_writes));
6492 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6494 session_deps_.socket_factory->AddSocketDataProvider(&data);
6495 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6497 TestCompletionCallback callback;
6499 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6500 scoped_ptr<HttpTransaction> trans(
6501 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6503 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6504 EXPECT_EQ(ERR_IO_PENDING, rv);
6506 rv = callback.WaitForResult();
6507 EXPECT_EQ(OK, rv);
6508 const HttpResponseInfo* response = trans->GetResponseInfo();
6510 ASSERT_TRUE(response != NULL);
6512 EXPECT_EQ(302, response->headers->response_code());
6513 std::string url;
6514 EXPECT_TRUE(response->headers->IsRedirect(&url));
6515 EXPECT_EQ("http://login.example.com/", url);
6517 // In the case of redirects from proxies, HttpNetworkTransaction returns
6518 // timing for the proxy connection instead of the connection to the host,
6519 // and no send / receive times.
6520 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6521 LoadTimingInfo load_timing_info;
6522 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6524 EXPECT_FALSE(load_timing_info.socket_reused);
6525 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6527 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6528 EXPECT_LE(load_timing_info.proxy_resolve_start,
6529 load_timing_info.proxy_resolve_end);
6530 EXPECT_LE(load_timing_info.proxy_resolve_end,
6531 load_timing_info.connect_timing.connect_start);
6532 ExpectConnectTimingHasTimes(
6533 load_timing_info.connect_timing,
6534 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6536 EXPECT_TRUE(load_timing_info.send_start.is_null());
6537 EXPECT_TRUE(load_timing_info.send_end.is_null());
6538 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6541 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6542 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6543 session_deps_.proxy_service.reset(
6544 ProxyService::CreateFixed("https://proxy:70"));
6546 HttpRequestInfo request;
6547 request.method = "GET";
6548 request.url = GURL("https://www.example.org/");
6549 request.load_flags = 0;
6551 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6552 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6553 scoped_ptr<SpdyFrame> goaway(
6554 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6555 MockWrite data_writes[] = {
6556 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6557 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
6560 static const char* const kExtraHeaders[] = {
6561 "location",
6562 "http://login.example.com/",
6564 scoped_ptr<SpdyFrame> resp(
6565 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6566 arraysize(kExtraHeaders)/2, 1));
6567 MockRead data_reads[] = {
6568 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
6571 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6572 arraysize(data_writes));
6573 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6574 proxy_ssl.SetNextProto(GetParam());
6576 session_deps_.socket_factory->AddSocketDataProvider(&data);
6577 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6579 TestCompletionCallback callback;
6581 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6582 scoped_ptr<HttpTransaction> trans(
6583 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6585 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6586 EXPECT_EQ(ERR_IO_PENDING, rv);
6588 rv = callback.WaitForResult();
6589 EXPECT_EQ(OK, rv);
6590 const HttpResponseInfo* response = trans->GetResponseInfo();
6592 ASSERT_TRUE(response != NULL);
6594 EXPECT_EQ(302, response->headers->response_code());
6595 std::string url;
6596 EXPECT_TRUE(response->headers->IsRedirect(&url));
6597 EXPECT_EQ("http://login.example.com/", url);
6600 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6601 TEST_P(HttpNetworkTransactionTest,
6602 ErrorResponseToHttpsConnectViaHttpsProxy) {
6603 session_deps_.proxy_service.reset(
6604 ProxyService::CreateFixed("https://proxy:70"));
6606 HttpRequestInfo request;
6607 request.method = "GET";
6608 request.url = GURL("https://www.example.org/");
6609 request.load_flags = 0;
6611 MockWrite data_writes[] = {
6612 MockWrite(
6613 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6614 "Host: www.example.org\r\n"
6615 "Proxy-Connection: keep-alive\r\n\r\n"),
6618 MockRead data_reads[] = {
6619 MockRead("HTTP/1.1 404 Not Found\r\n"),
6620 MockRead("Content-Length: 23\r\n\r\n"),
6621 MockRead("The host does not exist"),
6622 MockRead(SYNCHRONOUS, OK),
6625 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6626 data_writes, arraysize(data_writes));
6627 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6629 session_deps_.socket_factory->AddSocketDataProvider(&data);
6630 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6632 TestCompletionCallback callback;
6634 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6635 scoped_ptr<HttpTransaction> trans(
6636 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6638 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6639 EXPECT_EQ(ERR_IO_PENDING, rv);
6641 rv = callback.WaitForResult();
6642 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6644 // TODO(ttuttle): Anything else to check here?
6647 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6648 TEST_P(HttpNetworkTransactionTest,
6649 ErrorResponseToHttpsConnectViaSpdyProxy) {
6650 session_deps_.proxy_service.reset(
6651 ProxyService::CreateFixed("https://proxy:70"));
6653 HttpRequestInfo request;
6654 request.method = "GET";
6655 request.url = GURL("https://www.example.org/");
6656 request.load_flags = 0;
6658 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6659 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6660 scoped_ptr<SpdyFrame> rst(
6661 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6662 MockWrite data_writes[] = {
6663 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
6666 static const char* const kExtraHeaders[] = {
6667 "location",
6668 "http://login.example.com/",
6670 scoped_ptr<SpdyFrame> resp(
6671 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6672 arraysize(kExtraHeaders)/2, 1));
6673 scoped_ptr<SpdyFrame> body(
6674 spdy_util_.ConstructSpdyBodyFrame(
6675 1, "The host does not exist", 23, true));
6676 MockRead data_reads[] = {
6677 CreateMockRead(*resp.get(), 1),
6678 CreateMockRead(*body.get(), 2),
6679 MockRead(ASYNC, 0, 4), // EOF
6682 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6683 arraysize(data_writes));
6684 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6685 proxy_ssl.SetNextProto(GetParam());
6687 session_deps_.socket_factory->AddSocketDataProvider(&data);
6688 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6690 TestCompletionCallback callback;
6692 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6693 scoped_ptr<HttpTransaction> trans(
6694 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6696 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6697 EXPECT_EQ(ERR_IO_PENDING, rv);
6699 rv = callback.WaitForResult();
6700 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6702 // TODO(ttuttle): Anything else to check here?
6705 // Test the request-challenge-retry sequence for basic auth, through
6706 // a SPDY proxy over a single SPDY session.
6707 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6708 HttpRequestInfo request;
6709 request.method = "GET";
6710 request.url = GURL("https://www.example.org/");
6711 // when the no authentication data flag is set.
6712 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
6714 // Configure against https proxy server "myproxy:70".
6715 session_deps_.proxy_service.reset(
6716 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6717 BoundTestNetLog log;
6718 session_deps_.net_log = log.bound().net_log();
6719 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6721 // Since we have proxy, should try to establish tunnel.
6722 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
6723 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6724 scoped_ptr<SpdyFrame> rst(
6725 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6727 // After calling trans->RestartWithAuth(), this is the request we should
6728 // be issuing -- the final header line contains the credentials.
6729 const char* const kAuthCredentials[] = {
6730 "proxy-authorization", "Basic Zm9vOmJhcg==",
6732 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6733 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
6734 HostPortPair("www.example.org", 443)));
6735 // fetch https://www.example.org/ via HTTP
6736 const char get[] =
6737 "GET / HTTP/1.1\r\n"
6738 "Host: www.example.org\r\n"
6739 "Connection: keep-alive\r\n\r\n";
6740 scoped_ptr<SpdyFrame> wrapped_get(
6741 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6743 MockWrite spdy_writes[] = {
6744 CreateMockWrite(*req, 0, ASYNC),
6745 CreateMockWrite(*rst, 2, ASYNC),
6746 CreateMockWrite(*connect2, 3),
6747 CreateMockWrite(*wrapped_get, 5),
6750 // The proxy responds to the connect with a 407, using a persistent
6751 // connection.
6752 const char kAuthStatus[] = "407";
6753 const char* const kAuthChallenge[] = {
6754 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6756 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6757 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6759 scoped_ptr<SpdyFrame> conn_resp(
6760 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6761 const char resp[] = "HTTP/1.1 200 OK\r\n"
6762 "Content-Length: 5\r\n\r\n";
6764 scoped_ptr<SpdyFrame> wrapped_get_resp(
6765 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6766 scoped_ptr<SpdyFrame> wrapped_body(
6767 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6768 MockRead spdy_reads[] = {
6769 CreateMockRead(*conn_auth_resp, 1, ASYNC),
6770 CreateMockRead(*conn_resp, 4, ASYNC),
6771 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
6772 CreateMockRead(*wrapped_body, 7, ASYNC),
6773 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
6776 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6777 arraysize(spdy_writes));
6778 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6779 // Negotiate SPDY to the proxy
6780 SSLSocketDataProvider proxy(ASYNC, OK);
6781 proxy.SetNextProto(GetParam());
6782 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6783 // Vanilla SSL to the server
6784 SSLSocketDataProvider server(ASYNC, OK);
6785 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6787 TestCompletionCallback callback1;
6789 scoped_ptr<HttpTransaction> trans(
6790 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6792 int rv = trans->Start(&request, callback1.callback(), log.bound());
6793 EXPECT_EQ(ERR_IO_PENDING, rv);
6795 rv = callback1.WaitForResult();
6796 EXPECT_EQ(OK, rv);
6797 TestNetLogEntry::List entries;
6798 log.GetEntries(&entries);
6799 size_t pos = ExpectLogContainsSomewhere(
6800 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6801 NetLog::PHASE_NONE);
6802 ExpectLogContainsSomewhere(
6803 entries, pos,
6804 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6805 NetLog::PHASE_NONE);
6807 const HttpResponseInfo* response = trans->GetResponseInfo();
6808 ASSERT_TRUE(response != NULL);
6809 ASSERT_FALSE(response->headers.get() == NULL);
6810 EXPECT_EQ(407, response->headers->response_code());
6811 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6812 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6813 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6815 TestCompletionCallback callback2;
6817 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6818 callback2.callback());
6819 EXPECT_EQ(ERR_IO_PENDING, rv);
6821 rv = callback2.WaitForResult();
6822 EXPECT_EQ(OK, rv);
6824 response = trans->GetResponseInfo();
6825 ASSERT_TRUE(response != NULL);
6827 EXPECT_TRUE(response->headers->IsKeepAlive());
6828 EXPECT_EQ(200, response->headers->response_code());
6829 EXPECT_EQ(5, response->headers->GetContentLength());
6830 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6832 // The password prompt info should not be set.
6833 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6835 LoadTimingInfo load_timing_info;
6836 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6837 TestLoadTimingNotReusedWithPac(load_timing_info,
6838 CONNECT_TIMING_HAS_SSL_TIMES);
6840 trans.reset();
6841 session->CloseAllConnections();
6844 // Test that an explicitly trusted SPDY proxy can push a resource from an
6845 // origin that is different from that of its associated resource.
6846 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6847 HttpRequestInfo request;
6848 HttpRequestInfo push_request;
6850 request.method = "GET";
6851 request.url = GURL("http://www.example.org/");
6852 push_request.method = "GET";
6853 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6855 // Configure against https proxy server "myproxy:70".
6856 session_deps_.proxy_service.reset(
6857 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6858 BoundTestNetLog log;
6859 session_deps_.net_log = log.bound().net_log();
6861 // Enable cross-origin push.
6862 session_deps_.trusted_spdy_proxy = "myproxy:70";
6864 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6866 scoped_ptr<SpdyFrame> stream1_syn(
6867 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6869 MockWrite spdy_writes[] = {
6870 CreateMockWrite(*stream1_syn, 0, ASYNC),
6873 scoped_ptr<SpdyFrame>
6874 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6876 scoped_ptr<SpdyFrame>
6877 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6879 scoped_ptr<SpdyFrame>
6880 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6884 "http://www.another-origin.com/foo.dat"));
6885 const char kPushedData[] = "pushed";
6886 scoped_ptr<SpdyFrame> stream2_body(
6887 spdy_util_.ConstructSpdyBodyFrame(
6888 2, kPushedData, strlen(kPushedData), true));
6890 MockRead spdy_reads[] = {
6891 CreateMockRead(*stream1_reply, 1, ASYNC),
6892 CreateMockRead(*stream2_syn, 2, ASYNC),
6893 CreateMockRead(*stream1_body, 3, ASYNC),
6894 CreateMockRead(*stream2_body, 4, ASYNC),
6895 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
6898 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6899 arraysize(spdy_writes));
6900 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6901 // Negotiate SPDY to the proxy
6902 SSLSocketDataProvider proxy(ASYNC, OK);
6903 proxy.SetNextProto(GetParam());
6904 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6906 scoped_ptr<HttpTransaction> trans(
6907 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6908 TestCompletionCallback callback;
6909 int rv = trans->Start(&request, callback.callback(), log.bound());
6910 EXPECT_EQ(ERR_IO_PENDING, rv);
6912 rv = callback.WaitForResult();
6913 EXPECT_EQ(OK, rv);
6914 const HttpResponseInfo* response = trans->GetResponseInfo();
6916 scoped_ptr<HttpTransaction> push_trans(
6917 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6918 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6919 EXPECT_EQ(ERR_IO_PENDING, rv);
6921 rv = callback.WaitForResult();
6922 EXPECT_EQ(OK, rv);
6923 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6925 ASSERT_TRUE(response != NULL);
6926 EXPECT_TRUE(response->headers->IsKeepAlive());
6928 EXPECT_EQ(200, response->headers->response_code());
6929 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6931 std::string response_data;
6932 rv = ReadTransaction(trans.get(), &response_data);
6933 EXPECT_EQ(OK, rv);
6934 EXPECT_EQ("hello!", response_data);
6936 LoadTimingInfo load_timing_info;
6937 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6938 TestLoadTimingNotReusedWithPac(load_timing_info,
6939 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6941 // Verify the pushed stream.
6942 EXPECT_TRUE(push_response->headers.get() != NULL);
6943 EXPECT_EQ(200, push_response->headers->response_code());
6945 rv = ReadTransaction(push_trans.get(), &response_data);
6946 EXPECT_EQ(OK, rv);
6947 EXPECT_EQ("pushed", response_data);
6949 LoadTimingInfo push_load_timing_info;
6950 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6951 TestLoadTimingReusedWithPac(push_load_timing_info);
6952 // The transactions should share a socket ID, despite being for different
6953 // origins.
6954 EXPECT_EQ(load_timing_info.socket_log_id,
6955 push_load_timing_info.socket_log_id);
6957 trans.reset();
6958 push_trans.reset();
6959 session->CloseAllConnections();
6962 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6963 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6964 HttpRequestInfo request;
6966 request.method = "GET";
6967 request.url = GURL("http://www.example.org/");
6969 // Configure against https proxy server "myproxy:70".
6970 session_deps_.proxy_service.reset(
6971 ProxyService::CreateFixed("https://myproxy:70"));
6972 BoundTestNetLog log;
6973 session_deps_.net_log = log.bound().net_log();
6975 // Enable cross-origin push.
6976 session_deps_.trusted_spdy_proxy = "myproxy:70";
6978 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6980 scoped_ptr<SpdyFrame> stream1_syn(
6981 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6983 scoped_ptr<SpdyFrame> push_rst(
6984 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6986 MockWrite spdy_writes[] = {
6987 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
6990 scoped_ptr<SpdyFrame>
6991 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6993 scoped_ptr<SpdyFrame>
6994 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6996 scoped_ptr<SpdyFrame>
6997 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
7001 "https://www.another-origin.com/foo.dat"));
7003 MockRead spdy_reads[] = {
7004 CreateMockRead(*stream1_reply, 1, ASYNC),
7005 CreateMockRead(*stream2_syn, 2, ASYNC),
7006 CreateMockRead(*stream1_body, 4, ASYNC),
7007 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
7010 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7011 arraysize(spdy_writes));
7012 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7013 // Negotiate SPDY to the proxy
7014 SSLSocketDataProvider proxy(ASYNC, OK);
7015 proxy.SetNextProto(GetParam());
7016 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7018 scoped_ptr<HttpTransaction> trans(
7019 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7020 TestCompletionCallback callback;
7021 int rv = trans->Start(&request, callback.callback(), log.bound());
7022 EXPECT_EQ(ERR_IO_PENDING, rv);
7024 rv = callback.WaitForResult();
7025 EXPECT_EQ(OK, rv);
7026 const HttpResponseInfo* response = trans->GetResponseInfo();
7028 ASSERT_TRUE(response != NULL);
7029 EXPECT_TRUE(response->headers->IsKeepAlive());
7031 EXPECT_EQ(200, response->headers->response_code());
7032 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7034 std::string response_data;
7035 rv = ReadTransaction(trans.get(), &response_data);
7036 EXPECT_EQ(OK, rv);
7037 EXPECT_EQ("hello!", response_data);
7039 trans.reset();
7040 session->CloseAllConnections();
7043 // Test HTTPS connections to a site with a bad certificate, going through an
7044 // HTTPS proxy
7045 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
7046 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
7047 "https://proxy:70"));
7049 HttpRequestInfo request;
7050 request.method = "GET";
7051 request.url = GURL("https://www.example.org/");
7052 request.load_flags = 0;
7054 // Attempt to fetch the URL from a server with a bad cert
7055 MockWrite bad_cert_writes[] = {
7056 MockWrite(
7057 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7058 "Host: www.example.org\r\n"
7059 "Proxy-Connection: keep-alive\r\n\r\n"),
7062 MockRead bad_cert_reads[] = {
7063 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7064 MockRead(SYNCHRONOUS, OK)
7067 // Attempt to fetch the URL with a good cert
7068 MockWrite good_data_writes[] = {
7069 MockWrite(
7070 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7071 "Host: www.example.org\r\n"
7072 "Proxy-Connection: keep-alive\r\n\r\n"),
7073 MockWrite(
7074 "GET / HTTP/1.1\r\n"
7075 "Host: www.example.org\r\n"
7076 "Connection: keep-alive\r\n\r\n"),
7079 MockRead good_cert_reads[] = {
7080 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7081 MockRead("HTTP/1.0 200 OK\r\n"),
7082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7083 MockRead("Content-Length: 100\r\n\r\n"),
7084 MockRead(SYNCHRONOUS, OK),
7087 StaticSocketDataProvider ssl_bad_certificate(
7088 bad_cert_reads, arraysize(bad_cert_reads),
7089 bad_cert_writes, arraysize(bad_cert_writes));
7090 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7091 good_data_writes, arraysize(good_data_writes));
7092 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7093 SSLSocketDataProvider ssl(ASYNC, OK);
7095 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7096 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7097 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7098 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7100 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7101 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7102 session_deps_.socket_factory->AddSocketDataProvider(&data);
7103 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7105 TestCompletionCallback callback;
7107 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7108 scoped_ptr<HttpTransaction> trans(
7109 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7111 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7112 EXPECT_EQ(ERR_IO_PENDING, rv);
7114 rv = callback.WaitForResult();
7115 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7117 rv = trans->RestartIgnoringLastError(callback.callback());
7118 EXPECT_EQ(ERR_IO_PENDING, rv);
7120 rv = callback.WaitForResult();
7121 EXPECT_EQ(OK, rv);
7123 const HttpResponseInfo* response = trans->GetResponseInfo();
7125 ASSERT_TRUE(response != NULL);
7126 EXPECT_EQ(100, response->headers->GetContentLength());
7129 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
7130 HttpRequestInfo request;
7131 request.method = "GET";
7132 request.url = GURL("http://www.example.org/");
7133 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7134 "Chromium Ultra Awesome X Edition");
7136 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7137 scoped_ptr<HttpTransaction> trans(
7138 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7140 MockWrite data_writes[] = {
7141 MockWrite(
7142 "GET / HTTP/1.1\r\n"
7143 "Host: www.example.org\r\n"
7144 "Connection: keep-alive\r\n"
7145 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7148 // Lastly, the server responds with the actual content.
7149 MockRead data_reads[] = {
7150 MockRead("HTTP/1.0 200 OK\r\n"),
7151 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7152 MockRead("Content-Length: 100\r\n\r\n"),
7153 MockRead(SYNCHRONOUS, OK),
7156 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7157 data_writes, arraysize(data_writes));
7158 session_deps_.socket_factory->AddSocketDataProvider(&data);
7160 TestCompletionCallback callback;
7162 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7163 EXPECT_EQ(ERR_IO_PENDING, rv);
7165 rv = callback.WaitForResult();
7166 EXPECT_EQ(OK, rv);
7169 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
7170 HttpRequestInfo request;
7171 request.method = "GET";
7172 request.url = GURL("https://www.example.org/");
7173 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7174 "Chromium Ultra Awesome X Edition");
7176 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7177 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7178 scoped_ptr<HttpTransaction> trans(
7179 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7181 MockWrite data_writes[] = {
7182 MockWrite(
7183 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7184 "Host: www.example.org\r\n"
7185 "Proxy-Connection: keep-alive\r\n"
7186 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7188 MockRead data_reads[] = {
7189 // Return an error, so the transaction stops here (this test isn't
7190 // interested in the rest).
7191 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7192 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7193 MockRead("Proxy-Connection: close\r\n\r\n"),
7196 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7197 data_writes, arraysize(data_writes));
7198 session_deps_.socket_factory->AddSocketDataProvider(&data);
7200 TestCompletionCallback callback;
7202 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7203 EXPECT_EQ(ERR_IO_PENDING, rv);
7205 rv = callback.WaitForResult();
7206 EXPECT_EQ(OK, rv);
7209 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
7210 HttpRequestInfo request;
7211 request.method = "GET";
7212 request.url = GURL("http://www.example.org/");
7213 request.load_flags = 0;
7214 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7215 "http://the.previous.site.com/");
7217 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7218 scoped_ptr<HttpTransaction> trans(
7219 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7221 MockWrite data_writes[] = {
7222 MockWrite(
7223 "GET / HTTP/1.1\r\n"
7224 "Host: www.example.org\r\n"
7225 "Connection: keep-alive\r\n"
7226 "Referer: http://the.previous.site.com/\r\n\r\n"),
7229 // Lastly, the server responds with the actual content.
7230 MockRead data_reads[] = {
7231 MockRead("HTTP/1.0 200 OK\r\n"),
7232 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7233 MockRead("Content-Length: 100\r\n\r\n"),
7234 MockRead(SYNCHRONOUS, OK),
7237 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7238 data_writes, arraysize(data_writes));
7239 session_deps_.socket_factory->AddSocketDataProvider(&data);
7241 TestCompletionCallback callback;
7243 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7244 EXPECT_EQ(ERR_IO_PENDING, rv);
7246 rv = callback.WaitForResult();
7247 EXPECT_EQ(OK, rv);
7250 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
7251 HttpRequestInfo request;
7252 request.method = "POST";
7253 request.url = GURL("http://www.example.org/");
7255 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7256 scoped_ptr<HttpTransaction> trans(
7257 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7259 MockWrite data_writes[] = {
7260 MockWrite(
7261 "POST / HTTP/1.1\r\n"
7262 "Host: www.example.org\r\n"
7263 "Connection: keep-alive\r\n"
7264 "Content-Length: 0\r\n\r\n"),
7267 // Lastly, the server responds with the actual content.
7268 MockRead data_reads[] = {
7269 MockRead("HTTP/1.0 200 OK\r\n"),
7270 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7271 MockRead("Content-Length: 100\r\n\r\n"),
7272 MockRead(SYNCHRONOUS, OK),
7275 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7276 data_writes, arraysize(data_writes));
7277 session_deps_.socket_factory->AddSocketDataProvider(&data);
7279 TestCompletionCallback callback;
7281 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7282 EXPECT_EQ(ERR_IO_PENDING, rv);
7284 rv = callback.WaitForResult();
7285 EXPECT_EQ(OK, rv);
7288 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
7289 HttpRequestInfo request;
7290 request.method = "PUT";
7291 request.url = GURL("http://www.example.org/");
7293 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7294 scoped_ptr<HttpTransaction> trans(
7295 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7297 MockWrite data_writes[] = {
7298 MockWrite(
7299 "PUT / HTTP/1.1\r\n"
7300 "Host: www.example.org\r\n"
7301 "Connection: keep-alive\r\n"
7302 "Content-Length: 0\r\n\r\n"),
7305 // Lastly, the server responds with the actual content.
7306 MockRead data_reads[] = {
7307 MockRead("HTTP/1.0 200 OK\r\n"),
7308 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7309 MockRead("Content-Length: 100\r\n\r\n"),
7310 MockRead(SYNCHRONOUS, OK),
7313 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7314 data_writes, arraysize(data_writes));
7315 session_deps_.socket_factory->AddSocketDataProvider(&data);
7317 TestCompletionCallback callback;
7319 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7320 EXPECT_EQ(ERR_IO_PENDING, rv);
7322 rv = callback.WaitForResult();
7323 EXPECT_EQ(OK, rv);
7326 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
7327 HttpRequestInfo request;
7328 request.method = "HEAD";
7329 request.url = GURL("http://www.example.org/");
7331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7332 scoped_ptr<HttpTransaction> trans(
7333 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7335 MockWrite data_writes[] = {
7336 MockWrite("HEAD / HTTP/1.1\r\n"
7337 "Host: www.example.org\r\n"
7338 "Connection: keep-alive\r\n\r\n"),
7341 // Lastly, the server responds with the actual content.
7342 MockRead data_reads[] = {
7343 MockRead("HTTP/1.0 200 OK\r\n"),
7344 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7345 MockRead("Content-Length: 100\r\n\r\n"),
7346 MockRead(SYNCHRONOUS, OK),
7349 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7350 data_writes, arraysize(data_writes));
7351 session_deps_.socket_factory->AddSocketDataProvider(&data);
7353 TestCompletionCallback callback;
7355 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7356 EXPECT_EQ(ERR_IO_PENDING, rv);
7358 rv = callback.WaitForResult();
7359 EXPECT_EQ(OK, rv);
7362 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7363 HttpRequestInfo request;
7364 request.method = "GET";
7365 request.url = GURL("http://www.example.org/");
7366 request.load_flags = LOAD_BYPASS_CACHE;
7368 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7369 scoped_ptr<HttpTransaction> trans(
7370 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7372 MockWrite data_writes[] = {
7373 MockWrite(
7374 "GET / HTTP/1.1\r\n"
7375 "Host: www.example.org\r\n"
7376 "Connection: keep-alive\r\n"
7377 "Pragma: no-cache\r\n"
7378 "Cache-Control: no-cache\r\n\r\n"),
7381 // Lastly, the server responds with the actual content.
7382 MockRead data_reads[] = {
7383 MockRead("HTTP/1.0 200 OK\r\n"),
7384 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7385 MockRead("Content-Length: 100\r\n\r\n"),
7386 MockRead(SYNCHRONOUS, OK),
7389 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7390 data_writes, arraysize(data_writes));
7391 session_deps_.socket_factory->AddSocketDataProvider(&data);
7393 TestCompletionCallback callback;
7395 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7396 EXPECT_EQ(ERR_IO_PENDING, rv);
7398 rv = callback.WaitForResult();
7399 EXPECT_EQ(OK, rv);
7402 TEST_P(HttpNetworkTransactionTest,
7403 BuildRequest_CacheControlValidateCache) {
7404 HttpRequestInfo request;
7405 request.method = "GET";
7406 request.url = GURL("http://www.example.org/");
7407 request.load_flags = LOAD_VALIDATE_CACHE;
7409 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7410 scoped_ptr<HttpTransaction> trans(
7411 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7413 MockWrite data_writes[] = {
7414 MockWrite(
7415 "GET / HTTP/1.1\r\n"
7416 "Host: www.example.org\r\n"
7417 "Connection: keep-alive\r\n"
7418 "Cache-Control: max-age=0\r\n\r\n"),
7421 // Lastly, the server responds with the actual content.
7422 MockRead data_reads[] = {
7423 MockRead("HTTP/1.0 200 OK\r\n"),
7424 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7425 MockRead("Content-Length: 100\r\n\r\n"),
7426 MockRead(SYNCHRONOUS, OK),
7429 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7430 data_writes, arraysize(data_writes));
7431 session_deps_.socket_factory->AddSocketDataProvider(&data);
7433 TestCompletionCallback callback;
7435 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7436 EXPECT_EQ(ERR_IO_PENDING, rv);
7438 rv = callback.WaitForResult();
7439 EXPECT_EQ(OK, rv);
7442 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7443 HttpRequestInfo request;
7444 request.method = "GET";
7445 request.url = GURL("http://www.example.org/");
7446 request.extra_headers.SetHeader("FooHeader", "Bar");
7448 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7449 scoped_ptr<HttpTransaction> trans(
7450 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7452 MockWrite data_writes[] = {
7453 MockWrite(
7454 "GET / HTTP/1.1\r\n"
7455 "Host: www.example.org\r\n"
7456 "Connection: keep-alive\r\n"
7457 "FooHeader: Bar\r\n\r\n"),
7460 // Lastly, the server responds with the actual content.
7461 MockRead data_reads[] = {
7462 MockRead("HTTP/1.0 200 OK\r\n"),
7463 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7464 MockRead("Content-Length: 100\r\n\r\n"),
7465 MockRead(SYNCHRONOUS, OK),
7468 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7469 data_writes, arraysize(data_writes));
7470 session_deps_.socket_factory->AddSocketDataProvider(&data);
7472 TestCompletionCallback callback;
7474 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7475 EXPECT_EQ(ERR_IO_PENDING, rv);
7477 rv = callback.WaitForResult();
7478 EXPECT_EQ(OK, rv);
7481 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7482 HttpRequestInfo request;
7483 request.method = "GET";
7484 request.url = GURL("http://www.example.org/");
7485 request.extra_headers.SetHeader("referer", "www.foo.com");
7486 request.extra_headers.SetHeader("hEllo", "Kitty");
7487 request.extra_headers.SetHeader("FoO", "bar");
7489 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7490 scoped_ptr<HttpTransaction> trans(
7491 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7493 MockWrite data_writes[] = {
7494 MockWrite(
7495 "GET / HTTP/1.1\r\n"
7496 "Host: www.example.org\r\n"
7497 "Connection: keep-alive\r\n"
7498 "referer: www.foo.com\r\n"
7499 "hEllo: Kitty\r\n"
7500 "FoO: bar\r\n\r\n"),
7503 // Lastly, the server responds with the actual content.
7504 MockRead data_reads[] = {
7505 MockRead("HTTP/1.0 200 OK\r\n"),
7506 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7507 MockRead("Content-Length: 100\r\n\r\n"),
7508 MockRead(SYNCHRONOUS, OK),
7511 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7512 data_writes, arraysize(data_writes));
7513 session_deps_.socket_factory->AddSocketDataProvider(&data);
7515 TestCompletionCallback callback;
7517 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7518 EXPECT_EQ(ERR_IO_PENDING, rv);
7520 rv = callback.WaitForResult();
7521 EXPECT_EQ(OK, rv);
7524 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7525 HttpRequestInfo request;
7526 request.method = "GET";
7527 request.url = GURL("http://www.example.org/");
7528 request.load_flags = 0;
7530 session_deps_.proxy_service.reset(
7531 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7532 TestNetLog net_log;
7533 session_deps_.net_log = &net_log;
7535 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7536 scoped_ptr<HttpTransaction> trans(
7537 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7539 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7540 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7542 MockWrite data_writes[] = {
7543 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7544 MockWrite(
7545 "GET / HTTP/1.1\r\n"
7546 "Host: www.example.org\r\n"
7547 "Connection: keep-alive\r\n\r\n")};
7549 MockRead data_reads[] = {
7550 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7551 MockRead("HTTP/1.0 200 OK\r\n"),
7552 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7553 MockRead("Payload"),
7554 MockRead(SYNCHRONOUS, OK)
7557 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7558 data_writes, arraysize(data_writes));
7559 session_deps_.socket_factory->AddSocketDataProvider(&data);
7561 TestCompletionCallback callback;
7563 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7564 EXPECT_EQ(ERR_IO_PENDING, rv);
7566 rv = callback.WaitForResult();
7567 EXPECT_EQ(OK, rv);
7569 const HttpResponseInfo* response = trans->GetResponseInfo();
7570 ASSERT_TRUE(response != NULL);
7572 LoadTimingInfo load_timing_info;
7573 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7574 TestLoadTimingNotReusedWithPac(load_timing_info,
7575 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7577 std::string response_text;
7578 rv = ReadTransaction(trans.get(), &response_text);
7579 EXPECT_EQ(OK, rv);
7580 EXPECT_EQ("Payload", response_text);
7583 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7584 HttpRequestInfo request;
7585 request.method = "GET";
7586 request.url = GURL("https://www.example.org/");
7587 request.load_flags = 0;
7589 session_deps_.proxy_service.reset(
7590 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7591 TestNetLog net_log;
7592 session_deps_.net_log = &net_log;
7594 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7595 scoped_ptr<HttpTransaction> trans(
7596 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7598 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7599 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7601 MockWrite data_writes[] = {
7602 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7603 arraysize(write_buffer)),
7604 MockWrite(
7605 "GET / HTTP/1.1\r\n"
7606 "Host: www.example.org\r\n"
7607 "Connection: keep-alive\r\n\r\n")};
7609 MockRead data_reads[] = {
7610 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7611 arraysize(read_buffer)),
7612 MockRead("HTTP/1.0 200 OK\r\n"),
7613 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7614 MockRead("Payload"),
7615 MockRead(SYNCHRONOUS, OK)
7618 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7619 data_writes, arraysize(data_writes));
7620 session_deps_.socket_factory->AddSocketDataProvider(&data);
7622 SSLSocketDataProvider ssl(ASYNC, OK);
7623 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7625 TestCompletionCallback callback;
7627 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7628 EXPECT_EQ(ERR_IO_PENDING, rv);
7630 rv = callback.WaitForResult();
7631 EXPECT_EQ(OK, rv);
7633 LoadTimingInfo load_timing_info;
7634 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7635 TestLoadTimingNotReusedWithPac(load_timing_info,
7636 CONNECT_TIMING_HAS_SSL_TIMES);
7638 const HttpResponseInfo* response = trans->GetResponseInfo();
7639 ASSERT_TRUE(response != NULL);
7641 std::string response_text;
7642 rv = ReadTransaction(trans.get(), &response_text);
7643 EXPECT_EQ(OK, rv);
7644 EXPECT_EQ("Payload", response_text);
7647 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7648 HttpRequestInfo request;
7649 request.method = "GET";
7650 request.url = GURL("http://www.example.org/");
7651 request.load_flags = 0;
7653 session_deps_.proxy_service.reset(
7654 ProxyService::CreateFixed("socks4://myproxy:1080"));
7655 TestNetLog net_log;
7656 session_deps_.net_log = &net_log;
7658 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7659 scoped_ptr<HttpTransaction> trans(
7660 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7662 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7663 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7665 MockWrite data_writes[] = {
7666 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7667 MockWrite(
7668 "GET / HTTP/1.1\r\n"
7669 "Host: www.example.org\r\n"
7670 "Connection: keep-alive\r\n\r\n")};
7672 MockRead data_reads[] = {
7673 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7674 MockRead("HTTP/1.0 200 OK\r\n"),
7675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7676 MockRead("Payload"),
7677 MockRead(SYNCHRONOUS, OK)
7680 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7681 data_writes, arraysize(data_writes));
7682 session_deps_.socket_factory->AddSocketDataProvider(&data);
7684 TestCompletionCallback callback;
7686 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7687 EXPECT_EQ(ERR_IO_PENDING, rv);
7689 rv = callback.WaitForResult();
7690 EXPECT_EQ(OK, rv);
7692 const HttpResponseInfo* response = trans->GetResponseInfo();
7693 ASSERT_TRUE(response != NULL);
7695 LoadTimingInfo load_timing_info;
7696 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7697 TestLoadTimingNotReused(load_timing_info,
7698 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7700 std::string response_text;
7701 rv = ReadTransaction(trans.get(), &response_text);
7702 EXPECT_EQ(OK, rv);
7703 EXPECT_EQ("Payload", response_text);
7706 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7707 HttpRequestInfo request;
7708 request.method = "GET";
7709 request.url = GURL("http://www.example.org/");
7710 request.load_flags = 0;
7712 session_deps_.proxy_service.reset(
7713 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7714 TestNetLog net_log;
7715 session_deps_.net_log = &net_log;
7717 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7718 scoped_ptr<HttpTransaction> trans(
7719 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7721 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7722 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7723 const char kSOCKS5OkRequest[] = {
7724 0x05, // Version
7725 0x01, // Command (CONNECT)
7726 0x00, // Reserved.
7727 0x03, // Address type (DOMAINNAME).
7728 0x0F, // Length of domain (15)
7729 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7730 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7732 const char kSOCKS5OkResponse[] =
7733 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7735 MockWrite data_writes[] = {
7736 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7737 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7738 MockWrite(
7739 "GET / HTTP/1.1\r\n"
7740 "Host: www.example.org\r\n"
7741 "Connection: keep-alive\r\n\r\n")};
7743 MockRead data_reads[] = {
7744 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7745 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7746 MockRead("HTTP/1.0 200 OK\r\n"),
7747 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7748 MockRead("Payload"),
7749 MockRead(SYNCHRONOUS, OK)
7752 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7753 data_writes, arraysize(data_writes));
7754 session_deps_.socket_factory->AddSocketDataProvider(&data);
7756 TestCompletionCallback callback;
7758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7759 EXPECT_EQ(ERR_IO_PENDING, rv);
7761 rv = callback.WaitForResult();
7762 EXPECT_EQ(OK, rv);
7764 const HttpResponseInfo* response = trans->GetResponseInfo();
7765 ASSERT_TRUE(response != NULL);
7767 LoadTimingInfo load_timing_info;
7768 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7769 TestLoadTimingNotReusedWithPac(load_timing_info,
7770 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7772 std::string response_text;
7773 rv = ReadTransaction(trans.get(), &response_text);
7774 EXPECT_EQ(OK, rv);
7775 EXPECT_EQ("Payload", response_text);
7778 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7779 HttpRequestInfo request;
7780 request.method = "GET";
7781 request.url = GURL("https://www.example.org/");
7782 request.load_flags = 0;
7784 session_deps_.proxy_service.reset(
7785 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7786 TestNetLog net_log;
7787 session_deps_.net_log = &net_log;
7789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7790 scoped_ptr<HttpTransaction> trans(
7791 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7793 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7794 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7795 const unsigned char kSOCKS5OkRequest[] = {
7796 0x05, // Version
7797 0x01, // Command (CONNECT)
7798 0x00, // Reserved.
7799 0x03, // Address type (DOMAINNAME).
7800 0x0F, // Length of domain (15)
7801 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7802 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7805 const char kSOCKS5OkResponse[] =
7806 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7808 MockWrite data_writes[] = {
7809 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7810 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7811 arraysize(kSOCKS5OkRequest)),
7812 MockWrite(
7813 "GET / HTTP/1.1\r\n"
7814 "Host: www.example.org\r\n"
7815 "Connection: keep-alive\r\n\r\n")};
7817 MockRead data_reads[] = {
7818 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7819 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7820 MockRead("HTTP/1.0 200 OK\r\n"),
7821 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7822 MockRead("Payload"),
7823 MockRead(SYNCHRONOUS, OK)
7826 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7827 data_writes, arraysize(data_writes));
7828 session_deps_.socket_factory->AddSocketDataProvider(&data);
7830 SSLSocketDataProvider ssl(ASYNC, OK);
7831 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7833 TestCompletionCallback callback;
7835 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7836 EXPECT_EQ(ERR_IO_PENDING, rv);
7838 rv = callback.WaitForResult();
7839 EXPECT_EQ(OK, rv);
7841 const HttpResponseInfo* response = trans->GetResponseInfo();
7842 ASSERT_TRUE(response != NULL);
7844 LoadTimingInfo load_timing_info;
7845 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7846 TestLoadTimingNotReusedWithPac(load_timing_info,
7847 CONNECT_TIMING_HAS_SSL_TIMES);
7849 std::string response_text;
7850 rv = ReadTransaction(trans.get(), &response_text);
7851 EXPECT_EQ(OK, rv);
7852 EXPECT_EQ("Payload", response_text);
7855 namespace {
7857 // Tests that for connection endpoints the group names are correctly set.
7859 struct GroupNameTest {
7860 std::string proxy_server;
7861 std::string url;
7862 std::string expected_group_name;
7863 bool ssl;
7866 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7867 NextProto next_proto,
7868 SpdySessionDependencies* session_deps_) {
7869 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7871 base::WeakPtr<HttpServerProperties> http_server_properties =
7872 session->http_server_properties();
7873 AlternativeService alternative_service(
7874 AlternateProtocolFromNextProto(next_proto), "", 443);
7875 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
7876 http_server_properties->SetAlternativeService(
7877 HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
7878 expiration);
7880 return session;
7883 int GroupNameTransactionHelper(
7884 const std::string& url,
7885 const scoped_refptr<HttpNetworkSession>& session) {
7886 HttpRequestInfo request;
7887 request.method = "GET";
7888 request.url = GURL(url);
7889 request.load_flags = 0;
7891 scoped_ptr<HttpTransaction> trans(
7892 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7894 TestCompletionCallback callback;
7896 // We do not complete this request, the dtor will clean the transaction up.
7897 return trans->Start(&request, callback.callback(), BoundNetLog());
7900 } // namespace
7902 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7903 const GroupNameTest tests[] = {
7905 "", // unused
7906 "http://www.example.org/direct",
7907 "www.example.org:80",
7908 false,
7911 "", // unused
7912 "http://[2001:1418:13:1::25]/direct",
7913 "[2001:1418:13:1::25]:80",
7914 false,
7917 // SSL Tests
7919 "", // unused
7920 "https://www.example.org/direct_ssl",
7921 "ssl/www.example.org:443",
7922 true,
7925 "", // unused
7926 "https://[2001:1418:13:1::25]/direct",
7927 "ssl/[2001:1418:13:1::25]:443",
7928 true,
7931 "", // unused
7932 "http://host.with.alternate/direct",
7933 "ssl/host.with.alternate:443",
7934 true,
7938 session_deps_.use_alternative_services = true;
7940 for (size_t i = 0; i < arraysize(tests); ++i) {
7941 session_deps_.proxy_service.reset(
7942 ProxyService::CreateFixed(tests[i].proxy_server));
7943 scoped_refptr<HttpNetworkSession> session(
7944 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7946 HttpNetworkSessionPeer peer(session);
7947 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7948 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7949 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7950 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7951 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7952 new MockClientSocketPoolManager);
7953 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7954 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7955 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
7957 EXPECT_EQ(ERR_IO_PENDING,
7958 GroupNameTransactionHelper(tests[i].url, session));
7959 if (tests[i].ssl)
7960 EXPECT_EQ(tests[i].expected_group_name,
7961 ssl_conn_pool->last_group_name_received());
7962 else
7963 EXPECT_EQ(tests[i].expected_group_name,
7964 transport_conn_pool->last_group_name_received());
7968 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7969 const GroupNameTest tests[] = {
7971 "http_proxy",
7972 "http://www.example.org/http_proxy_normal",
7973 "www.example.org:80",
7974 false,
7977 // SSL Tests
7979 "http_proxy",
7980 "https://www.example.org/http_connect_ssl",
7981 "ssl/www.example.org:443",
7982 true,
7986 "http_proxy",
7987 "http://host.with.alternate/direct",
7988 "ssl/host.with.alternate:443",
7989 true,
7993 "http_proxy",
7994 "ftp://ftp.google.com/http_proxy_normal",
7995 "ftp/ftp.google.com:21",
7996 false,
8000 session_deps_.use_alternative_services = true;
8002 for (size_t i = 0; i < arraysize(tests); ++i) {
8003 session_deps_.proxy_service.reset(
8004 ProxyService::CreateFixed(tests[i].proxy_server));
8005 scoped_refptr<HttpNetworkSession> session(
8006 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8008 HttpNetworkSessionPeer peer(session);
8010 HostPortPair proxy_host("http_proxy", 80);
8011 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
8012 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
8013 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8014 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8016 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8017 new MockClientSocketPoolManager);
8018 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8019 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8020 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8022 EXPECT_EQ(ERR_IO_PENDING,
8023 GroupNameTransactionHelper(tests[i].url, session));
8024 if (tests[i].ssl)
8025 EXPECT_EQ(tests[i].expected_group_name,
8026 ssl_conn_pool->last_group_name_received());
8027 else
8028 EXPECT_EQ(tests[i].expected_group_name,
8029 http_proxy_pool->last_group_name_received());
8033 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
8034 const GroupNameTest tests[] = {
8036 "socks4://socks_proxy:1080",
8037 "http://www.example.org/socks4_direct",
8038 "socks4/www.example.org:80",
8039 false,
8042 "socks5://socks_proxy:1080",
8043 "http://www.example.org/socks5_direct",
8044 "socks5/www.example.org:80",
8045 false,
8048 // SSL Tests
8050 "socks4://socks_proxy:1080",
8051 "https://www.example.org/socks4_ssl",
8052 "socks4/ssl/www.example.org:443",
8053 true,
8056 "socks5://socks_proxy:1080",
8057 "https://www.example.org/socks5_ssl",
8058 "socks5/ssl/www.example.org:443",
8059 true,
8063 "socks4://socks_proxy:1080",
8064 "http://host.with.alternate/direct",
8065 "socks4/ssl/host.with.alternate:443",
8066 true,
8070 session_deps_.use_alternative_services = true;
8072 for (size_t i = 0; i < arraysize(tests); ++i) {
8073 session_deps_.proxy_service.reset(
8074 ProxyService::CreateFixed(tests[i].proxy_server));
8075 scoped_refptr<HttpNetworkSession> session(
8076 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8078 HttpNetworkSessionPeer peer(session);
8080 HostPortPair proxy_host("socks_proxy", 1080);
8081 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
8082 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
8083 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8084 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8086 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8087 new MockClientSocketPoolManager);
8088 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8089 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8090 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8092 scoped_ptr<HttpTransaction> trans(
8093 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8095 EXPECT_EQ(ERR_IO_PENDING,
8096 GroupNameTransactionHelper(tests[i].url, session));
8097 if (tests[i].ssl)
8098 EXPECT_EQ(tests[i].expected_group_name,
8099 ssl_conn_pool->last_group_name_received());
8100 else
8101 EXPECT_EQ(tests[i].expected_group_name,
8102 socks_conn_pool->last_group_name_received());
8106 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
8107 HttpRequestInfo request;
8108 request.method = "GET";
8109 request.url = GURL("http://www.example.org/");
8111 session_deps_.proxy_service.reset(
8112 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8114 // This simulates failure resolving all hostnames; that means we will fail
8115 // connecting to both proxies (myproxy:70 and foobar:80).
8116 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
8118 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8119 scoped_ptr<HttpTransaction> trans(
8120 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8122 TestCompletionCallback callback;
8124 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8125 EXPECT_EQ(ERR_IO_PENDING, rv);
8127 rv = callback.WaitForResult();
8128 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
8131 // Base test to make sure that when the load flags for a request specify to
8132 // bypass the cache, the DNS cache is not used.
8133 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8134 int load_flags) {
8135 // Issue a request, asking to bypass the cache(s).
8136 HttpRequestInfo request;
8137 request.method = "GET";
8138 request.load_flags = load_flags;
8139 request.url = GURL("http://www.example.org/");
8141 // Select a host resolver that does caching.
8142 session_deps_.host_resolver.reset(new MockCachingHostResolver);
8144 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8145 scoped_ptr<HttpTransaction> trans(
8146 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8148 // Warm up the host cache so it has an entry for "www.example.org".
8149 AddressList addrlist;
8150 TestCompletionCallback callback;
8151 int rv = session_deps_.host_resolver->Resolve(
8152 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8153 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8154 EXPECT_EQ(ERR_IO_PENDING, rv);
8155 rv = callback.WaitForResult();
8156 EXPECT_EQ(OK, rv);
8158 // Verify that it was added to host cache, by doing a subsequent async lookup
8159 // and confirming it completes synchronously.
8160 rv = session_deps_.host_resolver->Resolve(
8161 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8162 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8163 ASSERT_EQ(OK, rv);
8165 // Inject a failure the next time that "www.example.org" is resolved. This way
8166 // we can tell if the next lookup hit the cache, or the "network".
8167 // (cache --> success, "network" --> failure).
8168 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
8170 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8171 // first read -- this won't be reached as the host resolution will fail first.
8172 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
8173 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8174 session_deps_.socket_factory->AddSocketDataProvider(&data);
8176 // Run the request.
8177 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8178 ASSERT_EQ(ERR_IO_PENDING, rv);
8179 rv = callback.WaitForResult();
8181 // If we bypassed the cache, we would have gotten a failure while resolving
8182 // "www.example.org".
8183 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8186 // There are multiple load flags that should trigger the host cache bypass.
8187 // Test each in isolation:
8188 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
8189 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8192 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
8193 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8196 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
8197 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8200 // Make sure we can handle an error when writing the request.
8201 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
8202 HttpRequestInfo request;
8203 request.method = "GET";
8204 request.url = GURL("http://www.foo.com/");
8205 request.load_flags = 0;
8207 MockWrite write_failure[] = {
8208 MockWrite(ASYNC, ERR_CONNECTION_RESET),
8210 StaticSocketDataProvider data(NULL, 0,
8211 write_failure, arraysize(write_failure));
8212 session_deps_.socket_factory->AddSocketDataProvider(&data);
8213 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8215 TestCompletionCallback callback;
8217 scoped_ptr<HttpTransaction> trans(
8218 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8220 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8221 EXPECT_EQ(ERR_IO_PENDING, rv);
8223 rv = callback.WaitForResult();
8224 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
8227 // Check that a connection closed after the start of the headers finishes ok.
8228 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
8229 HttpRequestInfo request;
8230 request.method = "GET";
8231 request.url = GURL("http://www.foo.com/");
8232 request.load_flags = 0;
8234 MockRead data_reads[] = {
8235 MockRead("HTTP/1."),
8236 MockRead(SYNCHRONOUS, OK),
8239 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8240 session_deps_.socket_factory->AddSocketDataProvider(&data);
8241 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8243 TestCompletionCallback callback;
8245 scoped_ptr<HttpTransaction> trans(
8246 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8248 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8249 EXPECT_EQ(ERR_IO_PENDING, rv);
8251 rv = callback.WaitForResult();
8252 EXPECT_EQ(OK, rv);
8254 const HttpResponseInfo* response = trans->GetResponseInfo();
8255 ASSERT_TRUE(response != NULL);
8257 EXPECT_TRUE(response->headers.get() != NULL);
8258 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8260 std::string response_data;
8261 rv = ReadTransaction(trans.get(), &response_data);
8262 EXPECT_EQ(OK, rv);
8263 EXPECT_EQ("", response_data);
8266 // Make sure that a dropped connection while draining the body for auth
8267 // restart does the right thing.
8268 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
8269 HttpRequestInfo request;
8270 request.method = "GET";
8271 request.url = GURL("http://www.example.org/");
8272 request.load_flags = 0;
8274 MockWrite data_writes1[] = {
8275 MockWrite(
8276 "GET / HTTP/1.1\r\n"
8277 "Host: www.example.org\r\n"
8278 "Connection: keep-alive\r\n\r\n"),
8281 MockRead data_reads1[] = {
8282 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8283 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8284 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8285 MockRead("Content-Length: 14\r\n\r\n"),
8286 MockRead("Unauth"),
8287 MockRead(ASYNC, ERR_CONNECTION_RESET),
8290 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8291 data_writes1, arraysize(data_writes1));
8292 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8294 // After calling trans->RestartWithAuth(), this is the request we should
8295 // be issuing -- the final header line contains the credentials.
8296 MockWrite data_writes2[] = {
8297 MockWrite(
8298 "GET / HTTP/1.1\r\n"
8299 "Host: www.example.org\r\n"
8300 "Connection: keep-alive\r\n"
8301 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8304 // Lastly, the server responds with the actual content.
8305 MockRead data_reads2[] = {
8306 MockRead("HTTP/1.1 200 OK\r\n"),
8307 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8308 MockRead("Content-Length: 100\r\n\r\n"),
8309 MockRead(SYNCHRONOUS, OK),
8312 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8313 data_writes2, arraysize(data_writes2));
8314 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8315 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8317 TestCompletionCallback callback1;
8319 scoped_ptr<HttpTransaction> trans(
8320 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8322 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8323 EXPECT_EQ(ERR_IO_PENDING, rv);
8325 rv = callback1.WaitForResult();
8326 EXPECT_EQ(OK, rv);
8328 const HttpResponseInfo* response = trans->GetResponseInfo();
8329 ASSERT_TRUE(response != NULL);
8330 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8332 TestCompletionCallback callback2;
8334 rv = trans->RestartWithAuth(
8335 AuthCredentials(kFoo, kBar), callback2.callback());
8336 EXPECT_EQ(ERR_IO_PENDING, rv);
8338 rv = callback2.WaitForResult();
8339 EXPECT_EQ(OK, rv);
8341 response = trans->GetResponseInfo();
8342 ASSERT_TRUE(response != NULL);
8343 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8344 EXPECT_EQ(100, response->headers->GetContentLength());
8347 // Test HTTPS connections going through a proxy that sends extra data.
8348 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8349 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8351 HttpRequestInfo request;
8352 request.method = "GET";
8353 request.url = GURL("https://www.example.org/");
8354 request.load_flags = 0;
8356 MockRead proxy_reads[] = {
8357 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8358 MockRead(SYNCHRONOUS, OK)
8361 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8362 SSLSocketDataProvider ssl(ASYNC, OK);
8364 session_deps_.socket_factory->AddSocketDataProvider(&data);
8365 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8367 TestCompletionCallback callback;
8369 session_deps_.socket_factory->ResetNextMockIndexes();
8371 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8372 scoped_ptr<HttpTransaction> trans(
8373 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8375 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8376 EXPECT_EQ(ERR_IO_PENDING, rv);
8378 rv = callback.WaitForResult();
8379 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8382 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8383 HttpRequestInfo request;
8384 request.method = "GET";
8385 request.url = GURL("http://www.example.org/");
8386 request.load_flags = 0;
8388 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8389 scoped_ptr<HttpTransaction> trans(
8390 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8392 MockRead data_reads[] = {
8393 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8394 MockRead(SYNCHRONOUS, OK),
8397 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8398 session_deps_.socket_factory->AddSocketDataProvider(&data);
8400 TestCompletionCallback callback;
8402 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8403 EXPECT_EQ(ERR_IO_PENDING, rv);
8405 EXPECT_EQ(OK, callback.WaitForResult());
8407 const HttpResponseInfo* response = trans->GetResponseInfo();
8408 ASSERT_TRUE(response != NULL);
8410 EXPECT_TRUE(response->headers.get() != NULL);
8411 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8413 std::string response_data;
8414 rv = ReadTransaction(trans.get(), &response_data);
8415 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8418 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8419 base::FilePath temp_file_path;
8420 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8421 const uint64 kFakeSize = 100000; // file is actually blank
8422 UploadFileElementReader::ScopedOverridingContentLengthForTests
8423 overriding_content_length(kFakeSize);
8425 ScopedVector<UploadElementReader> element_readers;
8426 element_readers.push_back(
8427 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8428 temp_file_path, 0, kuint64max, base::Time()));
8429 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8431 HttpRequestInfo request;
8432 request.method = "POST";
8433 request.url = GURL("http://www.example.org/upload");
8434 request.upload_data_stream = &upload_data_stream;
8435 request.load_flags = 0;
8437 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8438 scoped_ptr<HttpTransaction> trans(
8439 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8441 MockRead data_reads[] = {
8442 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8443 MockRead("hello world"),
8444 MockRead(SYNCHRONOUS, OK),
8446 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8447 session_deps_.socket_factory->AddSocketDataProvider(&data);
8449 TestCompletionCallback callback;
8451 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8452 EXPECT_EQ(ERR_IO_PENDING, rv);
8454 rv = callback.WaitForResult();
8455 EXPECT_EQ(OK, rv);
8457 const HttpResponseInfo* response = trans->GetResponseInfo();
8458 ASSERT_TRUE(response != NULL);
8460 EXPECT_TRUE(response->headers.get() != NULL);
8461 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8463 std::string response_data;
8464 rv = ReadTransaction(trans.get(), &response_data);
8465 EXPECT_EQ(OK, rv);
8466 EXPECT_EQ("hello world", response_data);
8468 base::DeleteFile(temp_file_path, false);
8471 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8472 base::FilePath temp_file;
8473 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8474 std::string temp_file_content("Unreadable file.");
8475 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8476 temp_file_content.length()));
8477 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
8479 ScopedVector<UploadElementReader> element_readers;
8480 element_readers.push_back(
8481 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8482 temp_file, 0, kuint64max, base::Time()));
8483 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8485 HttpRequestInfo request;
8486 request.method = "POST";
8487 request.url = GURL("http://www.example.org/upload");
8488 request.upload_data_stream = &upload_data_stream;
8489 request.load_flags = 0;
8491 // If we try to upload an unreadable file, the transaction should fail.
8492 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8493 scoped_ptr<HttpTransaction> trans(
8494 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8496 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8497 session_deps_.socket_factory->AddSocketDataProvider(&data);
8499 TestCompletionCallback callback;
8501 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8502 EXPECT_EQ(ERR_IO_PENDING, rv);
8504 rv = callback.WaitForResult();
8505 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8507 base::DeleteFile(temp_file, false);
8510 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8511 class FakeUploadElementReader : public UploadElementReader {
8512 public:
8513 FakeUploadElementReader() {}
8514 ~FakeUploadElementReader() override {}
8516 const CompletionCallback& callback() const { return callback_; }
8518 // UploadElementReader overrides:
8519 int Init(const CompletionCallback& callback) override {
8520 callback_ = callback;
8521 return ERR_IO_PENDING;
8523 uint64 GetContentLength() const override { return 0; }
8524 uint64 BytesRemaining() const override { return 0; }
8525 int Read(IOBuffer* buf,
8526 int buf_length,
8527 const CompletionCallback& callback) override {
8528 return ERR_FAILED;
8531 private:
8532 CompletionCallback callback_;
8535 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8536 ScopedVector<UploadElementReader> element_readers;
8537 element_readers.push_back(fake_reader);
8538 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8540 HttpRequestInfo request;
8541 request.method = "POST";
8542 request.url = GURL("http://www.example.org/upload");
8543 request.upload_data_stream = &upload_data_stream;
8544 request.load_flags = 0;
8546 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8547 scoped_ptr<HttpTransaction> trans(
8548 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8550 StaticSocketDataProvider data;
8551 session_deps_.socket_factory->AddSocketDataProvider(&data);
8553 TestCompletionCallback callback;
8554 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8555 EXPECT_EQ(ERR_IO_PENDING, rv);
8556 base::MessageLoop::current()->RunUntilIdle();
8558 // Transaction is pending on request body initialization.
8559 ASSERT_FALSE(fake_reader->callback().is_null());
8561 // Return Init()'s result after the transaction gets destroyed.
8562 trans.reset();
8563 fake_reader->callback().Run(OK); // Should not crash.
8566 // Tests that changes to Auth realms are treated like auth rejections.
8567 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8568 HttpRequestInfo request;
8569 request.method = "GET";
8570 request.url = GURL("http://www.example.org/");
8571 request.load_flags = 0;
8573 // First transaction will request a resource and receive a Basic challenge
8574 // with realm="first_realm".
8575 MockWrite data_writes1[] = {
8576 MockWrite(
8577 "GET / HTTP/1.1\r\n"
8578 "Host: www.example.org\r\n"
8579 "Connection: keep-alive\r\n"
8580 "\r\n"),
8582 MockRead data_reads1[] = {
8583 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8584 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8585 "\r\n"),
8588 // After calling trans->RestartWithAuth(), provide an Authentication header
8589 // for first_realm. The server will reject and provide a challenge with
8590 // second_realm.
8591 MockWrite data_writes2[] = {
8592 MockWrite(
8593 "GET / HTTP/1.1\r\n"
8594 "Host: www.example.org\r\n"
8595 "Connection: keep-alive\r\n"
8596 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8597 "\r\n"),
8599 MockRead data_reads2[] = {
8600 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8601 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8602 "\r\n"),
8605 // This again fails, and goes back to first_realm. Make sure that the
8606 // entry is removed from cache.
8607 MockWrite data_writes3[] = {
8608 MockWrite(
8609 "GET / HTTP/1.1\r\n"
8610 "Host: www.example.org\r\n"
8611 "Connection: keep-alive\r\n"
8612 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8613 "\r\n"),
8615 MockRead data_reads3[] = {
8616 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8617 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8618 "\r\n"),
8621 // Try one last time (with the correct password) and get the resource.
8622 MockWrite data_writes4[] = {
8623 MockWrite(
8624 "GET / HTTP/1.1\r\n"
8625 "Host: www.example.org\r\n"
8626 "Connection: keep-alive\r\n"
8627 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8628 "\r\n"),
8630 MockRead data_reads4[] = {
8631 MockRead("HTTP/1.1 200 OK\r\n"
8632 "Content-Type: text/html; charset=iso-8859-1\r\n"
8633 "Content-Length: 5\r\n"
8634 "\r\n"
8635 "hello"),
8638 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8639 data_writes1, arraysize(data_writes1));
8640 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8641 data_writes2, arraysize(data_writes2));
8642 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8643 data_writes3, arraysize(data_writes3));
8644 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8645 data_writes4, arraysize(data_writes4));
8646 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8647 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8648 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8649 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8651 TestCompletionCallback callback1;
8653 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8654 scoped_ptr<HttpTransaction> trans(
8655 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8657 // Issue the first request with Authorize headers. There should be a
8658 // password prompt for first_realm waiting to be filled in after the
8659 // transaction completes.
8660 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8661 EXPECT_EQ(ERR_IO_PENDING, rv);
8662 rv = callback1.WaitForResult();
8663 EXPECT_EQ(OK, rv);
8664 const HttpResponseInfo* response = trans->GetResponseInfo();
8665 ASSERT_TRUE(response != NULL);
8666 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8667 ASSERT_FALSE(challenge == NULL);
8668 EXPECT_FALSE(challenge->is_proxy);
8669 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8670 EXPECT_EQ("first_realm", challenge->realm);
8671 EXPECT_EQ("basic", challenge->scheme);
8673 // Issue the second request with an incorrect password. There should be a
8674 // password prompt for second_realm waiting to be filled in after the
8675 // transaction completes.
8676 TestCompletionCallback callback2;
8677 rv = trans->RestartWithAuth(
8678 AuthCredentials(kFirst, kBaz), callback2.callback());
8679 EXPECT_EQ(ERR_IO_PENDING, rv);
8680 rv = callback2.WaitForResult();
8681 EXPECT_EQ(OK, rv);
8682 response = trans->GetResponseInfo();
8683 ASSERT_TRUE(response != NULL);
8684 challenge = response->auth_challenge.get();
8685 ASSERT_FALSE(challenge == NULL);
8686 EXPECT_FALSE(challenge->is_proxy);
8687 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8688 EXPECT_EQ("second_realm", challenge->realm);
8689 EXPECT_EQ("basic", challenge->scheme);
8691 // Issue the third request with another incorrect password. There should be
8692 // a password prompt for first_realm waiting to be filled in. If the password
8693 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8694 // first_realm was not correctly removed.
8695 TestCompletionCallback callback3;
8696 rv = trans->RestartWithAuth(
8697 AuthCredentials(kSecond, kFou), callback3.callback());
8698 EXPECT_EQ(ERR_IO_PENDING, rv);
8699 rv = callback3.WaitForResult();
8700 EXPECT_EQ(OK, rv);
8701 response = trans->GetResponseInfo();
8702 ASSERT_TRUE(response != NULL);
8703 challenge = response->auth_challenge.get();
8704 ASSERT_FALSE(challenge == NULL);
8705 EXPECT_FALSE(challenge->is_proxy);
8706 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8707 EXPECT_EQ("first_realm", challenge->realm);
8708 EXPECT_EQ("basic", challenge->scheme);
8710 // Issue the fourth request with the correct password and username.
8711 TestCompletionCallback callback4;
8712 rv = trans->RestartWithAuth(
8713 AuthCredentials(kFirst, kBar), callback4.callback());
8714 EXPECT_EQ(ERR_IO_PENDING, rv);
8715 rv = callback4.WaitForResult();
8716 EXPECT_EQ(OK, rv);
8717 response = trans->GetResponseInfo();
8718 ASSERT_TRUE(response != NULL);
8719 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8722 TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
8723 session_deps_.next_protos = SpdyNextProtos();
8724 session_deps_.use_alternative_services = true;
8726 std::string alternative_service_http_header =
8727 GetAlternativeServiceHttpHeader();
8729 MockRead data_reads[] = {
8730 MockRead("HTTP/1.1 200 OK\r\n"),
8731 MockRead(alternative_service_http_header.c_str()),
8732 MockRead("\r\n"),
8733 MockRead("hello world"),
8734 MockRead(SYNCHRONOUS, OK),
8737 HttpRequestInfo request;
8738 request.method = "GET";
8739 request.url = GURL("http://www.example.org/");
8740 request.load_flags = 0;
8742 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8744 session_deps_.socket_factory->AddSocketDataProvider(&data);
8746 TestCompletionCallback callback;
8748 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8749 scoped_ptr<HttpTransaction> trans(
8750 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8752 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8753 EXPECT_EQ(ERR_IO_PENDING, rv);
8755 HostPortPair http_host_port_pair("www.example.org", 80);
8756 HttpServerProperties& http_server_properties =
8757 *session->http_server_properties();
8758 AlternativeServiceVector alternative_service_vector =
8759 http_server_properties.GetAlternativeServices(http_host_port_pair);
8760 EXPECT_TRUE(alternative_service_vector.empty());
8762 EXPECT_EQ(OK, callback.WaitForResult());
8764 const HttpResponseInfo* response = trans->GetResponseInfo();
8765 ASSERT_TRUE(response != NULL);
8766 ASSERT_TRUE(response->headers.get() != NULL);
8767 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8768 EXPECT_FALSE(response->was_fetched_via_spdy);
8769 EXPECT_FALSE(response->was_npn_negotiated);
8771 std::string response_data;
8772 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8773 EXPECT_EQ("hello world", response_data);
8775 alternative_service_vector =
8776 http_server_properties.GetAlternativeServices(http_host_port_pair);
8777 ASSERT_EQ(1u, alternative_service_vector.size());
8778 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8779 alternative_service_vector[0].protocol);
8780 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
8781 EXPECT_EQ(443, alternative_service_vector[0].port);
8784 TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
8785 session_deps_.next_protos = SpdyNextProtos();
8786 session_deps_.use_alternative_services = true;
8788 MockRead data_reads[] = {
8789 MockRead("HTTP/1.1 200 OK\r\n"),
8790 MockRead("Alt-Svc: "),
8791 MockRead(GetAlternateProtocolFromParam()),
8792 MockRead("=\"www.example.com:443\";p=1.0,"),
8793 MockRead("quic=\":1234\"\r\n\r\n"),
8794 MockRead("hello world"),
8795 MockRead(SYNCHRONOUS, OK),
8798 HttpRequestInfo request;
8799 request.method = "GET";
8800 request.url = GURL("http://www.example.org/");
8801 request.load_flags = 0;
8803 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8805 session_deps_.socket_factory->AddSocketDataProvider(&data);
8807 TestCompletionCallback callback;
8809 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
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 HostPortPair http_host_port_pair("www.example.org", 80);
8817 HttpServerProperties& http_server_properties =
8818 *session->http_server_properties();
8819 AlternativeServiceVector alternative_service_vector =
8820 http_server_properties.GetAlternativeServices(http_host_port_pair);
8821 EXPECT_TRUE(alternative_service_vector.empty());
8823 EXPECT_EQ(OK, callback.WaitForResult());
8825 const HttpResponseInfo* response = trans->GetResponseInfo();
8826 ASSERT_TRUE(response != NULL);
8827 ASSERT_TRUE(response->headers.get() != NULL);
8828 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8829 EXPECT_FALSE(response->was_fetched_via_spdy);
8830 EXPECT_FALSE(response->was_npn_negotiated);
8832 std::string response_data;
8833 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8834 EXPECT_EQ("hello world", response_data);
8836 alternative_service_vector =
8837 http_server_properties.GetAlternativeServices(http_host_port_pair);
8838 ASSERT_EQ(2u, alternative_service_vector.size());
8839 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8840 alternative_service_vector[0].protocol);
8841 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
8842 EXPECT_EQ(443, alternative_service_vector[0].port);
8843 EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
8844 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
8845 EXPECT_EQ(1234, alternative_service_vector[1].port);
8848 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8849 session_deps_.next_protos = SpdyNextProtos();
8850 session_deps_.use_alternative_services = true;
8852 std::string alternate_protocol_http_header =
8853 GetAlternateProtocolHttpHeader();
8855 MockRead data_reads[] = {
8856 MockRead("HTTP/1.1 200 OK\r\n"),
8857 MockRead(alternate_protocol_http_header.c_str()),
8858 MockRead("\r\n"),
8859 MockRead("hello world"),
8860 MockRead(SYNCHRONOUS, OK),
8863 HttpRequestInfo request;
8864 request.method = "GET";
8865 request.url = GURL("http://www.example.org/");
8866 request.load_flags = 0;
8868 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8870 session_deps_.socket_factory->AddSocketDataProvider(&data);
8872 TestCompletionCallback callback;
8874 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8875 scoped_ptr<HttpTransaction> trans(
8876 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8878 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8879 EXPECT_EQ(ERR_IO_PENDING, rv);
8881 HostPortPair http_host_port_pair("www.example.org", 80);
8882 HttpServerProperties& http_server_properties =
8883 *session->http_server_properties();
8884 AlternativeServiceVector alternative_service_vector =
8885 http_server_properties.GetAlternativeServices(http_host_port_pair);
8886 EXPECT_TRUE(alternative_service_vector.empty());
8888 EXPECT_EQ(OK, callback.WaitForResult());
8890 const HttpResponseInfo* response = trans->GetResponseInfo();
8891 ASSERT_TRUE(response != NULL);
8892 ASSERT_TRUE(response->headers.get() != NULL);
8893 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8894 EXPECT_FALSE(response->was_fetched_via_spdy);
8895 EXPECT_FALSE(response->was_npn_negotiated);
8897 std::string response_data;
8898 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8899 EXPECT_EQ("hello world", response_data);
8901 alternative_service_vector =
8902 http_server_properties.GetAlternativeServices(http_host_port_pair);
8903 ASSERT_EQ(1u, alternative_service_vector.size());
8904 EXPECT_EQ(443, alternative_service_vector[0].port);
8905 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8906 alternative_service_vector[0].protocol);
8909 TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
8910 session_deps_.next_protos = SpdyNextProtos();
8911 session_deps_.use_alternative_services = true;
8913 MockRead data_reads[] = {
8914 MockRead("HTTP/1.1 200 OK\r\n"),
8915 MockRead("Alternate-Protocol: \r\n\r\n"),
8916 MockRead("hello world"),
8917 MockRead(SYNCHRONOUS, OK),
8920 HttpRequestInfo request;
8921 request.method = "GET";
8922 request.url = GURL("http://www.example.org/");
8923 request.load_flags = 0;
8925 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8927 session_deps_.socket_factory->AddSocketDataProvider(&data);
8929 TestCompletionCallback callback;
8931 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8933 HostPortPair http_host_port_pair("www.example.org", 80);
8934 HttpServerProperties& http_server_properties =
8935 *session->http_server_properties();
8936 AlternativeService alternative_service(QUIC, "", 80);
8937 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
8938 http_server_properties.SetAlternativeService(
8939 http_host_port_pair, alternative_service, 1.0, expiration);
8941 AlternativeServiceVector alternative_service_vector =
8942 http_server_properties.GetAlternativeServices(http_host_port_pair);
8943 ASSERT_EQ(1u, alternative_service_vector.size());
8944 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
8946 scoped_ptr<HttpTransaction> trans(
8947 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8949 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8950 EXPECT_EQ(ERR_IO_PENDING, rv);
8952 EXPECT_EQ(OK, callback.WaitForResult());
8954 const HttpResponseInfo* response = trans->GetResponseInfo();
8955 ASSERT_TRUE(response != NULL);
8956 ASSERT_TRUE(response->headers.get() != NULL);
8957 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8958 EXPECT_FALSE(response->was_fetched_via_spdy);
8959 EXPECT_FALSE(response->was_npn_negotiated);
8961 std::string response_data;
8962 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8963 EXPECT_EQ("hello world", response_data);
8965 alternative_service_vector =
8966 http_server_properties.GetAlternativeServices(http_host_port_pair);
8967 EXPECT_TRUE(alternative_service_vector.empty());
8970 TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
8971 session_deps_.next_protos = SpdyNextProtos();
8972 session_deps_.use_alternative_services = true;
8974 std::string alternative_service_http_header =
8975 GetAlternativeServiceHttpHeader();
8976 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
8978 MockRead data_reads[] = {
8979 MockRead("HTTP/1.1 200 OK\r\n"),
8980 MockRead(alternative_service_http_header.c_str()),
8981 MockRead(alternate_protocol_http_header.c_str()),
8982 MockRead("\r\n"),
8983 MockRead("hello world"),
8984 MockRead(SYNCHRONOUS, OK),
8987 HttpRequestInfo request;
8988 request.method = "GET";
8989 request.url = GURL("http://www.example.org/");
8990 request.load_flags = 0;
8992 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8994 session_deps_.socket_factory->AddSocketDataProvider(&data);
8996 TestCompletionCallback callback;
8998 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8999 scoped_ptr<HttpTransaction> trans(
9000 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9002 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9003 EXPECT_EQ(ERR_IO_PENDING, rv);
9005 HostPortPair http_host_port_pair("www.example.org", 80);
9006 HttpServerProperties& http_server_properties =
9007 *session->http_server_properties();
9008 AlternativeServiceVector alternative_service_vector =
9009 http_server_properties.GetAlternativeServices(http_host_port_pair);
9010 EXPECT_TRUE(alternative_service_vector.empty());
9012 EXPECT_EQ(OK, callback.WaitForResult());
9014 const HttpResponseInfo* response = trans->GetResponseInfo();
9015 ASSERT_TRUE(response != NULL);
9016 ASSERT_TRUE(response->headers.get() != NULL);
9017 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9018 EXPECT_FALSE(response->was_fetched_via_spdy);
9019 EXPECT_FALSE(response->was_npn_negotiated);
9021 std::string response_data;
9022 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9023 EXPECT_EQ("hello world", response_data);
9025 alternative_service_vector =
9026 http_server_properties.GetAlternativeServices(http_host_port_pair);
9027 ASSERT_EQ(1u, alternative_service_vector.size());
9028 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9029 alternative_service_vector[0].protocol);
9030 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9031 EXPECT_EQ(443, alternative_service_vector[0].port);
9034 TEST_P(HttpNetworkTransactionTest,
9035 MarkBrokenAlternateProtocolAndFallback) {
9036 session_deps_.use_alternative_services = true;
9038 HttpRequestInfo request;
9039 request.method = "GET";
9040 request.url = GURL("http://www.example.org/");
9041 request.load_flags = 0;
9043 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9044 StaticSocketDataProvider first_data;
9045 first_data.set_connect_data(mock_connect);
9046 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9048 MockRead data_reads[] = {
9049 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9050 MockRead("hello world"),
9051 MockRead(ASYNC, OK),
9053 StaticSocketDataProvider second_data(
9054 data_reads, arraysize(data_reads), NULL, 0);
9055 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9057 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9059 base::WeakPtr<HttpServerProperties> http_server_properties =
9060 session->http_server_properties();
9061 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
9062 // Port must be < 1024, or the header will be ignored (since initial port was
9063 // port 80 (another restricted port).
9064 const AlternativeService alternative_service(
9065 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9066 666); // Port is ignored by MockConnect anyway.
9067 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9068 http_server_properties->SetAlternativeService(
9069 host_port_pair, alternative_service, 1.0, expiration);
9071 scoped_ptr<HttpTransaction> trans(
9072 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9073 TestCompletionCallback callback;
9075 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9076 EXPECT_EQ(ERR_IO_PENDING, rv);
9077 EXPECT_EQ(OK, callback.WaitForResult());
9079 const HttpResponseInfo* response = trans->GetResponseInfo();
9080 ASSERT_TRUE(response != NULL);
9081 ASSERT_TRUE(response->headers.get() != NULL);
9082 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9084 std::string response_data;
9085 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9086 EXPECT_EQ("hello world", response_data);
9088 const AlternativeServiceVector alternative_service_vector =
9089 http_server_properties->GetAlternativeServices(host_port_pair);
9090 ASSERT_EQ(1u, alternative_service_vector.size());
9091 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
9092 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
9093 alternative_service_vector[0]));
9096 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9097 // to an unrestricted (port >= 1024) when the original traffic was on a
9098 // restricted port (port < 1024). Ensure that we can redirect in all other
9099 // cases.
9100 TEST_P(HttpNetworkTransactionTest,
9101 AlternateProtocolPortRestrictedBlocked) {
9102 session_deps_.use_alternative_services = true;
9104 HttpRequestInfo restricted_port_request;
9105 restricted_port_request.method = "GET";
9106 restricted_port_request.url = GURL("http://www.example.org:1023/");
9107 restricted_port_request.load_flags = 0;
9109 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9110 StaticSocketDataProvider first_data;
9111 first_data.set_connect_data(mock_connect);
9112 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9114 MockRead data_reads[] = {
9115 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9116 MockRead("hello world"),
9117 MockRead(ASYNC, OK),
9119 StaticSocketDataProvider second_data(
9120 data_reads, arraysize(data_reads), NULL, 0);
9121 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9123 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9125 base::WeakPtr<HttpServerProperties> http_server_properties =
9126 session->http_server_properties();
9127 const int kUnrestrictedAlternatePort = 1024;
9128 AlternativeService alternative_service(
9129 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9130 kUnrestrictedAlternatePort);
9131 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9132 http_server_properties->SetAlternativeService(
9133 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9134 1.0, expiration);
9136 scoped_ptr<HttpTransaction> trans(
9137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9138 TestCompletionCallback callback;
9140 int rv = trans->Start(
9141 &restricted_port_request,
9142 callback.callback(), BoundNetLog());
9143 EXPECT_EQ(ERR_IO_PENDING, rv);
9144 // Invalid change to unrestricted port should fail.
9145 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
9148 // Ensure that we are allowed to redirect traffic via an alternate protocol to
9149 // an unrestricted (port >= 1024) when the original traffic was on a restricted
9150 // port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
9151 TEST_P(HttpNetworkTransactionTest,
9152 AlternateProtocolPortRestrictedPermitted) {
9153 session_deps_.use_alternative_services = true;
9154 session_deps_.enable_user_alternate_protocol_ports = true;
9156 HttpRequestInfo restricted_port_request;
9157 restricted_port_request.method = "GET";
9158 restricted_port_request.url = GURL("http://www.example.org:1023/");
9159 restricted_port_request.load_flags = 0;
9161 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9162 StaticSocketDataProvider first_data;
9163 first_data.set_connect_data(mock_connect);
9164 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9166 MockRead data_reads[] = {
9167 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9168 MockRead("hello world"),
9169 MockRead(ASYNC, OK),
9171 StaticSocketDataProvider second_data(
9172 data_reads, arraysize(data_reads), NULL, 0);
9173 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9175 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9177 base::WeakPtr<HttpServerProperties> http_server_properties =
9178 session->http_server_properties();
9179 const int kUnrestrictedAlternatePort = 1024;
9180 AlternativeService alternative_service(
9181 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9182 kUnrestrictedAlternatePort);
9183 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9184 http_server_properties->SetAlternativeService(
9185 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9186 1.0, expiration);
9188 scoped_ptr<HttpTransaction> trans(
9189 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9190 TestCompletionCallback callback;
9192 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
9193 &restricted_port_request,
9194 callback.callback(), BoundNetLog()));
9195 // Change to unrestricted port should succeed.
9196 EXPECT_EQ(OK, callback.WaitForResult());
9199 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9200 // to an unrestricted (port >= 1024) when the original traffic was on a
9201 // restricted port (port < 1024). Ensure that we can redirect in all other
9202 // cases.
9203 TEST_P(HttpNetworkTransactionTest,
9204 AlternateProtocolPortRestrictedAllowed) {
9205 session_deps_.use_alternative_services = true;
9207 HttpRequestInfo restricted_port_request;
9208 restricted_port_request.method = "GET";
9209 restricted_port_request.url = GURL("http://www.example.org:1023/");
9210 restricted_port_request.load_flags = 0;
9212 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9213 StaticSocketDataProvider first_data;
9214 first_data.set_connect_data(mock_connect);
9215 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9217 MockRead data_reads[] = {
9218 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9219 MockRead("hello world"),
9220 MockRead(ASYNC, OK),
9222 StaticSocketDataProvider second_data(
9223 data_reads, arraysize(data_reads), NULL, 0);
9224 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9226 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9228 base::WeakPtr<HttpServerProperties> http_server_properties =
9229 session->http_server_properties();
9230 const int kRestrictedAlternatePort = 80;
9231 AlternativeService alternative_service(
9232 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9233 kRestrictedAlternatePort);
9234 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9235 http_server_properties->SetAlternativeService(
9236 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9237 1.0, expiration);
9239 scoped_ptr<HttpTransaction> trans(
9240 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9241 TestCompletionCallback callback;
9243 int rv = trans->Start(
9244 &restricted_port_request,
9245 callback.callback(), BoundNetLog());
9246 EXPECT_EQ(ERR_IO_PENDING, rv);
9247 // Valid change to restricted port should pass.
9248 EXPECT_EQ(OK, callback.WaitForResult());
9251 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9252 // to an unrestricted (port >= 1024) when the original traffic was on a
9253 // restricted port (port < 1024). Ensure that we can redirect in all other
9254 // cases.
9255 TEST_P(HttpNetworkTransactionTest,
9256 AlternateProtocolPortUnrestrictedAllowed1) {
9257 session_deps_.use_alternative_services = true;
9259 HttpRequestInfo unrestricted_port_request;
9260 unrestricted_port_request.method = "GET";
9261 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9262 unrestricted_port_request.load_flags = 0;
9264 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9265 StaticSocketDataProvider first_data;
9266 first_data.set_connect_data(mock_connect);
9267 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9269 MockRead data_reads[] = {
9270 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9271 MockRead("hello world"),
9272 MockRead(ASYNC, OK),
9274 StaticSocketDataProvider second_data(
9275 data_reads, arraysize(data_reads), NULL, 0);
9276 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9278 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9280 base::WeakPtr<HttpServerProperties> http_server_properties =
9281 session->http_server_properties();
9282 const int kRestrictedAlternatePort = 80;
9283 AlternativeService alternative_service(
9284 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9285 kRestrictedAlternatePort);
9286 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9287 http_server_properties->SetAlternativeService(
9288 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9289 1.0, expiration);
9291 scoped_ptr<HttpTransaction> trans(
9292 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9293 TestCompletionCallback callback;
9295 int rv = trans->Start(
9296 &unrestricted_port_request, callback.callback(), BoundNetLog());
9297 EXPECT_EQ(ERR_IO_PENDING, rv);
9298 // Valid change to restricted port should pass.
9299 EXPECT_EQ(OK, callback.WaitForResult());
9302 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9303 // to an unrestricted (port >= 1024) when the original traffic was on a
9304 // restricted port (port < 1024). Ensure that we can redirect in all other
9305 // cases.
9306 TEST_P(HttpNetworkTransactionTest,
9307 AlternateProtocolPortUnrestrictedAllowed2) {
9308 session_deps_.use_alternative_services = true;
9310 HttpRequestInfo unrestricted_port_request;
9311 unrestricted_port_request.method = "GET";
9312 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9313 unrestricted_port_request.load_flags = 0;
9315 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9316 StaticSocketDataProvider first_data;
9317 first_data.set_connect_data(mock_connect);
9318 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9320 MockRead data_reads[] = {
9321 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9322 MockRead("hello world"),
9323 MockRead(ASYNC, OK),
9325 StaticSocketDataProvider second_data(
9326 data_reads, arraysize(data_reads), NULL, 0);
9327 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9329 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9331 base::WeakPtr<HttpServerProperties> http_server_properties =
9332 session->http_server_properties();
9333 const int kUnrestrictedAlternatePort = 1025;
9334 AlternativeService alternative_service(
9335 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9336 kUnrestrictedAlternatePort);
9337 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9338 http_server_properties->SetAlternativeService(
9339 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9340 1.0, expiration);
9342 scoped_ptr<HttpTransaction> trans(
9343 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9344 TestCompletionCallback callback;
9346 int rv = trans->Start(
9347 &unrestricted_port_request, callback.callback(), BoundNetLog());
9348 EXPECT_EQ(ERR_IO_PENDING, rv);
9349 // Valid change to an unrestricted port should pass.
9350 EXPECT_EQ(OK, callback.WaitForResult());
9353 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9354 // to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
9355 // once the alternate protocol request fails.
9356 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
9357 session_deps_.use_alternative_services = true;
9359 HttpRequestInfo request;
9360 request.method = "GET";
9361 request.url = GURL("http://www.example.org/");
9362 request.load_flags = 0;
9364 // The alternate protocol request will error out before we attempt to connect,
9365 // so only the standard HTTP request will try to connect.
9366 MockRead data_reads[] = {
9367 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9368 MockRead("hello world"),
9369 MockRead(ASYNC, OK),
9371 StaticSocketDataProvider data(
9372 data_reads, arraysize(data_reads), NULL, 0);
9373 session_deps_.socket_factory->AddSocketDataProvider(&data);
9375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9377 base::WeakPtr<HttpServerProperties> http_server_properties =
9378 session->http_server_properties();
9379 const int kUnsafePort = 7;
9380 AlternativeService alternative_service(
9381 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9382 kUnsafePort);
9383 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9384 http_server_properties->SetAlternativeService(
9385 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
9387 scoped_ptr<HttpTransaction> trans(
9388 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9389 TestCompletionCallback callback;
9391 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9392 EXPECT_EQ(ERR_IO_PENDING, rv);
9393 // The HTTP request should succeed.
9394 EXPECT_EQ(OK, callback.WaitForResult());
9396 const HttpResponseInfo* response = trans->GetResponseInfo();
9397 ASSERT_TRUE(response != NULL);
9398 ASSERT_TRUE(response->headers.get() != NULL);
9399 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9401 std::string response_data;
9402 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9403 EXPECT_EQ("hello world", response_data);
9406 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
9407 session_deps_.use_alternative_services = true;
9408 session_deps_.next_protos = SpdyNextProtos();
9410 HttpRequestInfo request;
9411 request.method = "GET";
9412 request.url = GURL("http://www.example.org/");
9413 request.load_flags = 0;
9415 std::string alternate_protocol_http_header =
9416 GetAlternateProtocolHttpHeader();
9418 MockRead data_reads[] = {
9419 MockRead("HTTP/1.1 200 OK\r\n"),
9420 MockRead(alternate_protocol_http_header.c_str()),
9421 MockRead("\r\n"),
9422 MockRead("hello world"),
9423 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9424 MockRead(ASYNC, OK)};
9426 StaticSocketDataProvider first_transaction(
9427 data_reads, arraysize(data_reads), NULL, 0);
9428 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9430 SSLSocketDataProvider ssl(ASYNC, OK);
9431 ssl.SetNextProto(GetParam());
9432 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9433 ASSERT_TRUE(ssl.cert.get());
9434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9436 scoped_ptr<SpdyFrame> req(
9437 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9438 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9440 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9441 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9442 MockRead spdy_reads[] = {
9443 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9446 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9447 arraysize(spdy_writes));
9448 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9450 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9451 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9452 NULL, 0, NULL, 0);
9453 hanging_non_alternate_protocol_socket.set_connect_data(
9454 never_finishing_connect);
9455 session_deps_.socket_factory->AddSocketDataProvider(
9456 &hanging_non_alternate_protocol_socket);
9458 TestCompletionCallback callback;
9460 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9461 scoped_ptr<HttpTransaction> trans(
9462 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9464 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9465 EXPECT_EQ(ERR_IO_PENDING, rv);
9466 EXPECT_EQ(OK, callback.WaitForResult());
9468 const HttpResponseInfo* response = trans->GetResponseInfo();
9469 ASSERT_TRUE(response != NULL);
9470 ASSERT_TRUE(response->headers.get() != NULL);
9471 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9473 std::string response_data;
9474 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9475 EXPECT_EQ("hello world", response_data);
9477 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9479 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9480 EXPECT_EQ(ERR_IO_PENDING, rv);
9481 EXPECT_EQ(OK, callback.WaitForResult());
9483 response = trans->GetResponseInfo();
9484 ASSERT_TRUE(response != NULL);
9485 ASSERT_TRUE(response->headers.get() != NULL);
9486 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9487 EXPECT_TRUE(response->was_fetched_via_spdy);
9488 EXPECT_TRUE(response->was_npn_negotiated);
9490 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9491 EXPECT_EQ("hello!", response_data);
9494 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
9495 session_deps_.use_alternative_services = true;
9496 session_deps_.next_protos = SpdyNextProtos();
9498 HttpRequestInfo request;
9499 request.method = "GET";
9500 request.url = GURL("http://www.example.org/");
9501 request.load_flags = 0;
9503 std::string alternate_protocol_http_header =
9504 GetAlternateProtocolHttpHeader();
9506 MockRead data_reads[] = {
9507 MockRead("HTTP/1.1 200 OK\r\n"),
9508 MockRead(alternate_protocol_http_header.c_str()),
9509 MockRead("\r\n"),
9510 MockRead("hello world"),
9511 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9512 MockRead(ASYNC, OK),
9515 StaticSocketDataProvider first_transaction(
9516 data_reads, arraysize(data_reads), NULL, 0);
9517 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9518 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9520 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9521 StaticSocketDataProvider hanging_socket(
9522 NULL, 0, NULL, 0);
9523 hanging_socket.set_connect_data(never_finishing_connect);
9524 // Socket 2 and 3 are the hanging Alternate-Protocol and
9525 // non-Alternate-Protocol jobs from the 2nd transaction.
9526 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9527 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9529 SSLSocketDataProvider ssl(ASYNC, OK);
9530 ssl.SetNextProto(GetParam());
9531 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9532 ASSERT_TRUE(ssl.cert.get());
9533 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9535 scoped_ptr<SpdyFrame> req1(
9536 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9537 scoped_ptr<SpdyFrame> req2(
9538 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9539 MockWrite spdy_writes[] = {
9540 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
9542 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9543 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
9544 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9545 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9546 MockRead spdy_reads[] = {
9547 CreateMockRead(*resp1, 2),
9548 CreateMockRead(*data1, 3),
9549 CreateMockRead(*resp2, 4),
9550 CreateMockRead(*data2, 5),
9551 MockRead(ASYNC, 0, 6),
9554 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9555 arraysize(spdy_writes));
9556 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9557 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9559 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9560 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9562 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9563 TestCompletionCallback callback1;
9564 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9566 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
9567 EXPECT_EQ(ERR_IO_PENDING, rv);
9568 EXPECT_EQ(OK, callback1.WaitForResult());
9570 const HttpResponseInfo* response = trans1.GetResponseInfo();
9571 ASSERT_TRUE(response != NULL);
9572 ASSERT_TRUE(response->headers.get() != NULL);
9573 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9575 std::string response_data;
9576 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9577 EXPECT_EQ("hello world", response_data);
9579 TestCompletionCallback callback2;
9580 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9581 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
9582 EXPECT_EQ(ERR_IO_PENDING, rv);
9584 TestCompletionCallback callback3;
9585 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
9586 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
9587 EXPECT_EQ(ERR_IO_PENDING, rv);
9589 EXPECT_EQ(OK, callback2.WaitForResult());
9590 EXPECT_EQ(OK, callback3.WaitForResult());
9592 response = trans2.GetResponseInfo();
9593 ASSERT_TRUE(response != NULL);
9594 ASSERT_TRUE(response->headers.get() != NULL);
9595 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9596 EXPECT_TRUE(response->was_fetched_via_spdy);
9597 EXPECT_TRUE(response->was_npn_negotiated);
9598 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9599 EXPECT_EQ("hello!", response_data);
9601 response = trans3.GetResponseInfo();
9602 ASSERT_TRUE(response != NULL);
9603 ASSERT_TRUE(response->headers.get() != NULL);
9604 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9605 EXPECT_TRUE(response->was_fetched_via_spdy);
9606 EXPECT_TRUE(response->was_npn_negotiated);
9607 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9608 EXPECT_EQ("hello!", response_data);
9611 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9612 session_deps_.use_alternative_services = true;
9613 session_deps_.next_protos = SpdyNextProtos();
9615 HttpRequestInfo request;
9616 request.method = "GET";
9617 request.url = GURL("http://www.example.org/");
9618 request.load_flags = 0;
9620 std::string alternate_protocol_http_header =
9621 GetAlternateProtocolHttpHeader();
9623 MockRead data_reads[] = {
9624 MockRead("HTTP/1.1 200 OK\r\n"),
9625 MockRead(alternate_protocol_http_header.c_str()),
9626 MockRead("\r\n"),
9627 MockRead("hello world"),
9628 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9629 MockRead(ASYNC, OK),
9632 StaticSocketDataProvider first_transaction(
9633 data_reads, arraysize(data_reads), NULL, 0);
9634 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9636 SSLSocketDataProvider ssl(ASYNC, OK);
9637 ssl.SetNextProto(GetParam());
9638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9640 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9641 StaticSocketDataProvider hanging_alternate_protocol_socket(
9642 NULL, 0, NULL, 0);
9643 hanging_alternate_protocol_socket.set_connect_data(
9644 never_finishing_connect);
9645 session_deps_.socket_factory->AddSocketDataProvider(
9646 &hanging_alternate_protocol_socket);
9648 // 2nd request is just a copy of the first one, over HTTP again.
9649 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9651 TestCompletionCallback callback;
9653 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9654 scoped_ptr<HttpTransaction> trans(
9655 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9657 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9658 EXPECT_EQ(ERR_IO_PENDING, rv);
9659 EXPECT_EQ(OK, callback.WaitForResult());
9661 const HttpResponseInfo* response = trans->GetResponseInfo();
9662 ASSERT_TRUE(response != NULL);
9663 ASSERT_TRUE(response->headers.get() != NULL);
9664 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9666 std::string response_data;
9667 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9668 EXPECT_EQ("hello world", response_data);
9670 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9672 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9673 EXPECT_EQ(ERR_IO_PENDING, rv);
9674 EXPECT_EQ(OK, callback.WaitForResult());
9676 response = trans->GetResponseInfo();
9677 ASSERT_TRUE(response != NULL);
9678 ASSERT_TRUE(response->headers.get() != NULL);
9679 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9680 EXPECT_FALSE(response->was_fetched_via_spdy);
9681 EXPECT_FALSE(response->was_npn_negotiated);
9683 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9684 EXPECT_EQ("hello world", response_data);
9687 class CapturingProxyResolver : public ProxyResolver {
9688 public:
9689 CapturingProxyResolver() {}
9690 ~CapturingProxyResolver() override {}
9692 int GetProxyForURL(const GURL& url,
9693 ProxyInfo* results,
9694 const CompletionCallback& callback,
9695 RequestHandle* request,
9696 const BoundNetLog& net_log) override {
9697 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9698 HostPortPair("myproxy", 80));
9699 results->UseProxyServer(proxy_server);
9700 resolved_.push_back(url);
9701 return OK;
9704 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
9706 LoadState GetLoadState(RequestHandle request) const override {
9707 NOTREACHED();
9708 return LOAD_STATE_IDLE;
9711 const std::vector<GURL>& resolved() const { return resolved_; }
9713 private:
9714 std::vector<GURL> resolved_;
9716 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9719 class CapturingProxyResolverFactory : public ProxyResolverFactory {
9720 public:
9721 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
9722 : ProxyResolverFactory(false), resolver_(resolver) {}
9724 int CreateProxyResolver(
9725 const scoped_refptr<ProxyResolverScriptData>& pac_script,
9726 scoped_ptr<ProxyResolver>* resolver,
9727 const net::CompletionCallback& callback,
9728 scoped_ptr<Request>* request) override {
9729 resolver->reset(new ForwardingProxyResolver(resolver_));
9730 return OK;
9733 private:
9734 ProxyResolver* resolver_;
9737 TEST_P(HttpNetworkTransactionTest,
9738 UseAlternateProtocolForTunneledNpnSpdy) {
9739 session_deps_.use_alternative_services = true;
9740 session_deps_.next_protos = SpdyNextProtos();
9742 ProxyConfig proxy_config;
9743 proxy_config.set_auto_detect(true);
9744 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9746 CapturingProxyResolver capturing_proxy_resolver;
9747 session_deps_.proxy_service.reset(new ProxyService(
9748 new ProxyConfigServiceFixed(proxy_config),
9749 make_scoped_ptr(
9750 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
9751 NULL));
9752 TestNetLog net_log;
9753 session_deps_.net_log = &net_log;
9755 HttpRequestInfo request;
9756 request.method = "GET";
9757 request.url = GURL("http://www.example.org/");
9758 request.load_flags = 0;
9760 std::string alternate_protocol_http_header =
9761 GetAlternateProtocolHttpHeader();
9763 MockRead data_reads[] = {
9764 MockRead("HTTP/1.1 200 OK\r\n"),
9765 MockRead(alternate_protocol_http_header.c_str()),
9766 MockRead("\r\n"),
9767 MockRead("hello world"),
9768 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9769 MockRead(ASYNC, OK),
9772 StaticSocketDataProvider first_transaction(
9773 data_reads, arraysize(data_reads), NULL, 0);
9774 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9776 SSLSocketDataProvider ssl(ASYNC, OK);
9777 ssl.SetNextProto(GetParam());
9778 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9779 ASSERT_TRUE(ssl.cert.get());
9780 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9782 scoped_ptr<SpdyFrame> req(
9783 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9784 MockWrite spdy_writes[] = {
9785 MockWrite(ASYNC, 0,
9786 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9787 "Host: www.example.org\r\n"
9788 "Proxy-Connection: keep-alive\r\n\r\n"),
9789 CreateMockWrite(*req, 2),
9792 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9794 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9795 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9796 MockRead spdy_reads[] = {
9797 MockRead(ASYNC, 1, kCONNECTResponse),
9798 CreateMockRead(*resp.get(), 3),
9799 CreateMockRead(*data.get(), 4),
9800 MockRead(ASYNC, ERR_IO_PENDING, 5),
9803 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9804 arraysize(spdy_writes));
9805 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9807 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9808 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9809 NULL, 0, NULL, 0);
9810 hanging_non_alternate_protocol_socket.set_connect_data(
9811 never_finishing_connect);
9812 session_deps_.socket_factory->AddSocketDataProvider(
9813 &hanging_non_alternate_protocol_socket);
9815 TestCompletionCallback callback;
9817 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9818 scoped_ptr<HttpTransaction> trans(
9819 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9821 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9822 EXPECT_EQ(ERR_IO_PENDING, rv);
9823 EXPECT_EQ(OK, callback.WaitForResult());
9825 const HttpResponseInfo* response = trans->GetResponseInfo();
9826 ASSERT_TRUE(response != NULL);
9827 ASSERT_TRUE(response->headers.get() != NULL);
9828 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9829 EXPECT_FALSE(response->was_fetched_via_spdy);
9830 EXPECT_FALSE(response->was_npn_negotiated);
9832 std::string response_data;
9833 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9834 EXPECT_EQ("hello world", response_data);
9836 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9838 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9839 EXPECT_EQ(ERR_IO_PENDING, rv);
9840 EXPECT_EQ(OK, callback.WaitForResult());
9842 response = trans->GetResponseInfo();
9843 ASSERT_TRUE(response != NULL);
9844 ASSERT_TRUE(response->headers.get() != NULL);
9845 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9846 EXPECT_TRUE(response->was_fetched_via_spdy);
9847 EXPECT_TRUE(response->was_npn_negotiated);
9849 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9850 EXPECT_EQ("hello!", response_data);
9851 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
9852 EXPECT_EQ("http://www.example.org/",
9853 capturing_proxy_resolver.resolved()[0].spec());
9854 EXPECT_EQ("https://www.example.org/",
9855 capturing_proxy_resolver.resolved()[1].spec());
9857 LoadTimingInfo load_timing_info;
9858 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9859 TestLoadTimingNotReusedWithPac(load_timing_info,
9860 CONNECT_TIMING_HAS_SSL_TIMES);
9863 TEST_P(HttpNetworkTransactionTest,
9864 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9865 session_deps_.use_alternative_services = true;
9866 session_deps_.next_protos = SpdyNextProtos();
9868 HttpRequestInfo request;
9869 request.method = "GET";
9870 request.url = GURL("http://www.example.org/");
9871 request.load_flags = 0;
9873 std::string alternate_protocol_http_header =
9874 GetAlternateProtocolHttpHeader();
9876 MockRead data_reads[] = {
9877 MockRead("HTTP/1.1 200 OK\r\n"),
9878 MockRead(alternate_protocol_http_header.c_str()),
9879 MockRead("\r\n"),
9880 MockRead("hello world"),
9881 MockRead(ASYNC, OK),
9884 StaticSocketDataProvider first_transaction(
9885 data_reads, arraysize(data_reads), NULL, 0);
9886 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9888 SSLSocketDataProvider ssl(ASYNC, OK);
9889 ssl.SetNextProto(GetParam());
9890 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9891 ASSERT_TRUE(ssl.cert.get());
9892 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9894 scoped_ptr<SpdyFrame> req(
9895 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9896 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9898 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9899 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9900 MockRead spdy_reads[] = {
9901 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9904 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9905 arraysize(spdy_writes));
9906 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9908 TestCompletionCallback callback;
9910 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9912 scoped_ptr<HttpTransaction> trans(
9913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9915 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9916 EXPECT_EQ(ERR_IO_PENDING, rv);
9917 EXPECT_EQ(OK, callback.WaitForResult());
9919 const HttpResponseInfo* response = trans->GetResponseInfo();
9920 ASSERT_TRUE(response != NULL);
9921 ASSERT_TRUE(response->headers.get() != NULL);
9922 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9924 std::string response_data;
9925 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9926 EXPECT_EQ("hello world", response_data);
9928 // Set up an initial SpdySession in the pool to reuse.
9929 HostPortPair host_port_pair("www.example.org", 443);
9930 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9931 PRIVACY_MODE_DISABLED);
9932 base::WeakPtr<SpdySession> spdy_session =
9933 CreateSecureSpdySession(session, key, BoundNetLog());
9935 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9937 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9938 EXPECT_EQ(ERR_IO_PENDING, rv);
9939 EXPECT_EQ(OK, callback.WaitForResult());
9941 response = trans->GetResponseInfo();
9942 ASSERT_TRUE(response != NULL);
9943 ASSERT_TRUE(response->headers.get() != NULL);
9944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9945 EXPECT_TRUE(response->was_fetched_via_spdy);
9946 EXPECT_TRUE(response->was_npn_negotiated);
9948 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9949 EXPECT_EQ("hello!", response_data);
9952 // GenerateAuthToken is a mighty big test.
9953 // It tests all permutation of GenerateAuthToken behavior:
9954 // - Synchronous and Asynchronous completion.
9955 // - OK or error on completion.
9956 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9957 // - HTTP or HTTPS backend (to include proxy tunneling).
9958 // - Non-authenticating and authenticating backend.
9960 // In all, there are 44 reasonable permuations (for example, if there are
9961 // problems generating an auth token for an authenticating proxy, we don't
9962 // need to test all permutations of the backend server).
9964 // The test proceeds by going over each of the configuration cases, and
9965 // potentially running up to three rounds in each of the tests. The TestConfig
9966 // specifies both the configuration for the test as well as the expectations
9967 // for the results.
9968 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9969 static const char kServer[] = "http://www.example.com";
9970 static const char kSecureServer[] = "https://www.example.com";
9971 static const char kProxy[] = "myproxy:70";
9972 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9974 enum AuthTiming {
9975 AUTH_NONE,
9976 AUTH_SYNC,
9977 AUTH_ASYNC,
9980 const MockWrite kGet(
9981 "GET / HTTP/1.1\r\n"
9982 "Host: www.example.com\r\n"
9983 "Connection: keep-alive\r\n\r\n");
9984 const MockWrite kGetProxy(
9985 "GET http://www.example.com/ HTTP/1.1\r\n"
9986 "Host: www.example.com\r\n"
9987 "Proxy-Connection: keep-alive\r\n\r\n");
9988 const MockWrite kGetAuth(
9989 "GET / HTTP/1.1\r\n"
9990 "Host: www.example.com\r\n"
9991 "Connection: keep-alive\r\n"
9992 "Authorization: auth_token\r\n\r\n");
9993 const MockWrite kGetProxyAuth(
9994 "GET http://www.example.com/ HTTP/1.1\r\n"
9995 "Host: www.example.com\r\n"
9996 "Proxy-Connection: keep-alive\r\n"
9997 "Proxy-Authorization: auth_token\r\n\r\n");
9998 const MockWrite kGetAuthThroughProxy(
9999 "GET http://www.example.com/ HTTP/1.1\r\n"
10000 "Host: www.example.com\r\n"
10001 "Proxy-Connection: keep-alive\r\n"
10002 "Authorization: auth_token\r\n\r\n");
10003 const MockWrite kGetAuthWithProxyAuth(
10004 "GET http://www.example.com/ HTTP/1.1\r\n"
10005 "Host: www.example.com\r\n"
10006 "Proxy-Connection: keep-alive\r\n"
10007 "Proxy-Authorization: auth_token\r\n"
10008 "Authorization: auth_token\r\n\r\n");
10009 const MockWrite kConnect(
10010 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10011 "Host: www.example.com\r\n"
10012 "Proxy-Connection: keep-alive\r\n\r\n");
10013 const MockWrite kConnectProxyAuth(
10014 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10015 "Host: www.example.com\r\n"
10016 "Proxy-Connection: keep-alive\r\n"
10017 "Proxy-Authorization: auth_token\r\n\r\n");
10019 const MockRead kSuccess(
10020 "HTTP/1.1 200 OK\r\n"
10021 "Content-Type: text/html; charset=iso-8859-1\r\n"
10022 "Content-Length: 3\r\n\r\n"
10023 "Yes");
10024 const MockRead kFailure(
10025 "Should not be called.");
10026 const MockRead kServerChallenge(
10027 "HTTP/1.1 401 Unauthorized\r\n"
10028 "WWW-Authenticate: Mock realm=server\r\n"
10029 "Content-Type: text/html; charset=iso-8859-1\r\n"
10030 "Content-Length: 14\r\n\r\n"
10031 "Unauthorized\r\n");
10032 const MockRead kProxyChallenge(
10033 "HTTP/1.1 407 Unauthorized\r\n"
10034 "Proxy-Authenticate: Mock realm=proxy\r\n"
10035 "Proxy-Connection: close\r\n"
10036 "Content-Type: text/html; charset=iso-8859-1\r\n"
10037 "Content-Length: 14\r\n\r\n"
10038 "Unauthorized\r\n");
10039 const MockRead kProxyConnected(
10040 "HTTP/1.1 200 Connection Established\r\n\r\n");
10042 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10043 // no constructors, but the C++ compiler on Windows warns about
10044 // unspecified data in compound literals. So, moved to using constructors,
10045 // and TestRound's created with the default constructor should not be used.
10046 struct TestRound {
10047 TestRound()
10048 : expected_rv(ERR_UNEXPECTED),
10049 extra_write(NULL),
10050 extra_read(NULL) {
10052 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10053 int expected_rv_arg)
10054 : write(write_arg),
10055 read(read_arg),
10056 expected_rv(expected_rv_arg),
10057 extra_write(NULL),
10058 extra_read(NULL) {
10060 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10061 int expected_rv_arg, const MockWrite* extra_write_arg,
10062 const MockRead* extra_read_arg)
10063 : write(write_arg),
10064 read(read_arg),
10065 expected_rv(expected_rv_arg),
10066 extra_write(extra_write_arg),
10067 extra_read(extra_read_arg) {
10069 MockWrite write;
10070 MockRead read;
10071 int expected_rv;
10072 const MockWrite* extra_write;
10073 const MockRead* extra_read;
10076 static const int kNoSSL = 500;
10078 struct TestConfig {
10079 const char* const proxy_url;
10080 AuthTiming proxy_auth_timing;
10081 int proxy_auth_rv;
10082 const char* const server_url;
10083 AuthTiming server_auth_timing;
10084 int server_auth_rv;
10085 int num_auth_rounds;
10086 int first_ssl_round;
10087 TestRound rounds[3];
10088 } test_configs[] = {
10089 // Non-authenticating HTTP server with a direct connection.
10090 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10091 { TestRound(kGet, kSuccess, OK)}},
10092 // Authenticating HTTP server with a direct connection.
10093 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10094 { TestRound(kGet, kServerChallenge, OK),
10095 TestRound(kGetAuth, kSuccess, OK)}},
10096 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10097 { TestRound(kGet, kServerChallenge, OK),
10098 TestRound(kGetAuth, kFailure, kAuthErr)}},
10099 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10100 { TestRound(kGet, kServerChallenge, OK),
10101 TestRound(kGetAuth, kSuccess, OK)}},
10102 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10103 { TestRound(kGet, kServerChallenge, OK),
10104 TestRound(kGetAuth, kFailure, kAuthErr)}},
10105 // Non-authenticating HTTP server through a non-authenticating proxy.
10106 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10107 { TestRound(kGetProxy, kSuccess, OK)}},
10108 // Authenticating HTTP server through a non-authenticating proxy.
10109 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10110 { TestRound(kGetProxy, kServerChallenge, OK),
10111 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10112 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10113 { TestRound(kGetProxy, kServerChallenge, OK),
10114 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10115 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10116 { TestRound(kGetProxy, kServerChallenge, OK),
10117 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10118 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10119 { TestRound(kGetProxy, kServerChallenge, OK),
10120 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10121 // Non-authenticating HTTP server through an authenticating proxy.
10122 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10123 { TestRound(kGetProxy, kProxyChallenge, OK),
10124 TestRound(kGetProxyAuth, kSuccess, OK)}},
10125 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10126 { TestRound(kGetProxy, kProxyChallenge, OK),
10127 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10128 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10129 { TestRound(kGetProxy, kProxyChallenge, OK),
10130 TestRound(kGetProxyAuth, kSuccess, OK)}},
10131 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10132 { TestRound(kGetProxy, kProxyChallenge, OK),
10133 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10134 // Authenticating HTTP server through an authenticating proxy.
10135 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10136 { TestRound(kGetProxy, kProxyChallenge, OK),
10137 TestRound(kGetProxyAuth, kServerChallenge, OK),
10138 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10139 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10140 { TestRound(kGetProxy, kProxyChallenge, OK),
10141 TestRound(kGetProxyAuth, kServerChallenge, OK),
10142 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10143 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10144 { TestRound(kGetProxy, kProxyChallenge, OK),
10145 TestRound(kGetProxyAuth, kServerChallenge, OK),
10146 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10147 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10148 { TestRound(kGetProxy, kProxyChallenge, OK),
10149 TestRound(kGetProxyAuth, kServerChallenge, OK),
10150 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10151 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10152 { TestRound(kGetProxy, kProxyChallenge, OK),
10153 TestRound(kGetProxyAuth, kServerChallenge, OK),
10154 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10155 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10156 { TestRound(kGetProxy, kProxyChallenge, OK),
10157 TestRound(kGetProxyAuth, kServerChallenge, OK),
10158 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10159 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10160 { TestRound(kGetProxy, kProxyChallenge, OK),
10161 TestRound(kGetProxyAuth, kServerChallenge, OK),
10162 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10163 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10164 { TestRound(kGetProxy, kProxyChallenge, OK),
10165 TestRound(kGetProxyAuth, kServerChallenge, OK),
10166 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10167 // Non-authenticating HTTPS server with a direct connection.
10168 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10169 { TestRound(kGet, kSuccess, OK)}},
10170 // Authenticating HTTPS server with a direct connection.
10171 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10172 { TestRound(kGet, kServerChallenge, OK),
10173 TestRound(kGetAuth, kSuccess, OK)}},
10174 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10175 { TestRound(kGet, kServerChallenge, OK),
10176 TestRound(kGetAuth, kFailure, kAuthErr)}},
10177 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10178 { TestRound(kGet, kServerChallenge, OK),
10179 TestRound(kGetAuth, kSuccess, OK)}},
10180 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10181 { TestRound(kGet, kServerChallenge, OK),
10182 TestRound(kGetAuth, kFailure, kAuthErr)}},
10183 // Non-authenticating HTTPS server with a non-authenticating proxy.
10184 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10185 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
10186 // Authenticating HTTPS server through a non-authenticating proxy.
10187 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10188 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10189 TestRound(kGetAuth, kSuccess, OK)}},
10190 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10191 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10192 TestRound(kGetAuth, kFailure, kAuthErr)}},
10193 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10194 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10195 TestRound(kGetAuth, kSuccess, OK)}},
10196 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10197 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10198 TestRound(kGetAuth, kFailure, kAuthErr)}},
10199 // Non-Authenticating HTTPS server through an authenticating proxy.
10200 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10201 { TestRound(kConnect, kProxyChallenge, OK),
10202 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10203 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10204 { TestRound(kConnect, kProxyChallenge, OK),
10205 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10206 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10207 { TestRound(kConnect, kProxyChallenge, OK),
10208 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10209 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10210 { TestRound(kConnect, kProxyChallenge, OK),
10211 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10212 // Authenticating HTTPS server through an authenticating proxy.
10213 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10214 { TestRound(kConnect, kProxyChallenge, OK),
10215 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10216 &kGet, &kServerChallenge),
10217 TestRound(kGetAuth, kSuccess, OK)}},
10218 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10219 { TestRound(kConnect, kProxyChallenge, OK),
10220 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10221 &kGet, &kServerChallenge),
10222 TestRound(kGetAuth, kFailure, kAuthErr)}},
10223 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10224 { TestRound(kConnect, kProxyChallenge, OK),
10225 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10226 &kGet, &kServerChallenge),
10227 TestRound(kGetAuth, kSuccess, OK)}},
10228 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10229 { TestRound(kConnect, kProxyChallenge, OK),
10230 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10231 &kGet, &kServerChallenge),
10232 TestRound(kGetAuth, kFailure, kAuthErr)}},
10233 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10234 { TestRound(kConnect, kProxyChallenge, OK),
10235 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10236 &kGet, &kServerChallenge),
10237 TestRound(kGetAuth, kSuccess, OK)}},
10238 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10239 { TestRound(kConnect, kProxyChallenge, OK),
10240 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10241 &kGet, &kServerChallenge),
10242 TestRound(kGetAuth, kFailure, kAuthErr)}},
10243 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10244 { TestRound(kConnect, kProxyChallenge, OK),
10245 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10246 &kGet, &kServerChallenge),
10247 TestRound(kGetAuth, kSuccess, OK)}},
10248 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10249 { TestRound(kConnect, kProxyChallenge, OK),
10250 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10251 &kGet, &kServerChallenge),
10252 TestRound(kGetAuth, kFailure, kAuthErr)}},
10255 for (size_t i = 0; i < arraysize(test_configs); ++i) {
10256 HttpAuthHandlerMock::Factory* auth_factory(
10257 new HttpAuthHandlerMock::Factory());
10258 session_deps_.http_auth_handler_factory.reset(auth_factory);
10259 const TestConfig& test_config = test_configs[i];
10261 // Set up authentication handlers as necessary.
10262 if (test_config.proxy_auth_timing != AUTH_NONE) {
10263 for (int n = 0; n < 2; n++) {
10264 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10265 std::string auth_challenge = "Mock realm=proxy";
10266 GURL origin(test_config.proxy_url);
10267 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10268 auth_challenge.end());
10269 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
10270 origin, BoundNetLog());
10271 auth_handler->SetGenerateExpectation(
10272 test_config.proxy_auth_timing == AUTH_ASYNC,
10273 test_config.proxy_auth_rv);
10274 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10277 if (test_config.server_auth_timing != AUTH_NONE) {
10278 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10279 std::string auth_challenge = "Mock realm=server";
10280 GURL origin(test_config.server_url);
10281 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10282 auth_challenge.end());
10283 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10284 origin, BoundNetLog());
10285 auth_handler->SetGenerateExpectation(
10286 test_config.server_auth_timing == AUTH_ASYNC,
10287 test_config.server_auth_rv);
10288 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10290 if (test_config.proxy_url) {
10291 session_deps_.proxy_service.reset(
10292 ProxyService::CreateFixed(test_config.proxy_url));
10293 } else {
10294 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10297 HttpRequestInfo request;
10298 request.method = "GET";
10299 request.url = GURL(test_config.server_url);
10300 request.load_flags = 0;
10302 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10303 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10305 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
10307 std::vector<std::vector<MockRead>> mock_reads(1);
10308 std::vector<std::vector<MockWrite>> mock_writes(1);
10309 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10310 const TestRound& read_write_round = test_config.rounds[round];
10312 // Set up expected reads and writes.
10313 mock_reads.back().push_back(read_write_round.read);
10314 mock_writes.back().push_back(read_write_round.write);
10316 // kProxyChallenge uses Proxy-Connection: close which means that the
10317 // socket is closed and a new one will be created for the next request.
10318 if (read_write_round.read.data == kProxyChallenge.data &&
10319 read_write_round.write.data != kConnect.data) {
10320 mock_reads.push_back(std::vector<MockRead>());
10321 mock_writes.push_back(std::vector<MockWrite>());
10324 if (read_write_round.extra_read) {
10325 mock_reads.back().push_back(*read_write_round.extra_read);
10327 if (read_write_round.extra_write) {
10328 mock_writes.back().push_back(*read_write_round.extra_write);
10331 // Add an SSL sequence if necessary.
10332 if (round >= test_config.first_ssl_round)
10333 session_deps_.socket_factory->AddSSLSocketDataProvider(
10334 &ssl_socket_data_provider);
10337 ScopedVector<StaticSocketDataProvider> data_providers;
10338 for (size_t i = 0; i < mock_reads.size(); ++i) {
10339 data_providers.push_back(new StaticSocketDataProvider(
10340 vector_as_array(&mock_reads[i]), mock_reads[i].size(),
10341 vector_as_array(&mock_writes[i]), mock_writes[i].size()));
10342 session_deps_.socket_factory->AddSocketDataProvider(
10343 data_providers.back());
10346 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10347 const TestRound& read_write_round = test_config.rounds[round];
10348 // Start or restart the transaction.
10349 TestCompletionCallback callback;
10350 int rv;
10351 if (round == 0) {
10352 rv = trans.Start(&request, callback.callback(), BoundNetLog());
10353 } else {
10354 rv = trans.RestartWithAuth(
10355 AuthCredentials(kFoo, kBar), callback.callback());
10357 if (rv == ERR_IO_PENDING)
10358 rv = callback.WaitForResult();
10360 // Compare results with expected data.
10361 EXPECT_EQ(read_write_round.expected_rv, rv);
10362 const HttpResponseInfo* response = trans.GetResponseInfo();
10363 if (read_write_round.expected_rv != OK) {
10364 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
10365 continue;
10367 if (round + 1 < test_config.num_auth_rounds) {
10368 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10369 } else {
10370 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10376 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
10377 // Do multi-round authentication and make sure it works correctly.
10378 HttpAuthHandlerMock::Factory* auth_factory(
10379 new HttpAuthHandlerMock::Factory());
10380 session_deps_.http_auth_handler_factory.reset(auth_factory);
10381 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10382 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
10383 session_deps_.host_resolver->set_synchronous_mode(true);
10385 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10386 auth_handler->set_connection_based(true);
10387 std::string auth_challenge = "Mock realm=server";
10388 GURL origin("http://www.example.com");
10389 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10390 auth_challenge.end());
10391 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10392 origin, BoundNetLog());
10393 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10395 int rv = OK;
10396 const HttpResponseInfo* response = NULL;
10397 HttpRequestInfo request;
10398 request.method = "GET";
10399 request.url = origin;
10400 request.load_flags = 0;
10402 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10404 // Use a TCP Socket Pool with only one connection per group. This is used
10405 // to validate that the TCP socket is not released to the pool between
10406 // each round of multi-round authentication.
10407 HttpNetworkSessionPeer session_peer(session);
10408 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
10409 50, // Max sockets for pool
10410 1, // Max sockets per group
10411 session_deps_.host_resolver.get(),
10412 session_deps_.socket_factory.get(),
10413 session_deps_.net_log);
10414 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
10415 new MockClientSocketPoolManager);
10416 mock_pool_manager->SetTransportSocketPool(transport_pool);
10417 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
10419 scoped_ptr<HttpTransaction> trans(
10420 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10421 TestCompletionCallback callback;
10423 const MockWrite kGet(
10424 "GET / HTTP/1.1\r\n"
10425 "Host: www.example.com\r\n"
10426 "Connection: keep-alive\r\n\r\n");
10427 const MockWrite kGetAuth(
10428 "GET / HTTP/1.1\r\n"
10429 "Host: www.example.com\r\n"
10430 "Connection: keep-alive\r\n"
10431 "Authorization: auth_token\r\n\r\n");
10433 const MockRead kServerChallenge(
10434 "HTTP/1.1 401 Unauthorized\r\n"
10435 "WWW-Authenticate: Mock realm=server\r\n"
10436 "Content-Type: text/html; charset=iso-8859-1\r\n"
10437 "Content-Length: 14\r\n\r\n"
10438 "Unauthorized\r\n");
10439 const MockRead kSuccess(
10440 "HTTP/1.1 200 OK\r\n"
10441 "Content-Type: text/html; charset=iso-8859-1\r\n"
10442 "Content-Length: 3\r\n\r\n"
10443 "Yes");
10445 MockWrite writes[] = {
10446 // First round
10447 kGet,
10448 // Second round
10449 kGetAuth,
10450 // Third round
10451 kGetAuth,
10452 // Fourth round
10453 kGetAuth,
10454 // Competing request
10455 kGet,
10457 MockRead reads[] = {
10458 // First round
10459 kServerChallenge,
10460 // Second round
10461 kServerChallenge,
10462 // Third round
10463 kServerChallenge,
10464 // Fourth round
10465 kSuccess,
10466 // Competing response
10467 kSuccess,
10469 StaticSocketDataProvider data_provider(reads, arraysize(reads),
10470 writes, arraysize(writes));
10471 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10473 const char kSocketGroup[] = "www.example.com:80";
10475 // First round of authentication.
10476 auth_handler->SetGenerateExpectation(false, OK);
10477 rv = trans->Start(&request, callback.callback(), BoundNetLog());
10478 if (rv == ERR_IO_PENDING)
10479 rv = callback.WaitForResult();
10480 EXPECT_EQ(OK, rv);
10481 response = trans->GetResponseInfo();
10482 ASSERT_TRUE(response != NULL);
10483 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10484 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10486 // In between rounds, another request comes in for the same domain.
10487 // It should not be able to grab the TCP socket that trans has already
10488 // claimed.
10489 scoped_ptr<HttpTransaction> trans_compete(
10490 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10491 TestCompletionCallback callback_compete;
10492 rv = trans_compete->Start(
10493 &request, callback_compete.callback(), BoundNetLog());
10494 EXPECT_EQ(ERR_IO_PENDING, rv);
10495 // callback_compete.WaitForResult at this point would stall forever,
10496 // since the HttpNetworkTransaction does not release the request back to
10497 // the pool until after authentication completes.
10499 // Second round of authentication.
10500 auth_handler->SetGenerateExpectation(false, OK);
10501 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
10502 if (rv == ERR_IO_PENDING)
10503 rv = callback.WaitForResult();
10504 EXPECT_EQ(OK, rv);
10505 response = trans->GetResponseInfo();
10506 ASSERT_TRUE(response != NULL);
10507 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10508 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10510 // Third round of authentication.
10511 auth_handler->SetGenerateExpectation(false, OK);
10512 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10513 if (rv == ERR_IO_PENDING)
10514 rv = callback.WaitForResult();
10515 EXPECT_EQ(OK, rv);
10516 response = trans->GetResponseInfo();
10517 ASSERT_TRUE(response != NULL);
10518 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10519 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10521 // Fourth round of authentication, which completes successfully.
10522 auth_handler->SetGenerateExpectation(false, OK);
10523 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10524 if (rv == ERR_IO_PENDING)
10525 rv = callback.WaitForResult();
10526 EXPECT_EQ(OK, rv);
10527 response = trans->GetResponseInfo();
10528 ASSERT_TRUE(response != NULL);
10529 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10530 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10532 // Read the body since the fourth round was successful. This will also
10533 // release the socket back to the pool.
10534 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
10535 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10536 if (rv == ERR_IO_PENDING)
10537 rv = callback.WaitForResult();
10538 EXPECT_EQ(3, rv);
10539 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10540 EXPECT_EQ(0, rv);
10541 // There are still 0 idle sockets, since the trans_compete transaction
10542 // will be handed it immediately after trans releases it to the group.
10543 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10545 // The competing request can now finish. Wait for the headers and then
10546 // read the body.
10547 rv = callback_compete.WaitForResult();
10548 EXPECT_EQ(OK, rv);
10549 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10550 if (rv == ERR_IO_PENDING)
10551 rv = callback.WaitForResult();
10552 EXPECT_EQ(3, rv);
10553 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10554 EXPECT_EQ(0, rv);
10556 // Finally, the socket is released to the group.
10557 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10560 // This tests the case that a request is issued via http instead of spdy after
10561 // npn is negotiated.
10562 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
10563 session_deps_.use_alternative_services = true;
10564 NextProtoVector next_protos;
10565 next_protos.push_back(kProtoHTTP11);
10566 session_deps_.next_protos = next_protos;
10568 HttpRequestInfo request;
10569 request.method = "GET";
10570 request.url = GURL("https://www.example.org/");
10571 request.load_flags = 0;
10573 MockWrite data_writes[] = {
10574 MockWrite(
10575 "GET / HTTP/1.1\r\n"
10576 "Host: www.example.org\r\n"
10577 "Connection: keep-alive\r\n\r\n"),
10580 std::string alternate_protocol_http_header =
10581 GetAlternateProtocolHttpHeader();
10583 MockRead data_reads[] = {
10584 MockRead("HTTP/1.1 200 OK\r\n"),
10585 MockRead(alternate_protocol_http_header.c_str()),
10586 MockRead("\r\n"),
10587 MockRead("hello world"),
10588 MockRead(SYNCHRONOUS, OK),
10591 SSLSocketDataProvider ssl(ASYNC, OK);
10592 ssl.SetNextProto(kProtoHTTP11);
10594 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10596 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
10597 data_writes, arraysize(data_writes));
10598 session_deps_.socket_factory->AddSocketDataProvider(&data);
10600 TestCompletionCallback callback;
10602 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10603 scoped_ptr<HttpTransaction> trans(
10604 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10606 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10608 EXPECT_EQ(ERR_IO_PENDING, rv);
10609 EXPECT_EQ(OK, callback.WaitForResult());
10611 const HttpResponseInfo* response = trans->GetResponseInfo();
10612 ASSERT_TRUE(response != NULL);
10613 ASSERT_TRUE(response->headers.get() != NULL);
10614 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10616 std::string response_data;
10617 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10618 EXPECT_EQ("hello world", response_data);
10620 EXPECT_FALSE(response->was_fetched_via_spdy);
10621 EXPECT_TRUE(response->was_npn_negotiated);
10624 // Simulate the SSL handshake completing with an NPN negotiation followed by an
10625 // immediate server closing of the socket.
10626 // Regression test for https://crbug.com/46369.
10627 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
10628 session_deps_.use_alternative_services = true;
10629 session_deps_.next_protos = SpdyNextProtos();
10631 HttpRequestInfo request;
10632 request.method = "GET";
10633 request.url = GURL("https://www.example.org/");
10634 request.load_flags = 0;
10636 SSLSocketDataProvider ssl(ASYNC, OK);
10637 ssl.SetNextProto(GetParam());
10638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10640 scoped_ptr<SpdyFrame> req(
10641 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10642 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
10644 MockRead spdy_reads[] = {
10645 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10648 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10649 arraysize(spdy_writes));
10650 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10652 TestCompletionCallback callback;
10654 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10655 scoped_ptr<HttpTransaction> trans(
10656 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10658 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10659 EXPECT_EQ(ERR_IO_PENDING, rv);
10660 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10663 // A subclass of HttpAuthHandlerMock that records the request URL when
10664 // it gets it. This is needed since the auth handler may get destroyed
10665 // before we get a chance to query it.
10666 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10667 public:
10668 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10670 ~UrlRecordingHttpAuthHandlerMock() override {}
10672 protected:
10673 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10674 const HttpRequestInfo* request,
10675 const CompletionCallback& callback,
10676 std::string* auth_token) override {
10677 *url_ = request->url;
10678 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10679 credentials, request, callback, auth_token);
10682 private:
10683 GURL* url_;
10686 // This test ensures that the URL passed into the proxy is upgraded to https
10687 // when doing an Alternate Protocol upgrade.
10688 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10689 session_deps_.use_alternative_services = true;
10690 session_deps_.next_protos = SpdyNextProtos();
10692 session_deps_.proxy_service.reset(
10693 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10694 TestNetLog net_log;
10695 session_deps_.net_log = &net_log;
10696 GURL request_url;
10698 HttpAuthHandlerMock::Factory* auth_factory =
10699 new HttpAuthHandlerMock::Factory();
10700 UrlRecordingHttpAuthHandlerMock* auth_handler =
10701 new UrlRecordingHttpAuthHandlerMock(&request_url);
10702 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10703 auth_factory->set_do_init_from_challenge(true);
10704 session_deps_.http_auth_handler_factory.reset(auth_factory);
10707 HttpRequestInfo request;
10708 request.method = "GET";
10709 request.url = GURL("http://www.example.org");
10710 request.load_flags = 0;
10712 // First round goes unauthenticated through the proxy.
10713 MockWrite data_writes_1[] = {
10714 MockWrite(
10715 "GET http://www.example.org/ HTTP/1.1\r\n"
10716 "Host: www.example.org\r\n"
10717 "Proxy-Connection: keep-alive\r\n"
10718 "\r\n"),
10720 MockRead data_reads_1[] = {
10721 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10722 MockRead("HTTP/1.1 200 OK\r\n"),
10723 MockRead("Alternate-Protocol: 443:"),
10724 MockRead(GetAlternateProtocolFromParam()),
10725 MockRead("\r\n"),
10726 MockRead("Proxy-Connection: close\r\n"),
10727 MockRead("\r\n"),
10729 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10730 data_writes_1, arraysize(data_writes_1));
10732 // Second round tries to tunnel to www.example.org due to the
10733 // Alternate-Protocol announcement in the first round. It fails due
10734 // to a proxy authentication challenge.
10735 // After the failure, a tunnel is established to www.example.org using
10736 // Proxy-Authorization headers. There is then a SPDY request round.
10738 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10739 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10740 // does a Disconnect and Connect on the same socket, rather than trying
10741 // to obtain a new one.
10743 // NOTE: Originally, the proxy response to the second CONNECT request
10744 // simply returned another 407 so the unit test could skip the SSL connection
10745 // establishment and SPDY framing issues. Alas, the
10746 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10747 // complicated to set up expectations for than the SPDY session.
10749 scoped_ptr<SpdyFrame> req(
10750 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10751 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10752 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10754 MockWrite data_writes_2[] = {
10755 // First connection attempt without Proxy-Authorization.
10756 MockWrite(ASYNC, 0,
10757 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10758 "Host: www.example.org\r\n"
10759 "Proxy-Connection: keep-alive\r\n"
10760 "\r\n"),
10762 // Second connection attempt with Proxy-Authorization.
10763 MockWrite(ASYNC, 2,
10764 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10765 "Host: www.example.org\r\n"
10766 "Proxy-Connection: keep-alive\r\n"
10767 "Proxy-Authorization: auth_token\r\n"
10768 "\r\n"),
10770 // SPDY request
10771 CreateMockWrite(*req, 4),
10773 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10774 "Proxy-Authenticate: Mock\r\n"
10775 "Proxy-Connection: close\r\n"
10776 "\r\n");
10777 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10778 MockRead data_reads_2[] = {
10779 // First connection attempt fails
10780 MockRead(ASYNC, kRejectConnectResponse,
10781 arraysize(kRejectConnectResponse) - 1, 1),
10783 // Second connection attempt passes
10784 MockRead(ASYNC, kAcceptConnectResponse,
10785 arraysize(kAcceptConnectResponse) - 1, 3),
10787 // SPDY response
10788 CreateMockRead(*resp.get(), 5),
10789 CreateMockRead(*data.get(), 6),
10790 MockRead(ASYNC, 0, 0, 7),
10792 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
10793 data_writes_2, arraysize(data_writes_2));
10795 SSLSocketDataProvider ssl(ASYNC, OK);
10796 ssl.SetNextProto(GetParam());
10797 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10798 ASSERT_TRUE(ssl.cert.get());
10800 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10801 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10802 NULL, 0, NULL, 0);
10803 hanging_non_alternate_protocol_socket.set_connect_data(
10804 never_finishing_connect);
10806 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10807 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10808 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10809 session_deps_.socket_factory->AddSocketDataProvider(
10810 &hanging_non_alternate_protocol_socket);
10811 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10813 // First round should work and provide the Alternate-Protocol state.
10814 TestCompletionCallback callback_1;
10815 scoped_ptr<HttpTransaction> trans_1(
10816 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10817 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10818 EXPECT_EQ(ERR_IO_PENDING, rv);
10819 EXPECT_EQ(OK, callback_1.WaitForResult());
10821 // Second round should attempt a tunnel connect and get an auth challenge.
10822 TestCompletionCallback callback_2;
10823 scoped_ptr<HttpTransaction> trans_2(
10824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10825 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10826 EXPECT_EQ(ERR_IO_PENDING, rv);
10827 EXPECT_EQ(OK, callback_2.WaitForResult());
10828 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10829 ASSERT_TRUE(response != NULL);
10830 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10832 // Restart with auth. Tunnel should work and response received.
10833 TestCompletionCallback callback_3;
10834 rv = trans_2->RestartWithAuth(
10835 AuthCredentials(kFoo, kBar), callback_3.callback());
10836 EXPECT_EQ(ERR_IO_PENDING, rv);
10837 EXPECT_EQ(OK, callback_3.WaitForResult());
10839 // After all that work, these two lines (or actually, just the scheme) are
10840 // what this test is all about. Make sure it happens correctly.
10841 EXPECT_EQ("https", request_url.scheme());
10842 EXPECT_EQ("www.example.org", request_url.host());
10844 LoadTimingInfo load_timing_info;
10845 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10846 TestLoadTimingNotReusedWithPac(load_timing_info,
10847 CONNECT_TIMING_HAS_SSL_TIMES);
10850 // Test that if we cancel the transaction as the connection is completing, that
10851 // everything tears down correctly.
10852 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10853 // Setup everything about the connection to complete synchronously, so that
10854 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10855 // for is the callback from the HttpStreamRequest.
10856 // Then cancel the transaction.
10857 // Verify that we don't crash.
10858 MockConnect mock_connect(SYNCHRONOUS, OK);
10859 MockRead data_reads[] = {
10860 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10861 MockRead(SYNCHRONOUS, "hello world"),
10862 MockRead(SYNCHRONOUS, OK),
10865 HttpRequestInfo request;
10866 request.method = "GET";
10867 request.url = GURL("http://www.example.org/");
10868 request.load_flags = 0;
10870 session_deps_.host_resolver->set_synchronous_mode(true);
10871 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10872 scoped_ptr<HttpTransaction> trans(
10873 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10875 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10876 data.set_connect_data(mock_connect);
10877 session_deps_.socket_factory->AddSocketDataProvider(&data);
10879 TestCompletionCallback callback;
10881 BoundTestNetLog log;
10882 int rv = trans->Start(&request, callback.callback(), log.bound());
10883 EXPECT_EQ(ERR_IO_PENDING, rv);
10884 trans.reset(); // Cancel the transaction here.
10886 base::MessageLoop::current()->RunUntilIdle();
10889 // Test that if a transaction is cancelled after receiving the headers, the
10890 // stream is drained properly and added back to the socket pool. The main
10891 // purpose of this test is to make sure that an HttpStreamParser can be read
10892 // from after the HttpNetworkTransaction and the objects it owns have been
10893 // deleted.
10894 // See http://crbug.com/368418
10895 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10896 MockRead data_reads[] = {
10897 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10898 MockRead(ASYNC, "Content-Length: 2\r\n"),
10899 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10900 MockRead(ASYNC, "1"),
10901 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10902 // HttpNetworkTransaction has been deleted.
10903 MockRead(ASYNC, "2"),
10904 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10906 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10907 session_deps_.socket_factory->AddSocketDataProvider(&data);
10909 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10912 HttpRequestInfo request;
10913 request.method = "GET";
10914 request.url = GURL("http://www.example.org/");
10915 request.load_flags = 0;
10917 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10918 TestCompletionCallback callback;
10920 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10921 EXPECT_EQ(ERR_IO_PENDING, rv);
10922 callback.WaitForResult();
10924 const HttpResponseInfo* response = trans.GetResponseInfo();
10925 ASSERT_TRUE(response != NULL);
10926 EXPECT_TRUE(response->headers.get() != NULL);
10927 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10929 // The transaction and HttpRequestInfo are deleted.
10932 // Let the HttpResponseBodyDrainer drain the socket.
10933 base::MessageLoop::current()->RunUntilIdle();
10935 // Socket should now be idle, waiting to be reused.
10936 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
10939 // Test a basic GET request through a proxy.
10940 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10941 session_deps_.proxy_service.reset(
10942 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10943 BoundTestNetLog log;
10944 session_deps_.net_log = log.bound().net_log();
10945 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10947 HttpRequestInfo request;
10948 request.method = "GET";
10949 request.url = GURL("http://www.example.org/");
10951 MockWrite data_writes1[] = {
10952 MockWrite(
10953 "GET http://www.example.org/ HTTP/1.1\r\n"
10954 "Host: www.example.org\r\n"
10955 "Proxy-Connection: keep-alive\r\n\r\n"),
10958 MockRead data_reads1[] = {
10959 MockRead("HTTP/1.1 200 OK\r\n"),
10960 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10961 MockRead("Content-Length: 100\r\n\r\n"),
10962 MockRead(SYNCHRONOUS, OK),
10965 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10966 data_writes1, arraysize(data_writes1));
10967 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10969 TestCompletionCallback callback1;
10971 scoped_ptr<HttpTransaction> trans(
10972 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10973 BeforeProxyHeadersSentHandler proxy_headers_handler;
10974 trans->SetBeforeProxyHeadersSentCallback(
10975 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
10976 base::Unretained(&proxy_headers_handler)));
10978 int rv = trans->Start(&request, callback1.callback(), log.bound());
10979 EXPECT_EQ(ERR_IO_PENDING, rv);
10981 rv = callback1.WaitForResult();
10982 EXPECT_EQ(OK, rv);
10984 const HttpResponseInfo* response = trans->GetResponseInfo();
10985 ASSERT_TRUE(response != NULL);
10987 EXPECT_TRUE(response->headers->IsKeepAlive());
10988 EXPECT_EQ(200, response->headers->response_code());
10989 EXPECT_EQ(100, response->headers->GetContentLength());
10990 EXPECT_TRUE(response->was_fetched_via_proxy);
10991 EXPECT_TRUE(
10992 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10993 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
10994 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
10995 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10997 LoadTimingInfo load_timing_info;
10998 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10999 TestLoadTimingNotReusedWithPac(load_timing_info,
11000 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11003 // Test a basic HTTPS GET request through a proxy.
11004 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
11005 session_deps_.proxy_service.reset(
11006 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11007 BoundTestNetLog log;
11008 session_deps_.net_log = log.bound().net_log();
11009 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11011 HttpRequestInfo request;
11012 request.method = "GET";
11013 request.url = GURL("https://www.example.org/");
11015 // Since we have proxy, should try to establish tunnel.
11016 MockWrite data_writes1[] = {
11017 MockWrite(
11018 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11019 "Host: www.example.org\r\n"
11020 "Proxy-Connection: keep-alive\r\n\r\n"),
11022 MockWrite(
11023 "GET / HTTP/1.1\r\n"
11024 "Host: www.example.org\r\n"
11025 "Connection: keep-alive\r\n\r\n"),
11028 MockRead data_reads1[] = {
11029 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11031 MockRead("HTTP/1.1 200 OK\r\n"),
11032 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11033 MockRead("Content-Length: 100\r\n\r\n"),
11034 MockRead(SYNCHRONOUS, OK),
11037 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11038 data_writes1, arraysize(data_writes1));
11039 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11040 SSLSocketDataProvider ssl(ASYNC, OK);
11041 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11043 TestCompletionCallback callback1;
11045 scoped_ptr<HttpTransaction> trans(
11046 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11048 int rv = trans->Start(&request, callback1.callback(), log.bound());
11049 EXPECT_EQ(ERR_IO_PENDING, rv);
11051 rv = callback1.WaitForResult();
11052 EXPECT_EQ(OK, rv);
11053 TestNetLogEntry::List entries;
11054 log.GetEntries(&entries);
11055 size_t pos = ExpectLogContainsSomewhere(
11056 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11057 NetLog::PHASE_NONE);
11058 ExpectLogContainsSomewhere(
11059 entries, pos,
11060 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11061 NetLog::PHASE_NONE);
11063 const HttpResponseInfo* response = trans->GetResponseInfo();
11064 ASSERT_TRUE(response != NULL);
11066 EXPECT_TRUE(response->headers->IsKeepAlive());
11067 EXPECT_EQ(200, response->headers->response_code());
11068 EXPECT_EQ(100, response->headers->GetContentLength());
11069 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11070 EXPECT_TRUE(response->was_fetched_via_proxy);
11071 EXPECT_TRUE(
11072 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
11074 LoadTimingInfo load_timing_info;
11075 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11076 TestLoadTimingNotReusedWithPac(load_timing_info,
11077 CONNECT_TIMING_HAS_SSL_TIMES);
11080 // Test a basic HTTPS GET request through a proxy, but the server hangs up
11081 // while establishing the tunnel.
11082 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
11083 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
11084 BoundTestNetLog log;
11085 session_deps_.net_log = log.bound().net_log();
11086 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11088 HttpRequestInfo request;
11089 request.method = "GET";
11090 request.url = GURL("https://www.example.org/");
11092 // Since we have proxy, should try to establish tunnel.
11093 MockWrite data_writes1[] = {
11094 MockWrite(
11095 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11096 "Host: www.example.org\r\n"
11097 "Proxy-Connection: keep-alive\r\n\r\n"),
11099 MockWrite(
11100 "GET / HTTP/1.1\r\n"
11101 "Host: www.example.org\r\n"
11102 "Connection: keep-alive\r\n\r\n"),
11105 MockRead data_reads1[] = {
11106 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
11107 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11108 MockRead(ASYNC, 0, 0), // EOF
11111 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11112 data_writes1, arraysize(data_writes1));
11113 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11114 SSLSocketDataProvider ssl(ASYNC, OK);
11115 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11117 TestCompletionCallback callback1;
11119 scoped_ptr<HttpTransaction> trans(
11120 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11122 int rv = trans->Start(&request, callback1.callback(), log.bound());
11123 EXPECT_EQ(ERR_IO_PENDING, rv);
11125 rv = callback1.WaitForResult();
11126 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
11127 TestNetLogEntry::List entries;
11128 log.GetEntries(&entries);
11129 size_t pos = ExpectLogContainsSomewhere(
11130 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11131 NetLog::PHASE_NONE);
11132 ExpectLogContainsSomewhere(
11133 entries, pos,
11134 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11135 NetLog::PHASE_NONE);
11138 // Test for crbug.com/55424.
11139 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
11140 scoped_ptr<SpdyFrame> req(
11141 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11142 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
11144 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11145 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
11146 MockRead spdy_reads[] = {
11147 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
11150 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11151 arraysize(spdy_writes));
11152 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11154 SSLSocketDataProvider ssl(ASYNC, OK);
11155 ssl.SetNextProto(GetParam());
11156 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11158 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11160 // Set up an initial SpdySession in the pool to reuse.
11161 HostPortPair host_port_pair("www.example.org", 443);
11162 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
11163 PRIVACY_MODE_DISABLED);
11164 base::WeakPtr<SpdySession> spdy_session =
11165 CreateInsecureSpdySession(session, key, BoundNetLog());
11167 HttpRequestInfo request;
11168 request.method = "GET";
11169 request.url = GURL("https://www.example.org/");
11170 request.load_flags = 0;
11172 // This is the important line that marks this as a preconnect.
11173 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
11175 scoped_ptr<HttpTransaction> trans(
11176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11178 TestCompletionCallback callback;
11179 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11180 EXPECT_EQ(ERR_IO_PENDING, rv);
11181 EXPECT_EQ(OK, callback.WaitForResult());
11184 // Given a net error, cause that error to be returned from the first Write()
11185 // call and verify that the HttpTransaction fails with that error.
11186 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11187 int error, IoMode mode) {
11188 HttpRequestInfo request_info;
11189 request_info.url = GURL("https://www.example.com/");
11190 request_info.method = "GET";
11191 request_info.load_flags = LOAD_NORMAL;
11193 SSLSocketDataProvider ssl_data(mode, OK);
11194 MockWrite data_writes[] = {
11195 MockWrite(mode, error),
11197 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
11198 session_deps_.socket_factory->AddSocketDataProvider(&data);
11199 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
11201 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11202 scoped_ptr<HttpTransaction> trans(
11203 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11205 TestCompletionCallback callback;
11206 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11207 if (rv == ERR_IO_PENDING)
11208 rv = callback.WaitForResult();
11209 ASSERT_EQ(error, rv);
11212 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
11213 // Just check a grab bag of cert errors.
11214 static const int kErrors[] = {
11215 ERR_CERT_COMMON_NAME_INVALID,
11216 ERR_CERT_AUTHORITY_INVALID,
11217 ERR_CERT_DATE_INVALID,
11219 for (size_t i = 0; i < arraysize(kErrors); i++) {
11220 CheckErrorIsPassedBack(kErrors[i], ASYNC);
11221 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
11225 // Ensure that a client certificate is removed from the SSL client auth
11226 // cache when:
11227 // 1) No proxy is involved.
11228 // 2) TLS False Start is disabled.
11229 // 3) The initial TLS handshake requests a client certificate.
11230 // 4) The client supplies an invalid/unacceptable certificate.
11231 TEST_P(HttpNetworkTransactionTest,
11232 ClientAuthCertCache_Direct_NoFalseStart) {
11233 HttpRequestInfo request_info;
11234 request_info.url = GURL("https://www.example.com/");
11235 request_info.method = "GET";
11236 request_info.load_flags = LOAD_NORMAL;
11238 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11239 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11241 // [ssl_]data1 contains the data for the first SSL handshake. When a
11242 // CertificateRequest is received for the first time, the handshake will
11243 // be aborted to allow the caller to provide a certificate.
11244 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11245 ssl_data1.cert_request_info = cert_request.get();
11246 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11247 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11248 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11250 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11251 // False Start is not being used, the result of the SSL handshake will be
11252 // returned as part of the SSLClientSocket::Connect() call. This test
11253 // matches the result of a server sending a handshake_failure alert,
11254 // rather than a Finished message, because it requires a client
11255 // certificate and none was supplied.
11256 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11257 ssl_data2.cert_request_info = cert_request.get();
11258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11259 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11260 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11262 // [ssl_]data3 contains the data for the third SSL handshake. When a
11263 // connection to a server fails during an SSL handshake,
11264 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11265 // connection was attempted with TLSv1.2. This is transparent to the caller
11266 // of the HttpNetworkTransaction. Because this test failure is due to
11267 // requiring a client certificate, this fallback handshake should also
11268 // fail.
11269 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11270 ssl_data3.cert_request_info = cert_request.get();
11271 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11272 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11273 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11275 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11276 // connection to a server fails during an SSL handshake,
11277 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11278 // connection was attempted with TLSv1.1. This is transparent to the caller
11279 // of the HttpNetworkTransaction. Because this test failure is due to
11280 // requiring a client certificate, this fallback handshake should also
11281 // fail.
11282 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11283 ssl_data4.cert_request_info = cert_request.get();
11284 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11285 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
11286 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11288 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11289 scoped_ptr<HttpTransaction> trans(
11290 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11292 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11293 TestCompletionCallback callback;
11294 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11295 ASSERT_EQ(ERR_IO_PENDING, rv);
11297 // Complete the SSL handshake, which should abort due to requiring a
11298 // client certificate.
11299 rv = callback.WaitForResult();
11300 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11302 // Indicate that no certificate should be supplied. From the perspective
11303 // of SSLClientCertCache, NULL is just as meaningful as a real
11304 // certificate, so this is the same as supply a
11305 // legitimate-but-unacceptable certificate.
11306 rv = trans->RestartWithCertificate(NULL, callback.callback());
11307 ASSERT_EQ(ERR_IO_PENDING, rv);
11309 // Ensure the certificate was added to the client auth cache before
11310 // allowing the connection to continue restarting.
11311 scoped_refptr<X509Certificate> client_cert;
11312 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11313 HostPortPair("www.example.com", 443), &client_cert));
11314 ASSERT_EQ(NULL, client_cert.get());
11316 // Restart the handshake. This will consume ssl_data2, which fails, and
11317 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11318 // The result code is checked against what ssl_data4 should return.
11319 rv = callback.WaitForResult();
11320 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11322 // Ensure that the client certificate is removed from the cache on a
11323 // handshake failure.
11324 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11325 HostPortPair("www.example.com", 443), &client_cert));
11328 // Ensure that a client certificate is removed from the SSL client auth
11329 // cache when:
11330 // 1) No proxy is involved.
11331 // 2) TLS False Start is enabled.
11332 // 3) The initial TLS handshake requests a client certificate.
11333 // 4) The client supplies an invalid/unacceptable certificate.
11334 TEST_P(HttpNetworkTransactionTest,
11335 ClientAuthCertCache_Direct_FalseStart) {
11336 HttpRequestInfo request_info;
11337 request_info.url = GURL("https://www.example.com/");
11338 request_info.method = "GET";
11339 request_info.load_flags = LOAD_NORMAL;
11341 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11342 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11344 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11345 // return successfully after reading up to the peer's Certificate message.
11346 // This is to allow the caller to call SSLClientSocket::Write(), which can
11347 // enqueue application data to be sent in the same packet as the
11348 // ChangeCipherSpec and Finished messages.
11349 // The actual handshake will be finished when SSLClientSocket::Read() is
11350 // called, which expects to process the peer's ChangeCipherSpec and
11351 // Finished messages. If there was an error negotiating with the peer,
11352 // such as due to the peer requiring a client certificate when none was
11353 // supplied, the alert sent by the peer won't be processed until Read() is
11354 // called.
11356 // Like the non-False Start case, when a client certificate is requested by
11357 // the peer, the handshake is aborted during the Connect() call.
11358 // [ssl_]data1 represents the initial SSL handshake with the peer.
11359 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11360 ssl_data1.cert_request_info = cert_request.get();
11361 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11362 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11363 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11365 // When a client certificate is supplied, Connect() will not be aborted
11366 // when the peer requests the certificate. Instead, the handshake will
11367 // artificially succeed, allowing the caller to write the HTTP request to
11368 // the socket. The handshake messages are not processed until Read() is
11369 // called, which then detects that the handshake was aborted, due to the
11370 // peer sending a handshake_failure because it requires a client
11371 // certificate.
11372 SSLSocketDataProvider ssl_data2(ASYNC, OK);
11373 ssl_data2.cert_request_info = cert_request.get();
11374 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11375 MockRead data2_reads[] = {
11376 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
11378 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
11379 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11381 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11382 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11383 // TLSv1. It has the same behaviour as [ssl_]data2.
11384 SSLSocketDataProvider ssl_data3(ASYNC, OK);
11385 ssl_data3.cert_request_info = cert_request.get();
11386 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11387 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
11388 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11390 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11391 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11392 SSLSocketDataProvider ssl_data4(ASYNC, OK);
11393 ssl_data4.cert_request_info = cert_request.get();
11394 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11395 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
11396 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11398 // Need one more if TLSv1.2 is enabled.
11399 SSLSocketDataProvider ssl_data5(ASYNC, OK);
11400 ssl_data5.cert_request_info = cert_request.get();
11401 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11402 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
11403 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11406 scoped_ptr<HttpTransaction> trans(
11407 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11409 // Begin the initial SSL handshake.
11410 TestCompletionCallback callback;
11411 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11412 ASSERT_EQ(ERR_IO_PENDING, rv);
11414 // Complete the SSL handshake, which should abort due to requiring a
11415 // client certificate.
11416 rv = callback.WaitForResult();
11417 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11419 // Indicate that no certificate should be supplied. From the perspective
11420 // of SSLClientCertCache, NULL is just as meaningful as a real
11421 // certificate, so this is the same as supply a
11422 // legitimate-but-unacceptable certificate.
11423 rv = trans->RestartWithCertificate(NULL, callback.callback());
11424 ASSERT_EQ(ERR_IO_PENDING, rv);
11426 // Ensure the certificate was added to the client auth cache before
11427 // allowing the connection to continue restarting.
11428 scoped_refptr<X509Certificate> client_cert;
11429 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11430 HostPortPair("www.example.com", 443), &client_cert));
11431 ASSERT_EQ(NULL, client_cert.get());
11433 // Restart the handshake. This will consume ssl_data2, which fails, and
11434 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11435 // The result code is checked against what ssl_data4 should return.
11436 rv = callback.WaitForResult();
11437 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11439 // Ensure that the client certificate is removed from the cache on a
11440 // handshake failure.
11441 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11442 HostPortPair("www.example.com", 443), &client_cert));
11445 // Ensure that a client certificate is removed from the SSL client auth
11446 // cache when:
11447 // 1) An HTTPS proxy is involved.
11448 // 3) The HTTPS proxy requests a client certificate.
11449 // 4) The client supplies an invalid/unacceptable certificate for the
11450 // proxy.
11451 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11452 // then for connecting to an HTTP endpoint.
11453 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
11454 session_deps_.proxy_service.reset(
11455 ProxyService::CreateFixed("https://proxy:70"));
11456 BoundTestNetLog log;
11457 session_deps_.net_log = log.bound().net_log();
11459 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11460 cert_request->host_and_port = HostPortPair("proxy", 70);
11462 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11463 // [ssl_]data[1-3]. Rather than represending the endpoint
11464 // (www.example.com:443), they represent failures with the HTTPS proxy
11465 // (proxy:70).
11466 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11467 ssl_data1.cert_request_info = cert_request.get();
11468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11469 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11470 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11472 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11473 ssl_data2.cert_request_info = cert_request.get();
11474 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11475 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11476 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11478 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11479 #if 0
11480 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11481 ssl_data3.cert_request_info = cert_request.get();
11482 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11483 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11484 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11485 #endif
11487 HttpRequestInfo requests[2];
11488 requests[0].url = GURL("https://www.example.com/");
11489 requests[0].method = "GET";
11490 requests[0].load_flags = LOAD_NORMAL;
11492 requests[1].url = GURL("http://www.example.com/");
11493 requests[1].method = "GET";
11494 requests[1].load_flags = LOAD_NORMAL;
11496 for (size_t i = 0; i < arraysize(requests); ++i) {
11497 session_deps_.socket_factory->ResetNextMockIndexes();
11498 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11499 scoped_ptr<HttpNetworkTransaction> trans(
11500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11502 // Begin the SSL handshake with the proxy.
11503 TestCompletionCallback callback;
11504 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
11505 ASSERT_EQ(ERR_IO_PENDING, rv);
11507 // Complete the SSL handshake, which should abort due to requiring a
11508 // client certificate.
11509 rv = callback.WaitForResult();
11510 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11512 // Indicate that no certificate should be supplied. From the perspective
11513 // of SSLClientCertCache, NULL is just as meaningful as a real
11514 // certificate, so this is the same as supply a
11515 // legitimate-but-unacceptable certificate.
11516 rv = trans->RestartWithCertificate(NULL, callback.callback());
11517 ASSERT_EQ(ERR_IO_PENDING, rv);
11519 // Ensure the certificate was added to the client auth cache before
11520 // allowing the connection to continue restarting.
11521 scoped_refptr<X509Certificate> client_cert;
11522 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11523 HostPortPair("proxy", 70), &client_cert));
11524 ASSERT_EQ(NULL, client_cert.get());
11525 // Ensure the certificate was NOT cached for the endpoint. This only
11526 // applies to HTTPS requests, but is fine to check for HTTP requests.
11527 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11528 HostPortPair("www.example.com", 443), &client_cert));
11530 // Restart the handshake. This will consume ssl_data2, which fails, and
11531 // then consume ssl_data3, which should also fail. The result code is
11532 // checked against what ssl_data3 should return.
11533 rv = callback.WaitForResult();
11534 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
11536 // Now that the new handshake has failed, ensure that the client
11537 // certificate was removed from the client auth cache.
11538 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11539 HostPortPair("proxy", 70), &client_cert));
11540 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11541 HostPortPair("www.example.com", 443), &client_cert));
11545 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
11546 session_deps_.use_alternative_services = true;
11547 session_deps_.next_protos = SpdyNextProtos();
11549 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11550 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11551 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11552 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11553 pool_peer.DisableDomainAuthenticationVerification();
11555 SSLSocketDataProvider ssl(ASYNC, OK);
11556 ssl.SetNextProto(GetParam());
11557 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11559 scoped_ptr<SpdyFrame> host1_req(
11560 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11561 scoped_ptr<SpdyFrame> host2_req(
11562 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11563 MockWrite spdy_writes[] = {
11564 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11566 scoped_ptr<SpdyFrame> host1_resp(
11567 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11568 scoped_ptr<SpdyFrame> host1_resp_body(
11569 spdy_util_.ConstructSpdyBodyFrame(1, true));
11570 scoped_ptr<SpdyFrame> host2_resp(
11571 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11572 scoped_ptr<SpdyFrame> host2_resp_body(
11573 spdy_util_.ConstructSpdyBodyFrame(3, true));
11574 MockRead spdy_reads[] = {
11575 CreateMockRead(*host1_resp, 1),
11576 CreateMockRead(*host1_resp_body, 2),
11577 CreateMockRead(*host2_resp, 4),
11578 CreateMockRead(*host2_resp_body, 5),
11579 MockRead(ASYNC, 0, 6),
11582 IPAddressNumber ip;
11583 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11584 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11585 MockConnect connect(ASYNC, OK, peer_addr);
11586 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11587 spdy_writes, arraysize(spdy_writes));
11588 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11590 TestCompletionCallback callback;
11591 HttpRequestInfo request1;
11592 request1.method = "GET";
11593 request1.url = GURL("https://www.example.org/");
11594 request1.load_flags = 0;
11595 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11597 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11598 EXPECT_EQ(ERR_IO_PENDING, rv);
11599 EXPECT_EQ(OK, callback.WaitForResult());
11601 const HttpResponseInfo* response = trans1.GetResponseInfo();
11602 ASSERT_TRUE(response != NULL);
11603 ASSERT_TRUE(response->headers.get() != NULL);
11604 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11606 std::string response_data;
11607 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11608 EXPECT_EQ("hello!", response_data);
11610 // Preload www.gmail.com into HostCache.
11611 HostPortPair host_port("www.gmail.com", 443);
11612 HostResolver::RequestInfo resolve_info(host_port);
11613 AddressList ignored;
11614 rv = session_deps_.host_resolver->Resolve(resolve_info,
11615 DEFAULT_PRIORITY,
11616 &ignored,
11617 callback.callback(),
11618 NULL,
11619 BoundNetLog());
11620 EXPECT_EQ(ERR_IO_PENDING, rv);
11621 rv = callback.WaitForResult();
11622 EXPECT_EQ(OK, rv);
11624 HttpRequestInfo request2;
11625 request2.method = "GET";
11626 request2.url = GURL("https://www.gmail.com/");
11627 request2.load_flags = 0;
11628 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11630 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11631 EXPECT_EQ(ERR_IO_PENDING, rv);
11632 EXPECT_EQ(OK, callback.WaitForResult());
11634 response = trans2.GetResponseInfo();
11635 ASSERT_TRUE(response != NULL);
11636 ASSERT_TRUE(response->headers.get() != NULL);
11637 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11638 EXPECT_TRUE(response->was_fetched_via_spdy);
11639 EXPECT_TRUE(response->was_npn_negotiated);
11640 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11641 EXPECT_EQ("hello!", response_data);
11644 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11645 session_deps_.use_alternative_services = true;
11646 session_deps_.next_protos = SpdyNextProtos();
11648 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11649 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11651 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11652 pool_peer.DisableDomainAuthenticationVerification();
11654 SSLSocketDataProvider ssl(ASYNC, OK);
11655 ssl.SetNextProto(GetParam());
11656 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11658 scoped_ptr<SpdyFrame> host1_req(
11659 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11660 scoped_ptr<SpdyFrame> host2_req(
11661 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11662 MockWrite spdy_writes[] = {
11663 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11665 scoped_ptr<SpdyFrame> host1_resp(
11666 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11667 scoped_ptr<SpdyFrame> host1_resp_body(
11668 spdy_util_.ConstructSpdyBodyFrame(1, true));
11669 scoped_ptr<SpdyFrame> host2_resp(
11670 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11671 scoped_ptr<SpdyFrame> host2_resp_body(
11672 spdy_util_.ConstructSpdyBodyFrame(3, true));
11673 MockRead spdy_reads[] = {
11674 CreateMockRead(*host1_resp, 1),
11675 CreateMockRead(*host1_resp_body, 2),
11676 CreateMockRead(*host2_resp, 4),
11677 CreateMockRead(*host2_resp_body, 5),
11678 MockRead(ASYNC, 0, 6),
11681 IPAddressNumber ip;
11682 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11683 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11684 MockConnect connect(ASYNC, OK, peer_addr);
11685 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11686 spdy_writes, arraysize(spdy_writes));
11687 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11689 TestCompletionCallback callback;
11690 HttpRequestInfo request1;
11691 request1.method = "GET";
11692 request1.url = GURL("https://www.example.org/");
11693 request1.load_flags = 0;
11694 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11696 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11697 EXPECT_EQ(ERR_IO_PENDING, rv);
11698 EXPECT_EQ(OK, callback.WaitForResult());
11700 const HttpResponseInfo* response = trans1.GetResponseInfo();
11701 ASSERT_TRUE(response != NULL);
11702 ASSERT_TRUE(response->headers.get() != NULL);
11703 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11705 std::string response_data;
11706 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11707 EXPECT_EQ("hello!", response_data);
11709 HttpRequestInfo request2;
11710 request2.method = "GET";
11711 request2.url = GURL("https://www.gmail.com/");
11712 request2.load_flags = 0;
11713 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11715 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11716 EXPECT_EQ(ERR_IO_PENDING, rv);
11717 EXPECT_EQ(OK, callback.WaitForResult());
11719 response = trans2.GetResponseInfo();
11720 ASSERT_TRUE(response != NULL);
11721 ASSERT_TRUE(response->headers.get() != NULL);
11722 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11723 EXPECT_TRUE(response->was_fetched_via_spdy);
11724 EXPECT_TRUE(response->was_npn_negotiated);
11725 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11726 EXPECT_EQ("hello!", response_data);
11729 class OneTimeCachingHostResolver : public HostResolver {
11730 public:
11731 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11732 : host_port_(host_port) {}
11733 ~OneTimeCachingHostResolver() override {}
11735 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11737 // HostResolver methods:
11738 int Resolve(const RequestInfo& info,
11739 RequestPriority priority,
11740 AddressList* addresses,
11741 const CompletionCallback& callback,
11742 RequestHandle* out_req,
11743 const BoundNetLog& net_log) override {
11744 return host_resolver_.Resolve(
11745 info, priority, addresses, callback, out_req, net_log);
11748 int ResolveFromCache(const RequestInfo& info,
11749 AddressList* addresses,
11750 const BoundNetLog& net_log) override {
11751 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11752 if (rv == OK && info.host_port_pair().Equals(host_port_))
11753 host_resolver_.GetHostCache()->clear();
11754 return rv;
11757 void CancelRequest(RequestHandle req) override {
11758 host_resolver_.CancelRequest(req);
11761 MockCachingHostResolver* GetMockHostResolver() {
11762 return &host_resolver_;
11765 private:
11766 MockCachingHostResolver host_resolver_;
11767 const HostPortPair host_port_;
11770 TEST_P(HttpNetworkTransactionTest,
11771 UseIPConnectionPoolingWithHostCacheExpiration) {
11772 session_deps_.use_alternative_services = true;
11773 session_deps_.next_protos = SpdyNextProtos();
11775 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11776 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11777 HttpNetworkSession::Params params =
11778 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11779 params.host_resolver = &host_resolver;
11780 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11781 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11782 pool_peer.DisableDomainAuthenticationVerification();
11784 SSLSocketDataProvider ssl(ASYNC, OK);
11785 ssl.SetNextProto(GetParam());
11786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11788 scoped_ptr<SpdyFrame> host1_req(
11789 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11790 scoped_ptr<SpdyFrame> host2_req(
11791 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11792 MockWrite spdy_writes[] = {
11793 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11795 scoped_ptr<SpdyFrame> host1_resp(
11796 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11797 scoped_ptr<SpdyFrame> host1_resp_body(
11798 spdy_util_.ConstructSpdyBodyFrame(1, true));
11799 scoped_ptr<SpdyFrame> host2_resp(
11800 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11801 scoped_ptr<SpdyFrame> host2_resp_body(
11802 spdy_util_.ConstructSpdyBodyFrame(3, true));
11803 MockRead spdy_reads[] = {
11804 CreateMockRead(*host1_resp, 1),
11805 CreateMockRead(*host1_resp_body, 2),
11806 CreateMockRead(*host2_resp, 4),
11807 CreateMockRead(*host2_resp_body, 5),
11808 MockRead(ASYNC, 0, 6),
11811 IPAddressNumber ip;
11812 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11813 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11814 MockConnect connect(ASYNC, OK, peer_addr);
11815 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11816 spdy_writes, arraysize(spdy_writes));
11817 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11819 TestCompletionCallback callback;
11820 HttpRequestInfo request1;
11821 request1.method = "GET";
11822 request1.url = GURL("https://www.example.org/");
11823 request1.load_flags = 0;
11824 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11826 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11827 EXPECT_EQ(ERR_IO_PENDING, rv);
11828 EXPECT_EQ(OK, callback.WaitForResult());
11830 const HttpResponseInfo* response = trans1.GetResponseInfo();
11831 ASSERT_TRUE(response != NULL);
11832 ASSERT_TRUE(response->headers.get() != NULL);
11833 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11835 std::string response_data;
11836 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11837 EXPECT_EQ("hello!", response_data);
11839 // Preload cache entries into HostCache.
11840 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11841 AddressList ignored;
11842 rv = host_resolver.Resolve(resolve_info,
11843 DEFAULT_PRIORITY,
11844 &ignored,
11845 callback.callback(),
11846 NULL,
11847 BoundNetLog());
11848 EXPECT_EQ(ERR_IO_PENDING, rv);
11849 rv = callback.WaitForResult();
11850 EXPECT_EQ(OK, rv);
11852 HttpRequestInfo request2;
11853 request2.method = "GET";
11854 request2.url = GURL("https://www.gmail.com/");
11855 request2.load_flags = 0;
11856 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11858 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11859 EXPECT_EQ(ERR_IO_PENDING, rv);
11860 EXPECT_EQ(OK, callback.WaitForResult());
11862 response = trans2.GetResponseInfo();
11863 ASSERT_TRUE(response != NULL);
11864 ASSERT_TRUE(response->headers.get() != NULL);
11865 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11866 EXPECT_TRUE(response->was_fetched_via_spdy);
11867 EXPECT_TRUE(response->was_npn_negotiated);
11868 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11869 EXPECT_EQ("hello!", response_data);
11872 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11873 const std::string https_url = "https://www.example.org:8080/";
11874 const std::string http_url = "http://www.example.org:8080/";
11876 // SPDY GET for HTTPS URL
11877 scoped_ptr<SpdyFrame> req1(
11878 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11880 MockWrite writes1[] = {
11881 CreateMockWrite(*req1, 0),
11884 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11885 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11886 MockRead reads1[] = {
11887 CreateMockRead(*resp1, 1),
11888 CreateMockRead(*body1, 2),
11889 MockRead(ASYNC, ERR_IO_PENDING, 3)
11892 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
11893 arraysize(writes1));
11894 MockConnect connect_data1(ASYNC, OK);
11895 data1.set_connect_data(connect_data1);
11897 // HTTP GET for the HTTP URL
11898 MockWrite writes2[] = {
11899 MockWrite(ASYNC, 0,
11900 "GET / HTTP/1.1\r\n"
11901 "Host: www.example.org:8080\r\n"
11902 "Connection: keep-alive\r\n\r\n"),
11905 MockRead reads2[] = {
11906 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11907 MockRead(ASYNC, 2, "hello"),
11908 MockRead(ASYNC, OK, 3),
11911 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
11912 arraysize(writes2));
11914 SSLSocketDataProvider ssl(ASYNC, OK);
11915 ssl.SetNextProto(GetParam());
11916 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11917 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11918 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11920 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11922 // Start the first transaction to set up the SpdySession
11923 HttpRequestInfo request1;
11924 request1.method = "GET";
11925 request1.url = GURL(https_url);
11926 request1.load_flags = 0;
11927 HttpNetworkTransaction trans1(LOWEST, session.get());
11928 TestCompletionCallback callback1;
11929 EXPECT_EQ(ERR_IO_PENDING,
11930 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11931 base::MessageLoop::current()->RunUntilIdle();
11933 EXPECT_EQ(OK, callback1.WaitForResult());
11934 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11936 // Now, start the HTTP request
11937 HttpRequestInfo request2;
11938 request2.method = "GET";
11939 request2.url = GURL(http_url);
11940 request2.load_flags = 0;
11941 HttpNetworkTransaction trans2(MEDIUM, session.get());
11942 TestCompletionCallback callback2;
11943 EXPECT_EQ(ERR_IO_PENDING,
11944 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11945 base::MessageLoop::current()->RunUntilIdle();
11947 EXPECT_EQ(OK, callback2.WaitForResult());
11948 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11951 class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
11952 public:
11953 void Run(bool pooling, bool valid) {
11954 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
11955 443);
11956 HostPortPair alternative("www.example.org", 443);
11958 base::FilePath certs_dir = GetTestCertsDirectory();
11959 scoped_refptr<X509Certificate> cert(
11960 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
11961 ASSERT_TRUE(cert.get());
11962 bool common_name_fallback_used;
11963 EXPECT_EQ(valid,
11964 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
11965 EXPECT_TRUE(
11966 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
11967 SSLSocketDataProvider ssl(ASYNC, OK);
11968 ssl.SetNextProto(GetParam());
11969 ssl.cert = cert;
11970 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11972 // If pooling, then start a request to alternative first to create a
11973 // SpdySession.
11974 std::string url0 = "https://www.example.org:443";
11975 // Second request to origin, which has an alternative service, and could
11976 // open a connection to the alternative host or pool to the existing one.
11977 std::string url1("https://");
11978 url1.append(origin.host());
11979 url1.append(":443");
11981 scoped_ptr<SpdyFrame> req0;
11982 scoped_ptr<SpdyFrame> req1;
11983 scoped_ptr<SpdyFrame> resp0;
11984 scoped_ptr<SpdyFrame> body0;
11985 scoped_ptr<SpdyFrame> resp1;
11986 scoped_ptr<SpdyFrame> body1;
11987 std::vector<MockWrite> writes;
11988 std::vector<MockRead> reads;
11990 if (pooling) {
11991 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
11992 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
11994 writes.push_back(CreateMockWrite(*req0, 0));
11995 writes.push_back(CreateMockWrite(*req1, 3));
11997 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11998 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
11999 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12000 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
12002 reads.push_back(CreateMockRead(*resp0, 1));
12003 reads.push_back(CreateMockRead(*body0, 2));
12004 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
12005 reads.push_back(CreateMockRead(*resp1, 5));
12006 reads.push_back(CreateMockRead(*body1, 6));
12007 reads.push_back(MockRead(ASYNC, OK, 7));
12008 } else {
12009 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
12011 writes.push_back(CreateMockWrite(*req1, 0));
12013 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12014 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12016 reads.push_back(CreateMockRead(*resp1, 1));
12017 reads.push_back(CreateMockRead(*body1, 2));
12018 reads.push_back(MockRead(ASYNC, OK, 3));
12021 SequencedSocketData data(vector_as_array(&reads), reads.size(),
12022 vector_as_array(&writes), writes.size());
12023 session_deps_.socket_factory->AddSocketDataProvider(&data);
12025 // Connection to the origin fails.
12026 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12027 StaticSocketDataProvider data_refused;
12028 data_refused.set_connect_data(mock_connect);
12029 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12031 session_deps_.use_alternative_services = true;
12032 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12033 base::WeakPtr<HttpServerProperties> http_server_properties =
12034 session->http_server_properties();
12035 AlternativeService alternative_service(
12036 AlternateProtocolFromNextProto(GetParam()), alternative);
12037 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12038 http_server_properties->SetAlternativeService(origin, alternative_service,
12039 1.0, expiration);
12041 // First request to alternative.
12042 if (pooling) {
12043 scoped_ptr<HttpTransaction> trans0(
12044 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12045 HttpRequestInfo request0;
12046 request0.method = "GET";
12047 request0.url = GURL(url0);
12048 request0.load_flags = 0;
12049 TestCompletionCallback callback0;
12051 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
12052 EXPECT_EQ(ERR_IO_PENDING, rv);
12053 rv = callback0.WaitForResult();
12054 EXPECT_EQ(OK, rv);
12057 // Second request to origin.
12058 scoped_ptr<HttpTransaction> trans1(
12059 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12060 HttpRequestInfo request1;
12061 request1.method = "GET";
12062 request1.url = GURL(url1);
12063 request1.load_flags = 0;
12064 TestCompletionCallback callback1;
12066 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12067 EXPECT_EQ(ERR_IO_PENDING, rv);
12068 base::MessageLoop::current()->RunUntilIdle();
12069 if (data.IsReadPaused()) {
12070 data.CompleteRead();
12072 rv = callback1.WaitForResult();
12073 if (valid) {
12074 EXPECT_EQ(OK, rv);
12075 } else {
12076 if (pooling) {
12077 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12078 } else {
12079 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
12085 INSTANTIATE_TEST_CASE_P(NextProto,
12086 AltSvcCertificateVerificationTest,
12087 testing::Values(kProtoSPDY31,
12088 kProtoHTTP2_14,
12089 kProtoHTTP2));
12091 // The alternative service host must exhibit a certificate that is valid for the
12092 // origin host. Test that this is enforced when pooling to an existing
12093 // connection.
12094 TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
12095 Run(true, true);
12098 TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
12099 Run(true, false);
12102 // The alternative service host must exhibit a certificate that is valid for the
12103 // origin host. Test that this is enforced when opening a new connection.
12104 TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
12105 Run(false, true);
12108 TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
12109 Run(false, false);
12112 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12113 // with the alternative server. That connection should not be used.
12114 TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
12115 HostPortPair origin("origin.example.org", 443);
12116 HostPortPair alternative("alternative.example.org", 443);
12118 // Negotiate HTTP/1.1 with alternative.example.org.
12119 SSLSocketDataProvider ssl(ASYNC, OK);
12120 ssl.SetNextProto(kProtoHTTP11);
12121 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12123 // No data should be read from the alternative, because HTTP/1.1 is
12124 // negotiated.
12125 StaticSocketDataProvider data;
12126 session_deps_.socket_factory->AddSocketDataProvider(&data);
12128 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12129 // negotiated. In order to test this, a failed connection to the origin is
12130 // mocked. This way the request relies on the alternate Job.
12131 StaticSocketDataProvider data_refused;
12132 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12133 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12135 // Set up alternative service for origin.
12136 session_deps_.use_alternative_services = true;
12137 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12138 base::WeakPtr<HttpServerProperties> http_server_properties =
12139 session->http_server_properties();
12140 AlternativeService alternative_service(
12141 AlternateProtocolFromNextProto(GetParam()), alternative);
12142 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12143 http_server_properties->SetAlternativeService(origin, alternative_service,
12144 1.0, expiration);
12146 scoped_ptr<HttpTransaction> trans(
12147 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12148 HttpRequestInfo request;
12149 request.method = "GET";
12150 request.url = GURL("https://origin.example.org:443");
12151 request.load_flags = 0;
12152 TestCompletionCallback callback;
12154 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12155 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12156 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12157 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
12160 // A request to a server with an alternative service fires two Jobs: one to the
12161 // origin, and an alternate one to the alternative server. If the former
12162 // succeeds, the request should succeed, even if the latter fails because
12163 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12164 TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
12165 HostPortPair origin("origin.example.org", 443);
12166 HostPortPair alternative("alternative.example.org", 443);
12168 // Negotiate HTTP/1.1 with alternative.
12169 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
12170 alternative_ssl.SetNextProto(kProtoHTTP11);
12171 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
12173 // No data should be read from the alternative, because HTTP/1.1 is
12174 // negotiated.
12175 StaticSocketDataProvider data;
12176 session_deps_.socket_factory->AddSocketDataProvider(&data);
12178 // Negotiate HTTP/1.1 with origin.
12179 SSLSocketDataProvider origin_ssl(ASYNC, OK);
12180 origin_ssl.SetNextProto(kProtoHTTP11);
12181 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
12183 MockWrite http_writes[] = {
12184 MockWrite(
12185 "GET / HTTP/1.1\r\n"
12186 "Host: origin.example.org\r\n"
12187 "Connection: keep-alive\r\n\r\n"),
12188 MockWrite(
12189 "GET /second HTTP/1.1\r\n"
12190 "Host: origin.example.org\r\n"
12191 "Connection: keep-alive\r\n\r\n"),
12194 MockRead http_reads[] = {
12195 MockRead("HTTP/1.1 200 OK\r\n"),
12196 MockRead("Content-Type: text/html\r\n"),
12197 MockRead("Content-Length: 6\r\n\r\n"),
12198 MockRead("foobar"),
12199 MockRead("HTTP/1.1 200 OK\r\n"),
12200 MockRead("Content-Type: text/html\r\n"),
12201 MockRead("Content-Length: 7\r\n\r\n"),
12202 MockRead("another"),
12204 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12205 http_writes, arraysize(http_writes));
12206 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12208 // Set up alternative service for origin.
12209 session_deps_.use_alternative_services = true;
12210 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12211 base::WeakPtr<HttpServerProperties> http_server_properties =
12212 session->http_server_properties();
12213 AlternativeService alternative_service(
12214 AlternateProtocolFromNextProto(GetParam()), alternative);
12215 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12216 http_server_properties->SetAlternativeService(origin, alternative_service,
12217 1.0, expiration);
12219 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
12220 HttpRequestInfo request1;
12221 request1.method = "GET";
12222 request1.url = GURL("https://origin.example.org:443");
12223 request1.load_flags = 0;
12224 TestCompletionCallback callback1;
12226 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
12227 rv = callback1.GetResult(rv);
12228 EXPECT_EQ(OK, rv);
12230 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
12231 ASSERT_TRUE(response1 != nullptr);
12232 ASSERT_TRUE(response1->headers.get() != nullptr);
12233 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12235 std::string response_data1;
12236 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
12237 EXPECT_EQ("foobar", response_data1);
12239 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12240 // for alternative service.
12241 EXPECT_TRUE(
12242 http_server_properties->IsAlternativeServiceBroken(alternative_service));
12244 // Since |alternative_service| is broken, a second transaction to origin
12245 // should not start an alternate Job. It should pool to existing connection
12246 // to origin.
12247 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
12248 HttpRequestInfo request2;
12249 request2.method = "GET";
12250 request2.url = GURL("https://origin.example.org:443/second");
12251 request2.load_flags = 0;
12252 TestCompletionCallback callback2;
12254 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
12255 rv = callback2.GetResult(rv);
12256 EXPECT_EQ(OK, rv);
12258 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
12259 ASSERT_TRUE(response2 != nullptr);
12260 ASSERT_TRUE(response2->headers.get() != nullptr);
12261 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
12263 std::string response_data2;
12264 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
12265 EXPECT_EQ("another", response_data2);
12268 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12269 // HTTP/1.1 socket open to the alternative server. That socket should not be
12270 // used.
12271 TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
12272 HostPortPair origin("origin.example.org", 443);
12273 HostPortPair alternative("alternative.example.org", 443);
12274 std::string origin_url = "https://origin.example.org:443";
12275 std::string alternative_url = "https://alternative.example.org:443";
12277 // Negotiate HTTP/1.1 with alternative.example.org.
12278 SSLSocketDataProvider ssl(ASYNC, OK);
12279 ssl.SetNextProto(kProtoHTTP11);
12280 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12282 // HTTP/1.1 data for |request1| and |request2|.
12283 MockWrite http_writes[] = {
12284 MockWrite(
12285 "GET / HTTP/1.1\r\n"
12286 "Host: alternative.example.org\r\n"
12287 "Connection: keep-alive\r\n\r\n"),
12288 MockWrite(
12289 "GET / HTTP/1.1\r\n"
12290 "Host: alternative.example.org\r\n"
12291 "Connection: keep-alive\r\n\r\n"),
12294 MockRead http_reads[] = {
12295 MockRead(
12296 "HTTP/1.1 200 OK\r\n"
12297 "Content-Type: text/html; charset=iso-8859-1\r\n"
12298 "Content-Length: 40\r\n\r\n"
12299 "first HTTP/1.1 response from alternative"),
12300 MockRead(
12301 "HTTP/1.1 200 OK\r\n"
12302 "Content-Type: text/html; charset=iso-8859-1\r\n"
12303 "Content-Length: 41\r\n\r\n"
12304 "second HTTP/1.1 response from alternative"),
12306 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12307 http_writes, arraysize(http_writes));
12308 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12310 // This test documents that an alternate Job should not pool to an already
12311 // existing HTTP/1.1 connection. In order to test this, a failed connection
12312 // to the origin is mocked. This way |request2| relies on the alternate Job.
12313 StaticSocketDataProvider data_refused;
12314 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12315 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12317 // Set up alternative service for origin.
12318 session_deps_.use_alternative_services = true;
12319 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12320 base::WeakPtr<HttpServerProperties> http_server_properties =
12321 session->http_server_properties();
12322 AlternativeService alternative_service(
12323 AlternateProtocolFromNextProto(GetParam()), alternative);
12324 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12325 http_server_properties->SetAlternativeService(origin, alternative_service,
12326 1.0, expiration);
12328 // First transaction to alternative to open an HTTP/1.1 socket.
12329 scoped_ptr<HttpTransaction> trans1(
12330 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12331 HttpRequestInfo request1;
12332 request1.method = "GET";
12333 request1.url = GURL(alternative_url);
12334 request1.load_flags = 0;
12335 TestCompletionCallback callback1;
12337 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12338 EXPECT_EQ(OK, callback1.GetResult(rv));
12339 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12340 ASSERT_TRUE(response1);
12341 ASSERT_TRUE(response1->headers.get());
12342 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12343 EXPECT_TRUE(response1->was_npn_negotiated);
12344 EXPECT_FALSE(response1->was_fetched_via_spdy);
12345 std::string response_data1;
12346 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
12347 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
12349 // Request for origin.example.org, which has an alternative service. This
12350 // will start two Jobs: the alternative looks for connections to pool to,
12351 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12352 // open other connections to alternative server. The Job to origin fails, so
12353 // this request fails.
12354 scoped_ptr<HttpTransaction> trans2(
12355 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12356 HttpRequestInfo request2;
12357 request2.method = "GET";
12358 request2.url = GURL(origin_url);
12359 request2.load_flags = 0;
12360 TestCompletionCallback callback2;
12362 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
12363 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
12365 // Another transaction to alternative. This is to test that the HTTP/1.1
12366 // socket is still open and in the pool.
12367 scoped_ptr<HttpTransaction> trans3(
12368 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12369 HttpRequestInfo request3;
12370 request3.method = "GET";
12371 request3.url = GURL(alternative_url);
12372 request3.load_flags = 0;
12373 TestCompletionCallback callback3;
12375 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
12376 EXPECT_EQ(OK, callback3.GetResult(rv));
12377 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
12378 ASSERT_TRUE(response3);
12379 ASSERT_TRUE(response3->headers.get());
12380 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
12381 EXPECT_TRUE(response3->was_npn_negotiated);
12382 EXPECT_FALSE(response3->was_fetched_via_spdy);
12383 std::string response_data3;
12384 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
12385 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
12388 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
12389 const std::string https_url = "https://www.example.org:8080/";
12390 const std::string http_url = "http://www.example.org:8080/";
12392 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12393 const HostPortPair host_port_pair("www.example.org", 8080);
12394 scoped_ptr<SpdyFrame> connect(
12395 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
12396 scoped_ptr<SpdyFrame> req1(
12397 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
12398 scoped_ptr<SpdyFrame> wrapped_req1(
12399 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
12401 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12402 SpdyHeaderBlock req2_block;
12403 req2_block[spdy_util_.GetMethodKey()] = "GET";
12404 req2_block[spdy_util_.GetPathKey()] = "/";
12405 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
12406 req2_block[spdy_util_.GetSchemeKey()] = "http";
12407 spdy_util_.MaybeAddVersionHeader(&req2_block);
12408 scoped_ptr<SpdyFrame> req2(
12409 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
12411 MockWrite writes1[] = {
12412 CreateMockWrite(*connect, 0),
12413 CreateMockWrite(*wrapped_req1, 2),
12414 CreateMockWrite(*req2, 5),
12417 scoped_ptr<SpdyFrame> conn_resp(
12418 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12419 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12420 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12421 scoped_ptr<SpdyFrame> wrapped_resp1(
12422 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
12423 scoped_ptr<SpdyFrame> wrapped_body1(
12424 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
12425 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12426 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
12427 MockRead reads1[] = {
12428 CreateMockRead(*conn_resp, 1),
12429 CreateMockRead(*wrapped_resp1, 3),
12430 CreateMockRead(*wrapped_body1, 4),
12431 CreateMockRead(*resp2, 6),
12432 CreateMockRead(*body2, 7),
12433 MockRead(ASYNC, ERR_IO_PENDING, 8)
12436 DeterministicSocketData data1(reads1, arraysize(reads1),
12437 writes1, arraysize(writes1));
12438 MockConnect connect_data1(ASYNC, OK);
12439 data1.set_connect_data(connect_data1);
12441 session_deps_.proxy_service.reset(
12442 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12443 TestNetLog log;
12444 session_deps_.net_log = &log;
12445 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12446 ssl1.SetNextProto(GetParam());
12447 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12448 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12449 ssl2.SetNextProto(GetParam());
12450 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12451 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
12453 scoped_refptr<HttpNetworkSession> session(
12454 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12456 // Start the first transaction to set up the SpdySession
12457 HttpRequestInfo request1;
12458 request1.method = "GET";
12459 request1.url = GURL(https_url);
12460 request1.load_flags = 0;
12461 HttpNetworkTransaction trans1(LOWEST, session.get());
12462 TestCompletionCallback callback1;
12463 EXPECT_EQ(ERR_IO_PENDING,
12464 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12465 base::MessageLoop::current()->RunUntilIdle();
12466 data1.RunFor(4);
12468 EXPECT_EQ(OK, callback1.WaitForResult());
12469 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12471 LoadTimingInfo load_timing_info1;
12472 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
12473 TestLoadTimingNotReusedWithPac(load_timing_info1,
12474 CONNECT_TIMING_HAS_SSL_TIMES);
12476 // Now, start the HTTP request
12477 HttpRequestInfo request2;
12478 request2.method = "GET";
12479 request2.url = GURL(http_url);
12480 request2.load_flags = 0;
12481 HttpNetworkTransaction trans2(MEDIUM, session.get());
12482 TestCompletionCallback callback2;
12483 EXPECT_EQ(ERR_IO_PENDING,
12484 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12485 base::MessageLoop::current()->RunUntilIdle();
12486 data1.RunFor(3);
12488 EXPECT_EQ(OK, callback2.WaitForResult());
12489 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12491 LoadTimingInfo load_timing_info2;
12492 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
12493 // The established SPDY sessions is considered reused by the HTTP request.
12494 TestLoadTimingReusedWithPac(load_timing_info2);
12495 // HTTP requests over a SPDY session should have a different connection
12496 // socket_log_id than requests over a tunnel.
12497 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
12500 // Test that in the case where we have a SPDY session to a SPDY proxy
12501 // that we do not pool other origins that resolve to the same IP when
12502 // the certificate does not match the new origin.
12503 // http://crbug.com/134690
12504 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
12505 const std::string url1 = "http://www.example.org/";
12506 const std::string url2 = "https://news.example.org/";
12507 const std::string ip_addr = "1.2.3.4";
12509 // SPDY GET for HTTP URL (through SPDY proxy)
12510 scoped_ptr<SpdyHeaderBlock> headers(
12511 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12512 scoped_ptr<SpdyFrame> req1(
12513 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
12515 MockWrite writes1[] = {
12516 CreateMockWrite(*req1, 0),
12519 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12520 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12521 MockRead reads1[] = {
12522 CreateMockRead(*resp1, 1),
12523 CreateMockRead(*body1, 2),
12524 MockRead(ASYNC, OK, 3) // EOF
12527 scoped_ptr<DeterministicSocketData> data1(
12528 new DeterministicSocketData(reads1, arraysize(reads1),
12529 writes1, arraysize(writes1)));
12530 IPAddressNumber ip;
12531 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
12532 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12533 MockConnect connect_data1(ASYNC, OK, peer_addr);
12534 data1->set_connect_data(connect_data1);
12536 // SPDY GET for HTTPS URL (direct)
12537 scoped_ptr<SpdyFrame> req2(
12538 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
12540 MockWrite writes2[] = {
12541 CreateMockWrite(*req2, 0),
12544 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12545 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12546 MockRead reads2[] = {
12547 CreateMockRead(*resp2, 1),
12548 CreateMockRead(*body2, 2),
12549 MockRead(ASYNC, OK, 3) // EOF
12552 scoped_ptr<DeterministicSocketData> data2(
12553 new DeterministicSocketData(reads2, arraysize(reads2),
12554 writes2, arraysize(writes2)));
12555 MockConnect connect_data2(ASYNC, OK);
12556 data2->set_connect_data(connect_data2);
12558 // Set up a proxy config that sends HTTP requests to a proxy, and
12559 // all others direct.
12560 ProxyConfig proxy_config;
12561 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
12562 session_deps_.proxy_service.reset(new ProxyService(
12563 new ProxyConfigServiceFixed(proxy_config), nullptr, NULL));
12565 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12566 ssl1.SetNextProto(GetParam());
12567 // Load a valid cert. Note, that this does not need to
12568 // be valid for proxy because the MockSSLClientSocket does
12569 // not actually verify it. But SpdySession will use this
12570 // to see if it is valid for the new origin
12571 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12572 ASSERT_TRUE(ssl1.cert.get());
12573 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12574 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12575 data1.get());
12577 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12578 ssl2.SetNextProto(GetParam());
12579 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12580 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12581 data2.get());
12583 session_deps_.host_resolver.reset(new MockCachingHostResolver());
12584 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
12585 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
12587 scoped_refptr<HttpNetworkSession> session(
12588 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12590 // Start the first transaction to set up the SpdySession
12591 HttpRequestInfo request1;
12592 request1.method = "GET";
12593 request1.url = GURL(url1);
12594 request1.load_flags = 0;
12595 HttpNetworkTransaction trans1(LOWEST, session.get());
12596 TestCompletionCallback callback1;
12597 ASSERT_EQ(ERR_IO_PENDING,
12598 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12599 data1->RunFor(3);
12601 ASSERT_TRUE(callback1.have_result());
12602 EXPECT_EQ(OK, callback1.WaitForResult());
12603 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12605 // Now, start the HTTP request
12606 HttpRequestInfo request2;
12607 request2.method = "GET";
12608 request2.url = GURL(url2);
12609 request2.load_flags = 0;
12610 HttpNetworkTransaction trans2(MEDIUM, session.get());
12611 TestCompletionCallback callback2;
12612 EXPECT_EQ(ERR_IO_PENDING,
12613 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12614 base::MessageLoop::current()->RunUntilIdle();
12615 data2->RunFor(3);
12617 ASSERT_TRUE(callback2.have_result());
12618 EXPECT_EQ(OK, callback2.WaitForResult());
12619 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12622 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12623 // error) in SPDY session, removes the socket from pool and closes the SPDY
12624 // session. Verify that new url's from the same HttpNetworkSession (and a new
12625 // SpdySession) do work. http://crbug.com/224701
12626 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
12627 const std::string https_url = "https://www.example.org/";
12629 MockRead reads1[] = {
12630 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
12633 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
12635 scoped_ptr<SpdyFrame> req2(
12636 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
12637 MockWrite writes2[] = {
12638 CreateMockWrite(*req2, 0),
12641 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12642 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12643 MockRead reads2[] = {
12644 CreateMockRead(*resp2, 1),
12645 CreateMockRead(*body2, 2),
12646 MockRead(ASYNC, OK, 3) // EOF
12649 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
12650 arraysize(writes2));
12652 SSLSocketDataProvider ssl1(ASYNC, OK);
12653 ssl1.SetNextProto(GetParam());
12654 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12655 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12657 SSLSocketDataProvider ssl2(ASYNC, OK);
12658 ssl2.SetNextProto(GetParam());
12659 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12660 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12662 scoped_refptr<HttpNetworkSession> session(
12663 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
12665 // Start the first transaction to set up the SpdySession and verify that
12666 // connection was closed.
12667 HttpRequestInfo request1;
12668 request1.method = "GET";
12669 request1.url = GURL(https_url);
12670 request1.load_flags = 0;
12671 HttpNetworkTransaction trans1(MEDIUM, session.get());
12672 TestCompletionCallback callback1;
12673 EXPECT_EQ(ERR_IO_PENDING,
12674 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12675 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
12677 // Now, start the second request and make sure it succeeds.
12678 HttpRequestInfo request2;
12679 request2.method = "GET";
12680 request2.url = GURL(https_url);
12681 request2.load_flags = 0;
12682 HttpNetworkTransaction trans2(MEDIUM, session.get());
12683 TestCompletionCallback callback2;
12684 EXPECT_EQ(ERR_IO_PENDING,
12685 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12687 ASSERT_EQ(OK, callback2.WaitForResult());
12688 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12691 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
12692 session_deps_.next_protos = SpdyNextProtos();
12693 ClientSocketPoolManager::set_max_sockets_per_group(
12694 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12695 ClientSocketPoolManager::set_max_sockets_per_pool(
12696 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12698 // Use two different hosts with different IPs so they don't get pooled.
12699 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
12700 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
12701 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12703 SSLSocketDataProvider ssl1(ASYNC, OK);
12704 ssl1.SetNextProto(GetParam());
12705 SSLSocketDataProvider ssl2(ASYNC, OK);
12706 ssl2.SetNextProto(GetParam());
12707 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12708 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12710 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
12711 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
12712 MockWrite spdy1_writes[] = {
12713 CreateMockWrite(*host1_req, 0),
12715 scoped_ptr<SpdyFrame> host1_resp(
12716 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12717 scoped_ptr<SpdyFrame> host1_resp_body(
12718 spdy_util_.ConstructSpdyBodyFrame(1, true));
12719 MockRead spdy1_reads[] = {
12720 CreateMockRead(*host1_resp, 1),
12721 CreateMockRead(*host1_resp_body, 2),
12722 MockRead(ASYNC, ERR_IO_PENDING, 3),
12725 scoped_ptr<SequencedSocketData> spdy1_data(
12726 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
12727 arraysize(spdy1_writes)));
12728 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
12730 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
12731 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
12732 MockWrite spdy2_writes[] = {
12733 CreateMockWrite(*host2_req, 0),
12735 scoped_ptr<SpdyFrame> host2_resp(
12736 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12737 scoped_ptr<SpdyFrame> host2_resp_body(
12738 spdy_util_.ConstructSpdyBodyFrame(1, true));
12739 MockRead spdy2_reads[] = {
12740 CreateMockRead(*host2_resp, 1),
12741 CreateMockRead(*host2_resp_body, 2),
12742 MockRead(ASYNC, ERR_IO_PENDING, 3),
12745 scoped_ptr<SequencedSocketData> spdy2_data(
12746 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
12747 arraysize(spdy2_writes)));
12748 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
12750 MockWrite http_write[] = {
12751 MockWrite("GET / HTTP/1.1\r\n"
12752 "Host: www.a.com\r\n"
12753 "Connection: keep-alive\r\n\r\n"),
12756 MockRead http_read[] = {
12757 MockRead("HTTP/1.1 200 OK\r\n"),
12758 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12759 MockRead("Content-Length: 6\r\n\r\n"),
12760 MockRead("hello!"),
12762 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
12763 http_write, arraysize(http_write));
12764 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12766 HostPortPair host_port_pair_a("www.a.com", 443);
12767 SpdySessionKey spdy_session_key_a(
12768 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12769 EXPECT_FALSE(
12770 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12772 TestCompletionCallback callback;
12773 HttpRequestInfo request1;
12774 request1.method = "GET";
12775 request1.url = GURL("https://www.a.com/");
12776 request1.load_flags = 0;
12777 scoped_ptr<HttpNetworkTransaction> trans(
12778 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12780 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
12781 EXPECT_EQ(ERR_IO_PENDING, rv);
12782 EXPECT_EQ(OK, callback.WaitForResult());
12784 const HttpResponseInfo* response = trans->GetResponseInfo();
12785 ASSERT_TRUE(response != NULL);
12786 ASSERT_TRUE(response->headers.get() != NULL);
12787 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12788 EXPECT_TRUE(response->was_fetched_via_spdy);
12789 EXPECT_TRUE(response->was_npn_negotiated);
12791 std::string response_data;
12792 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12793 EXPECT_EQ("hello!", response_data);
12794 trans.reset();
12795 EXPECT_TRUE(
12796 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12798 HostPortPair host_port_pair_b("www.b.com", 443);
12799 SpdySessionKey spdy_session_key_b(
12800 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12801 EXPECT_FALSE(
12802 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12803 HttpRequestInfo request2;
12804 request2.method = "GET";
12805 request2.url = GURL("https://www.b.com/");
12806 request2.load_flags = 0;
12807 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12809 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
12810 EXPECT_EQ(ERR_IO_PENDING, rv);
12811 EXPECT_EQ(OK, callback.WaitForResult());
12813 response = trans->GetResponseInfo();
12814 ASSERT_TRUE(response != NULL);
12815 ASSERT_TRUE(response->headers.get() != NULL);
12816 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12817 EXPECT_TRUE(response->was_fetched_via_spdy);
12818 EXPECT_TRUE(response->was_npn_negotiated);
12819 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12820 EXPECT_EQ("hello!", response_data);
12821 EXPECT_FALSE(
12822 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12823 EXPECT_TRUE(
12824 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12826 HostPortPair host_port_pair_a1("www.a.com", 80);
12827 SpdySessionKey spdy_session_key_a1(
12828 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12829 EXPECT_FALSE(
12830 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
12831 HttpRequestInfo request3;
12832 request3.method = "GET";
12833 request3.url = GURL("http://www.a.com/");
12834 request3.load_flags = 0;
12835 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12837 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
12838 EXPECT_EQ(ERR_IO_PENDING, rv);
12839 EXPECT_EQ(OK, callback.WaitForResult());
12841 response = trans->GetResponseInfo();
12842 ASSERT_TRUE(response != NULL);
12843 ASSERT_TRUE(response->headers.get() != NULL);
12844 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12845 EXPECT_FALSE(response->was_fetched_via_spdy);
12846 EXPECT_FALSE(response->was_npn_negotiated);
12847 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12848 EXPECT_EQ("hello!", response_data);
12849 EXPECT_FALSE(
12850 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12851 EXPECT_FALSE(
12852 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12855 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
12856 HttpRequestInfo request;
12857 request.method = "GET";
12858 request.url = GURL("http://www.example.org/");
12859 request.load_flags = 0;
12861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12862 scoped_ptr<HttpTransaction> trans(
12863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12865 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
12866 StaticSocketDataProvider data;
12867 data.set_connect_data(mock_connect);
12868 session_deps_.socket_factory->AddSocketDataProvider(&data);
12870 TestCompletionCallback callback;
12872 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12873 EXPECT_EQ(ERR_IO_PENDING, rv);
12875 rv = callback.WaitForResult();
12876 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12878 // We don't care whether this succeeds or fails, but it shouldn't crash.
12879 HttpRequestHeaders request_headers;
12880 trans->GetFullRequestHeaders(&request_headers);
12882 ConnectionAttempts attempts;
12883 trans->GetConnectionAttempts(&attempts);
12884 ASSERT_EQ(1u, attempts.size());
12885 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12888 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
12889 HttpRequestInfo request;
12890 request.method = "GET";
12891 request.url = GURL("http://www.example.org/");
12892 request.load_flags = 0;
12894 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12895 scoped_ptr<HttpTransaction> trans(
12896 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12898 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12899 StaticSocketDataProvider data;
12900 data.set_connect_data(mock_connect);
12901 session_deps_.socket_factory->AddSocketDataProvider(&data);
12903 TestCompletionCallback callback;
12905 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12906 EXPECT_EQ(ERR_IO_PENDING, rv);
12908 rv = callback.WaitForResult();
12909 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12911 // We don't care whether this succeeds or fails, but it shouldn't crash.
12912 HttpRequestHeaders request_headers;
12913 trans->GetFullRequestHeaders(&request_headers);
12915 ConnectionAttempts attempts;
12916 trans->GetConnectionAttempts(&attempts);
12917 ASSERT_EQ(1u, attempts.size());
12918 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12921 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
12922 HttpRequestInfo request;
12923 request.method = "GET";
12924 request.url = GURL("http://www.example.org/");
12925 request.load_flags = 0;
12927 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12928 scoped_ptr<HttpTransaction> trans(
12929 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12931 MockWrite data_writes[] = {
12932 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12934 MockRead data_reads[] = {
12935 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12938 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12939 data_writes, arraysize(data_writes));
12940 session_deps_.socket_factory->AddSocketDataProvider(&data);
12942 TestCompletionCallback callback;
12944 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12945 EXPECT_EQ(ERR_IO_PENDING, rv);
12947 rv = callback.WaitForResult();
12948 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12950 HttpRequestHeaders request_headers;
12951 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12952 EXPECT_TRUE(request_headers.HasHeader("Host"));
12955 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
12956 HttpRequestInfo request;
12957 request.method = "GET";
12958 request.url = GURL("http://www.example.org/");
12959 request.load_flags = 0;
12961 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12962 scoped_ptr<HttpTransaction> trans(
12963 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12965 MockWrite data_writes[] = {
12966 MockWrite(ASYNC, ERR_CONNECTION_RESET),
12968 MockRead data_reads[] = {
12969 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12972 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12973 data_writes, arraysize(data_writes));
12974 session_deps_.socket_factory->AddSocketDataProvider(&data);
12976 TestCompletionCallback callback;
12978 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12979 EXPECT_EQ(ERR_IO_PENDING, rv);
12981 rv = callback.WaitForResult();
12982 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12984 HttpRequestHeaders request_headers;
12985 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12986 EXPECT_TRUE(request_headers.HasHeader("Host"));
12989 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
12990 HttpRequestInfo request;
12991 request.method = "GET";
12992 request.url = GURL("http://www.example.org/");
12993 request.load_flags = 0;
12995 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12996 scoped_ptr<HttpTransaction> trans(
12997 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12999 MockWrite data_writes[] = {
13000 MockWrite(
13001 "GET / HTTP/1.1\r\n"
13002 "Host: www.example.org\r\n"
13003 "Connection: keep-alive\r\n\r\n"),
13005 MockRead data_reads[] = {
13006 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
13009 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13010 data_writes, arraysize(data_writes));
13011 session_deps_.socket_factory->AddSocketDataProvider(&data);
13013 TestCompletionCallback callback;
13015 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13016 EXPECT_EQ(ERR_IO_PENDING, rv);
13018 rv = callback.WaitForResult();
13019 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13021 HttpRequestHeaders request_headers;
13022 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13023 EXPECT_TRUE(request_headers.HasHeader("Host"));
13026 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
13027 HttpRequestInfo request;
13028 request.method = "GET";
13029 request.url = GURL("http://www.example.org/");
13030 request.load_flags = 0;
13032 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13033 scoped_ptr<HttpTransaction> trans(
13034 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13036 MockWrite data_writes[] = {
13037 MockWrite(
13038 "GET / HTTP/1.1\r\n"
13039 "Host: www.example.org\r\n"
13040 "Connection: keep-alive\r\n\r\n"),
13042 MockRead data_reads[] = {
13043 MockRead(ASYNC, ERR_CONNECTION_RESET),
13046 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13047 data_writes, arraysize(data_writes));
13048 session_deps_.socket_factory->AddSocketDataProvider(&data);
13050 TestCompletionCallback callback;
13052 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13053 EXPECT_EQ(ERR_IO_PENDING, rv);
13055 rv = callback.WaitForResult();
13056 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13058 HttpRequestHeaders request_headers;
13059 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13060 EXPECT_TRUE(request_headers.HasHeader("Host"));
13063 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
13064 HttpRequestInfo request;
13065 request.method = "GET";
13066 request.url = GURL("http://www.example.org/");
13067 request.load_flags = 0;
13068 request.extra_headers.SetHeader("X-Foo", "bar");
13070 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13071 scoped_ptr<HttpTransaction> trans(
13072 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13074 MockWrite data_writes[] = {
13075 MockWrite(
13076 "GET / HTTP/1.1\r\n"
13077 "Host: www.example.org\r\n"
13078 "Connection: keep-alive\r\n"
13079 "X-Foo: bar\r\n\r\n"),
13081 MockRead data_reads[] = {
13082 MockRead("HTTP/1.1 200 OK\r\n"
13083 "Content-Length: 5\r\n\r\n"
13084 "hello"),
13085 MockRead(ASYNC, ERR_UNEXPECTED),
13088 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13089 data_writes, arraysize(data_writes));
13090 session_deps_.socket_factory->AddSocketDataProvider(&data);
13092 TestCompletionCallback callback;
13094 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13095 EXPECT_EQ(ERR_IO_PENDING, rv);
13097 rv = callback.WaitForResult();
13098 EXPECT_EQ(OK, rv);
13100 HttpRequestHeaders request_headers;
13101 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13102 std::string foo;
13103 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
13104 EXPECT_EQ("bar", foo);
13107 namespace {
13109 // Fake HttpStream that simply records calls to SetPriority().
13110 class FakeStream : public HttpStream,
13111 public base::SupportsWeakPtr<FakeStream> {
13112 public:
13113 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
13114 ~FakeStream() override {}
13116 RequestPriority priority() const { return priority_; }
13118 int InitializeStream(const HttpRequestInfo* request_info,
13119 RequestPriority priority,
13120 const BoundNetLog& net_log,
13121 const CompletionCallback& callback) override {
13122 return ERR_IO_PENDING;
13125 int SendRequest(const HttpRequestHeaders& request_headers,
13126 HttpResponseInfo* response,
13127 const CompletionCallback& callback) override {
13128 ADD_FAILURE();
13129 return ERR_UNEXPECTED;
13132 int ReadResponseHeaders(const CompletionCallback& callback) override {
13133 ADD_FAILURE();
13134 return ERR_UNEXPECTED;
13137 int ReadResponseBody(IOBuffer* buf,
13138 int buf_len,
13139 const CompletionCallback& callback) override {
13140 ADD_FAILURE();
13141 return ERR_UNEXPECTED;
13144 void Close(bool not_reusable) override {}
13146 bool IsResponseBodyComplete() const override {
13147 ADD_FAILURE();
13148 return false;
13151 bool CanFindEndOfResponse() const override { return false; }
13153 bool IsConnectionReused() const override {
13154 ADD_FAILURE();
13155 return false;
13158 void SetConnectionReused() override { ADD_FAILURE(); }
13160 bool IsConnectionReusable() const override {
13161 ADD_FAILURE();
13162 return false;
13165 int64 GetTotalReceivedBytes() const override {
13166 ADD_FAILURE();
13167 return 0;
13170 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13171 ADD_FAILURE();
13172 return false;
13175 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
13177 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13178 ADD_FAILURE();
13181 bool IsSpdyHttpStream() const override {
13182 ADD_FAILURE();
13183 return false;
13186 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
13188 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13190 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
13192 HttpStream* RenewStreamForAuth() override { return NULL; }
13194 private:
13195 RequestPriority priority_;
13197 DISALLOW_COPY_AND_ASSIGN(FakeStream);
13200 // Fake HttpStreamRequest that simply records calls to SetPriority()
13201 // and vends FakeStreams with its current priority.
13202 class FakeStreamRequest : public HttpStreamRequest,
13203 public base::SupportsWeakPtr<FakeStreamRequest> {
13204 public:
13205 FakeStreamRequest(RequestPriority priority,
13206 HttpStreamRequest::Delegate* delegate)
13207 : priority_(priority),
13208 delegate_(delegate),
13209 websocket_stream_create_helper_(NULL) {}
13211 FakeStreamRequest(RequestPriority priority,
13212 HttpStreamRequest::Delegate* delegate,
13213 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
13214 : priority_(priority),
13215 delegate_(delegate),
13216 websocket_stream_create_helper_(create_helper) {}
13218 ~FakeStreamRequest() override {}
13220 RequestPriority priority() const { return priority_; }
13222 const WebSocketHandshakeStreamBase::CreateHelper*
13223 websocket_stream_create_helper() const {
13224 return websocket_stream_create_helper_;
13227 // Create a new FakeStream and pass it to the request's
13228 // delegate. Returns a weak pointer to the FakeStream.
13229 base::WeakPtr<FakeStream> FinishStreamRequest() {
13230 FakeStream* fake_stream = new FakeStream(priority_);
13231 // Do this before calling OnStreamReady() as OnStreamReady() may
13232 // immediately delete |fake_stream|.
13233 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
13234 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
13235 return weak_stream;
13238 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
13239 ADD_FAILURE();
13240 return ERR_UNEXPECTED;
13243 LoadState GetLoadState() const override {
13244 ADD_FAILURE();
13245 return LoadState();
13248 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13250 bool was_npn_negotiated() const override { return false; }
13252 NextProto protocol_negotiated() const override { return kProtoUnknown; }
13254 bool using_spdy() const override { return false; }
13256 const ConnectionAttempts& connection_attempts() const override {
13257 static ConnectionAttempts no_attempts;
13258 return no_attempts;
13261 private:
13262 RequestPriority priority_;
13263 HttpStreamRequest::Delegate* const delegate_;
13264 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
13266 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
13269 // Fake HttpStreamFactory that vends FakeStreamRequests.
13270 class FakeStreamFactory : public HttpStreamFactory {
13271 public:
13272 FakeStreamFactory() {}
13273 ~FakeStreamFactory() override {}
13275 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13276 // RequestStream() (which may be NULL if it was destroyed already).
13277 base::WeakPtr<FakeStreamRequest> last_stream_request() {
13278 return last_stream_request_;
13281 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
13282 RequestPriority priority,
13283 const SSLConfig& server_ssl_config,
13284 const SSLConfig& proxy_ssl_config,
13285 HttpStreamRequest::Delegate* delegate,
13286 const BoundNetLog& net_log) override {
13287 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
13288 last_stream_request_ = fake_request->AsWeakPtr();
13289 return fake_request;
13292 HttpStreamRequest* RequestWebSocketHandshakeStream(
13293 const HttpRequestInfo& info,
13294 RequestPriority priority,
13295 const SSLConfig& server_ssl_config,
13296 const SSLConfig& proxy_ssl_config,
13297 HttpStreamRequest::Delegate* delegate,
13298 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
13299 const BoundNetLog& net_log) override {
13300 FakeStreamRequest* fake_request =
13301 new FakeStreamRequest(priority, delegate, create_helper);
13302 last_stream_request_ = fake_request->AsWeakPtr();
13303 return fake_request;
13306 void PreconnectStreams(int num_streams,
13307 const HttpRequestInfo& info,
13308 const SSLConfig& server_ssl_config,
13309 const SSLConfig& proxy_ssl_config) override {
13310 ADD_FAILURE();
13313 const HostMappingRules* GetHostMappingRules() const override {
13314 ADD_FAILURE();
13315 return NULL;
13318 private:
13319 base::WeakPtr<FakeStreamRequest> last_stream_request_;
13321 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
13324 // TODO(ricea): Maybe unify this with the one in
13325 // url_request_http_job_unittest.cc ?
13326 class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
13327 public:
13328 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
13329 bool using_proxy)
13330 : state_(connection.release(), using_proxy) {}
13332 // Fake implementation of HttpStreamBase methods.
13333 // This ends up being quite "real" because this object has to really send data
13334 // on the mock socket. It might be easier to use the real implementation, but
13335 // the fact that the WebSocket code is not compiled on iOS makes that
13336 // difficult.
13337 int InitializeStream(const HttpRequestInfo* request_info,
13338 RequestPriority priority,
13339 const BoundNetLog& net_log,
13340 const CompletionCallback& callback) override {
13341 state_.Initialize(request_info, priority, net_log, callback);
13342 return OK;
13345 int SendRequest(const HttpRequestHeaders& request_headers,
13346 HttpResponseInfo* response,
13347 const CompletionCallback& callback) override {
13348 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
13349 response, callback);
13352 int ReadResponseHeaders(const CompletionCallback& callback) override {
13353 return parser()->ReadResponseHeaders(callback);
13356 int ReadResponseBody(IOBuffer* buf,
13357 int buf_len,
13358 const CompletionCallback& callback) override {
13359 NOTREACHED();
13360 return ERR_IO_PENDING;
13363 void Close(bool not_reusable) override {
13364 if (parser())
13365 parser()->Close(true);
13368 bool IsResponseBodyComplete() const override {
13369 NOTREACHED();
13370 return false;
13373 bool CanFindEndOfResponse() const override {
13374 return parser()->CanFindEndOfResponse();
13377 bool IsConnectionReused() const override {
13378 NOTREACHED();
13379 return false;
13381 void SetConnectionReused() override { NOTREACHED(); }
13383 bool IsConnectionReusable() const override {
13384 NOTREACHED();
13385 return false;
13388 int64 GetTotalReceivedBytes() const override {
13389 NOTREACHED();
13390 return 0;
13393 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13394 NOTREACHED();
13395 return false;
13398 void GetSSLInfo(SSLInfo* ssl_info) override {}
13400 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13401 NOTREACHED();
13404 bool IsSpdyHttpStream() const override {
13405 NOTREACHED();
13406 return false;
13409 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
13411 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
13413 UploadProgress GetUploadProgress() const override {
13414 NOTREACHED();
13415 return UploadProgress();
13418 HttpStream* RenewStreamForAuth() override {
13419 NOTREACHED();
13420 return nullptr;
13423 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13424 scoped_ptr<WebSocketStream> Upgrade() override {
13425 NOTREACHED();
13426 return scoped_ptr<WebSocketStream>();
13429 private:
13430 HttpStreamParser* parser() const { return state_.parser(); }
13431 HttpBasicState state_;
13433 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
13436 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13437 // worth doing.
13438 class FakeWebSocketStreamCreateHelper :
13439 public WebSocketHandshakeStreamBase::CreateHelper {
13440 public:
13441 WebSocketHandshakeStreamBase* CreateBasicStream(
13442 scoped_ptr<ClientSocketHandle> connection,
13443 bool using_proxy) override {
13444 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
13445 using_proxy);
13448 WebSocketHandshakeStreamBase* CreateSpdyStream(
13449 const base::WeakPtr<SpdySession>& session,
13450 bool use_relative_url) override {
13451 NOTREACHED();
13452 return NULL;
13455 ~FakeWebSocketStreamCreateHelper() override {}
13457 virtual scoped_ptr<WebSocketStream> Upgrade() {
13458 NOTREACHED();
13459 return scoped_ptr<WebSocketStream>();
13463 } // namespace
13465 // Make sure that HttpNetworkTransaction passes on its priority to its
13466 // stream request on start.
13467 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
13468 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13469 HttpNetworkSessionPeer peer(session);
13470 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13471 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13473 HttpNetworkTransaction trans(LOW, session.get());
13475 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
13477 HttpRequestInfo request;
13478 TestCompletionCallback callback;
13479 EXPECT_EQ(ERR_IO_PENDING,
13480 trans.Start(&request, callback.callback(), BoundNetLog()));
13482 base::WeakPtr<FakeStreamRequest> fake_request =
13483 fake_factory->last_stream_request();
13484 ASSERT_TRUE(fake_request != NULL);
13485 EXPECT_EQ(LOW, fake_request->priority());
13488 // Make sure that HttpNetworkTransaction passes on its priority
13489 // updates to its stream request.
13490 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
13491 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13492 HttpNetworkSessionPeer peer(session);
13493 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13494 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13496 HttpNetworkTransaction trans(LOW, session.get());
13498 HttpRequestInfo request;
13499 TestCompletionCallback callback;
13500 EXPECT_EQ(ERR_IO_PENDING,
13501 trans.Start(&request, callback.callback(), BoundNetLog()));
13503 base::WeakPtr<FakeStreamRequest> fake_request =
13504 fake_factory->last_stream_request();
13505 ASSERT_TRUE(fake_request != NULL);
13506 EXPECT_EQ(LOW, fake_request->priority());
13508 trans.SetPriority(LOWEST);
13509 ASSERT_TRUE(fake_request != NULL);
13510 EXPECT_EQ(LOWEST, fake_request->priority());
13513 // Make sure that HttpNetworkTransaction passes on its priority
13514 // updates to its stream.
13515 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
13516 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13517 HttpNetworkSessionPeer peer(session);
13518 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13519 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13521 HttpNetworkTransaction trans(LOW, session.get());
13523 HttpRequestInfo request;
13524 TestCompletionCallback callback;
13525 EXPECT_EQ(ERR_IO_PENDING,
13526 trans.Start(&request, callback.callback(), BoundNetLog()));
13528 base::WeakPtr<FakeStreamRequest> fake_request =
13529 fake_factory->last_stream_request();
13530 ASSERT_TRUE(fake_request != NULL);
13531 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
13532 ASSERT_TRUE(fake_stream != NULL);
13533 EXPECT_EQ(LOW, fake_stream->priority());
13535 trans.SetPriority(LOWEST);
13536 EXPECT_EQ(LOWEST, fake_stream->priority());
13539 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
13540 // The same logic needs to be tested for both ws: and wss: schemes, but this
13541 // test is already parameterised on NextProto, so it uses a loop to verify
13542 // that the different schemes work.
13543 std::string test_cases[] = {"ws://www.example.org/",
13544 "wss://www.example.org/"};
13545 for (size_t i = 0; i < arraysize(test_cases); ++i) {
13546 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13547 HttpNetworkSessionPeer peer(session);
13548 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13549 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13550 peer.SetHttpStreamFactoryForWebSocket(
13551 scoped_ptr<HttpStreamFactory>(fake_factory));
13553 HttpNetworkTransaction trans(LOW, session.get());
13554 trans.SetWebSocketHandshakeStreamCreateHelper(
13555 &websocket_stream_create_helper);
13557 HttpRequestInfo request;
13558 TestCompletionCallback callback;
13559 request.method = "GET";
13560 request.url = GURL(test_cases[i]);
13562 EXPECT_EQ(ERR_IO_PENDING,
13563 trans.Start(&request, callback.callback(), BoundNetLog()));
13565 base::WeakPtr<FakeStreamRequest> fake_request =
13566 fake_factory->last_stream_request();
13567 ASSERT_TRUE(fake_request != NULL);
13568 EXPECT_EQ(&websocket_stream_create_helper,
13569 fake_request->websocket_stream_create_helper());
13573 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13574 // if the transport socket pool is stalled on the global socket limit.
13575 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
13576 ClientSocketPoolManager::set_max_sockets_per_group(
13577 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13578 ClientSocketPoolManager::set_max_sockets_per_pool(
13579 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13581 // Set up SSL request.
13583 HttpRequestInfo ssl_request;
13584 ssl_request.method = "GET";
13585 ssl_request.url = GURL("https://www.example.org/");
13587 MockWrite ssl_writes[] = {
13588 MockWrite(
13589 "GET / HTTP/1.1\r\n"
13590 "Host: www.example.org\r\n"
13591 "Connection: keep-alive\r\n\r\n"),
13593 MockRead ssl_reads[] = {
13594 MockRead("HTTP/1.1 200 OK\r\n"),
13595 MockRead("Content-Length: 11\r\n\r\n"),
13596 MockRead("hello world"),
13597 MockRead(SYNCHRONOUS, OK),
13599 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
13600 ssl_writes, arraysize(ssl_writes));
13601 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13603 SSLSocketDataProvider ssl(ASYNC, OK);
13604 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13606 // Set up HTTP request.
13608 HttpRequestInfo http_request;
13609 http_request.method = "GET";
13610 http_request.url = GURL("http://www.example.org/");
13612 MockWrite http_writes[] = {
13613 MockWrite(
13614 "GET / HTTP/1.1\r\n"
13615 "Host: www.example.org\r\n"
13616 "Connection: keep-alive\r\n\r\n"),
13618 MockRead http_reads[] = {
13619 MockRead("HTTP/1.1 200 OK\r\n"),
13620 MockRead("Content-Length: 7\r\n\r\n"),
13621 MockRead("falafel"),
13622 MockRead(SYNCHRONOUS, OK),
13624 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13625 http_writes, arraysize(http_writes));
13626 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13628 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13630 // Start the SSL request.
13631 TestCompletionCallback ssl_callback;
13632 scoped_ptr<HttpTransaction> ssl_trans(
13633 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13634 ASSERT_EQ(ERR_IO_PENDING,
13635 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
13636 BoundNetLog()));
13638 // Start the HTTP request. Pool should stall.
13639 TestCompletionCallback http_callback;
13640 scoped_ptr<HttpTransaction> http_trans(
13641 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13642 ASSERT_EQ(ERR_IO_PENDING,
13643 http_trans->Start(&http_request, http_callback.callback(),
13644 BoundNetLog()));
13645 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13647 // Wait for response from SSL request.
13648 ASSERT_EQ(OK, ssl_callback.WaitForResult());
13649 std::string response_data;
13650 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
13651 EXPECT_EQ("hello world", response_data);
13653 // The SSL socket should automatically be closed, so the HTTP request can
13654 // start.
13655 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13656 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
13658 // The HTTP request can now complete.
13659 ASSERT_EQ(OK, http_callback.WaitForResult());
13660 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13661 EXPECT_EQ("falafel", response_data);
13663 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13666 // Tests that when a SSL connection is established but there's no corresponding
13667 // request that needs it, the new socket is closed if the transport socket pool
13668 // is stalled on the global socket limit.
13669 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
13670 ClientSocketPoolManager::set_max_sockets_per_group(
13671 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13672 ClientSocketPoolManager::set_max_sockets_per_pool(
13673 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13675 // Set up an ssl request.
13677 HttpRequestInfo ssl_request;
13678 ssl_request.method = "GET";
13679 ssl_request.url = GURL("https://www.foopy.com/");
13681 // No data will be sent on the SSL socket.
13682 StaticSocketDataProvider ssl_data;
13683 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13685 SSLSocketDataProvider ssl(ASYNC, OK);
13686 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13688 // Set up HTTP request.
13690 HttpRequestInfo http_request;
13691 http_request.method = "GET";
13692 http_request.url = GURL("http://www.example.org/");
13694 MockWrite http_writes[] = {
13695 MockWrite(
13696 "GET / HTTP/1.1\r\n"
13697 "Host: www.example.org\r\n"
13698 "Connection: keep-alive\r\n\r\n"),
13700 MockRead http_reads[] = {
13701 MockRead("HTTP/1.1 200 OK\r\n"),
13702 MockRead("Content-Length: 7\r\n\r\n"),
13703 MockRead("falafel"),
13704 MockRead(SYNCHRONOUS, OK),
13706 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13707 http_writes, arraysize(http_writes));
13708 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13710 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13712 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13713 // cancelled when a normal transaction is cancelled.
13714 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
13715 SSLConfig ssl_config;
13716 session->ssl_config_service()->GetSSLConfig(&ssl_config);
13717 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
13718 ssl_config);
13719 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13721 // Start the HTTP request. Pool should stall.
13722 TestCompletionCallback http_callback;
13723 scoped_ptr<HttpTransaction> http_trans(
13724 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13725 ASSERT_EQ(ERR_IO_PENDING,
13726 http_trans->Start(&http_request, http_callback.callback(),
13727 BoundNetLog()));
13728 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13730 // The SSL connection will automatically be closed once the connection is
13731 // established, to let the HTTP request start.
13732 ASSERT_EQ(OK, http_callback.WaitForResult());
13733 std::string response_data;
13734 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13735 EXPECT_EQ("falafel", response_data);
13737 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13740 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
13741 ScopedVector<UploadElementReader> element_readers;
13742 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13743 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13745 HttpRequestInfo request;
13746 request.method = "POST";
13747 request.url = GURL("http://www.foo.com/");
13748 request.upload_data_stream = &upload_data_stream;
13749 request.load_flags = 0;
13751 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13752 scoped_ptr<HttpTransaction> trans(
13753 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13754 // Send headers successfully, but get an error while sending the body.
13755 MockWrite data_writes[] = {
13756 MockWrite("POST / HTTP/1.1\r\n"
13757 "Host: www.foo.com\r\n"
13758 "Connection: keep-alive\r\n"
13759 "Content-Length: 3\r\n\r\n"),
13760 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13763 MockRead data_reads[] = {
13764 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13765 MockRead("hello world"),
13766 MockRead(SYNCHRONOUS, OK),
13768 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13769 arraysize(data_writes));
13770 session_deps_.socket_factory->AddSocketDataProvider(&data);
13772 TestCompletionCallback callback;
13774 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13775 EXPECT_EQ(ERR_IO_PENDING, rv);
13777 rv = callback.WaitForResult();
13778 EXPECT_EQ(OK, rv);
13780 const HttpResponseInfo* response = trans->GetResponseInfo();
13781 ASSERT_TRUE(response != NULL);
13783 EXPECT_TRUE(response->headers.get() != NULL);
13784 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13786 std::string response_data;
13787 rv = ReadTransaction(trans.get(), &response_data);
13788 EXPECT_EQ(OK, rv);
13789 EXPECT_EQ("hello world", response_data);
13792 // This test makes sure the retry logic doesn't trigger when reading an error
13793 // response from a server that rejected a POST with a CONNECTION_RESET.
13794 TEST_P(HttpNetworkTransactionTest,
13795 PostReadsErrorResponseAfterResetOnReusedSocket) {
13796 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13797 MockWrite data_writes[] = {
13798 MockWrite("GET / HTTP/1.1\r\n"
13799 "Host: www.foo.com\r\n"
13800 "Connection: keep-alive\r\n\r\n"),
13801 MockWrite("POST / HTTP/1.1\r\n"
13802 "Host: www.foo.com\r\n"
13803 "Connection: keep-alive\r\n"
13804 "Content-Length: 3\r\n\r\n"),
13805 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13808 MockRead data_reads[] = {
13809 MockRead("HTTP/1.1 200 Peachy\r\n"
13810 "Content-Length: 14\r\n\r\n"),
13811 MockRead("first response"),
13812 MockRead("HTTP/1.1 400 Not OK\r\n"
13813 "Content-Length: 15\r\n\r\n"),
13814 MockRead("second response"),
13815 MockRead(SYNCHRONOUS, OK),
13817 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13818 arraysize(data_writes));
13819 session_deps_.socket_factory->AddSocketDataProvider(&data);
13821 TestCompletionCallback callback;
13822 HttpRequestInfo request1;
13823 request1.method = "GET";
13824 request1.url = GURL("http://www.foo.com/");
13825 request1.load_flags = 0;
13827 scoped_ptr<HttpTransaction> trans1(
13828 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13829 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
13830 EXPECT_EQ(ERR_IO_PENDING, rv);
13832 rv = callback.WaitForResult();
13833 EXPECT_EQ(OK, rv);
13835 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13836 ASSERT_TRUE(response1 != NULL);
13838 EXPECT_TRUE(response1->headers.get() != NULL);
13839 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
13841 std::string response_data1;
13842 rv = ReadTransaction(trans1.get(), &response_data1);
13843 EXPECT_EQ(OK, rv);
13844 EXPECT_EQ("first response", response_data1);
13845 // Delete the transaction to release the socket back into the socket pool.
13846 trans1.reset();
13848 ScopedVector<UploadElementReader> element_readers;
13849 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13850 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13852 HttpRequestInfo request2;
13853 request2.method = "POST";
13854 request2.url = GURL("http://www.foo.com/");
13855 request2.upload_data_stream = &upload_data_stream;
13856 request2.load_flags = 0;
13858 scoped_ptr<HttpTransaction> trans2(
13859 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13860 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
13861 EXPECT_EQ(ERR_IO_PENDING, rv);
13863 rv = callback.WaitForResult();
13864 EXPECT_EQ(OK, rv);
13866 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
13867 ASSERT_TRUE(response2 != NULL);
13869 EXPECT_TRUE(response2->headers.get() != NULL);
13870 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
13872 std::string response_data2;
13873 rv = ReadTransaction(trans2.get(), &response_data2);
13874 EXPECT_EQ(OK, rv);
13875 EXPECT_EQ("second response", response_data2);
13878 TEST_P(HttpNetworkTransactionTest,
13879 PostReadsErrorResponseAfterResetPartialBodySent) {
13880 ScopedVector<UploadElementReader> element_readers;
13881 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13882 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13884 HttpRequestInfo request;
13885 request.method = "POST";
13886 request.url = GURL("http://www.foo.com/");
13887 request.upload_data_stream = &upload_data_stream;
13888 request.load_flags = 0;
13890 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13891 scoped_ptr<HttpTransaction> trans(
13892 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13893 // Send headers successfully, but get an error while sending the body.
13894 MockWrite data_writes[] = {
13895 MockWrite("POST / HTTP/1.1\r\n"
13896 "Host: www.foo.com\r\n"
13897 "Connection: keep-alive\r\n"
13898 "Content-Length: 3\r\n\r\n"
13899 "fo"),
13900 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13903 MockRead data_reads[] = {
13904 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13905 MockRead("hello world"),
13906 MockRead(SYNCHRONOUS, OK),
13908 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13909 arraysize(data_writes));
13910 session_deps_.socket_factory->AddSocketDataProvider(&data);
13912 TestCompletionCallback callback;
13914 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13915 EXPECT_EQ(ERR_IO_PENDING, rv);
13917 rv = callback.WaitForResult();
13918 EXPECT_EQ(OK, rv);
13920 const HttpResponseInfo* response = trans->GetResponseInfo();
13921 ASSERT_TRUE(response != NULL);
13923 EXPECT_TRUE(response->headers.get() != NULL);
13924 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13926 std::string response_data;
13927 rv = ReadTransaction(trans.get(), &response_data);
13928 EXPECT_EQ(OK, rv);
13929 EXPECT_EQ("hello world", response_data);
13932 // This tests the more common case than the previous test, where headers and
13933 // body are not merged into a single request.
13934 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
13935 ScopedVector<UploadElementReader> element_readers;
13936 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13937 ChunkedUploadDataStream upload_data_stream(0);
13939 HttpRequestInfo request;
13940 request.method = "POST";
13941 request.url = GURL("http://www.foo.com/");
13942 request.upload_data_stream = &upload_data_stream;
13943 request.load_flags = 0;
13945 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13946 scoped_ptr<HttpTransaction> trans(
13947 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13948 // Send headers successfully, but get an error while sending the body.
13949 MockWrite data_writes[] = {
13950 MockWrite("POST / HTTP/1.1\r\n"
13951 "Host: www.foo.com\r\n"
13952 "Connection: keep-alive\r\n"
13953 "Transfer-Encoding: chunked\r\n\r\n"),
13954 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13957 MockRead data_reads[] = {
13958 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13959 MockRead("hello world"),
13960 MockRead(SYNCHRONOUS, OK),
13962 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13963 arraysize(data_writes));
13964 session_deps_.socket_factory->AddSocketDataProvider(&data);
13966 TestCompletionCallback callback;
13968 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13969 EXPECT_EQ(ERR_IO_PENDING, rv);
13970 // Make sure the headers are sent before adding a chunk. This ensures that
13971 // they can't be merged with the body in a single send. Not currently
13972 // necessary since a chunked body is never merged with headers, but this makes
13973 // the test more future proof.
13974 base::RunLoop().RunUntilIdle();
13976 upload_data_stream.AppendData("last chunk", 10, true);
13978 rv = callback.WaitForResult();
13979 EXPECT_EQ(OK, rv);
13981 const HttpResponseInfo* response = trans->GetResponseInfo();
13982 ASSERT_TRUE(response != NULL);
13984 EXPECT_TRUE(response->headers.get() != NULL);
13985 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13987 std::string response_data;
13988 rv = ReadTransaction(trans.get(), &response_data);
13989 EXPECT_EQ(OK, rv);
13990 EXPECT_EQ("hello world", response_data);
13993 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
13994 ScopedVector<UploadElementReader> element_readers;
13995 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13996 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13998 HttpRequestInfo request;
13999 request.method = "POST";
14000 request.url = GURL("http://www.foo.com/");
14001 request.upload_data_stream = &upload_data_stream;
14002 request.load_flags = 0;
14004 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14005 scoped_ptr<HttpTransaction> trans(
14006 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14008 MockWrite data_writes[] = {
14009 MockWrite("POST / HTTP/1.1\r\n"
14010 "Host: www.foo.com\r\n"
14011 "Connection: keep-alive\r\n"
14012 "Content-Length: 3\r\n\r\n"),
14013 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14016 MockRead data_reads[] = {
14017 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14018 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14019 MockRead("hello world"),
14020 MockRead(SYNCHRONOUS, OK),
14022 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14023 arraysize(data_writes));
14024 session_deps_.socket_factory->AddSocketDataProvider(&data);
14026 TestCompletionCallback callback;
14028 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14029 EXPECT_EQ(ERR_IO_PENDING, rv);
14031 rv = callback.WaitForResult();
14032 EXPECT_EQ(OK, rv);
14034 const HttpResponseInfo* response = trans->GetResponseInfo();
14035 ASSERT_TRUE(response != NULL);
14037 EXPECT_TRUE(response->headers.get() != NULL);
14038 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14040 std::string response_data;
14041 rv = ReadTransaction(trans.get(), &response_data);
14042 EXPECT_EQ(OK, rv);
14043 EXPECT_EQ("hello world", response_data);
14046 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
14047 ScopedVector<UploadElementReader> element_readers;
14048 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14049 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14051 HttpRequestInfo request;
14052 request.method = "POST";
14053 request.url = GURL("http://www.foo.com/");
14054 request.upload_data_stream = &upload_data_stream;
14055 request.load_flags = 0;
14057 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14058 scoped_ptr<HttpTransaction> trans(
14059 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14060 // Send headers successfully, but get an error while sending the body.
14061 MockWrite data_writes[] = {
14062 MockWrite("POST / HTTP/1.1\r\n"
14063 "Host: www.foo.com\r\n"
14064 "Connection: keep-alive\r\n"
14065 "Content-Length: 3\r\n\r\n"),
14066 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14069 MockRead data_reads[] = {
14070 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14071 MockRead("hello world"),
14072 MockRead(SYNCHRONOUS, OK),
14074 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14075 arraysize(data_writes));
14076 session_deps_.socket_factory->AddSocketDataProvider(&data);
14078 TestCompletionCallback callback;
14080 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14081 EXPECT_EQ(ERR_IO_PENDING, rv);
14083 rv = callback.WaitForResult();
14084 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14087 TEST_P(HttpNetworkTransactionTest,
14088 PostIgnoresNonErrorResponseAfterResetAnd100) {
14089 ScopedVector<UploadElementReader> element_readers;
14090 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14091 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14093 HttpRequestInfo request;
14094 request.method = "POST";
14095 request.url = GURL("http://www.foo.com/");
14096 request.upload_data_stream = &upload_data_stream;
14097 request.load_flags = 0;
14099 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14100 scoped_ptr<HttpTransaction> trans(
14101 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14102 // Send headers successfully, but get an error while sending the body.
14103 MockWrite data_writes[] = {
14104 MockWrite("POST / HTTP/1.1\r\n"
14105 "Host: www.foo.com\r\n"
14106 "Connection: keep-alive\r\n"
14107 "Content-Length: 3\r\n\r\n"),
14108 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14111 MockRead data_reads[] = {
14112 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14113 MockRead("HTTP/1.0 302 Redirect\r\n"),
14114 MockRead("Location: http://somewhere-else.com/\r\n"),
14115 MockRead("Content-Length: 0\r\n\r\n"),
14116 MockRead(SYNCHRONOUS, OK),
14118 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14119 arraysize(data_writes));
14120 session_deps_.socket_factory->AddSocketDataProvider(&data);
14122 TestCompletionCallback callback;
14124 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14125 EXPECT_EQ(ERR_IO_PENDING, rv);
14127 rv = callback.WaitForResult();
14128 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14131 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
14132 ScopedVector<UploadElementReader> element_readers;
14133 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14134 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14136 HttpRequestInfo request;
14137 request.method = "POST";
14138 request.url = GURL("http://www.foo.com/");
14139 request.upload_data_stream = &upload_data_stream;
14140 request.load_flags = 0;
14142 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14143 scoped_ptr<HttpTransaction> trans(
14144 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14145 // Send headers successfully, but get an error while sending the body.
14146 MockWrite data_writes[] = {
14147 MockWrite("POST / HTTP/1.1\r\n"
14148 "Host: www.foo.com\r\n"
14149 "Connection: keep-alive\r\n"
14150 "Content-Length: 3\r\n\r\n"),
14151 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14154 MockRead data_reads[] = {
14155 MockRead("HTTP 0.9 rocks!"),
14156 MockRead(SYNCHRONOUS, OK),
14158 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14159 arraysize(data_writes));
14160 session_deps_.socket_factory->AddSocketDataProvider(&data);
14162 TestCompletionCallback callback;
14164 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14165 EXPECT_EQ(ERR_IO_PENDING, rv);
14167 rv = callback.WaitForResult();
14168 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14171 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
14172 ScopedVector<UploadElementReader> element_readers;
14173 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14174 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14176 HttpRequestInfo request;
14177 request.method = "POST";
14178 request.url = GURL("http://www.foo.com/");
14179 request.upload_data_stream = &upload_data_stream;
14180 request.load_flags = 0;
14182 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14183 scoped_ptr<HttpTransaction> trans(
14184 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14185 // Send headers successfully, but get an error while sending the body.
14186 MockWrite data_writes[] = {
14187 MockWrite("POST / HTTP/1.1\r\n"
14188 "Host: www.foo.com\r\n"
14189 "Connection: keep-alive\r\n"
14190 "Content-Length: 3\r\n\r\n"),
14191 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14194 MockRead data_reads[] = {
14195 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14196 MockRead(SYNCHRONOUS, OK),
14198 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14199 arraysize(data_writes));
14200 session_deps_.socket_factory->AddSocketDataProvider(&data);
14202 TestCompletionCallback callback;
14204 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14205 EXPECT_EQ(ERR_IO_PENDING, rv);
14207 rv = callback.WaitForResult();
14208 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14211 // Verify that proxy headers are not sent to the destination server when
14212 // establishing a tunnel for a secure WebSocket connection.
14213 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
14214 HttpRequestInfo request;
14215 request.method = "GET";
14216 request.url = GURL("wss://www.example.org/");
14217 AddWebSocketHeaders(&request.extra_headers);
14219 // Configure against proxy server "myproxy:70".
14220 session_deps_.proxy_service.reset(
14221 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14223 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14225 // Since a proxy is configured, try to establish a tunnel.
14226 MockWrite data_writes[] = {
14227 MockWrite(
14228 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14229 "Host: www.example.org\r\n"
14230 "Proxy-Connection: keep-alive\r\n\r\n"),
14232 // After calling trans->RestartWithAuth(), this is the request we should
14233 // be issuing -- the final header line contains the credentials.
14234 MockWrite(
14235 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14236 "Host: www.example.org\r\n"
14237 "Proxy-Connection: keep-alive\r\n"
14238 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14240 MockWrite(
14241 "GET / HTTP/1.1\r\n"
14242 "Host: www.example.org\r\n"
14243 "Connection: Upgrade\r\n"
14244 "Upgrade: websocket\r\n"
14245 "Origin: http://www.example.org\r\n"
14246 "Sec-WebSocket-Version: 13\r\n"
14247 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14250 // The proxy responds to the connect with a 407, using a persistent
14251 // connection.
14252 MockRead data_reads[] = {
14253 // No credentials.
14254 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14255 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14256 MockRead("Proxy-Connection: close\r\n\r\n"),
14258 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14260 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14261 MockRead("Upgrade: websocket\r\n"),
14262 MockRead("Connection: Upgrade\r\n"),
14263 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14266 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14267 arraysize(data_writes));
14268 session_deps_.socket_factory->AddSocketDataProvider(&data);
14269 SSLSocketDataProvider ssl(ASYNC, OK);
14270 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14272 scoped_ptr<HttpTransaction> trans(
14273 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14274 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14275 trans->SetWebSocketHandshakeStreamCreateHelper(
14276 &websocket_stream_create_helper);
14279 TestCompletionCallback callback;
14281 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14282 EXPECT_EQ(ERR_IO_PENDING, rv);
14284 rv = callback.WaitForResult();
14285 EXPECT_EQ(OK, rv);
14288 const HttpResponseInfo* response = trans->GetResponseInfo();
14289 ASSERT_TRUE(response);
14290 ASSERT_TRUE(response->headers.get());
14291 EXPECT_EQ(407, response->headers->response_code());
14294 TestCompletionCallback callback;
14296 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
14297 callback.callback());
14298 EXPECT_EQ(ERR_IO_PENDING, rv);
14300 rv = callback.WaitForResult();
14301 EXPECT_EQ(OK, rv);
14304 response = trans->GetResponseInfo();
14305 ASSERT_TRUE(response);
14306 ASSERT_TRUE(response->headers.get());
14308 EXPECT_EQ(101, response->headers->response_code());
14310 trans.reset();
14311 session->CloseAllConnections();
14314 // Verify that proxy headers are not sent to the destination server when
14315 // establishing a tunnel for an insecure WebSocket connection.
14316 // This requires the authentication info to be injected into the auth cache
14317 // due to crbug.com/395064
14318 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14319 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
14320 HttpRequestInfo request;
14321 request.method = "GET";
14322 request.url = GURL("ws://www.example.org/");
14323 AddWebSocketHeaders(&request.extra_headers);
14325 // Configure against proxy server "myproxy:70".
14326 session_deps_.proxy_service.reset(
14327 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14329 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14331 MockWrite data_writes[] = {
14332 // Try to establish a tunnel for the WebSocket connection, with
14333 // credentials. Because WebSockets have a separate set of socket pools,
14334 // they cannot and will not use the same TCP/IP connection as the
14335 // preflight HTTP request.
14336 MockWrite(
14337 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14338 "Host: www.example.org:80\r\n"
14339 "Proxy-Connection: keep-alive\r\n"
14340 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14342 MockWrite(
14343 "GET / HTTP/1.1\r\n"
14344 "Host: www.example.org\r\n"
14345 "Connection: Upgrade\r\n"
14346 "Upgrade: websocket\r\n"
14347 "Origin: http://www.example.org\r\n"
14348 "Sec-WebSocket-Version: 13\r\n"
14349 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14352 MockRead data_reads[] = {
14353 // HTTP CONNECT with credentials.
14354 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14356 // WebSocket connection established inside tunnel.
14357 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14358 MockRead("Upgrade: websocket\r\n"),
14359 MockRead("Connection: Upgrade\r\n"),
14360 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14363 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14364 arraysize(data_writes));
14365 session_deps_.socket_factory->AddSocketDataProvider(&data);
14367 session->http_auth_cache()->Add(
14368 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
14369 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
14371 scoped_ptr<HttpTransaction> trans(
14372 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14373 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14374 trans->SetWebSocketHandshakeStreamCreateHelper(
14375 &websocket_stream_create_helper);
14377 TestCompletionCallback callback;
14379 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14380 EXPECT_EQ(ERR_IO_PENDING, rv);
14382 rv = callback.WaitForResult();
14383 EXPECT_EQ(OK, rv);
14385 const HttpResponseInfo* response = trans->GetResponseInfo();
14386 ASSERT_TRUE(response);
14387 ASSERT_TRUE(response->headers.get());
14389 EXPECT_EQ(101, response->headers->response_code());
14391 trans.reset();
14392 session->CloseAllConnections();
14395 } // namespace net