Roll src/third_party/skia 4cf9e7e:8ee06f2
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blobe4a638280994d3da85fbc5840e552f11e614a2fb
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(
1039 "HEAD / HTTP/1.1\r\n"
1040 "Host: www.example.org\r\n"
1041 "Connection: keep-alive\r\n"
1042 "Content-Length: 0\r\n\r\n"),
1044 MockRead data_reads1[] = {
1045 MockRead("HTTP/1.1 404 Not Found\r\n"),
1046 MockRead("Server: Blah\r\n"),
1047 MockRead("Content-Length: 1234\r\n\r\n"),
1049 // No response body because the test stops reading here.
1050 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1053 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1054 data_writes1, arraysize(data_writes1));
1055 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1057 TestCompletionCallback callback1;
1059 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1060 EXPECT_EQ(ERR_IO_PENDING, rv);
1062 rv = callback1.WaitForResult();
1063 EXPECT_EQ(OK, rv);
1065 const HttpResponseInfo* response = trans->GetResponseInfo();
1066 ASSERT_TRUE(response != NULL);
1068 // Check that the headers got parsed.
1069 EXPECT_TRUE(response->headers.get() != NULL);
1070 EXPECT_EQ(1234, response->headers->GetContentLength());
1071 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1072 EXPECT_TRUE(response->proxy_server.IsEmpty());
1073 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1075 std::string server_header;
1076 void* iter = NULL;
1077 bool has_server_header = response->headers->EnumerateHeader(
1078 &iter, "Server", &server_header);
1079 EXPECT_TRUE(has_server_header);
1080 EXPECT_EQ("Blah", server_header);
1082 // Reading should give EOF right away, since there is no message body
1083 // (despite non-zero content-length).
1084 std::string response_data;
1085 rv = ReadTransaction(trans.get(), &response_data);
1086 EXPECT_EQ(OK, rv);
1087 EXPECT_EQ("", response_data);
1090 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1091 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1093 MockRead data_reads[] = {
1094 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1095 MockRead("hello"),
1096 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1097 MockRead("world"),
1098 MockRead(SYNCHRONOUS, OK),
1100 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1101 session_deps_.socket_factory->AddSocketDataProvider(&data);
1103 const char* const kExpectedResponseData[] = {
1104 "hello", "world"
1107 for (int i = 0; i < 2; ++i) {
1108 HttpRequestInfo request;
1109 request.method = "GET";
1110 request.url = GURL("http://www.example.org/");
1111 request.load_flags = 0;
1113 scoped_ptr<HttpTransaction> trans(
1114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1116 TestCompletionCallback callback;
1118 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1119 EXPECT_EQ(ERR_IO_PENDING, rv);
1121 rv = callback.WaitForResult();
1122 EXPECT_EQ(OK, rv);
1124 const HttpResponseInfo* response = trans->GetResponseInfo();
1125 ASSERT_TRUE(response != NULL);
1127 EXPECT_TRUE(response->headers.get() != NULL);
1128 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1129 EXPECT_TRUE(response->proxy_server.IsEmpty());
1131 std::string response_data;
1132 rv = ReadTransaction(trans.get(), &response_data);
1133 EXPECT_EQ(OK, rv);
1134 EXPECT_EQ(kExpectedResponseData[i], response_data);
1138 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1139 ScopedVector<UploadElementReader> element_readers;
1140 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1141 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
1143 HttpRequestInfo request;
1144 request.method = "POST";
1145 request.url = GURL("http://www.foo.com/");
1146 request.upload_data_stream = &upload_data_stream;
1147 request.load_flags = 0;
1149 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1150 scoped_ptr<HttpTransaction> trans(
1151 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1153 MockRead data_reads[] = {
1154 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1155 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1156 MockRead("hello world"),
1157 MockRead(SYNCHRONOUS, OK),
1159 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1160 session_deps_.socket_factory->AddSocketDataProvider(&data);
1162 TestCompletionCallback callback;
1164 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1165 EXPECT_EQ(ERR_IO_PENDING, rv);
1167 rv = callback.WaitForResult();
1168 EXPECT_EQ(OK, rv);
1170 const HttpResponseInfo* response = trans->GetResponseInfo();
1171 ASSERT_TRUE(response != NULL);
1173 EXPECT_TRUE(response->headers.get() != NULL);
1174 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1176 std::string response_data;
1177 rv = ReadTransaction(trans.get(), &response_data);
1178 EXPECT_EQ(OK, rv);
1179 EXPECT_EQ("hello world", response_data);
1182 // This test is almost the same as Ignores100 above, but the response contains
1183 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1184 // HTTP/1.1 and the two status headers are read in one read.
1185 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1186 HttpRequestInfo request;
1187 request.method = "GET";
1188 request.url = GURL("http://www.foo.com/");
1189 request.load_flags = 0;
1191 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1192 scoped_ptr<HttpTransaction> trans(
1193 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1195 MockRead data_reads[] = {
1196 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1197 "HTTP/1.1 200 OK\r\n\r\n"),
1198 MockRead("hello world"),
1199 MockRead(SYNCHRONOUS, OK),
1201 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1202 session_deps_.socket_factory->AddSocketDataProvider(&data);
1204 TestCompletionCallback callback;
1206 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1207 EXPECT_EQ(ERR_IO_PENDING, rv);
1209 rv = callback.WaitForResult();
1210 EXPECT_EQ(OK, rv);
1212 const HttpResponseInfo* response = trans->GetResponseInfo();
1213 ASSERT_TRUE(response != NULL);
1215 EXPECT_TRUE(response->headers.get() != NULL);
1216 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1218 std::string response_data;
1219 rv = ReadTransaction(trans.get(), &response_data);
1220 EXPECT_EQ(OK, rv);
1221 EXPECT_EQ("hello world", response_data);
1224 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1225 HttpRequestInfo request;
1226 request.method = "POST";
1227 request.url = GURL("http://www.foo.com/");
1228 request.load_flags = 0;
1230 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1231 scoped_ptr<HttpTransaction> trans(
1232 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1234 MockRead data_reads[] = {
1235 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1236 MockRead(ASYNC, 0),
1238 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1239 session_deps_.socket_factory->AddSocketDataProvider(&data);
1241 TestCompletionCallback callback;
1243 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1244 EXPECT_EQ(ERR_IO_PENDING, rv);
1246 rv = callback.WaitForResult();
1247 EXPECT_EQ(OK, rv);
1249 std::string response_data;
1250 rv = ReadTransaction(trans.get(), &response_data);
1251 EXPECT_EQ(OK, rv);
1252 EXPECT_EQ("", response_data);
1255 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1256 HttpRequestInfo request;
1257 request.method = "POST";
1258 request.url = GURL("http://www.foo.com/");
1259 request.load_flags = 0;
1261 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1262 scoped_ptr<HttpTransaction> trans(
1263 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1265 MockRead data_reads[] = {
1266 MockRead(ASYNC, 0),
1268 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1269 session_deps_.socket_factory->AddSocketDataProvider(&data);
1271 TestCompletionCallback callback;
1273 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1274 EXPECT_EQ(ERR_IO_PENDING, rv);
1276 rv = callback.WaitForResult();
1277 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1280 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1281 const MockWrite* write_failure,
1282 const MockRead* read_failure) {
1283 HttpRequestInfo request;
1284 request.method = "GET";
1285 request.url = GURL("http://www.foo.com/");
1286 request.load_flags = 0;
1288 TestNetLog net_log;
1289 session_deps_.net_log = &net_log;
1290 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1292 // Written data for successfully sending both requests.
1293 MockWrite data1_writes[] = {
1294 MockWrite("GET / HTTP/1.1\r\n"
1295 "Host: www.foo.com\r\n"
1296 "Connection: keep-alive\r\n\r\n"),
1297 MockWrite("GET / HTTP/1.1\r\n"
1298 "Host: www.foo.com\r\n"
1299 "Connection: keep-alive\r\n\r\n")
1302 // Read results for the first request.
1303 MockRead data1_reads[] = {
1304 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1305 MockRead("hello"),
1306 MockRead(ASYNC, OK),
1309 if (write_failure) {
1310 ASSERT_FALSE(read_failure);
1311 data1_writes[1] = *write_failure;
1312 } else {
1313 ASSERT_TRUE(read_failure);
1314 data1_reads[2] = *read_failure;
1317 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1318 data1_writes, arraysize(data1_writes));
1319 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1321 MockRead data2_reads[] = {
1322 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1323 MockRead("world"),
1324 MockRead(ASYNC, OK),
1326 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1327 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1329 const char* const kExpectedResponseData[] = {
1330 "hello", "world"
1333 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1334 for (int i = 0; i < 2; ++i) {
1335 TestCompletionCallback callback;
1337 scoped_ptr<HttpTransaction> trans(
1338 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1340 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1341 EXPECT_EQ(ERR_IO_PENDING, rv);
1343 rv = callback.WaitForResult();
1344 EXPECT_EQ(OK, rv);
1346 LoadTimingInfo load_timing_info;
1347 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1348 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1349 if (i == 0) {
1350 first_socket_log_id = load_timing_info.socket_log_id;
1351 } else {
1352 // The second request should be using a new socket.
1353 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1356 const HttpResponseInfo* response = trans->GetResponseInfo();
1357 ASSERT_TRUE(response != NULL);
1359 EXPECT_TRUE(response->headers.get() != NULL);
1360 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1362 std::string response_data;
1363 rv = ReadTransaction(trans.get(), &response_data);
1364 EXPECT_EQ(OK, rv);
1365 EXPECT_EQ(kExpectedResponseData[i], response_data);
1369 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1370 const MockWrite* write_failure,
1371 const MockRead* read_failure,
1372 bool use_spdy) {
1373 HttpRequestInfo request;
1374 request.method = "GET";
1375 request.url = GURL("https://www.foo.com/");
1376 request.load_flags = 0;
1378 TestNetLog net_log;
1379 session_deps_.net_log = &net_log;
1380 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1382 SSLSocketDataProvider ssl1(ASYNC, OK);
1383 SSLSocketDataProvider ssl2(ASYNC, OK);
1384 if (use_spdy) {
1385 ssl1.SetNextProto(GetParam());
1386 ssl2.SetNextProto(GetParam());
1388 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1389 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1391 // SPDY versions of the request and response.
1392 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1393 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1394 scoped_ptr<SpdyFrame> spdy_response(
1395 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1396 scoped_ptr<SpdyFrame> spdy_data(
1397 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1399 // HTTP/1.1 versions of the request and response.
1400 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1401 "Host: www.foo.com\r\n"
1402 "Connection: keep-alive\r\n\r\n";
1403 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1404 const char kHttpData[] = "hello";
1406 std::vector<MockRead> data1_reads;
1407 std::vector<MockWrite> data1_writes;
1408 if (write_failure) {
1409 ASSERT_FALSE(read_failure);
1410 data1_writes.push_back(*write_failure);
1411 data1_reads.push_back(MockRead(ASYNC, OK));
1412 } else {
1413 ASSERT_TRUE(read_failure);
1414 if (use_spdy) {
1415 data1_writes.push_back(CreateMockWrite(*spdy_request));
1416 } else {
1417 data1_writes.push_back(MockWrite(kHttpRequest));
1419 data1_reads.push_back(*read_failure);
1422 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1423 &data1_writes[0], data1_writes.size());
1424 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1426 std::vector<MockRead> data2_reads;
1427 std::vector<MockWrite> data2_writes;
1429 if (use_spdy) {
1430 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1432 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1433 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1434 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1435 } else {
1436 data2_writes.push_back(
1437 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1439 data2_reads.push_back(
1440 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1441 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1442 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1444 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1445 &data2_writes[0], data2_writes.size());
1446 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1448 // Preconnect a socket.
1449 SSLConfig ssl_config;
1450 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1451 session->GetNextProtos(&ssl_config.next_protos);
1452 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1453 ssl_config);
1454 // Wait for the preconnect to complete.
1455 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1456 base::RunLoop().RunUntilIdle();
1457 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1459 // Make the request.
1460 TestCompletionCallback callback;
1462 scoped_ptr<HttpTransaction> trans(
1463 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1465 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1466 EXPECT_EQ(ERR_IO_PENDING, rv);
1468 rv = callback.WaitForResult();
1469 EXPECT_EQ(OK, rv);
1471 LoadTimingInfo load_timing_info;
1472 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1473 TestLoadTimingNotReused(
1474 load_timing_info,
1475 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1477 const HttpResponseInfo* response = trans->GetResponseInfo();
1478 ASSERT_TRUE(response != NULL);
1480 EXPECT_TRUE(response->headers.get() != NULL);
1481 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1483 std::string response_data;
1484 rv = ReadTransaction(trans.get(), &response_data);
1485 EXPECT_EQ(OK, rv);
1486 EXPECT_EQ(kHttpData, response_data);
1489 TEST_P(HttpNetworkTransactionTest,
1490 KeepAliveConnectionNotConnectedOnWrite) {
1491 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1492 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1495 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1496 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1497 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1500 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1501 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1502 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1505 // Make sure that on a 408 response (Request Timeout), the request is retried,
1506 // if the socket was a reused keep alive socket.
1507 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1508 MockRead read_failure(SYNCHRONOUS,
1509 "HTTP/1.1 408 Request Timeout\r\n"
1510 "Connection: Keep-Alive\r\n"
1511 "Content-Length: 6\r\n\r\n"
1512 "Pickle");
1513 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1516 TEST_P(HttpNetworkTransactionTest,
1517 PreconnectErrorNotConnectedOnWrite) {
1518 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1519 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1522 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1523 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1524 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1527 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1528 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1529 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1532 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1533 MockRead read_failure(ASYNC, OK); // EOF
1534 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1537 // Make sure that on a 408 response (Request Timeout), the request is retried,
1538 // if the socket was a preconnected (UNUSED_IDLE) socket.
1539 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1540 MockRead read_failure(SYNCHRONOUS,
1541 "HTTP/1.1 408 Request Timeout\r\n"
1542 "Connection: Keep-Alive\r\n"
1543 "Content-Length: 6\r\n\r\n"
1544 "Pickle");
1545 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1546 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1549 TEST_P(HttpNetworkTransactionTest,
1550 SpdyPreconnectErrorNotConnectedOnWrite) {
1551 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1552 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1555 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1556 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1557 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1560 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1561 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1562 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1565 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1566 MockRead read_failure(ASYNC, OK); // EOF
1567 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1570 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1571 HttpRequestInfo request;
1572 request.method = "GET";
1573 request.url = GURL("http://www.example.org/");
1574 request.load_flags = 0;
1576 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1577 scoped_ptr<HttpTransaction> trans(
1578 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1580 MockRead data_reads[] = {
1581 MockRead(ASYNC, ERR_CONNECTION_RESET),
1582 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1583 MockRead("hello world"),
1584 MockRead(SYNCHRONOUS, OK),
1586 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1587 session_deps_.socket_factory->AddSocketDataProvider(&data);
1589 TestCompletionCallback callback;
1591 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1592 EXPECT_EQ(ERR_IO_PENDING, rv);
1594 rv = callback.WaitForResult();
1595 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1598 // What do various browsers do when the server closes a non-keepalive
1599 // connection without sending any response header or body?
1601 // IE7: error page
1602 // Safari 3.1.2 (Windows): error page
1603 // Firefox 3.0.1: blank page
1604 // Opera 9.52: after five attempts, blank page
1605 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1606 // Us: error page (EMPTY_RESPONSE)
1607 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1608 MockRead data_reads[] = {
1609 MockRead(SYNCHRONOUS, OK), // EOF
1610 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1611 MockRead("hello world"),
1612 MockRead(SYNCHRONOUS, OK),
1614 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1615 arraysize(data_reads));
1616 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1619 // Test that network access can be deferred and resumed.
1620 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1621 HttpRequestInfo request;
1622 request.method = "GET";
1623 request.url = GURL("http://www.example.org/");
1624 request.load_flags = 0;
1626 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1627 scoped_ptr<HttpTransaction> trans(
1628 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1630 // Defer on OnBeforeNetworkStart.
1631 BeforeNetworkStartHandler net_start_handler(true); // defer
1632 trans->SetBeforeNetworkStartCallback(
1633 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1634 base::Unretained(&net_start_handler)));
1636 MockRead data_reads[] = {
1637 MockRead("HTTP/1.0 200 OK\r\n"),
1638 MockRead("Content-Length: 5\r\n\r\n"),
1639 MockRead("hello"),
1640 MockRead(SYNCHRONOUS, 0),
1642 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1643 session_deps_.socket_factory->AddSocketDataProvider(&data);
1645 TestCompletionCallback callback;
1647 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1648 EXPECT_EQ(ERR_IO_PENDING, rv);
1649 base::MessageLoop::current()->RunUntilIdle();
1651 // Should have deferred for network start.
1652 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1653 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1655 trans->ResumeNetworkStart();
1656 rv = callback.WaitForResult();
1657 EXPECT_EQ(OK, rv);
1658 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1660 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1661 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1662 if (rv == ERR_IO_PENDING)
1663 rv = callback.WaitForResult();
1664 EXPECT_EQ(5, rv);
1665 trans.reset();
1668 // Test that network use can be deferred and canceled.
1669 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1670 HttpRequestInfo request;
1671 request.method = "GET";
1672 request.url = GURL("http://www.example.org/");
1673 request.load_flags = 0;
1675 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1676 scoped_ptr<HttpTransaction> trans(
1677 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1679 // Defer on OnBeforeNetworkStart.
1680 BeforeNetworkStartHandler net_start_handler(true); // defer
1681 trans->SetBeforeNetworkStartCallback(
1682 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1683 base::Unretained(&net_start_handler)));
1685 TestCompletionCallback callback;
1687 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1688 EXPECT_EQ(ERR_IO_PENDING, rv);
1689 base::MessageLoop::current()->RunUntilIdle();
1691 // Should have deferred for network start.
1692 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1693 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1696 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1697 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1698 // destructor in such situations.
1699 // See http://crbug.com/154712 and http://crbug.com/156609.
1700 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1701 HttpRequestInfo request;
1702 request.method = "GET";
1703 request.url = GURL("http://www.example.org/");
1704 request.load_flags = 0;
1706 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1707 scoped_ptr<HttpTransaction> trans(
1708 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1710 MockRead data_reads[] = {
1711 MockRead("HTTP/1.0 200 OK\r\n"),
1712 MockRead("Connection: keep-alive\r\n"),
1713 MockRead("Content-Length: 100\r\n\r\n"),
1714 MockRead("hello"),
1715 MockRead(SYNCHRONOUS, 0),
1717 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1718 session_deps_.socket_factory->AddSocketDataProvider(&data);
1720 TestCompletionCallback callback;
1722 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1723 EXPECT_EQ(ERR_IO_PENDING, rv);
1725 rv = callback.WaitForResult();
1726 EXPECT_EQ(OK, rv);
1728 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1729 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1730 if (rv == ERR_IO_PENDING)
1731 rv = callback.WaitForResult();
1732 EXPECT_EQ(5, rv);
1733 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1734 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1736 trans.reset();
1737 base::MessageLoop::current()->RunUntilIdle();
1738 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1741 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1742 HttpRequestInfo request;
1743 request.method = "GET";
1744 request.url = GURL("http://www.example.org/");
1745 request.load_flags = 0;
1747 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1748 scoped_ptr<HttpTransaction> trans(
1749 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1751 MockRead data_reads[] = {
1752 MockRead("HTTP/1.0 200 OK\r\n"),
1753 MockRead("Connection: keep-alive\r\n"),
1754 MockRead("Content-Length: 100\r\n\r\n"),
1755 MockRead(SYNCHRONOUS, 0),
1757 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1758 session_deps_.socket_factory->AddSocketDataProvider(&data);
1760 TestCompletionCallback callback;
1762 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1763 EXPECT_EQ(ERR_IO_PENDING, rv);
1765 rv = callback.WaitForResult();
1766 EXPECT_EQ(OK, rv);
1768 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1769 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1770 if (rv == ERR_IO_PENDING)
1771 rv = callback.WaitForResult();
1772 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1774 trans.reset();
1775 base::MessageLoop::current()->RunUntilIdle();
1776 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1779 // Test that we correctly reuse a keep-alive connection after not explicitly
1780 // reading the body.
1781 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1782 HttpRequestInfo request;
1783 request.method = "GET";
1784 request.url = GURL("http://www.foo.com/");
1785 request.load_flags = 0;
1787 TestNetLog net_log;
1788 session_deps_.net_log = &net_log;
1789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1791 // Note that because all these reads happen in the same
1792 // StaticSocketDataProvider, it shows that the same socket is being reused for
1793 // all transactions.
1794 MockRead data1_reads[] = {
1795 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1796 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1797 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1798 MockRead("HTTP/1.1 302 Found\r\n"
1799 "Content-Length: 0\r\n\r\n"),
1800 MockRead("HTTP/1.1 302 Found\r\n"
1801 "Content-Length: 5\r\n\r\n"
1802 "hello"),
1803 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1804 "Content-Length: 0\r\n\r\n"),
1805 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1806 "Content-Length: 5\r\n\r\n"
1807 "hello"),
1808 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1809 MockRead("hello"),
1811 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1812 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1814 MockRead data2_reads[] = {
1815 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1817 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1818 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1820 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1821 std::string response_lines[kNumUnreadBodies];
1823 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1824 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1825 TestCompletionCallback callback;
1827 scoped_ptr<HttpTransaction> trans(
1828 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1830 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1831 EXPECT_EQ(ERR_IO_PENDING, rv);
1833 rv = callback.WaitForResult();
1834 EXPECT_EQ(OK, rv);
1836 LoadTimingInfo load_timing_info;
1837 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1838 if (i == 0) {
1839 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1840 first_socket_log_id = load_timing_info.socket_log_id;
1841 } else {
1842 TestLoadTimingReused(load_timing_info);
1843 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1846 const HttpResponseInfo* response = trans->GetResponseInfo();
1847 ASSERT_TRUE(response != NULL);
1849 ASSERT_TRUE(response->headers.get() != NULL);
1850 response_lines[i] = response->headers->GetStatusLine();
1852 // We intentionally don't read the response bodies.
1855 const char* const kStatusLines[] = {
1856 "HTTP/1.1 204 No Content",
1857 "HTTP/1.1 205 Reset Content",
1858 "HTTP/1.1 304 Not Modified",
1859 "HTTP/1.1 302 Found",
1860 "HTTP/1.1 302 Found",
1861 "HTTP/1.1 301 Moved Permanently",
1862 "HTTP/1.1 301 Moved Permanently",
1865 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1866 "forgot to update kStatusLines");
1868 for (int i = 0; i < kNumUnreadBodies; ++i)
1869 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1871 TestCompletionCallback callback;
1872 scoped_ptr<HttpTransaction> trans(
1873 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1874 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1875 EXPECT_EQ(ERR_IO_PENDING, rv);
1876 rv = callback.WaitForResult();
1877 EXPECT_EQ(OK, rv);
1878 const HttpResponseInfo* response = trans->GetResponseInfo();
1879 ASSERT_TRUE(response != NULL);
1880 ASSERT_TRUE(response->headers.get() != NULL);
1881 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1882 std::string response_data;
1883 rv = ReadTransaction(trans.get(), &response_data);
1884 EXPECT_EQ(OK, rv);
1885 EXPECT_EQ("hello", response_data);
1888 // Test the request-challenge-retry sequence for basic auth.
1889 // (basic auth is the easiest to mock, because it has no randomness).
1890 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1891 HttpRequestInfo request;
1892 request.method = "GET";
1893 request.url = GURL("http://www.example.org/");
1894 request.load_flags = 0;
1896 TestNetLog log;
1897 session_deps_.net_log = &log;
1898 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1899 scoped_ptr<HttpTransaction> trans(
1900 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1902 MockWrite data_writes1[] = {
1903 MockWrite(
1904 "GET / HTTP/1.1\r\n"
1905 "Host: www.example.org\r\n"
1906 "Connection: keep-alive\r\n\r\n"),
1909 MockRead data_reads1[] = {
1910 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1911 // Give a couple authenticate options (only the middle one is actually
1912 // supported).
1913 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1914 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1915 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1916 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1917 // Large content-length -- won't matter, as connection will be reset.
1918 MockRead("Content-Length: 10000\r\n\r\n"),
1919 MockRead(SYNCHRONOUS, ERR_FAILED),
1922 // After calling trans->RestartWithAuth(), this is the request we should
1923 // be issuing -- the final header line contains the credentials.
1924 MockWrite data_writes2[] = {
1925 MockWrite(
1926 "GET / HTTP/1.1\r\n"
1927 "Host: www.example.org\r\n"
1928 "Connection: keep-alive\r\n"
1929 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1932 // Lastly, the server responds with the actual content.
1933 MockRead data_reads2[] = {
1934 MockRead("HTTP/1.0 200 OK\r\n"),
1935 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1936 MockRead("Content-Length: 100\r\n\r\n"),
1937 MockRead(SYNCHRONOUS, OK),
1940 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1941 data_writes1, arraysize(data_writes1));
1942 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1943 data_writes2, arraysize(data_writes2));
1944 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1945 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1947 TestCompletionCallback callback1;
1949 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1950 EXPECT_EQ(ERR_IO_PENDING, rv);
1952 rv = callback1.WaitForResult();
1953 EXPECT_EQ(OK, rv);
1955 LoadTimingInfo load_timing_info1;
1956 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1957 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1959 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1960 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1962 const HttpResponseInfo* response = trans->GetResponseInfo();
1963 ASSERT_TRUE(response != NULL);
1964 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1966 TestCompletionCallback callback2;
1968 rv = trans->RestartWithAuth(
1969 AuthCredentials(kFoo, kBar), callback2.callback());
1970 EXPECT_EQ(ERR_IO_PENDING, rv);
1972 rv = callback2.WaitForResult();
1973 EXPECT_EQ(OK, rv);
1975 LoadTimingInfo load_timing_info2;
1976 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1977 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1978 // The load timing after restart should have a new socket ID, and times after
1979 // those of the first load timing.
1980 EXPECT_LE(load_timing_info1.receive_headers_end,
1981 load_timing_info2.connect_timing.connect_start);
1982 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1984 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1985 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1987 response = trans->GetResponseInfo();
1988 ASSERT_TRUE(response != NULL);
1989 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1990 EXPECT_EQ(100, response->headers->GetContentLength());
1993 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1994 HttpRequestInfo request;
1995 request.method = "GET";
1996 request.url = GURL("http://www.example.org/");
1997 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
1999 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2000 scoped_ptr<HttpTransaction> trans(
2001 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2003 MockWrite data_writes[] = {
2004 MockWrite(
2005 "GET / HTTP/1.1\r\n"
2006 "Host: www.example.org\r\n"
2007 "Connection: keep-alive\r\n\r\n"),
2010 MockRead data_reads[] = {
2011 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2012 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2013 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2014 // Large content-length -- won't matter, as connection will be reset.
2015 MockRead("Content-Length: 10000\r\n\r\n"),
2016 MockRead(SYNCHRONOUS, ERR_FAILED),
2019 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2020 data_writes, arraysize(data_writes));
2021 session_deps_.socket_factory->AddSocketDataProvider(&data);
2022 TestCompletionCallback callback;
2024 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2025 EXPECT_EQ(ERR_IO_PENDING, rv);
2027 rv = callback.WaitForResult();
2028 EXPECT_EQ(0, rv);
2030 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2031 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2033 const HttpResponseInfo* response = trans->GetResponseInfo();
2034 ASSERT_TRUE(response != NULL);
2035 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2038 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2039 // connection.
2040 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2041 HttpRequestInfo request;
2042 request.method = "GET";
2043 request.url = GURL("http://www.example.org/");
2044 request.load_flags = 0;
2046 TestNetLog log;
2047 session_deps_.net_log = &log;
2048 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2050 MockWrite data_writes1[] = {
2051 MockWrite(
2052 "GET / HTTP/1.1\r\n"
2053 "Host: www.example.org\r\n"
2054 "Connection: keep-alive\r\n\r\n"),
2056 // After calling trans->RestartWithAuth(), this is the request we should
2057 // be issuing -- the final header line contains the credentials.
2058 MockWrite(
2059 "GET / HTTP/1.1\r\n"
2060 "Host: www.example.org\r\n"
2061 "Connection: keep-alive\r\n"
2062 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2065 MockRead data_reads1[] = {
2066 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2067 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2068 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2069 MockRead("Content-Length: 14\r\n\r\n"),
2070 MockRead("Unauthorized\r\n"),
2072 // Lastly, the server responds with the actual content.
2073 MockRead("HTTP/1.1 200 OK\r\n"),
2074 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2075 MockRead("Content-Length: 5\r\n\r\n"),
2076 MockRead("Hello"),
2079 // If there is a regression where we disconnect a Keep-Alive
2080 // connection during an auth roundtrip, we'll end up reading this.
2081 MockRead data_reads2[] = {
2082 MockRead(SYNCHRONOUS, ERR_FAILED),
2085 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2086 data_writes1, arraysize(data_writes1));
2087 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2088 NULL, 0);
2089 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2090 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2092 TestCompletionCallback callback1;
2094 scoped_ptr<HttpTransaction> trans(
2095 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2096 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2097 EXPECT_EQ(ERR_IO_PENDING, rv);
2099 rv = callback1.WaitForResult();
2100 EXPECT_EQ(OK, rv);
2102 LoadTimingInfo load_timing_info1;
2103 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2104 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2106 const HttpResponseInfo* response = trans->GetResponseInfo();
2107 ASSERT_TRUE(response != NULL);
2108 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2110 TestCompletionCallback callback2;
2112 rv = trans->RestartWithAuth(
2113 AuthCredentials(kFoo, kBar), callback2.callback());
2114 EXPECT_EQ(ERR_IO_PENDING, rv);
2116 rv = callback2.WaitForResult();
2117 EXPECT_EQ(OK, rv);
2119 LoadTimingInfo load_timing_info2;
2120 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2121 TestLoadTimingReused(load_timing_info2);
2122 // The load timing after restart should have the same socket ID, and times
2123 // those of the first load timing.
2124 EXPECT_LE(load_timing_info1.receive_headers_end,
2125 load_timing_info2.send_start);
2126 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2128 response = trans->GetResponseInfo();
2129 ASSERT_TRUE(response != NULL);
2130 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2131 EXPECT_EQ(5, response->headers->GetContentLength());
2133 std::string response_data;
2134 rv = ReadTransaction(trans.get(), &response_data);
2135 EXPECT_EQ(OK, rv);
2136 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2137 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2140 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2141 // connection and with no response body to drain.
2142 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2143 HttpRequestInfo request;
2144 request.method = "GET";
2145 request.url = GURL("http://www.example.org/");
2146 request.load_flags = 0;
2148 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2150 MockWrite data_writes1[] = {
2151 MockWrite(
2152 "GET / HTTP/1.1\r\n"
2153 "Host: www.example.org\r\n"
2154 "Connection: keep-alive\r\n\r\n"),
2156 // After calling trans->RestartWithAuth(), this is the request we should
2157 // be issuing -- the final header line contains the credentials.
2158 MockWrite(
2159 "GET / HTTP/1.1\r\n"
2160 "Host: www.example.org\r\n"
2161 "Connection: keep-alive\r\n"
2162 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2165 MockRead data_reads1[] = {
2166 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2167 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2168 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2170 // Lastly, the server responds with the actual content.
2171 MockRead("HTTP/1.1 200 OK\r\n"),
2172 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2173 MockRead("Content-Length: 5\r\n\r\n"),
2174 MockRead("hello"),
2177 // An incorrect reconnect would cause this to be read.
2178 MockRead data_reads2[] = {
2179 MockRead(SYNCHRONOUS, ERR_FAILED),
2182 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2183 data_writes1, arraysize(data_writes1));
2184 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2185 NULL, 0);
2186 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2187 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2189 TestCompletionCallback callback1;
2191 scoped_ptr<HttpTransaction> trans(
2192 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2193 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2194 EXPECT_EQ(ERR_IO_PENDING, rv);
2196 rv = callback1.WaitForResult();
2197 EXPECT_EQ(OK, rv);
2199 const HttpResponseInfo* response = trans->GetResponseInfo();
2200 ASSERT_TRUE(response != NULL);
2201 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2203 TestCompletionCallback callback2;
2205 rv = trans->RestartWithAuth(
2206 AuthCredentials(kFoo, kBar), callback2.callback());
2207 EXPECT_EQ(ERR_IO_PENDING, rv);
2209 rv = callback2.WaitForResult();
2210 EXPECT_EQ(OK, rv);
2212 response = trans->GetResponseInfo();
2213 ASSERT_TRUE(response != NULL);
2214 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2215 EXPECT_EQ(5, response->headers->GetContentLength());
2218 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2219 // connection and with a large response body to drain.
2220 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2221 HttpRequestInfo request;
2222 request.method = "GET";
2223 request.url = GURL("http://www.example.org/");
2224 request.load_flags = 0;
2226 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2228 MockWrite data_writes1[] = {
2229 MockWrite(
2230 "GET / HTTP/1.1\r\n"
2231 "Host: www.example.org\r\n"
2232 "Connection: keep-alive\r\n\r\n"),
2234 // After calling trans->RestartWithAuth(), this is the request we should
2235 // be issuing -- the final header line contains the credentials.
2236 MockWrite(
2237 "GET / HTTP/1.1\r\n"
2238 "Host: www.example.org\r\n"
2239 "Connection: keep-alive\r\n"
2240 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2243 // Respond with 5 kb of response body.
2244 std::string large_body_string("Unauthorized");
2245 large_body_string.append(5 * 1024, ' ');
2246 large_body_string.append("\r\n");
2248 MockRead data_reads1[] = {
2249 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2250 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2252 // 5134 = 12 + 5 * 1024 + 2
2253 MockRead("Content-Length: 5134\r\n\r\n"),
2254 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2256 // Lastly, the server responds with the actual content.
2257 MockRead("HTTP/1.1 200 OK\r\n"),
2258 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2259 MockRead("Content-Length: 5\r\n\r\n"),
2260 MockRead("hello"),
2263 // An incorrect reconnect would cause this to be read.
2264 MockRead data_reads2[] = {
2265 MockRead(SYNCHRONOUS, ERR_FAILED),
2268 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2269 data_writes1, arraysize(data_writes1));
2270 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2271 NULL, 0);
2272 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2273 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2275 TestCompletionCallback callback1;
2277 scoped_ptr<HttpTransaction> trans(
2278 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2279 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2280 EXPECT_EQ(ERR_IO_PENDING, rv);
2282 rv = callback1.WaitForResult();
2283 EXPECT_EQ(OK, rv);
2285 const HttpResponseInfo* response = trans->GetResponseInfo();
2286 ASSERT_TRUE(response != NULL);
2287 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2289 TestCompletionCallback callback2;
2291 rv = trans->RestartWithAuth(
2292 AuthCredentials(kFoo, kBar), callback2.callback());
2293 EXPECT_EQ(ERR_IO_PENDING, rv);
2295 rv = callback2.WaitForResult();
2296 EXPECT_EQ(OK, rv);
2298 response = trans->GetResponseInfo();
2299 ASSERT_TRUE(response != NULL);
2300 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2301 EXPECT_EQ(5, response->headers->GetContentLength());
2304 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2305 // connection, but the server gets impatient and closes the connection.
2306 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2307 HttpRequestInfo request;
2308 request.method = "GET";
2309 request.url = GURL("http://www.example.org/");
2310 request.load_flags = 0;
2312 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2314 MockWrite data_writes1[] = {
2315 MockWrite(
2316 "GET / HTTP/1.1\r\n"
2317 "Host: www.example.org\r\n"
2318 "Connection: keep-alive\r\n\r\n"),
2319 // This simulates the seemingly successful write to a closed connection
2320 // if the bug is not fixed.
2321 MockWrite(
2322 "GET / HTTP/1.1\r\n"
2323 "Host: www.example.org\r\n"
2324 "Connection: keep-alive\r\n"
2325 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2328 MockRead data_reads1[] = {
2329 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2330 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2331 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2332 MockRead("Content-Length: 14\r\n\r\n"),
2333 // Tell MockTCPClientSocket to simulate the server closing the connection.
2334 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2335 MockRead("Unauthorized\r\n"),
2336 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2339 // After calling trans->RestartWithAuth(), this is the request we should
2340 // be issuing -- the final header line contains the credentials.
2341 MockWrite data_writes2[] = {
2342 MockWrite(
2343 "GET / HTTP/1.1\r\n"
2344 "Host: www.example.org\r\n"
2345 "Connection: keep-alive\r\n"
2346 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2349 // Lastly, the server responds with the actual content.
2350 MockRead data_reads2[] = {
2351 MockRead("HTTP/1.1 200 OK\r\n"),
2352 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2353 MockRead("Content-Length: 5\r\n\r\n"),
2354 MockRead("hello"),
2357 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2358 data_writes1, arraysize(data_writes1));
2359 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2360 data_writes2, arraysize(data_writes2));
2361 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2362 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2364 TestCompletionCallback callback1;
2366 scoped_ptr<HttpTransaction> trans(
2367 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2368 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2369 EXPECT_EQ(ERR_IO_PENDING, rv);
2371 rv = callback1.WaitForResult();
2372 EXPECT_EQ(OK, rv);
2374 const HttpResponseInfo* response = trans->GetResponseInfo();
2375 ASSERT_TRUE(response != NULL);
2376 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2378 TestCompletionCallback callback2;
2380 rv = trans->RestartWithAuth(
2381 AuthCredentials(kFoo, kBar), callback2.callback());
2382 EXPECT_EQ(ERR_IO_PENDING, rv);
2384 rv = callback2.WaitForResult();
2385 EXPECT_EQ(OK, rv);
2387 response = trans->GetResponseInfo();
2388 ASSERT_TRUE(response != NULL);
2389 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2390 EXPECT_EQ(5, response->headers->GetContentLength());
2393 // Test the request-challenge-retry sequence for basic auth, over a connection
2394 // that requires a restart when setting up an SSL tunnel.
2395 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2396 HttpRequestInfo request;
2397 request.method = "GET";
2398 request.url = GURL("https://www.example.org/");
2399 // when the no authentication data flag is set.
2400 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2402 // Configure against proxy server "myproxy:70".
2403 session_deps_.proxy_service.reset(
2404 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2405 BoundTestNetLog log;
2406 session_deps_.net_log = log.bound().net_log();
2407 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2409 // Since we have proxy, should try to establish tunnel.
2410 MockWrite data_writes1[] = {
2411 MockWrite(
2412 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2413 "Host: www.example.org\r\n"
2414 "Proxy-Connection: keep-alive\r\n\r\n"),
2416 // After calling trans->RestartWithAuth(), this is the request we should
2417 // be issuing -- the final header line contains the credentials.
2418 MockWrite(
2419 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2420 "Host: www.example.org\r\n"
2421 "Proxy-Connection: keep-alive\r\n"
2422 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2424 MockWrite(
2425 "GET / HTTP/1.1\r\n"
2426 "Host: www.example.org\r\n"
2427 "Connection: keep-alive\r\n\r\n"),
2430 // The proxy responds to the connect with a 407, using a persistent
2431 // connection.
2432 MockRead data_reads1[] = {
2433 // No credentials.
2434 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2435 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2437 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2439 MockRead("HTTP/1.1 200 OK\r\n"),
2440 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2441 MockRead("Content-Length: 5\r\n\r\n"),
2442 MockRead(SYNCHRONOUS, "hello"),
2445 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2446 data_writes1, arraysize(data_writes1));
2447 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2448 SSLSocketDataProvider ssl(ASYNC, OK);
2449 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2451 TestCompletionCallback callback1;
2453 scoped_ptr<HttpTransaction> trans(
2454 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2456 int rv = trans->Start(&request, callback1.callback(), log.bound());
2457 EXPECT_EQ(ERR_IO_PENDING, rv);
2459 rv = callback1.WaitForResult();
2460 EXPECT_EQ(OK, rv);
2461 TestNetLogEntry::List entries;
2462 log.GetEntries(&entries);
2463 size_t pos = ExpectLogContainsSomewhere(
2464 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2465 NetLog::PHASE_NONE);
2466 ExpectLogContainsSomewhere(
2467 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2468 NetLog::PHASE_NONE);
2470 const HttpResponseInfo* response = trans->GetResponseInfo();
2471 ASSERT_TRUE(response != NULL);
2472 EXPECT_FALSE(response->headers->IsKeepAlive());
2473 ASSERT_FALSE(response->headers.get() == NULL);
2474 EXPECT_EQ(407, response->headers->response_code());
2475 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2476 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2478 LoadTimingInfo load_timing_info;
2479 // CONNECT requests and responses are handled at the connect job level, so
2480 // the transaction does not yet have a connection.
2481 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2483 TestCompletionCallback callback2;
2485 rv =
2486 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2487 EXPECT_EQ(ERR_IO_PENDING, rv);
2489 rv = callback2.WaitForResult();
2490 EXPECT_EQ(OK, rv);
2492 response = trans->GetResponseInfo();
2493 ASSERT_TRUE(response != NULL);
2495 EXPECT_TRUE(response->headers->IsKeepAlive());
2496 EXPECT_EQ(200, response->headers->response_code());
2497 EXPECT_EQ(5, response->headers->GetContentLength());
2498 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2500 // The password prompt info should not be set.
2501 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2503 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2504 TestLoadTimingNotReusedWithPac(load_timing_info,
2505 CONNECT_TIMING_HAS_SSL_TIMES);
2507 trans.reset();
2508 session->CloseAllConnections();
2511 // Test the request-challenge-retry sequence for basic auth, over a connection
2512 // that requires a restart when setting up an SSL tunnel.
2513 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
2514 HttpRequestInfo request;
2515 request.method = "GET";
2516 request.url = GURL("https://www.example.org/");
2517 // when the no authentication data flag is set.
2518 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2520 // Configure against proxy server "myproxy:70".
2521 session_deps_.proxy_service.reset(
2522 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2523 BoundTestNetLog log;
2524 session_deps_.net_log = log.bound().net_log();
2525 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2527 // Since we have proxy, should try to establish tunnel.
2528 MockWrite data_writes1[] = {
2529 MockWrite(
2530 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2531 "Host: www.example.org\r\n"
2532 "Proxy-Connection: keep-alive\r\n\r\n"),
2534 // After calling trans->RestartWithAuth(), this is the request we should
2535 // be issuing -- the final header line contains the credentials.
2536 MockWrite(
2537 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2538 "Host: www.example.org\r\n"
2539 "Proxy-Connection: keep-alive\r\n"
2540 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2542 MockWrite(
2543 "GET / HTTP/1.1\r\n"
2544 "Host: www.example.org\r\n"
2545 "Connection: keep-alive\r\n\r\n"),
2548 // The proxy responds to the connect with a 407, using a persistent
2549 // connection.
2550 MockRead data_reads1[] = {
2551 // No credentials.
2552 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2553 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2554 MockRead("Proxy-Connection: close\r\n\r\n"),
2556 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2558 MockRead("HTTP/1.1 200 OK\r\n"),
2559 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2560 MockRead("Content-Length: 5\r\n\r\n"),
2561 MockRead(SYNCHRONOUS, "hello"),
2564 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2565 data_writes1, arraysize(data_writes1));
2566 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2567 SSLSocketDataProvider ssl(ASYNC, OK);
2568 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2570 TestCompletionCallback callback1;
2572 scoped_ptr<HttpTransaction> trans(
2573 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2575 int rv = trans->Start(&request, callback1.callback(), log.bound());
2576 EXPECT_EQ(ERR_IO_PENDING, rv);
2578 rv = callback1.WaitForResult();
2579 EXPECT_EQ(OK, rv);
2580 TestNetLogEntry::List entries;
2581 log.GetEntries(&entries);
2582 size_t pos = ExpectLogContainsSomewhere(
2583 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2584 NetLog::PHASE_NONE);
2585 ExpectLogContainsSomewhere(
2586 entries, pos,
2587 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2588 NetLog::PHASE_NONE);
2590 const HttpResponseInfo* response = trans->GetResponseInfo();
2591 ASSERT_TRUE(response != NULL);
2592 EXPECT_FALSE(response->headers->IsKeepAlive());
2593 ASSERT_FALSE(response->headers.get() == NULL);
2594 EXPECT_EQ(407, response->headers->response_code());
2595 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2596 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2598 LoadTimingInfo load_timing_info;
2599 // CONNECT requests and responses are handled at the connect job level, so
2600 // the transaction does not yet have a connection.
2601 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2603 TestCompletionCallback callback2;
2605 rv = trans->RestartWithAuth(
2606 AuthCredentials(kFoo, kBar), callback2.callback());
2607 EXPECT_EQ(ERR_IO_PENDING, rv);
2609 rv = callback2.WaitForResult();
2610 EXPECT_EQ(OK, rv);
2612 response = trans->GetResponseInfo();
2613 ASSERT_TRUE(response != NULL);
2615 EXPECT_TRUE(response->headers->IsKeepAlive());
2616 EXPECT_EQ(200, response->headers->response_code());
2617 EXPECT_EQ(5, response->headers->GetContentLength());
2618 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2620 // The password prompt info should not be set.
2621 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2623 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2624 TestLoadTimingNotReusedWithPac(load_timing_info,
2625 CONNECT_TIMING_HAS_SSL_TIMES);
2627 trans.reset();
2628 session->CloseAllConnections();
2631 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2632 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2633 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2634 HttpRequestInfo request;
2635 request.method = "GET";
2636 request.url = GURL("https://www.example.org/");
2637 // Ensure that proxy authentication is attempted even
2638 // when the no authentication data flag is set.
2639 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2641 // Configure against proxy server "myproxy:70".
2642 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2643 BoundTestNetLog log;
2644 session_deps_.net_log = log.bound().net_log();
2645 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2647 scoped_ptr<HttpTransaction> trans(
2648 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2650 // Since we have proxy, should try to establish tunnel.
2651 MockWrite data_writes1[] = {
2652 MockWrite(
2653 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2654 "Host: www.example.org\r\n"
2655 "Proxy-Connection: keep-alive\r\n\r\n"),
2657 // After calling trans->RestartWithAuth(), this is the request we should
2658 // be issuing -- the final header line contains the credentials.
2659 MockWrite(
2660 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2661 "Host: www.example.org\r\n"
2662 "Proxy-Connection: keep-alive\r\n"
2663 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2666 // The proxy responds to the connect with a 407, using a persistent
2667 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2668 MockRead data_reads1[] = {
2669 // No credentials.
2670 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2671 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2672 MockRead("Proxy-Connection: keep-alive\r\n"),
2673 MockRead("Content-Length: 10\r\n\r\n"),
2674 MockRead("0123456789"),
2676 // Wrong credentials (wrong password).
2677 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2678 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2679 MockRead("Proxy-Connection: keep-alive\r\n"),
2680 MockRead("Content-Length: 10\r\n\r\n"),
2681 // No response body because the test stops reading here.
2682 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2685 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2686 data_writes1, arraysize(data_writes1));
2687 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2689 TestCompletionCallback callback1;
2691 int rv = trans->Start(&request, callback1.callback(), log.bound());
2692 EXPECT_EQ(ERR_IO_PENDING, rv);
2694 rv = callback1.WaitForResult();
2695 EXPECT_EQ(OK, rv);
2696 TestNetLogEntry::List entries;
2697 log.GetEntries(&entries);
2698 size_t pos = ExpectLogContainsSomewhere(
2699 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2700 NetLog::PHASE_NONE);
2701 ExpectLogContainsSomewhere(
2702 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2703 NetLog::PHASE_NONE);
2705 const HttpResponseInfo* response = trans->GetResponseInfo();
2706 ASSERT_TRUE(response);
2707 ASSERT_TRUE(response->headers);
2708 EXPECT_TRUE(response->headers->IsKeepAlive());
2709 EXPECT_EQ(407, response->headers->response_code());
2710 EXPECT_EQ(10, response->headers->GetContentLength());
2711 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2712 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2714 TestCompletionCallback callback2;
2716 // Wrong password (should be "bar").
2717 rv =
2718 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2719 EXPECT_EQ(ERR_IO_PENDING, rv);
2721 rv = callback2.WaitForResult();
2722 EXPECT_EQ(OK, rv);
2724 response = trans->GetResponseInfo();
2725 ASSERT_TRUE(response);
2726 ASSERT_TRUE(response->headers);
2727 EXPECT_TRUE(response->headers->IsKeepAlive());
2728 EXPECT_EQ(407, response->headers->response_code());
2729 EXPECT_EQ(10, response->headers->GetContentLength());
2730 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2731 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2733 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2734 // out of scope.
2735 session->CloseAllConnections();
2738 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2739 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2740 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
2741 HttpRequestInfo request;
2742 request.method = "GET";
2743 request.url = GURL("https://www.example.org/");
2744 // Ensure that proxy authentication is attempted even
2745 // when the no authentication data flag is set.
2746 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2748 // Configure against proxy server "myproxy:70".
2749 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2750 BoundTestNetLog log;
2751 session_deps_.net_log = log.bound().net_log();
2752 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2754 scoped_ptr<HttpTransaction> trans(
2755 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2757 // Since we have proxy, should try to establish tunnel.
2758 MockWrite data_writes1[] = {
2759 MockWrite(
2760 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2761 "Host: www.example.org\r\n"
2762 "Proxy-Connection: keep-alive\r\n\r\n"),
2764 // After calling trans->RestartWithAuth(), this is the request we should
2765 // be issuing -- the final header line contains the credentials.
2766 MockWrite(
2767 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2768 "Host: www.example.org\r\n"
2769 "Proxy-Connection: keep-alive\r\n"
2770 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2773 // The proxy responds to the connect with a 407, using a persistent
2774 // connection.
2775 MockRead data_reads1[] = {
2776 // No credentials.
2777 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2778 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2779 MockRead("Content-Length: 10\r\n\r\n"),
2780 MockRead("0123456789"),
2782 // Wrong credentials (wrong password).
2783 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2784 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2785 MockRead("Content-Length: 10\r\n\r\n"),
2786 // No response body because the test stops reading here.
2787 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2790 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2791 data_writes1, arraysize(data_writes1));
2792 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2794 TestCompletionCallback callback1;
2796 int rv = trans->Start(&request, callback1.callback(), log.bound());
2797 EXPECT_EQ(ERR_IO_PENDING, rv);
2799 rv = callback1.WaitForResult();
2800 EXPECT_EQ(OK, rv);
2801 TestNetLogEntry::List entries;
2802 log.GetEntries(&entries);
2803 size_t pos = ExpectLogContainsSomewhere(
2804 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2805 NetLog::PHASE_NONE);
2806 ExpectLogContainsSomewhere(
2807 entries, pos,
2808 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2809 NetLog::PHASE_NONE);
2811 const HttpResponseInfo* response = trans->GetResponseInfo();
2812 ASSERT_TRUE(response);
2813 ASSERT_TRUE(response->headers);
2814 EXPECT_TRUE(response->headers->IsKeepAlive());
2815 EXPECT_EQ(407, response->headers->response_code());
2816 EXPECT_EQ(10, response->headers->GetContentLength());
2817 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2818 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2820 TestCompletionCallback callback2;
2822 // Wrong password (should be "bar").
2823 rv = trans->RestartWithAuth(
2824 AuthCredentials(kFoo, kBaz), callback2.callback());
2825 EXPECT_EQ(ERR_IO_PENDING, rv);
2827 rv = callback2.WaitForResult();
2828 EXPECT_EQ(OK, rv);
2830 response = trans->GetResponseInfo();
2831 ASSERT_TRUE(response);
2832 ASSERT_TRUE(response->headers);
2833 EXPECT_TRUE(response->headers->IsKeepAlive());
2834 EXPECT_EQ(407, response->headers->response_code());
2835 EXPECT_EQ(10, response->headers->GetContentLength());
2836 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2837 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2839 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2840 // out of scope.
2841 session->CloseAllConnections();
2844 // Test that we don't read the response body when we fail to establish a tunnel,
2845 // even if the user cancels the proxy's auth attempt.
2846 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2847 HttpRequestInfo request;
2848 request.method = "GET";
2849 request.url = GURL("https://www.example.org/");
2850 request.load_flags = 0;
2852 // Configure against proxy server "myproxy:70".
2853 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2855 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2857 scoped_ptr<HttpTransaction> trans(
2858 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2860 // Since we have proxy, should try to establish tunnel.
2861 MockWrite data_writes[] = {
2862 MockWrite(
2863 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2864 "Host: www.example.org\r\n"
2865 "Proxy-Connection: keep-alive\r\n\r\n"),
2868 // The proxy responds to the connect with a 407.
2869 MockRead data_reads[] = {
2870 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2871 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2872 MockRead("Content-Length: 10\r\n\r\n"),
2873 MockRead("0123456789"), // Should not be reached.
2874 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
2877 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2878 data_writes, arraysize(data_writes));
2879 session_deps_.socket_factory->AddSocketDataProvider(&data);
2881 TestCompletionCallback callback;
2883 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2884 EXPECT_EQ(ERR_IO_PENDING, rv);
2886 rv = callback.WaitForResult();
2887 EXPECT_EQ(OK, rv);
2889 const HttpResponseInfo* response = trans->GetResponseInfo();
2890 ASSERT_TRUE(response);
2891 ASSERT_TRUE(response->headers);
2892 EXPECT_TRUE(response->headers->IsKeepAlive());
2893 EXPECT_EQ(407, response->headers->response_code());
2894 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2896 std::string response_data;
2897 rv = ReadTransaction(trans.get(), &response_data);
2898 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2900 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2901 session->CloseAllConnections();
2904 // Test that we don't pass extraneous headers from the proxy's response to the
2905 // caller when the proxy responds to CONNECT with 407.
2906 TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
2907 HttpRequestInfo request;
2908 request.method = "GET";
2909 request.url = GURL("https://www.example.org/");
2910 request.load_flags = 0;
2912 // Configure against proxy server "myproxy:70".
2913 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2915 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2917 scoped_ptr<HttpTransaction> trans(
2918 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2920 // Since we have proxy, should try to establish tunnel.
2921 MockWrite data_writes[] = {
2922 MockWrite(
2923 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2924 "Host: www.example.org\r\n"
2925 "Proxy-Connection: keep-alive\r\n\r\n"),
2928 // The proxy responds to the connect with a 407.
2929 MockRead data_reads[] = {
2930 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2931 MockRead("X-Foo: bar\r\n"),
2932 MockRead("Set-Cookie: foo=bar\r\n"),
2933 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2934 MockRead("Content-Length: 10\r\n\r\n"),
2935 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2938 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
2939 arraysize(data_writes));
2940 session_deps_.socket_factory->AddSocketDataProvider(&data);
2942 TestCompletionCallback callback;
2944 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2945 EXPECT_EQ(ERR_IO_PENDING, rv);
2947 rv = callback.WaitForResult();
2948 EXPECT_EQ(OK, rv);
2950 const HttpResponseInfo* response = trans->GetResponseInfo();
2951 ASSERT_TRUE(response);
2952 ASSERT_TRUE(response->headers);
2953 EXPECT_TRUE(response->headers->IsKeepAlive());
2954 EXPECT_EQ(407, response->headers->response_code());
2955 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2956 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
2957 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
2959 std::string response_data;
2960 rv = ReadTransaction(trans.get(), &response_data);
2961 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2963 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2964 session->CloseAllConnections();
2967 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2968 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2969 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2970 HttpRequestInfo request;
2971 request.method = "GET";
2972 request.url = GURL("http://www.example.org/");
2973 request.load_flags = 0;
2975 // We are using a DIRECT connection (i.e. no proxy) for this session.
2976 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2977 scoped_ptr<HttpTransaction> trans(
2978 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2980 MockWrite data_writes1[] = {
2981 MockWrite(
2982 "GET / HTTP/1.1\r\n"
2983 "Host: www.example.org\r\n"
2984 "Connection: keep-alive\r\n\r\n"),
2987 MockRead data_reads1[] = {
2988 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2989 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2990 // Large content-length -- won't matter, as connection will be reset.
2991 MockRead("Content-Length: 10000\r\n\r\n"),
2992 MockRead(SYNCHRONOUS, ERR_FAILED),
2995 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2996 data_writes1, arraysize(data_writes1));
2997 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2999 TestCompletionCallback callback;
3001 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3002 EXPECT_EQ(ERR_IO_PENDING, rv);
3004 rv = callback.WaitForResult();
3005 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3008 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3009 // through a non-authenticating proxy. The request should fail with
3010 // ERR_UNEXPECTED_PROXY_AUTH.
3011 // Note that it is impossible to detect if an HTTP server returns a 407 through
3012 // a non-authenticating proxy - there is nothing to indicate whether the
3013 // response came from the proxy or the server, so it is treated as if the proxy
3014 // issued the challenge.
3015 TEST_P(HttpNetworkTransactionTest,
3016 HttpsServerRequestsProxyAuthThroughProxy) {
3017 HttpRequestInfo request;
3018 request.method = "GET";
3019 request.url = GURL("https://www.example.org/");
3021 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3022 BoundTestNetLog log;
3023 session_deps_.net_log = log.bound().net_log();
3024 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3026 // Since we have proxy, should try to establish tunnel.
3027 MockWrite data_writes1[] = {
3028 MockWrite(
3029 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3030 "Host: www.example.org\r\n"
3031 "Proxy-Connection: keep-alive\r\n\r\n"),
3033 MockWrite(
3034 "GET / HTTP/1.1\r\n"
3035 "Host: www.example.org\r\n"
3036 "Connection: keep-alive\r\n\r\n"),
3039 MockRead data_reads1[] = {
3040 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3042 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3043 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3044 MockRead("\r\n"),
3045 MockRead(SYNCHRONOUS, OK),
3048 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3049 data_writes1, arraysize(data_writes1));
3050 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3051 SSLSocketDataProvider ssl(ASYNC, OK);
3052 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3054 TestCompletionCallback callback1;
3056 scoped_ptr<HttpTransaction> trans(
3057 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3059 int rv = trans->Start(&request, callback1.callback(), log.bound());
3060 EXPECT_EQ(ERR_IO_PENDING, rv);
3062 rv = callback1.WaitForResult();
3063 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3064 TestNetLogEntry::List entries;
3065 log.GetEntries(&entries);
3066 size_t pos = ExpectLogContainsSomewhere(
3067 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3068 NetLog::PHASE_NONE);
3069 ExpectLogContainsSomewhere(
3070 entries, pos,
3071 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3072 NetLog::PHASE_NONE);
3075 // Test the load timing for HTTPS requests with an HTTP proxy.
3076 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
3077 HttpRequestInfo request1;
3078 request1.method = "GET";
3079 request1.url = GURL("https://www.example.org/1");
3081 HttpRequestInfo request2;
3082 request2.method = "GET";
3083 request2.url = GURL("https://www.example.org/2");
3085 // Configure against proxy server "myproxy:70".
3086 session_deps_.proxy_service.reset(
3087 ProxyService::CreateFixed("PROXY myproxy:70"));
3088 BoundTestNetLog log;
3089 session_deps_.net_log = log.bound().net_log();
3090 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3092 // Since we have proxy, should try to establish tunnel.
3093 MockWrite data_writes1[] = {
3094 MockWrite(
3095 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3096 "Host: www.example.org\r\n"
3097 "Proxy-Connection: keep-alive\r\n\r\n"),
3099 MockWrite(
3100 "GET /1 HTTP/1.1\r\n"
3101 "Host: www.example.org\r\n"
3102 "Connection: keep-alive\r\n\r\n"),
3104 MockWrite(
3105 "GET /2 HTTP/1.1\r\n"
3106 "Host: www.example.org\r\n"
3107 "Connection: keep-alive\r\n\r\n"),
3110 // The proxy responds to the connect with a 407, using a persistent
3111 // connection.
3112 MockRead data_reads1[] = {
3113 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3115 MockRead("HTTP/1.1 200 OK\r\n"),
3116 MockRead("Content-Length: 1\r\n\r\n"),
3117 MockRead(SYNCHRONOUS, "1"),
3119 MockRead("HTTP/1.1 200 OK\r\n"),
3120 MockRead("Content-Length: 2\r\n\r\n"),
3121 MockRead(SYNCHRONOUS, "22"),
3124 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3125 data_writes1, arraysize(data_writes1));
3126 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3127 SSLSocketDataProvider ssl(ASYNC, OK);
3128 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3130 TestCompletionCallback callback1;
3131 scoped_ptr<HttpTransaction> trans1(
3132 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3134 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3135 EXPECT_EQ(ERR_IO_PENDING, rv);
3137 rv = callback1.WaitForResult();
3138 EXPECT_EQ(OK, rv);
3140 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3141 ASSERT_TRUE(response1 != NULL);
3142 ASSERT_TRUE(response1->headers.get() != NULL);
3143 EXPECT_EQ(1, response1->headers->GetContentLength());
3145 LoadTimingInfo load_timing_info1;
3146 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3147 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3149 trans1.reset();
3151 TestCompletionCallback callback2;
3152 scoped_ptr<HttpTransaction> trans2(
3153 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3155 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3156 EXPECT_EQ(ERR_IO_PENDING, rv);
3158 rv = callback2.WaitForResult();
3159 EXPECT_EQ(OK, rv);
3161 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3162 ASSERT_TRUE(response2 != NULL);
3163 ASSERT_TRUE(response2->headers.get() != NULL);
3164 EXPECT_EQ(2, response2->headers->GetContentLength());
3166 LoadTimingInfo load_timing_info2;
3167 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3168 TestLoadTimingReused(load_timing_info2);
3170 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3172 trans2.reset();
3173 session->CloseAllConnections();
3176 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3177 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
3178 HttpRequestInfo request1;
3179 request1.method = "GET";
3180 request1.url = GURL("https://www.example.org/1");
3182 HttpRequestInfo request2;
3183 request2.method = "GET";
3184 request2.url = GURL("https://www.example.org/2");
3186 // Configure against proxy server "myproxy:70".
3187 session_deps_.proxy_service.reset(
3188 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3189 BoundTestNetLog log;
3190 session_deps_.net_log = log.bound().net_log();
3191 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3193 // Since we have proxy, should try to establish tunnel.
3194 MockWrite data_writes1[] = {
3195 MockWrite(
3196 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3197 "Host: www.example.org\r\n"
3198 "Proxy-Connection: keep-alive\r\n\r\n"),
3200 MockWrite(
3201 "GET /1 HTTP/1.1\r\n"
3202 "Host: www.example.org\r\n"
3203 "Connection: keep-alive\r\n\r\n"),
3205 MockWrite(
3206 "GET /2 HTTP/1.1\r\n"
3207 "Host: www.example.org\r\n"
3208 "Connection: keep-alive\r\n\r\n"),
3211 // The proxy responds to the connect with a 407, using a persistent
3212 // connection.
3213 MockRead data_reads1[] = {
3214 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3216 MockRead("HTTP/1.1 200 OK\r\n"),
3217 MockRead("Content-Length: 1\r\n\r\n"),
3218 MockRead(SYNCHRONOUS, "1"),
3220 MockRead("HTTP/1.1 200 OK\r\n"),
3221 MockRead("Content-Length: 2\r\n\r\n"),
3222 MockRead(SYNCHRONOUS, "22"),
3225 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3226 data_writes1, arraysize(data_writes1));
3227 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3228 SSLSocketDataProvider ssl(ASYNC, OK);
3229 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3231 TestCompletionCallback callback1;
3232 scoped_ptr<HttpTransaction> trans1(
3233 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3235 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3236 EXPECT_EQ(ERR_IO_PENDING, rv);
3238 rv = callback1.WaitForResult();
3239 EXPECT_EQ(OK, rv);
3241 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3242 ASSERT_TRUE(response1 != NULL);
3243 ASSERT_TRUE(response1->headers.get() != NULL);
3244 EXPECT_EQ(1, response1->headers->GetContentLength());
3246 LoadTimingInfo load_timing_info1;
3247 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3248 TestLoadTimingNotReusedWithPac(load_timing_info1,
3249 CONNECT_TIMING_HAS_SSL_TIMES);
3251 trans1.reset();
3253 TestCompletionCallback callback2;
3254 scoped_ptr<HttpTransaction> trans2(
3255 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3257 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3258 EXPECT_EQ(ERR_IO_PENDING, rv);
3260 rv = callback2.WaitForResult();
3261 EXPECT_EQ(OK, rv);
3263 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3264 ASSERT_TRUE(response2 != NULL);
3265 ASSERT_TRUE(response2->headers.get() != NULL);
3266 EXPECT_EQ(2, response2->headers->GetContentLength());
3268 LoadTimingInfo load_timing_info2;
3269 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3270 TestLoadTimingReusedWithPac(load_timing_info2);
3272 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3274 trans2.reset();
3275 session->CloseAllConnections();
3278 // Test a simple get through an HTTPS Proxy.
3279 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
3280 HttpRequestInfo request;
3281 request.method = "GET";
3282 request.url = GURL("http://www.example.org/");
3284 // Configure against https proxy server "proxy:70".
3285 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3286 "https://proxy:70"));
3287 BoundTestNetLog log;
3288 session_deps_.net_log = log.bound().net_log();
3289 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3291 // Since we have proxy, should use full url
3292 MockWrite data_writes1[] = {
3293 MockWrite(
3294 "GET http://www.example.org/ HTTP/1.1\r\n"
3295 "Host: www.example.org\r\n"
3296 "Proxy-Connection: keep-alive\r\n\r\n"),
3299 MockRead data_reads1[] = {
3300 MockRead("HTTP/1.1 200 OK\r\n"),
3301 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3302 MockRead("Content-Length: 100\r\n\r\n"),
3303 MockRead(SYNCHRONOUS, OK),
3306 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3307 data_writes1, arraysize(data_writes1));
3308 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3309 SSLSocketDataProvider ssl(ASYNC, OK);
3310 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3312 TestCompletionCallback callback1;
3314 scoped_ptr<HttpTransaction> trans(
3315 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3317 int rv = trans->Start(&request, callback1.callback(), log.bound());
3318 EXPECT_EQ(ERR_IO_PENDING, rv);
3320 rv = callback1.WaitForResult();
3321 EXPECT_EQ(OK, rv);
3323 LoadTimingInfo load_timing_info;
3324 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3325 TestLoadTimingNotReused(load_timing_info,
3326 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3328 const HttpResponseInfo* response = trans->GetResponseInfo();
3329 ASSERT_TRUE(response != NULL);
3331 EXPECT_TRUE(response->headers->IsKeepAlive());
3332 EXPECT_EQ(200, response->headers->response_code());
3333 EXPECT_EQ(100, response->headers->GetContentLength());
3334 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3336 // The password prompt info should not be set.
3337 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3340 // Test a SPDY get through an HTTPS Proxy.
3341 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3342 HttpRequestInfo request;
3343 request.method = "GET";
3344 request.url = GURL("http://www.example.org/");
3345 request.load_flags = 0;
3347 // Configure against https proxy server "proxy:70".
3348 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3349 "https://proxy:70"));
3350 BoundTestNetLog log;
3351 session_deps_.net_log = log.bound().net_log();
3352 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3354 // fetch http://www.example.org/ via SPDY
3355 scoped_ptr<SpdyFrame> req(
3356 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3357 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3359 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3360 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3361 MockRead spdy_reads[] = {
3362 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3365 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3366 arraysize(spdy_writes));
3367 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3369 SSLSocketDataProvider ssl(ASYNC, OK);
3370 ssl.SetNextProto(GetParam());
3371 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3373 TestCompletionCallback callback1;
3375 scoped_ptr<HttpTransaction> trans(
3376 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3378 int rv = trans->Start(&request, callback1.callback(), log.bound());
3379 EXPECT_EQ(ERR_IO_PENDING, rv);
3381 rv = callback1.WaitForResult();
3382 EXPECT_EQ(OK, rv);
3384 LoadTimingInfo load_timing_info;
3385 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3386 TestLoadTimingNotReused(load_timing_info,
3387 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3389 const HttpResponseInfo* response = trans->GetResponseInfo();
3390 ASSERT_TRUE(response != NULL);
3391 ASSERT_TRUE(response->headers.get() != NULL);
3392 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3394 std::string response_data;
3395 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3396 EXPECT_EQ(kUploadData, response_data);
3399 // Verifies that a session which races and wins against the owning transaction
3400 // (completing prior to host resolution), doesn't fail the transaction.
3401 // Regression test for crbug.com/334413.
3402 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3403 HttpRequestInfo request;
3404 request.method = "GET";
3405 request.url = GURL("http://www.example.org/");
3406 request.load_flags = 0;
3408 // Configure SPDY proxy server "proxy:70".
3409 session_deps_.proxy_service.reset(
3410 ProxyService::CreateFixed("https://proxy:70"));
3411 BoundTestNetLog log;
3412 session_deps_.net_log = log.bound().net_log();
3413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3415 // Fetch http://www.example.org/ through the SPDY proxy.
3416 scoped_ptr<SpdyFrame> req(
3417 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3418 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3420 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3421 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3422 MockRead spdy_reads[] = {
3423 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3426 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3427 arraysize(spdy_writes));
3428 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3430 SSLSocketDataProvider ssl(ASYNC, OK);
3431 ssl.SetNextProto(GetParam());
3432 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3434 TestCompletionCallback callback1;
3436 scoped_ptr<HttpTransaction> trans(
3437 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3439 // Stall the hostname resolution begun by the transaction.
3440 session_deps_.host_resolver->set_synchronous_mode(false);
3441 session_deps_.host_resolver->set_ondemand_mode(true);
3443 int rv = trans->Start(&request, callback1.callback(), log.bound());
3444 EXPECT_EQ(ERR_IO_PENDING, rv);
3446 // Race a session to the proxy, which completes first.
3447 session_deps_.host_resolver->set_ondemand_mode(false);
3448 SpdySessionKey key(
3449 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3450 base::WeakPtr<SpdySession> spdy_session =
3451 CreateSecureSpdySession(session, key, log.bound());
3453 // Unstall the resolution begun by the transaction.
3454 session_deps_.host_resolver->set_ondemand_mode(true);
3455 session_deps_.host_resolver->ResolveAllPending();
3457 EXPECT_FALSE(callback1.have_result());
3458 rv = callback1.WaitForResult();
3459 EXPECT_EQ(OK, rv);
3461 const HttpResponseInfo* response = trans->GetResponseInfo();
3462 ASSERT_TRUE(response != NULL);
3463 ASSERT_TRUE(response->headers.get() != NULL);
3464 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3466 std::string response_data;
3467 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3468 EXPECT_EQ(kUploadData, response_data);
3471 // Test a SPDY get through an HTTPS Proxy.
3472 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3473 HttpRequestInfo request;
3474 request.method = "GET";
3475 request.url = GURL("http://www.example.org/");
3476 request.load_flags = 0;
3478 // Configure against https proxy server "myproxy:70".
3479 session_deps_.proxy_service.reset(
3480 ProxyService::CreateFixed("https://myproxy:70"));
3481 BoundTestNetLog log;
3482 session_deps_.net_log = log.bound().net_log();
3483 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3485 // The first request will be a bare GET, the second request will be a
3486 // GET with a Proxy-Authorization header.
3487 scoped_ptr<SpdyFrame> req_get(
3488 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3489 const char* const kExtraAuthorizationHeaders[] = {
3490 "proxy-authorization", "Basic Zm9vOmJhcg=="
3492 scoped_ptr<SpdyFrame> req_get_authorization(
3493 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3494 arraysize(kExtraAuthorizationHeaders) / 2,
3495 false,
3497 LOWEST,
3498 false));
3499 MockWrite spdy_writes[] = {
3500 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
3503 // The first response is a 407 proxy authentication challenge, and the second
3504 // response will be a 200 response since the second request includes a valid
3505 // Authorization header.
3506 const char* const kExtraAuthenticationHeaders[] = {
3507 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3509 scoped_ptr<SpdyFrame> resp_authentication(
3510 spdy_util_.ConstructSpdySynReplyError(
3511 "407 Proxy Authentication Required",
3512 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3513 1));
3514 scoped_ptr<SpdyFrame> body_authentication(
3515 spdy_util_.ConstructSpdyBodyFrame(1, true));
3516 scoped_ptr<SpdyFrame> resp_data(
3517 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3518 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3519 MockRead spdy_reads[] = {
3520 CreateMockRead(*resp_authentication, 1),
3521 CreateMockRead(*body_authentication, 2),
3522 CreateMockRead(*resp_data, 4),
3523 CreateMockRead(*body_data, 5),
3524 MockRead(ASYNC, 0, 6),
3527 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3528 arraysize(spdy_writes));
3529 session_deps_.socket_factory->AddSocketDataProvider(&data);
3531 SSLSocketDataProvider ssl(ASYNC, OK);
3532 ssl.SetNextProto(GetParam());
3533 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3535 TestCompletionCallback callback1;
3537 scoped_ptr<HttpTransaction> trans(
3538 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3540 int rv = trans->Start(&request, callback1.callback(), log.bound());
3541 EXPECT_EQ(ERR_IO_PENDING, rv);
3543 rv = callback1.WaitForResult();
3544 EXPECT_EQ(OK, rv);
3546 const HttpResponseInfo* const response = trans->GetResponseInfo();
3548 ASSERT_TRUE(response != NULL);
3549 ASSERT_TRUE(response->headers.get() != NULL);
3550 EXPECT_EQ(407, response->headers->response_code());
3551 EXPECT_TRUE(response->was_fetched_via_spdy);
3552 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3554 TestCompletionCallback callback2;
3556 rv = trans->RestartWithAuth(
3557 AuthCredentials(kFoo, kBar), callback2.callback());
3558 EXPECT_EQ(ERR_IO_PENDING, rv);
3560 rv = callback2.WaitForResult();
3561 EXPECT_EQ(OK, rv);
3563 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3565 ASSERT_TRUE(response_restart != NULL);
3566 ASSERT_TRUE(response_restart->headers.get() != NULL);
3567 EXPECT_EQ(200, response_restart->headers->response_code());
3568 // The password prompt info should not be set.
3569 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3572 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3573 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3574 HttpRequestInfo request;
3575 request.method = "GET";
3576 request.url = GURL("https://www.example.org/");
3577 request.load_flags = 0;
3579 // Configure against https proxy server "proxy:70".
3580 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3581 "https://proxy:70"));
3582 BoundTestNetLog log;
3583 session_deps_.net_log = log.bound().net_log();
3584 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3586 scoped_ptr<HttpTransaction> trans(
3587 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3589 // CONNECT to www.example.org:443 via SPDY
3590 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3591 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3592 // fetch https://www.example.org/ via HTTP
3594 const char get[] =
3595 "GET / HTTP/1.1\r\n"
3596 "Host: www.example.org\r\n"
3597 "Connection: keep-alive\r\n\r\n";
3598 scoped_ptr<SpdyFrame> wrapped_get(
3599 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3600 scoped_ptr<SpdyFrame> conn_resp(
3601 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3602 const char resp[] = "HTTP/1.1 200 OK\r\n"
3603 "Content-Length: 10\r\n\r\n";
3604 scoped_ptr<SpdyFrame> wrapped_get_resp(
3605 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3606 scoped_ptr<SpdyFrame> wrapped_body(
3607 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3608 scoped_ptr<SpdyFrame> window_update(
3609 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3611 MockWrite spdy_writes[] = {
3612 CreateMockWrite(*connect, 0),
3613 CreateMockWrite(*wrapped_get, 2),
3614 CreateMockWrite(*window_update, 6),
3617 MockRead spdy_reads[] = {
3618 CreateMockRead(*conn_resp, 1, ASYNC),
3619 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
3620 CreateMockRead(*wrapped_body, 4, ASYNC),
3621 CreateMockRead(*wrapped_body, 5, ASYNC),
3622 MockRead(ASYNC, 0, 7),
3625 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3626 arraysize(spdy_writes));
3627 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3629 SSLSocketDataProvider ssl(ASYNC, OK);
3630 ssl.SetNextProto(GetParam());
3631 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3632 SSLSocketDataProvider ssl2(ASYNC, OK);
3633 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3635 TestCompletionCallback callback1;
3637 int rv = trans->Start(&request, callback1.callback(), log.bound());
3638 EXPECT_EQ(ERR_IO_PENDING, rv);
3640 rv = callback1.WaitForResult();
3641 ASSERT_EQ(OK, rv);
3643 LoadTimingInfo load_timing_info;
3644 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3645 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3647 const HttpResponseInfo* response = trans->GetResponseInfo();
3648 ASSERT_TRUE(response != NULL);
3649 ASSERT_TRUE(response->headers.get() != NULL);
3650 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3652 std::string response_data;
3653 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3654 EXPECT_EQ("1234567890", response_data);
3657 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3658 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3659 HttpRequestInfo request;
3660 request.method = "GET";
3661 request.url = GURL("https://www.example.org/");
3662 request.load_flags = 0;
3664 // Configure against https proxy server "proxy:70".
3665 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3666 "https://proxy:70"));
3667 BoundTestNetLog log;
3668 session_deps_.net_log = log.bound().net_log();
3669 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3671 scoped_ptr<HttpTransaction> trans(
3672 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3674 // CONNECT to www.example.org:443 via SPDY
3675 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3676 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3677 // fetch https://www.example.org/ via SPDY
3678 const char kMyUrl[] = "https://www.example.org/";
3679 scoped_ptr<SpdyFrame> get(
3680 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3681 scoped_ptr<SpdyFrame> wrapped_get(
3682 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3683 scoped_ptr<SpdyFrame> conn_resp(
3684 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3685 scoped_ptr<SpdyFrame> get_resp(
3686 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3687 scoped_ptr<SpdyFrame> wrapped_get_resp(
3688 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3689 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3690 scoped_ptr<SpdyFrame> wrapped_body(
3691 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3692 scoped_ptr<SpdyFrame> window_update_get_resp(
3693 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3694 scoped_ptr<SpdyFrame> window_update_body(
3695 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3697 MockWrite spdy_writes[] = {
3698 CreateMockWrite(*connect, 0),
3699 CreateMockWrite(*wrapped_get, 2),
3700 CreateMockWrite(*window_update_get_resp, 6),
3701 CreateMockWrite(*window_update_body, 7),
3704 MockRead spdy_reads[] = {
3705 CreateMockRead(*conn_resp, 1, ASYNC),
3706 MockRead(ASYNC, ERR_IO_PENDING, 3),
3707 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3708 CreateMockRead(*wrapped_body, 5, ASYNC),
3709 MockRead(ASYNC, 0, 8),
3712 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3713 arraysize(spdy_writes));
3714 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3716 SSLSocketDataProvider ssl(ASYNC, OK);
3717 ssl.SetNextProto(GetParam());
3718 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3719 SSLSocketDataProvider ssl2(ASYNC, OK);
3720 ssl2.SetNextProto(GetParam());
3721 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3723 TestCompletionCallback callback1;
3725 int rv = trans->Start(&request, callback1.callback(), log.bound());
3726 EXPECT_EQ(ERR_IO_PENDING, rv);
3728 // Allow the SpdyProxyClientSocket's write callback to complete.
3729 base::MessageLoop::current()->RunUntilIdle();
3730 // Now allow the read of the response to complete.
3731 spdy_data.CompleteRead();
3732 rv = callback1.WaitForResult();
3733 EXPECT_EQ(OK, rv);
3735 LoadTimingInfo load_timing_info;
3736 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3737 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3739 const HttpResponseInfo* response = trans->GetResponseInfo();
3740 ASSERT_TRUE(response != NULL);
3741 ASSERT_TRUE(response->headers.get() != NULL);
3742 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3744 std::string response_data;
3745 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3746 EXPECT_EQ(kUploadData, response_data);
3749 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3750 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3751 HttpRequestInfo request;
3752 request.method = "GET";
3753 request.url = GURL("https://www.example.org/");
3754 request.load_flags = 0;
3756 // Configure against https proxy server "proxy:70".
3757 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3758 "https://proxy:70"));
3759 BoundTestNetLog log;
3760 session_deps_.net_log = log.bound().net_log();
3761 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3763 scoped_ptr<HttpTransaction> trans(
3764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3766 // CONNECT to www.example.org:443 via SPDY
3767 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3768 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3769 scoped_ptr<SpdyFrame> get(
3770 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3772 MockWrite spdy_writes[] = {
3773 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
3776 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3777 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3778 MockRead spdy_reads[] = {
3779 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
3782 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3783 arraysize(spdy_writes));
3784 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3786 SSLSocketDataProvider ssl(ASYNC, OK);
3787 ssl.SetNextProto(GetParam());
3788 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3789 SSLSocketDataProvider ssl2(ASYNC, OK);
3790 ssl2.SetNextProto(GetParam());
3791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3793 TestCompletionCallback callback1;
3795 int rv = trans->Start(&request, callback1.callback(), log.bound());
3796 EXPECT_EQ(ERR_IO_PENDING, rv);
3798 rv = callback1.WaitForResult();
3799 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3801 // TODO(ttuttle): Anything else to check here?
3804 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3805 // HTTPS Proxy to different servers.
3806 TEST_P(HttpNetworkTransactionTest,
3807 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3808 // Configure against https proxy server "proxy:70".
3809 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3810 "https://proxy:70"));
3811 BoundTestNetLog log;
3812 session_deps_.net_log = log.bound().net_log();
3813 scoped_refptr<HttpNetworkSession> session(
3814 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
3816 HttpRequestInfo request1;
3817 request1.method = "GET";
3818 request1.url = GURL("https://www.example.org/");
3819 request1.load_flags = 0;
3821 HttpRequestInfo request2;
3822 request2.method = "GET";
3823 request2.url = GURL("https://mail.example.org/");
3824 request2.load_flags = 0;
3826 // CONNECT to www.example.org:443 via SPDY.
3827 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3828 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3829 scoped_ptr<SpdyFrame> conn_resp1(
3830 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3832 // Fetch https://www.example.org/ via HTTP.
3833 const char get1[] =
3834 "GET / HTTP/1.1\r\n"
3835 "Host: www.example.org\r\n"
3836 "Connection: keep-alive\r\n\r\n";
3837 scoped_ptr<SpdyFrame> wrapped_get1(
3838 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3839 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3840 "Content-Length: 1\r\n\r\n";
3841 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3842 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3843 scoped_ptr<SpdyFrame> wrapped_body1(
3844 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3845 scoped_ptr<SpdyFrame> window_update(
3846 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3848 // CONNECT to mail.example.org:443 via SPDY.
3849 SpdyHeaderBlock connect2_block;
3850 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3851 if (GetParam() >= kProtoHTTP2MinimumVersion) {
3852 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
3853 } else {
3854 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
3855 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
3857 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3858 scoped_ptr<SpdyFrame> connect2(
3859 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3861 scoped_ptr<SpdyFrame> conn_resp2(
3862 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3864 // Fetch https://mail.example.org/ via HTTP.
3865 const char get2[] =
3866 "GET / HTTP/1.1\r\n"
3867 "Host: mail.example.org\r\n"
3868 "Connection: keep-alive\r\n\r\n";
3869 scoped_ptr<SpdyFrame> wrapped_get2(
3870 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3871 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3872 "Content-Length: 2\r\n\r\n";
3873 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3874 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3875 scoped_ptr<SpdyFrame> wrapped_body2(
3876 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3878 MockWrite spdy_writes[] = {
3879 CreateMockWrite(*connect1, 0),
3880 CreateMockWrite(*wrapped_get1, 2),
3881 CreateMockWrite(*connect2, 5),
3882 CreateMockWrite(*wrapped_get2, 7),
3885 MockRead spdy_reads[] = {
3886 CreateMockRead(*conn_resp1, 1, ASYNC),
3887 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3888 CreateMockRead(*wrapped_body1, 4, ASYNC),
3889 CreateMockRead(*conn_resp2, 6, ASYNC),
3890 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3891 CreateMockRead(*wrapped_body2, 9, ASYNC),
3892 MockRead(ASYNC, 0, 10),
3895 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3896 arraysize(spdy_writes));
3897 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3899 SSLSocketDataProvider ssl(ASYNC, OK);
3900 ssl.SetNextProto(GetParam());
3901 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3902 SSLSocketDataProvider ssl2(ASYNC, OK);
3903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3904 SSLSocketDataProvider ssl3(ASYNC, OK);
3905 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
3907 TestCompletionCallback callback;
3909 scoped_ptr<HttpTransaction> trans(
3910 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3911 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3912 EXPECT_EQ(OK, callback.GetResult(rv));
3914 LoadTimingInfo load_timing_info;
3915 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3916 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3918 const HttpResponseInfo* response = trans->GetResponseInfo();
3919 ASSERT_TRUE(response != NULL);
3920 ASSERT_TRUE(response->headers.get() != NULL);
3921 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3923 std::string response_data;
3924 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
3925 rv = trans->Read(buf.get(), 256, callback.callback());
3926 EXPECT_EQ(1, callback.GetResult(rv));
3928 scoped_ptr<HttpTransaction> trans2(
3929 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3930 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3931 EXPECT_EQ(OK, callback.GetResult(rv));
3933 LoadTimingInfo load_timing_info2;
3934 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3935 // Even though the SPDY connection is reused, a new tunnelled connection has
3936 // to be created, so the socket's load timing looks like a fresh connection.
3937 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3939 // The requests should have different IDs, since they each are using their own
3940 // separate stream.
3941 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3943 rv = trans2->Read(buf.get(), 256, callback.callback());
3944 EXPECT_EQ(2, callback.GetResult(rv));
3947 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3948 // HTTPS Proxy to the same server.
3949 TEST_P(HttpNetworkTransactionTest,
3950 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3951 // Configure against https proxy server "proxy:70".
3952 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3953 "https://proxy:70"));
3954 BoundTestNetLog log;
3955 session_deps_.net_log = log.bound().net_log();
3956 scoped_refptr<HttpNetworkSession> session(
3957 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
3959 HttpRequestInfo request1;
3960 request1.method = "GET";
3961 request1.url = GURL("https://www.example.org/");
3962 request1.load_flags = 0;
3964 HttpRequestInfo request2;
3965 request2.method = "GET";
3966 request2.url = GURL("https://www.example.org/2");
3967 request2.load_flags = 0;
3969 // CONNECT to www.example.org:443 via SPDY.
3970 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3971 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3972 scoped_ptr<SpdyFrame> conn_resp1(
3973 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3975 // Fetch https://www.example.org/ via HTTP.
3976 const char get1[] =
3977 "GET / HTTP/1.1\r\n"
3978 "Host: www.example.org\r\n"
3979 "Connection: keep-alive\r\n\r\n";
3980 scoped_ptr<SpdyFrame> wrapped_get1(
3981 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3982 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3983 "Content-Length: 1\r\n\r\n";
3984 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3985 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3986 scoped_ptr<SpdyFrame> wrapped_body1(
3987 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3988 scoped_ptr<SpdyFrame> window_update(
3989 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3991 // Fetch https://www.example.org/2 via HTTP.
3992 const char get2[] =
3993 "GET /2 HTTP/1.1\r\n"
3994 "Host: www.example.org\r\n"
3995 "Connection: keep-alive\r\n\r\n";
3996 scoped_ptr<SpdyFrame> wrapped_get2(
3997 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3998 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3999 "Content-Length: 2\r\n\r\n";
4000 scoped_ptr<SpdyFrame> wrapped_get_resp2(
4001 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
4002 scoped_ptr<SpdyFrame> wrapped_body2(
4003 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
4005 MockWrite spdy_writes[] = {
4006 CreateMockWrite(*connect1, 0),
4007 CreateMockWrite(*wrapped_get1, 2),
4008 CreateMockWrite(*wrapped_get2, 5),
4011 MockRead spdy_reads[] = {
4012 CreateMockRead(*conn_resp1, 1, ASYNC),
4013 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4014 CreateMockRead(*wrapped_body1, 4, ASYNC),
4015 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4016 CreateMockRead(*wrapped_body2, 7, ASYNC),
4017 MockRead(ASYNC, 0, 8),
4020 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4021 arraysize(spdy_writes));
4022 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4024 SSLSocketDataProvider ssl(ASYNC, OK);
4025 ssl.SetNextProto(GetParam());
4026 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4027 SSLSocketDataProvider ssl2(ASYNC, OK);
4028 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4030 TestCompletionCallback callback;
4032 scoped_ptr<HttpTransaction> trans(
4033 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4034 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4035 EXPECT_EQ(ERR_IO_PENDING, rv);
4037 rv = callback.WaitForResult();
4038 EXPECT_EQ(OK, rv);
4040 LoadTimingInfo load_timing_info;
4041 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4042 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4044 const HttpResponseInfo* response = trans->GetResponseInfo();
4045 ASSERT_TRUE(response != NULL);
4046 ASSERT_TRUE(response->headers.get() != NULL);
4047 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4049 std::string response_data;
4050 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4051 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
4052 trans.reset();
4054 scoped_ptr<HttpTransaction> trans2(
4055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4056 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4057 EXPECT_EQ(ERR_IO_PENDING, rv);
4059 rv = callback.WaitForResult();
4060 EXPECT_EQ(OK, rv);
4062 LoadTimingInfo load_timing_info2;
4063 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4064 TestLoadTimingReused(load_timing_info2);
4066 // The requests should have the same ID.
4067 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4069 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
4072 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4073 // Proxy to different servers.
4074 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
4075 // Configure against https proxy server "proxy:70".
4076 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
4077 "https://proxy:70"));
4078 BoundTestNetLog log;
4079 session_deps_.net_log = log.bound().net_log();
4080 scoped_refptr<HttpNetworkSession> session(
4081 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
4083 HttpRequestInfo request1;
4084 request1.method = "GET";
4085 request1.url = GURL("http://www.example.org/");
4086 request1.load_flags = 0;
4088 HttpRequestInfo request2;
4089 request2.method = "GET";
4090 request2.url = GURL("http://mail.example.org/");
4091 request2.load_flags = 0;
4093 // http://www.example.org/
4094 scoped_ptr<SpdyHeaderBlock> headers(
4095 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4096 scoped_ptr<SpdyFrame> get1(
4097 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4098 scoped_ptr<SpdyFrame> get_resp1(
4099 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4100 scoped_ptr<SpdyFrame> body1(
4101 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
4103 // http://mail.example.org/
4104 scoped_ptr<SpdyHeaderBlock> headers2(
4105 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4106 scoped_ptr<SpdyFrame> get2(
4107 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
4108 scoped_ptr<SpdyFrame> get_resp2(
4109 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4110 scoped_ptr<SpdyFrame> body2(
4111 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
4113 MockWrite spdy_writes[] = {
4114 CreateMockWrite(*get1, 0),
4115 CreateMockWrite(*get2, 3),
4118 MockRead spdy_reads[] = {
4119 CreateMockRead(*get_resp1, 1, ASYNC),
4120 CreateMockRead(*body1, 2, ASYNC),
4121 CreateMockRead(*get_resp2, 4, ASYNC),
4122 CreateMockRead(*body2, 5, ASYNC),
4123 MockRead(ASYNC, 0, 6),
4126 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4127 arraysize(spdy_writes));
4128 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4130 SSLSocketDataProvider ssl(ASYNC, OK);
4131 ssl.SetNextProto(GetParam());
4132 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4134 TestCompletionCallback callback;
4136 scoped_ptr<HttpTransaction> trans(
4137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4138 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4139 EXPECT_EQ(OK, callback.GetResult(rv));
4141 LoadTimingInfo load_timing_info;
4142 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4143 TestLoadTimingNotReused(load_timing_info,
4144 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4146 const HttpResponseInfo* response = trans->GetResponseInfo();
4147 ASSERT_TRUE(response != NULL);
4148 ASSERT_TRUE(response->headers.get() != NULL);
4149 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4151 std::string response_data;
4152 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4153 rv = trans->Read(buf.get(), 256, callback.callback());
4154 EXPECT_EQ(1, callback.GetResult(rv));
4155 // Delete the first request, so the second one can reuse the socket.
4156 trans.reset();
4158 scoped_ptr<HttpTransaction> trans2(
4159 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4160 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4161 EXPECT_EQ(OK, callback.GetResult(rv));
4163 LoadTimingInfo load_timing_info2;
4164 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4165 TestLoadTimingReused(load_timing_info2);
4167 // The requests should have the same ID.
4168 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4170 rv = trans2->Read(buf.get(), 256, callback.callback());
4171 EXPECT_EQ(2, callback.GetResult(rv));
4174 // Test the challenge-response-retry sequence through an HTTPS Proxy
4175 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
4176 HttpRequestInfo request;
4177 request.method = "GET";
4178 request.url = GURL("http://www.example.org/");
4179 // when the no authentication data flag is set.
4180 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
4182 // Configure against https proxy server "myproxy:70".
4183 session_deps_.proxy_service.reset(
4184 ProxyService::CreateFixed("https://myproxy:70"));
4185 BoundTestNetLog log;
4186 session_deps_.net_log = log.bound().net_log();
4187 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4189 // Since we have proxy, should use full url
4190 MockWrite data_writes1[] = {
4191 MockWrite(
4192 "GET http://www.example.org/ HTTP/1.1\r\n"
4193 "Host: www.example.org\r\n"
4194 "Proxy-Connection: keep-alive\r\n\r\n"),
4196 // After calling trans->RestartWithAuth(), this is the request we should
4197 // be issuing -- the final header line contains the credentials.
4198 MockWrite(
4199 "GET http://www.example.org/ HTTP/1.1\r\n"
4200 "Host: www.example.org\r\n"
4201 "Proxy-Connection: keep-alive\r\n"
4202 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4205 // The proxy responds to the GET with a 407, using a persistent
4206 // connection.
4207 MockRead data_reads1[] = {
4208 // No credentials.
4209 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4210 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4211 MockRead("Proxy-Connection: keep-alive\r\n"),
4212 MockRead("Content-Length: 0\r\n\r\n"),
4214 MockRead("HTTP/1.1 200 OK\r\n"),
4215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4216 MockRead("Content-Length: 100\r\n\r\n"),
4217 MockRead(SYNCHRONOUS, OK),
4220 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4221 data_writes1, arraysize(data_writes1));
4222 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4223 SSLSocketDataProvider ssl(ASYNC, OK);
4224 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4226 TestCompletionCallback callback1;
4228 scoped_ptr<HttpTransaction> trans(
4229 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4231 int rv = trans->Start(&request, callback1.callback(), log.bound());
4232 EXPECT_EQ(ERR_IO_PENDING, rv);
4234 rv = callback1.WaitForResult();
4235 EXPECT_EQ(OK, rv);
4237 LoadTimingInfo load_timing_info;
4238 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4239 TestLoadTimingNotReused(load_timing_info,
4240 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4242 const HttpResponseInfo* response = trans->GetResponseInfo();
4243 ASSERT_TRUE(response != NULL);
4244 ASSERT_FALSE(response->headers.get() == NULL);
4245 EXPECT_EQ(407, response->headers->response_code());
4246 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4247 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4249 TestCompletionCallback callback2;
4251 rv = trans->RestartWithAuth(
4252 AuthCredentials(kFoo, kBar), callback2.callback());
4253 EXPECT_EQ(ERR_IO_PENDING, rv);
4255 rv = callback2.WaitForResult();
4256 EXPECT_EQ(OK, rv);
4258 load_timing_info = LoadTimingInfo();
4259 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4260 // Retrying with HTTP AUTH is considered to be reusing a socket.
4261 TestLoadTimingReused(load_timing_info);
4263 response = trans->GetResponseInfo();
4264 ASSERT_TRUE(response != NULL);
4266 EXPECT_TRUE(response->headers->IsKeepAlive());
4267 EXPECT_EQ(200, response->headers->response_code());
4268 EXPECT_EQ(100, response->headers->GetContentLength());
4269 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4271 // The password prompt info should not be set.
4272 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4275 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4276 const MockRead& status, int expected_status) {
4277 HttpRequestInfo request;
4278 request.method = "GET";
4279 request.url = GURL("https://www.example.org/");
4280 request.load_flags = 0;
4282 // Configure against proxy server "myproxy:70".
4283 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4284 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4286 // Since we have proxy, should try to establish tunnel.
4287 MockWrite data_writes[] = {
4288 MockWrite(
4289 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4290 "Host: www.example.org\r\n"
4291 "Proxy-Connection: keep-alive\r\n\r\n"),
4294 MockRead data_reads[] = {
4295 status,
4296 MockRead("Content-Length: 10\r\n\r\n"),
4297 // No response body because the test stops reading here.
4298 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4301 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4302 data_writes, arraysize(data_writes));
4303 session_deps_.socket_factory->AddSocketDataProvider(&data);
4305 TestCompletionCallback callback;
4307 scoped_ptr<HttpTransaction> trans(
4308 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4310 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4311 EXPECT_EQ(ERR_IO_PENDING, rv);
4313 rv = callback.WaitForResult();
4314 EXPECT_EQ(expected_status, rv);
4317 void HttpNetworkTransactionTest::ConnectStatusHelper(
4318 const MockRead& status) {
4319 ConnectStatusHelperWithExpectedStatus(
4320 status, ERR_TUNNEL_CONNECTION_FAILED);
4323 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4324 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4327 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4328 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4331 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4332 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4335 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4336 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4339 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4340 ConnectStatusHelper(
4341 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4344 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4345 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4348 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4349 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4352 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4353 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4356 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4357 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4360 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4361 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4364 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4365 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4368 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4369 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4372 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4373 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4376 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4377 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4380 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4381 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4384 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4385 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4388 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4389 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4392 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4393 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4396 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4397 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4400 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4401 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4404 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4405 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4408 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4409 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4412 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4413 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4416 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4417 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4420 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4421 ConnectStatusHelperWithExpectedStatus(
4422 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4423 ERR_PROXY_AUTH_UNSUPPORTED);
4426 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4427 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4430 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4431 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4434 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4435 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4438 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4439 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4442 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4443 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4446 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4447 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4450 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4451 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4454 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4455 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4458 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4459 ConnectStatusHelper(
4460 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4463 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4464 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4467 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4468 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4471 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4472 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4475 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4476 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4479 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4480 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4483 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4484 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4487 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4488 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4491 // Test the flow when both the proxy server AND origin server require
4492 // authentication. Again, this uses basic auth for both since that is
4493 // the simplest to mock.
4494 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4495 HttpRequestInfo request;
4496 request.method = "GET";
4497 request.url = GURL("http://www.example.org/");
4498 request.load_flags = 0;
4500 // Configure against proxy server "myproxy:70".
4501 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4502 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4504 scoped_ptr<HttpTransaction> trans(
4505 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4507 MockWrite data_writes1[] = {
4508 MockWrite(
4509 "GET http://www.example.org/ HTTP/1.1\r\n"
4510 "Host: www.example.org\r\n"
4511 "Proxy-Connection: keep-alive\r\n\r\n"),
4514 MockRead data_reads1[] = {
4515 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4516 // Give a couple authenticate options (only the middle one is actually
4517 // supported).
4518 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4519 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4520 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4521 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4522 // Large content-length -- won't matter, as connection will be reset.
4523 MockRead("Content-Length: 10000\r\n\r\n"),
4524 MockRead(SYNCHRONOUS, ERR_FAILED),
4527 // After calling trans->RestartWithAuth() the first time, this is the
4528 // request we should be issuing -- the final header line contains the
4529 // proxy's credentials.
4530 MockWrite data_writes2[] = {
4531 MockWrite(
4532 "GET http://www.example.org/ HTTP/1.1\r\n"
4533 "Host: www.example.org\r\n"
4534 "Proxy-Connection: keep-alive\r\n"
4535 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4538 // Now the proxy server lets the request pass through to origin server.
4539 // The origin server responds with a 401.
4540 MockRead data_reads2[] = {
4541 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4542 // Note: We are using the same realm-name as the proxy server. This is
4543 // completely valid, as realms are unique across hosts.
4544 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4545 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4546 MockRead("Content-Length: 2000\r\n\r\n"),
4547 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4550 // After calling trans->RestartWithAuth() the second time, we should send
4551 // the credentials for both the proxy and origin server.
4552 MockWrite data_writes3[] = {
4553 MockWrite(
4554 "GET http://www.example.org/ HTTP/1.1\r\n"
4555 "Host: www.example.org\r\n"
4556 "Proxy-Connection: keep-alive\r\n"
4557 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4558 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4561 // Lastly we get the desired content.
4562 MockRead data_reads3[] = {
4563 MockRead("HTTP/1.0 200 OK\r\n"),
4564 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4565 MockRead("Content-Length: 100\r\n\r\n"),
4566 MockRead(SYNCHRONOUS, OK),
4569 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4570 data_writes1, arraysize(data_writes1));
4571 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4572 data_writes2, arraysize(data_writes2));
4573 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4574 data_writes3, arraysize(data_writes3));
4575 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4576 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4577 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4579 TestCompletionCallback callback1;
4581 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4582 EXPECT_EQ(ERR_IO_PENDING, rv);
4584 rv = callback1.WaitForResult();
4585 EXPECT_EQ(OK, rv);
4587 const HttpResponseInfo* response = trans->GetResponseInfo();
4588 ASSERT_TRUE(response != NULL);
4589 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4591 TestCompletionCallback callback2;
4593 rv = trans->RestartWithAuth(
4594 AuthCredentials(kFoo, kBar), callback2.callback());
4595 EXPECT_EQ(ERR_IO_PENDING, rv);
4597 rv = callback2.WaitForResult();
4598 EXPECT_EQ(OK, rv);
4600 response = trans->GetResponseInfo();
4601 ASSERT_TRUE(response != NULL);
4602 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4604 TestCompletionCallback callback3;
4606 rv = trans->RestartWithAuth(
4607 AuthCredentials(kFoo2, kBar2), callback3.callback());
4608 EXPECT_EQ(ERR_IO_PENDING, rv);
4610 rv = callback3.WaitForResult();
4611 EXPECT_EQ(OK, rv);
4613 response = trans->GetResponseInfo();
4614 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4615 EXPECT_EQ(100, response->headers->GetContentLength());
4618 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4619 // can't hook into its internals to cause it to generate predictable NTLM
4620 // authorization headers.
4621 #if defined(NTLM_PORTABLE)
4622 // The NTLM authentication unit tests were generated by capturing the HTTP
4623 // requests and responses using Fiddler 2 and inspecting the generated random
4624 // bytes in the debugger.
4626 // Enter the correct password and authenticate successfully.
4627 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4628 HttpRequestInfo request;
4629 request.method = "GET";
4630 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4632 // Ensure load is not disrupted by flags which suppress behaviour specific
4633 // to other auth schemes.
4634 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4636 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4637 MockGetHostName);
4638 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4640 MockWrite data_writes1[] = {
4641 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4642 "Host: 172.22.68.17\r\n"
4643 "Connection: keep-alive\r\n\r\n"),
4646 MockRead data_reads1[] = {
4647 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4648 // Negotiate and NTLM are often requested together. However, we only want
4649 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4650 // the header that requests Negotiate for this test.
4651 MockRead("WWW-Authenticate: NTLM\r\n"),
4652 MockRead("Connection: close\r\n"),
4653 MockRead("Content-Length: 42\r\n"),
4654 MockRead("Content-Type: text/html\r\n\r\n"),
4655 // Missing content -- won't matter, as connection will be reset.
4656 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4659 MockWrite data_writes2[] = {
4660 // After restarting with a null identity, this is the
4661 // request we should be issuing -- the final header line contains a Type
4662 // 1 message.
4663 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4664 "Host: 172.22.68.17\r\n"
4665 "Connection: keep-alive\r\n"
4666 "Authorization: NTLM "
4667 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4669 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4670 // (the credentials for the origin server). The second request continues
4671 // on the same connection.
4672 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4673 "Host: 172.22.68.17\r\n"
4674 "Connection: keep-alive\r\n"
4675 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4676 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4677 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4678 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4679 "ahlhx5I=\r\n\r\n"),
4682 MockRead data_reads2[] = {
4683 // The origin server responds with a Type 2 message.
4684 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4685 MockRead("WWW-Authenticate: NTLM "
4686 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4687 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4688 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4689 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4690 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4691 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4692 "BtAAAAAAA=\r\n"),
4693 MockRead("Content-Length: 42\r\n"),
4694 MockRead("Content-Type: text/html\r\n\r\n"),
4695 MockRead("You are not authorized to view this page\r\n"),
4697 // Lastly we get the desired content.
4698 MockRead("HTTP/1.1 200 OK\r\n"),
4699 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4700 MockRead("Content-Length: 13\r\n\r\n"),
4701 MockRead("Please Login\r\n"),
4702 MockRead(SYNCHRONOUS, OK),
4705 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4706 data_writes1, arraysize(data_writes1));
4707 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4708 data_writes2, arraysize(data_writes2));
4709 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4710 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4712 TestCompletionCallback callback1;
4714 scoped_ptr<HttpTransaction> trans(
4715 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4717 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4718 EXPECT_EQ(ERR_IO_PENDING, rv);
4720 rv = callback1.WaitForResult();
4721 EXPECT_EQ(OK, rv);
4723 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4725 const HttpResponseInfo* response = trans->GetResponseInfo();
4726 ASSERT_FALSE(response == NULL);
4727 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4729 TestCompletionCallback callback2;
4731 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4732 callback2.callback());
4733 EXPECT_EQ(ERR_IO_PENDING, rv);
4735 rv = callback2.WaitForResult();
4736 EXPECT_EQ(OK, rv);
4738 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4740 response = trans->GetResponseInfo();
4741 ASSERT_TRUE(response != NULL);
4742 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4744 TestCompletionCallback callback3;
4746 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4747 EXPECT_EQ(ERR_IO_PENDING, rv);
4749 rv = callback3.WaitForResult();
4750 EXPECT_EQ(OK, rv);
4752 response = trans->GetResponseInfo();
4753 ASSERT_TRUE(response != NULL);
4754 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4755 EXPECT_EQ(13, response->headers->GetContentLength());
4758 // Enter a wrong password, and then the correct one.
4759 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4760 HttpRequestInfo request;
4761 request.method = "GET";
4762 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4763 request.load_flags = 0;
4765 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4766 MockGetHostName);
4767 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4769 MockWrite data_writes1[] = {
4770 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4771 "Host: 172.22.68.17\r\n"
4772 "Connection: keep-alive\r\n\r\n"),
4775 MockRead data_reads1[] = {
4776 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4777 // Negotiate and NTLM are often requested together. However, we only want
4778 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4779 // the header that requests Negotiate for this test.
4780 MockRead("WWW-Authenticate: NTLM\r\n"),
4781 MockRead("Connection: close\r\n"),
4782 MockRead("Content-Length: 42\r\n"),
4783 MockRead("Content-Type: text/html\r\n\r\n"),
4784 // Missing content -- won't matter, as connection will be reset.
4785 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4788 MockWrite data_writes2[] = {
4789 // After restarting with a null identity, this is the
4790 // request we should be issuing -- the final header line contains a Type
4791 // 1 message.
4792 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4793 "Host: 172.22.68.17\r\n"
4794 "Connection: keep-alive\r\n"
4795 "Authorization: NTLM "
4796 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4798 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4799 // (the credentials for the origin server). The second request continues
4800 // on the same connection.
4801 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4802 "Host: 172.22.68.17\r\n"
4803 "Connection: keep-alive\r\n"
4804 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4805 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4806 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4807 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4808 "4Ww7b7E=\r\n\r\n"),
4811 MockRead data_reads2[] = {
4812 // The origin server responds with a Type 2 message.
4813 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4814 MockRead("WWW-Authenticate: NTLM "
4815 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4816 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4817 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4818 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4819 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4820 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4821 "BtAAAAAAA=\r\n"),
4822 MockRead("Content-Length: 42\r\n"),
4823 MockRead("Content-Type: text/html\r\n\r\n"),
4824 MockRead("You are not authorized to view this page\r\n"),
4826 // Wrong password.
4827 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4828 MockRead("WWW-Authenticate: NTLM\r\n"),
4829 MockRead("Connection: close\r\n"),
4830 MockRead("Content-Length: 42\r\n"),
4831 MockRead("Content-Type: text/html\r\n\r\n"),
4832 // Missing content -- won't matter, as connection will be reset.
4833 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4836 MockWrite data_writes3[] = {
4837 // After restarting with a null identity, this is the
4838 // request we should be issuing -- the final header line contains a Type
4839 // 1 message.
4840 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4841 "Host: 172.22.68.17\r\n"
4842 "Connection: keep-alive\r\n"
4843 "Authorization: NTLM "
4844 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4846 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4847 // (the credentials for the origin server). The second request continues
4848 // on the same connection.
4849 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4850 "Host: 172.22.68.17\r\n"
4851 "Connection: keep-alive\r\n"
4852 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4853 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4854 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4855 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4856 "+4MUm7c=\r\n\r\n"),
4859 MockRead data_reads3[] = {
4860 // The origin server responds with a Type 2 message.
4861 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4862 MockRead("WWW-Authenticate: NTLM "
4863 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4864 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4865 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4866 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4867 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4868 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4869 "BtAAAAAAA=\r\n"),
4870 MockRead("Content-Length: 42\r\n"),
4871 MockRead("Content-Type: text/html\r\n\r\n"),
4872 MockRead("You are not authorized to view this page\r\n"),
4874 // Lastly we get the desired content.
4875 MockRead("HTTP/1.1 200 OK\r\n"),
4876 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4877 MockRead("Content-Length: 13\r\n\r\n"),
4878 MockRead("Please Login\r\n"),
4879 MockRead(SYNCHRONOUS, OK),
4882 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4883 data_writes1, arraysize(data_writes1));
4884 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4885 data_writes2, arraysize(data_writes2));
4886 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4887 data_writes3, arraysize(data_writes3));
4888 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4889 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4890 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4892 TestCompletionCallback callback1;
4894 scoped_ptr<HttpTransaction> trans(
4895 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4897 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4898 EXPECT_EQ(ERR_IO_PENDING, rv);
4900 rv = callback1.WaitForResult();
4901 EXPECT_EQ(OK, rv);
4903 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4905 const HttpResponseInfo* response = trans->GetResponseInfo();
4906 ASSERT_TRUE(response != NULL);
4907 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4909 TestCompletionCallback callback2;
4911 // Enter the wrong password.
4912 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4913 callback2.callback());
4914 EXPECT_EQ(ERR_IO_PENDING, rv);
4916 rv = callback2.WaitForResult();
4917 EXPECT_EQ(OK, rv);
4919 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4920 TestCompletionCallback callback3;
4921 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4922 EXPECT_EQ(ERR_IO_PENDING, rv);
4923 rv = callback3.WaitForResult();
4924 EXPECT_EQ(OK, rv);
4925 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4927 response = trans->GetResponseInfo();
4928 ASSERT_FALSE(response == NULL);
4929 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4931 TestCompletionCallback callback4;
4933 // Now enter the right password.
4934 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4935 callback4.callback());
4936 EXPECT_EQ(ERR_IO_PENDING, rv);
4938 rv = callback4.WaitForResult();
4939 EXPECT_EQ(OK, rv);
4941 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4943 TestCompletionCallback callback5;
4945 // One more roundtrip
4946 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4947 EXPECT_EQ(ERR_IO_PENDING, rv);
4949 rv = callback5.WaitForResult();
4950 EXPECT_EQ(OK, rv);
4952 response = trans->GetResponseInfo();
4953 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4954 EXPECT_EQ(13, response->headers->GetContentLength());
4956 #endif // NTLM_PORTABLE
4958 // Test reading a server response which has only headers, and no body.
4959 // After some maximum number of bytes is consumed, the transaction should
4960 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4961 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4962 HttpRequestInfo request;
4963 request.method = "GET";
4964 request.url = GURL("http://www.example.org/");
4965 request.load_flags = 0;
4967 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4968 scoped_ptr<HttpTransaction> trans(
4969 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4971 // Respond with 300 kb of headers (we should fail after 256 kb).
4972 std::string large_headers_string;
4973 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4975 MockRead data_reads[] = {
4976 MockRead("HTTP/1.0 200 OK\r\n"),
4977 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4978 MockRead("\r\nBODY"),
4979 MockRead(SYNCHRONOUS, OK),
4981 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4982 session_deps_.socket_factory->AddSocketDataProvider(&data);
4984 TestCompletionCallback callback;
4986 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4987 EXPECT_EQ(ERR_IO_PENDING, rv);
4989 rv = callback.WaitForResult();
4990 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4993 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4994 // establish tunnel.
4995 // http://code.google.com/p/chromium/issues/detail?id=3772
4996 TEST_P(HttpNetworkTransactionTest,
4997 DontRecycleTransportSocketForSSLTunnel) {
4998 HttpRequestInfo request;
4999 request.method = "GET";
5000 request.url = GURL("https://www.example.org/");
5001 request.load_flags = 0;
5003 // Configure against proxy server "myproxy:70".
5004 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5006 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5008 scoped_ptr<HttpTransaction> trans(
5009 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5011 // Since we have proxy, should try to establish tunnel.
5012 MockWrite data_writes1[] = {
5013 MockWrite(
5014 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5015 "Host: www.example.org\r\n"
5016 "Proxy-Connection: keep-alive\r\n\r\n"),
5019 // The proxy responds to the connect with a 404, using a persistent
5020 // connection. Usually a proxy would return 501 (not implemented),
5021 // or 200 (tunnel established).
5022 MockRead data_reads1[] = {
5023 MockRead("HTTP/1.1 404 Not Found\r\n"),
5024 MockRead("Content-Length: 10\r\n\r\n"),
5025 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
5028 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5029 data_writes1, arraysize(data_writes1));
5030 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5032 TestCompletionCallback callback1;
5034 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5035 EXPECT_EQ(ERR_IO_PENDING, rv);
5037 rv = callback1.WaitForResult();
5038 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5040 // Empty the current queue. This is necessary because idle sockets are
5041 // added to the connection pool asynchronously with a PostTask.
5042 base::MessageLoop::current()->RunUntilIdle();
5044 // We now check to make sure the TCPClientSocket was not added back to
5045 // the pool.
5046 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5047 trans.reset();
5048 base::MessageLoop::current()->RunUntilIdle();
5049 // Make sure that the socket didn't get recycled after calling the destructor.
5050 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5053 // Make sure that we recycle a socket after reading all of the response body.
5054 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
5055 HttpRequestInfo request;
5056 request.method = "GET";
5057 request.url = GURL("http://www.example.org/");
5058 request.load_flags = 0;
5060 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5062 scoped_ptr<HttpTransaction> trans(
5063 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5065 MockRead data_reads[] = {
5066 // A part of the response body is received with the response headers.
5067 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5068 // The rest of the response body is received in two parts.
5069 MockRead("lo"),
5070 MockRead(" world"),
5071 MockRead("junk"), // Should not be read!!
5072 MockRead(SYNCHRONOUS, OK),
5075 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5076 session_deps_.socket_factory->AddSocketDataProvider(&data);
5078 TestCompletionCallback callback;
5080 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5081 EXPECT_EQ(ERR_IO_PENDING, rv);
5083 rv = callback.WaitForResult();
5084 EXPECT_EQ(OK, rv);
5086 const HttpResponseInfo* response = trans->GetResponseInfo();
5087 ASSERT_TRUE(response != NULL);
5089 EXPECT_TRUE(response->headers.get() != NULL);
5090 std::string status_line = response->headers->GetStatusLine();
5091 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5093 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5095 std::string response_data;
5096 rv = ReadTransaction(trans.get(), &response_data);
5097 EXPECT_EQ(OK, rv);
5098 EXPECT_EQ("hello world", response_data);
5100 // Empty the current queue. This is necessary because idle sockets are
5101 // added to the connection pool asynchronously with a PostTask.
5102 base::MessageLoop::current()->RunUntilIdle();
5104 // We now check to make sure the socket was added back to the pool.
5105 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5108 // Make sure that we recycle a SSL socket after reading all of the response
5109 // body.
5110 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
5111 HttpRequestInfo request;
5112 request.method = "GET";
5113 request.url = GURL("https://www.example.org/");
5114 request.load_flags = 0;
5116 MockWrite data_writes[] = {
5117 MockWrite(
5118 "GET / HTTP/1.1\r\n"
5119 "Host: www.example.org\r\n"
5120 "Connection: keep-alive\r\n\r\n"),
5123 MockRead data_reads[] = {
5124 MockRead("HTTP/1.1 200 OK\r\n"),
5125 MockRead("Content-Length: 11\r\n\r\n"),
5126 MockRead("hello world"),
5127 MockRead(SYNCHRONOUS, OK),
5130 SSLSocketDataProvider ssl(ASYNC, OK);
5131 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5133 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5134 data_writes, arraysize(data_writes));
5135 session_deps_.socket_factory->AddSocketDataProvider(&data);
5137 TestCompletionCallback callback;
5139 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5140 scoped_ptr<HttpTransaction> trans(
5141 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5143 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5145 EXPECT_EQ(ERR_IO_PENDING, rv);
5146 EXPECT_EQ(OK, callback.WaitForResult());
5148 const HttpResponseInfo* response = trans->GetResponseInfo();
5149 ASSERT_TRUE(response != NULL);
5150 ASSERT_TRUE(response->headers.get() != NULL);
5151 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5153 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5155 std::string response_data;
5156 rv = ReadTransaction(trans.get(), &response_data);
5157 EXPECT_EQ(OK, rv);
5158 EXPECT_EQ("hello world", response_data);
5160 // Empty the current queue. This is necessary because idle sockets are
5161 // added to the connection pool asynchronously with a PostTask.
5162 base::MessageLoop::current()->RunUntilIdle();
5164 // We now check to make sure the socket was added back to the pool.
5165 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5168 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5169 // from the pool and make sure that we recover okay.
5170 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
5171 HttpRequestInfo request;
5172 request.method = "GET";
5173 request.url = GURL("https://www.example.org/");
5174 request.load_flags = 0;
5176 MockWrite data_writes[] = {
5177 MockWrite(
5178 "GET / HTTP/1.1\r\n"
5179 "Host: www.example.org\r\n"
5180 "Connection: keep-alive\r\n\r\n"),
5181 MockWrite(
5182 "GET / HTTP/1.1\r\n"
5183 "Host: www.example.org\r\n"
5184 "Connection: keep-alive\r\n\r\n"),
5187 MockRead data_reads[] = {
5188 MockRead("HTTP/1.1 200 OK\r\n"),
5189 MockRead("Content-Length: 11\r\n\r\n"),
5190 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
5191 MockRead("hello world"),
5192 MockRead(ASYNC, 0, 0) // EOF
5195 SSLSocketDataProvider ssl(ASYNC, OK);
5196 SSLSocketDataProvider ssl2(ASYNC, OK);
5197 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5198 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5200 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5201 data_writes, arraysize(data_writes));
5202 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5203 data_writes, arraysize(data_writes));
5204 session_deps_.socket_factory->AddSocketDataProvider(&data);
5205 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5207 TestCompletionCallback callback;
5209 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5210 scoped_ptr<HttpTransaction> trans(
5211 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5213 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5215 EXPECT_EQ(ERR_IO_PENDING, rv);
5216 EXPECT_EQ(OK, callback.WaitForResult());
5218 const HttpResponseInfo* response = trans->GetResponseInfo();
5219 ASSERT_TRUE(response != NULL);
5220 ASSERT_TRUE(response->headers.get() != NULL);
5221 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5223 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5225 std::string response_data;
5226 rv = ReadTransaction(trans.get(), &response_data);
5227 EXPECT_EQ(OK, rv);
5228 EXPECT_EQ("hello world", response_data);
5230 // Empty the current queue. This is necessary because idle sockets are
5231 // added to the connection pool asynchronously with a PostTask.
5232 base::MessageLoop::current()->RunUntilIdle();
5234 // We now check to make sure the socket was added back to the pool.
5235 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5237 // Now start the second transaction, which should reuse the previous socket.
5239 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5241 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5243 EXPECT_EQ(ERR_IO_PENDING, rv);
5244 EXPECT_EQ(OK, callback.WaitForResult());
5246 response = trans->GetResponseInfo();
5247 ASSERT_TRUE(response != NULL);
5248 ASSERT_TRUE(response->headers.get() != NULL);
5249 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5251 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5253 rv = ReadTransaction(trans.get(), &response_data);
5254 EXPECT_EQ(OK, rv);
5255 EXPECT_EQ("hello world", response_data);
5257 // Empty the current queue. This is necessary because idle sockets are
5258 // added to the connection pool asynchronously with a PostTask.
5259 base::MessageLoop::current()->RunUntilIdle();
5261 // We now check to make sure the socket was added back to the pool.
5262 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5265 // Make sure that we recycle a socket after a zero-length response.
5266 // http://crbug.com/9880
5267 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
5268 HttpRequestInfo request;
5269 request.method = "GET";
5270 request.url = GURL(
5271 "http://www.example.org/csi?v=3&s=web&action=&"
5272 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5273 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5274 "rt=prt.2642,ol.2649,xjs.2951");
5275 request.load_flags = 0;
5277 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5279 scoped_ptr<HttpTransaction> trans(
5280 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5282 MockRead data_reads[] = {
5283 MockRead("HTTP/1.1 204 No Content\r\n"
5284 "Content-Length: 0\r\n"
5285 "Content-Type: text/html\r\n\r\n"),
5286 MockRead("junk"), // Should not be read!!
5287 MockRead(SYNCHRONOUS, OK),
5290 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5291 session_deps_.socket_factory->AddSocketDataProvider(&data);
5293 TestCompletionCallback callback;
5295 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5296 EXPECT_EQ(ERR_IO_PENDING, rv);
5298 rv = callback.WaitForResult();
5299 EXPECT_EQ(OK, rv);
5301 const HttpResponseInfo* response = trans->GetResponseInfo();
5302 ASSERT_TRUE(response != NULL);
5304 EXPECT_TRUE(response->headers.get() != NULL);
5305 std::string status_line = response->headers->GetStatusLine();
5306 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5308 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5310 std::string response_data;
5311 rv = ReadTransaction(trans.get(), &response_data);
5312 EXPECT_EQ(OK, rv);
5313 EXPECT_EQ("", response_data);
5315 // Empty the current queue. This is necessary because idle sockets are
5316 // added to the connection pool asynchronously with a PostTask.
5317 base::MessageLoop::current()->RunUntilIdle();
5319 // We now check to make sure the socket was added back to the pool.
5320 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5323 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5324 ScopedVector<UploadElementReader> element_readers;
5325 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5326 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
5328 HttpRequestInfo request[2];
5329 // Transaction 1: a GET request that succeeds. The socket is recycled
5330 // after use.
5331 request[0].method = "GET";
5332 request[0].url = GURL("http://www.google.com/");
5333 request[0].load_flags = 0;
5334 // Transaction 2: a POST request. Reuses the socket kept alive from
5335 // transaction 1. The first attempts fails when writing the POST data.
5336 // This causes the transaction to retry with a new socket. The second
5337 // attempt succeeds.
5338 request[1].method = "POST";
5339 request[1].url = GURL("http://www.google.com/login.cgi");
5340 request[1].upload_data_stream = &upload_data_stream;
5341 request[1].load_flags = 0;
5343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5345 // The first socket is used for transaction 1 and the first attempt of
5346 // transaction 2.
5348 // The response of transaction 1.
5349 MockRead data_reads1[] = {
5350 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5351 MockRead("hello world"),
5352 MockRead(SYNCHRONOUS, OK),
5354 // The mock write results of transaction 1 and the first attempt of
5355 // transaction 2.
5356 MockWrite data_writes1[] = {
5357 MockWrite(SYNCHRONOUS, 64), // GET
5358 MockWrite(SYNCHRONOUS, 93), // POST
5359 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5361 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5362 data_writes1, arraysize(data_writes1));
5364 // The second socket is used for the second attempt of transaction 2.
5366 // The response of transaction 2.
5367 MockRead data_reads2[] = {
5368 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5369 MockRead("welcome"),
5370 MockRead(SYNCHRONOUS, OK),
5372 // The mock write results of the second attempt of transaction 2.
5373 MockWrite data_writes2[] = {
5374 MockWrite(SYNCHRONOUS, 93), // POST
5375 MockWrite(SYNCHRONOUS, 3), // POST data
5377 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5378 data_writes2, arraysize(data_writes2));
5380 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5381 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5383 const char* const kExpectedResponseData[] = {
5384 "hello world", "welcome"
5387 for (int i = 0; i < 2; ++i) {
5388 scoped_ptr<HttpTransaction> trans(
5389 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5391 TestCompletionCallback callback;
5393 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5394 EXPECT_EQ(ERR_IO_PENDING, rv);
5396 rv = callback.WaitForResult();
5397 EXPECT_EQ(OK, rv);
5399 const HttpResponseInfo* response = trans->GetResponseInfo();
5400 ASSERT_TRUE(response != NULL);
5402 EXPECT_TRUE(response->headers.get() != NULL);
5403 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5405 std::string response_data;
5406 rv = ReadTransaction(trans.get(), &response_data);
5407 EXPECT_EQ(OK, rv);
5408 EXPECT_EQ(kExpectedResponseData[i], response_data);
5412 // Test the request-challenge-retry sequence for basic auth when there is
5413 // an identity in the URL. The request should be sent as normal, but when
5414 // it fails the identity from the URL is used to answer the challenge.
5415 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5416 HttpRequestInfo request;
5417 request.method = "GET";
5418 request.url = GURL("http://foo:b@r@www.example.org/");
5419 request.load_flags = LOAD_NORMAL;
5421 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5422 scoped_ptr<HttpTransaction> trans(
5423 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5425 // The password contains an escaped character -- for this test to pass it
5426 // will need to be unescaped by HttpNetworkTransaction.
5427 EXPECT_EQ("b%40r", request.url.password());
5429 MockWrite data_writes1[] = {
5430 MockWrite(
5431 "GET / HTTP/1.1\r\n"
5432 "Host: www.example.org\r\n"
5433 "Connection: keep-alive\r\n\r\n"),
5436 MockRead data_reads1[] = {
5437 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5438 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5439 MockRead("Content-Length: 10\r\n\r\n"),
5440 MockRead(SYNCHRONOUS, ERR_FAILED),
5443 // After the challenge above, the transaction will be restarted using the
5444 // identity from the url (foo, b@r) to answer the challenge.
5445 MockWrite data_writes2[] = {
5446 MockWrite(
5447 "GET / HTTP/1.1\r\n"
5448 "Host: www.example.org\r\n"
5449 "Connection: keep-alive\r\n"
5450 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5453 MockRead data_reads2[] = {
5454 MockRead("HTTP/1.0 200 OK\r\n"),
5455 MockRead("Content-Length: 100\r\n\r\n"),
5456 MockRead(SYNCHRONOUS, OK),
5459 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5460 data_writes1, arraysize(data_writes1));
5461 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5462 data_writes2, arraysize(data_writes2));
5463 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5464 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5466 TestCompletionCallback callback1;
5467 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5468 EXPECT_EQ(ERR_IO_PENDING, rv);
5469 rv = callback1.WaitForResult();
5470 EXPECT_EQ(OK, rv);
5471 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5473 TestCompletionCallback callback2;
5474 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5475 EXPECT_EQ(ERR_IO_PENDING, rv);
5476 rv = callback2.WaitForResult();
5477 EXPECT_EQ(OK, rv);
5478 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5480 const HttpResponseInfo* response = trans->GetResponseInfo();
5481 ASSERT_TRUE(response != NULL);
5483 // There is no challenge info, since the identity in URL worked.
5484 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5486 EXPECT_EQ(100, response->headers->GetContentLength());
5488 // Empty the current queue.
5489 base::MessageLoop::current()->RunUntilIdle();
5492 // Test the request-challenge-retry sequence for basic auth when there is an
5493 // incorrect identity in the URL. The identity from the URL should be used only
5494 // once.
5495 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5496 HttpRequestInfo request;
5497 request.method = "GET";
5498 // Note: the URL has a username:password in it. The password "baz" is
5499 // wrong (should be "bar").
5500 request.url = GURL("http://foo:baz@www.example.org/");
5502 request.load_flags = LOAD_NORMAL;
5504 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5505 scoped_ptr<HttpTransaction> trans(
5506 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5508 MockWrite data_writes1[] = {
5509 MockWrite(
5510 "GET / HTTP/1.1\r\n"
5511 "Host: www.example.org\r\n"
5512 "Connection: keep-alive\r\n\r\n"),
5515 MockRead data_reads1[] = {
5516 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5517 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5518 MockRead("Content-Length: 10\r\n\r\n"),
5519 MockRead(SYNCHRONOUS, ERR_FAILED),
5522 // After the challenge above, the transaction will be restarted using the
5523 // identity from the url (foo, baz) to answer the challenge.
5524 MockWrite data_writes2[] = {
5525 MockWrite(
5526 "GET / HTTP/1.1\r\n"
5527 "Host: www.example.org\r\n"
5528 "Connection: keep-alive\r\n"
5529 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5532 MockRead data_reads2[] = {
5533 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5534 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5535 MockRead("Content-Length: 10\r\n\r\n"),
5536 MockRead(SYNCHRONOUS, ERR_FAILED),
5539 // After the challenge above, the transaction will be restarted using the
5540 // identity supplied by the user (foo, bar) to answer the challenge.
5541 MockWrite data_writes3[] = {
5542 MockWrite(
5543 "GET / HTTP/1.1\r\n"
5544 "Host: www.example.org\r\n"
5545 "Connection: keep-alive\r\n"
5546 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5549 MockRead data_reads3[] = {
5550 MockRead("HTTP/1.0 200 OK\r\n"),
5551 MockRead("Content-Length: 100\r\n\r\n"),
5552 MockRead(SYNCHRONOUS, OK),
5555 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5556 data_writes1, arraysize(data_writes1));
5557 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5558 data_writes2, arraysize(data_writes2));
5559 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5560 data_writes3, arraysize(data_writes3));
5561 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5562 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5563 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5565 TestCompletionCallback callback1;
5567 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5568 EXPECT_EQ(ERR_IO_PENDING, rv);
5570 rv = callback1.WaitForResult();
5571 EXPECT_EQ(OK, rv);
5573 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5574 TestCompletionCallback callback2;
5575 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5576 EXPECT_EQ(ERR_IO_PENDING, rv);
5577 rv = callback2.WaitForResult();
5578 EXPECT_EQ(OK, rv);
5579 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5581 const HttpResponseInfo* response = trans->GetResponseInfo();
5582 ASSERT_TRUE(response != NULL);
5583 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5585 TestCompletionCallback callback3;
5586 rv = trans->RestartWithAuth(
5587 AuthCredentials(kFoo, kBar), callback3.callback());
5588 EXPECT_EQ(ERR_IO_PENDING, rv);
5589 rv = callback3.WaitForResult();
5590 EXPECT_EQ(OK, rv);
5591 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5593 response = trans->GetResponseInfo();
5594 ASSERT_TRUE(response != NULL);
5596 // There is no challenge info, since the identity worked.
5597 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5599 EXPECT_EQ(100, response->headers->GetContentLength());
5601 // Empty the current queue.
5602 base::MessageLoop::current()->RunUntilIdle();
5606 // Test the request-challenge-retry sequence for basic auth when there is a
5607 // correct identity in the URL, but its use is being suppressed. The identity
5608 // from the URL should never be used.
5609 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5610 HttpRequestInfo request;
5611 request.method = "GET";
5612 request.url = GURL("http://foo:bar@www.example.org/");
5613 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5615 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5616 scoped_ptr<HttpTransaction> trans(
5617 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5619 MockWrite data_writes1[] = {
5620 MockWrite(
5621 "GET / HTTP/1.1\r\n"
5622 "Host: www.example.org\r\n"
5623 "Connection: keep-alive\r\n\r\n"),
5626 MockRead data_reads1[] = {
5627 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5628 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5629 MockRead("Content-Length: 10\r\n\r\n"),
5630 MockRead(SYNCHRONOUS, ERR_FAILED),
5633 // After the challenge above, the transaction will be restarted using the
5634 // identity supplied by the user, not the one in the URL, to answer the
5635 // challenge.
5636 MockWrite data_writes3[] = {
5637 MockWrite(
5638 "GET / HTTP/1.1\r\n"
5639 "Host: www.example.org\r\n"
5640 "Connection: keep-alive\r\n"
5641 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5644 MockRead data_reads3[] = {
5645 MockRead("HTTP/1.0 200 OK\r\n"),
5646 MockRead("Content-Length: 100\r\n\r\n"),
5647 MockRead(SYNCHRONOUS, OK),
5650 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5651 data_writes1, arraysize(data_writes1));
5652 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5653 data_writes3, arraysize(data_writes3));
5654 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5655 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5657 TestCompletionCallback callback1;
5658 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5659 EXPECT_EQ(ERR_IO_PENDING, rv);
5660 rv = callback1.WaitForResult();
5661 EXPECT_EQ(OK, rv);
5662 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5664 const HttpResponseInfo* response = trans->GetResponseInfo();
5665 ASSERT_TRUE(response != NULL);
5666 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5668 TestCompletionCallback callback3;
5669 rv = trans->RestartWithAuth(
5670 AuthCredentials(kFoo, kBar), callback3.callback());
5671 EXPECT_EQ(ERR_IO_PENDING, rv);
5672 rv = callback3.WaitForResult();
5673 EXPECT_EQ(OK, rv);
5674 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5676 response = trans->GetResponseInfo();
5677 ASSERT_TRUE(response != NULL);
5679 // There is no challenge info, since the identity worked.
5680 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5681 EXPECT_EQ(100, response->headers->GetContentLength());
5683 // Empty the current queue.
5684 base::MessageLoop::current()->RunUntilIdle();
5687 // Test that previously tried username/passwords for a realm get re-used.
5688 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5689 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5691 // Transaction 1: authenticate (foo, bar) on MyRealm1
5693 HttpRequestInfo request;
5694 request.method = "GET";
5695 request.url = GURL("http://www.example.org/x/y/z");
5696 request.load_flags = 0;
5698 scoped_ptr<HttpTransaction> trans(
5699 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5701 MockWrite data_writes1[] = {
5702 MockWrite(
5703 "GET /x/y/z HTTP/1.1\r\n"
5704 "Host: www.example.org\r\n"
5705 "Connection: keep-alive\r\n\r\n"),
5708 MockRead data_reads1[] = {
5709 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5710 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5711 MockRead("Content-Length: 10000\r\n\r\n"),
5712 MockRead(SYNCHRONOUS, ERR_FAILED),
5715 // Resend with authorization (username=foo, password=bar)
5716 MockWrite data_writes2[] = {
5717 MockWrite(
5718 "GET /x/y/z HTTP/1.1\r\n"
5719 "Host: www.example.org\r\n"
5720 "Connection: keep-alive\r\n"
5721 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5724 // Sever accepts the authorization.
5725 MockRead data_reads2[] = {
5726 MockRead("HTTP/1.0 200 OK\r\n"),
5727 MockRead("Content-Length: 100\r\n\r\n"),
5728 MockRead(SYNCHRONOUS, OK),
5731 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5732 data_writes1, arraysize(data_writes1));
5733 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5734 data_writes2, arraysize(data_writes2));
5735 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5736 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5738 TestCompletionCallback callback1;
5740 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5741 EXPECT_EQ(ERR_IO_PENDING, rv);
5743 rv = callback1.WaitForResult();
5744 EXPECT_EQ(OK, rv);
5746 const HttpResponseInfo* response = trans->GetResponseInfo();
5747 ASSERT_TRUE(response != NULL);
5748 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5750 TestCompletionCallback callback2;
5752 rv = trans->RestartWithAuth(
5753 AuthCredentials(kFoo, kBar), callback2.callback());
5754 EXPECT_EQ(ERR_IO_PENDING, rv);
5756 rv = callback2.WaitForResult();
5757 EXPECT_EQ(OK, rv);
5759 response = trans->GetResponseInfo();
5760 ASSERT_TRUE(response != NULL);
5761 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5762 EXPECT_EQ(100, response->headers->GetContentLength());
5765 // ------------------------------------------------------------------------
5767 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5769 HttpRequestInfo request;
5770 request.method = "GET";
5771 // Note that Transaction 1 was at /x/y/z, so this is in the same
5772 // protection space as MyRealm1.
5773 request.url = GURL("http://www.example.org/x/y/a/b");
5774 request.load_flags = 0;
5776 scoped_ptr<HttpTransaction> trans(
5777 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5779 MockWrite data_writes1[] = {
5780 MockWrite(
5781 "GET /x/y/a/b HTTP/1.1\r\n"
5782 "Host: www.example.org\r\n"
5783 "Connection: keep-alive\r\n"
5784 // Send preemptive authorization for MyRealm1
5785 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5788 // The server didn't like the preemptive authorization, and
5789 // challenges us for a different realm (MyRealm2).
5790 MockRead data_reads1[] = {
5791 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5792 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5793 MockRead("Content-Length: 10000\r\n\r\n"),
5794 MockRead(SYNCHRONOUS, ERR_FAILED),
5797 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5798 MockWrite data_writes2[] = {
5799 MockWrite(
5800 "GET /x/y/a/b HTTP/1.1\r\n"
5801 "Host: www.example.org\r\n"
5802 "Connection: keep-alive\r\n"
5803 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5806 // Sever accepts the authorization.
5807 MockRead data_reads2[] = {
5808 MockRead("HTTP/1.0 200 OK\r\n"),
5809 MockRead("Content-Length: 100\r\n\r\n"),
5810 MockRead(SYNCHRONOUS, OK),
5813 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5814 data_writes1, arraysize(data_writes1));
5815 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5816 data_writes2, arraysize(data_writes2));
5817 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5818 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5820 TestCompletionCallback callback1;
5822 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5823 EXPECT_EQ(ERR_IO_PENDING, rv);
5825 rv = callback1.WaitForResult();
5826 EXPECT_EQ(OK, rv);
5828 const HttpResponseInfo* response = trans->GetResponseInfo();
5829 ASSERT_TRUE(response != NULL);
5830 ASSERT_TRUE(response->auth_challenge.get());
5831 EXPECT_FALSE(response->auth_challenge->is_proxy);
5832 EXPECT_EQ("www.example.org:80",
5833 response->auth_challenge->challenger.ToString());
5834 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5835 EXPECT_EQ("basic", response->auth_challenge->scheme);
5837 TestCompletionCallback callback2;
5839 rv = trans->RestartWithAuth(
5840 AuthCredentials(kFoo2, kBar2), callback2.callback());
5841 EXPECT_EQ(ERR_IO_PENDING, rv);
5843 rv = callback2.WaitForResult();
5844 EXPECT_EQ(OK, rv);
5846 response = trans->GetResponseInfo();
5847 ASSERT_TRUE(response != NULL);
5848 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5849 EXPECT_EQ(100, response->headers->GetContentLength());
5852 // ------------------------------------------------------------------------
5854 // Transaction 3: Resend a request in MyRealm's protection space --
5855 // succeed with preemptive authorization.
5857 HttpRequestInfo request;
5858 request.method = "GET";
5859 request.url = GURL("http://www.example.org/x/y/z2");
5860 request.load_flags = 0;
5862 scoped_ptr<HttpTransaction> trans(
5863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5865 MockWrite data_writes1[] = {
5866 MockWrite(
5867 "GET /x/y/z2 HTTP/1.1\r\n"
5868 "Host: www.example.org\r\n"
5869 "Connection: keep-alive\r\n"
5870 // The authorization for MyRealm1 gets sent preemptively
5871 // (since the url is in the same protection space)
5872 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5875 // Sever accepts the preemptive authorization
5876 MockRead data_reads1[] = {
5877 MockRead("HTTP/1.0 200 OK\r\n"),
5878 MockRead("Content-Length: 100\r\n\r\n"),
5879 MockRead(SYNCHRONOUS, OK),
5882 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5883 data_writes1, arraysize(data_writes1));
5884 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5886 TestCompletionCallback callback1;
5888 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5889 EXPECT_EQ(ERR_IO_PENDING, rv);
5891 rv = callback1.WaitForResult();
5892 EXPECT_EQ(OK, rv);
5894 const HttpResponseInfo* response = trans->GetResponseInfo();
5895 ASSERT_TRUE(response != NULL);
5897 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5898 EXPECT_EQ(100, response->headers->GetContentLength());
5901 // ------------------------------------------------------------------------
5903 // Transaction 4: request another URL in MyRealm (however the
5904 // url is not known to belong to the protection space, so no pre-auth).
5906 HttpRequestInfo request;
5907 request.method = "GET";
5908 request.url = GURL("http://www.example.org/x/1");
5909 request.load_flags = 0;
5911 scoped_ptr<HttpTransaction> trans(
5912 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5914 MockWrite data_writes1[] = {
5915 MockWrite(
5916 "GET /x/1 HTTP/1.1\r\n"
5917 "Host: www.example.org\r\n"
5918 "Connection: keep-alive\r\n\r\n"),
5921 MockRead data_reads1[] = {
5922 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5923 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5924 MockRead("Content-Length: 10000\r\n\r\n"),
5925 MockRead(SYNCHRONOUS, ERR_FAILED),
5928 // Resend with authorization from MyRealm's cache.
5929 MockWrite data_writes2[] = {
5930 MockWrite(
5931 "GET /x/1 HTTP/1.1\r\n"
5932 "Host: www.example.org\r\n"
5933 "Connection: keep-alive\r\n"
5934 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5937 // Sever accepts the authorization.
5938 MockRead data_reads2[] = {
5939 MockRead("HTTP/1.0 200 OK\r\n"),
5940 MockRead("Content-Length: 100\r\n\r\n"),
5941 MockRead(SYNCHRONOUS, OK),
5944 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5945 data_writes1, arraysize(data_writes1));
5946 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5947 data_writes2, arraysize(data_writes2));
5948 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5949 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5951 TestCompletionCallback callback1;
5953 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5954 EXPECT_EQ(ERR_IO_PENDING, rv);
5956 rv = callback1.WaitForResult();
5957 EXPECT_EQ(OK, rv);
5959 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5960 TestCompletionCallback callback2;
5961 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5962 EXPECT_EQ(ERR_IO_PENDING, rv);
5963 rv = callback2.WaitForResult();
5964 EXPECT_EQ(OK, rv);
5965 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5967 const HttpResponseInfo* response = trans->GetResponseInfo();
5968 ASSERT_TRUE(response != NULL);
5969 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5970 EXPECT_EQ(100, response->headers->GetContentLength());
5973 // ------------------------------------------------------------------------
5975 // Transaction 5: request a URL in MyRealm, but the server rejects the
5976 // cached identity. Should invalidate and re-prompt.
5978 HttpRequestInfo request;
5979 request.method = "GET";
5980 request.url = GURL("http://www.example.org/p/q/t");
5981 request.load_flags = 0;
5983 scoped_ptr<HttpTransaction> trans(
5984 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5986 MockWrite data_writes1[] = {
5987 MockWrite(
5988 "GET /p/q/t HTTP/1.1\r\n"
5989 "Host: www.example.org\r\n"
5990 "Connection: keep-alive\r\n\r\n"),
5993 MockRead data_reads1[] = {
5994 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5995 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5996 MockRead("Content-Length: 10000\r\n\r\n"),
5997 MockRead(SYNCHRONOUS, ERR_FAILED),
6000 // Resend with authorization from cache for MyRealm.
6001 MockWrite data_writes2[] = {
6002 MockWrite(
6003 "GET /p/q/t HTTP/1.1\r\n"
6004 "Host: www.example.org\r\n"
6005 "Connection: keep-alive\r\n"
6006 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6009 // Sever rejects the authorization.
6010 MockRead data_reads2[] = {
6011 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6012 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6013 MockRead("Content-Length: 10000\r\n\r\n"),
6014 MockRead(SYNCHRONOUS, ERR_FAILED),
6017 // At this point we should prompt for new credentials for MyRealm.
6018 // Restart with username=foo3, password=foo4.
6019 MockWrite data_writes3[] = {
6020 MockWrite(
6021 "GET /p/q/t HTTP/1.1\r\n"
6022 "Host: www.example.org\r\n"
6023 "Connection: keep-alive\r\n"
6024 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6027 // Sever accepts the authorization.
6028 MockRead data_reads3[] = {
6029 MockRead("HTTP/1.0 200 OK\r\n"),
6030 MockRead("Content-Length: 100\r\n\r\n"),
6031 MockRead(SYNCHRONOUS, OK),
6034 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6035 data_writes1, arraysize(data_writes1));
6036 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6037 data_writes2, arraysize(data_writes2));
6038 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6039 data_writes3, arraysize(data_writes3));
6040 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6041 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6042 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6044 TestCompletionCallback callback1;
6046 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6047 EXPECT_EQ(ERR_IO_PENDING, rv);
6049 rv = callback1.WaitForResult();
6050 EXPECT_EQ(OK, rv);
6052 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6053 TestCompletionCallback callback2;
6054 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6055 EXPECT_EQ(ERR_IO_PENDING, rv);
6056 rv = callback2.WaitForResult();
6057 EXPECT_EQ(OK, rv);
6058 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6060 const HttpResponseInfo* response = trans->GetResponseInfo();
6061 ASSERT_TRUE(response != NULL);
6062 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6064 TestCompletionCallback callback3;
6066 rv = trans->RestartWithAuth(
6067 AuthCredentials(kFoo3, kBar3), callback3.callback());
6068 EXPECT_EQ(ERR_IO_PENDING, rv);
6070 rv = callback3.WaitForResult();
6071 EXPECT_EQ(OK, rv);
6073 response = trans->GetResponseInfo();
6074 ASSERT_TRUE(response != NULL);
6075 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6076 EXPECT_EQ(100, response->headers->GetContentLength());
6080 // Tests that nonce count increments when multiple auth attempts
6081 // are started with the same nonce.
6082 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
6083 HttpAuthHandlerDigest::Factory* digest_factory =
6084 new HttpAuthHandlerDigest::Factory();
6085 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6086 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6087 digest_factory->set_nonce_generator(nonce_generator);
6088 session_deps_.http_auth_handler_factory.reset(digest_factory);
6089 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6091 // Transaction 1: authenticate (foo, bar) on MyRealm1
6093 HttpRequestInfo request;
6094 request.method = "GET";
6095 request.url = GURL("http://www.example.org/x/y/z");
6096 request.load_flags = 0;
6098 scoped_ptr<HttpTransaction> trans(
6099 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6101 MockWrite data_writes1[] = {
6102 MockWrite(
6103 "GET /x/y/z HTTP/1.1\r\n"
6104 "Host: www.example.org\r\n"
6105 "Connection: keep-alive\r\n\r\n"),
6108 MockRead data_reads1[] = {
6109 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6110 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6111 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6112 MockRead(SYNCHRONOUS, OK),
6115 // Resend with authorization (username=foo, password=bar)
6116 MockWrite data_writes2[] = {
6117 MockWrite(
6118 "GET /x/y/z HTTP/1.1\r\n"
6119 "Host: www.example.org\r\n"
6120 "Connection: keep-alive\r\n"
6121 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6122 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6123 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6124 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6127 // Sever accepts the authorization.
6128 MockRead data_reads2[] = {
6129 MockRead("HTTP/1.0 200 OK\r\n"),
6130 MockRead(SYNCHRONOUS, OK),
6133 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6134 data_writes1, arraysize(data_writes1));
6135 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6136 data_writes2, arraysize(data_writes2));
6137 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6138 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6140 TestCompletionCallback callback1;
6142 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6143 EXPECT_EQ(ERR_IO_PENDING, rv);
6145 rv = callback1.WaitForResult();
6146 EXPECT_EQ(OK, rv);
6148 const HttpResponseInfo* response = trans->GetResponseInfo();
6149 ASSERT_TRUE(response != NULL);
6150 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
6152 TestCompletionCallback callback2;
6154 rv = trans->RestartWithAuth(
6155 AuthCredentials(kFoo, kBar), callback2.callback());
6156 EXPECT_EQ(ERR_IO_PENDING, rv);
6158 rv = callback2.WaitForResult();
6159 EXPECT_EQ(OK, rv);
6161 response = trans->GetResponseInfo();
6162 ASSERT_TRUE(response != NULL);
6163 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6166 // ------------------------------------------------------------------------
6168 // Transaction 2: Request another resource in digestive's protection space.
6169 // This will preemptively add an Authorization header which should have an
6170 // "nc" value of 2 (as compared to 1 in the first use.
6172 HttpRequestInfo request;
6173 request.method = "GET";
6174 // Note that Transaction 1 was at /x/y/z, so this is in the same
6175 // protection space as digest.
6176 request.url = GURL("http://www.example.org/x/y/a/b");
6177 request.load_flags = 0;
6179 scoped_ptr<HttpTransaction> trans(
6180 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6182 MockWrite data_writes1[] = {
6183 MockWrite(
6184 "GET /x/y/a/b HTTP/1.1\r\n"
6185 "Host: www.example.org\r\n"
6186 "Connection: keep-alive\r\n"
6187 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6188 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6189 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6190 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6193 // Sever accepts the authorization.
6194 MockRead data_reads1[] = {
6195 MockRead("HTTP/1.0 200 OK\r\n"),
6196 MockRead("Content-Length: 100\r\n\r\n"),
6197 MockRead(SYNCHRONOUS, OK),
6200 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6201 data_writes1, arraysize(data_writes1));
6202 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6204 TestCompletionCallback callback1;
6206 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6207 EXPECT_EQ(ERR_IO_PENDING, rv);
6209 rv = callback1.WaitForResult();
6210 EXPECT_EQ(OK, rv);
6212 const HttpResponseInfo* response = trans->GetResponseInfo();
6213 ASSERT_TRUE(response != NULL);
6214 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6218 // Test the ResetStateForRestart() private method.
6219 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
6220 // Create a transaction (the dependencies aren't important).
6221 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6222 scoped_ptr<HttpNetworkTransaction> trans(
6223 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6225 // Setup some state (which we expect ResetStateForRestart() will clear).
6226 trans->read_buf_ = new IOBuffer(15);
6227 trans->read_buf_len_ = 15;
6228 trans->request_headers_.SetHeader("Authorization", "NTLM");
6230 // Setup state in response_
6231 HttpResponseInfo* response = &trans->response_;
6232 response->auth_challenge = new AuthChallengeInfo();
6233 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
6234 response->response_time = base::Time::Now();
6235 response->was_cached = true; // (Wouldn't ever actually be true...)
6237 { // Setup state for response_.vary_data
6238 HttpRequestInfo request;
6239 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6240 std::replace(temp.begin(), temp.end(), '\n', '\0');
6241 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
6242 request.extra_headers.SetHeader("Foo", "1");
6243 request.extra_headers.SetHeader("bar", "23");
6244 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
6247 // Cause the above state to be reset.
6248 trans->ResetStateForRestart();
6250 // Verify that the state that needed to be reset, has been reset.
6251 EXPECT_TRUE(trans->read_buf_.get() == NULL);
6252 EXPECT_EQ(0, trans->read_buf_len_);
6253 EXPECT_TRUE(trans->request_headers_.IsEmpty());
6254 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6255 EXPECT_TRUE(response->headers.get() == NULL);
6256 EXPECT_FALSE(response->was_cached);
6257 EXPECT_EQ(0U, response->ssl_info.cert_status);
6258 EXPECT_FALSE(response->vary_data.is_valid());
6261 // Test HTTPS connections to a site with a bad certificate
6262 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
6263 HttpRequestInfo request;
6264 request.method = "GET";
6265 request.url = GURL("https://www.example.org/");
6266 request.load_flags = 0;
6268 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6269 scoped_ptr<HttpTransaction> trans(
6270 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6272 MockWrite data_writes[] = {
6273 MockWrite(
6274 "GET / HTTP/1.1\r\n"
6275 "Host: www.example.org\r\n"
6276 "Connection: keep-alive\r\n\r\n"),
6279 MockRead data_reads[] = {
6280 MockRead("HTTP/1.0 200 OK\r\n"),
6281 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6282 MockRead("Content-Length: 100\r\n\r\n"),
6283 MockRead(SYNCHRONOUS, OK),
6286 StaticSocketDataProvider ssl_bad_certificate;
6287 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6288 data_writes, arraysize(data_writes));
6289 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6290 SSLSocketDataProvider ssl(ASYNC, OK);
6292 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6293 session_deps_.socket_factory->AddSocketDataProvider(&data);
6294 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6295 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6297 TestCompletionCallback callback;
6299 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6300 EXPECT_EQ(ERR_IO_PENDING, rv);
6302 rv = callback.WaitForResult();
6303 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6305 rv = trans->RestartIgnoringLastError(callback.callback());
6306 EXPECT_EQ(ERR_IO_PENDING, rv);
6308 rv = callback.WaitForResult();
6309 EXPECT_EQ(OK, rv);
6311 const HttpResponseInfo* response = trans->GetResponseInfo();
6313 ASSERT_TRUE(response != NULL);
6314 EXPECT_EQ(100, response->headers->GetContentLength());
6317 // Test HTTPS connections to a site with a bad certificate, going through a
6318 // proxy
6319 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
6320 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6322 HttpRequestInfo request;
6323 request.method = "GET";
6324 request.url = GURL("https://www.example.org/");
6325 request.load_flags = 0;
6327 MockWrite proxy_writes[] = {
6328 MockWrite(
6329 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6330 "Host: www.example.org\r\n"
6331 "Proxy-Connection: keep-alive\r\n\r\n"),
6334 MockRead proxy_reads[] = {
6335 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6336 MockRead(SYNCHRONOUS, OK)
6339 MockWrite data_writes[] = {
6340 MockWrite(
6341 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6342 "Host: www.example.org\r\n"
6343 "Proxy-Connection: keep-alive\r\n\r\n"),
6344 MockWrite(
6345 "GET / HTTP/1.1\r\n"
6346 "Host: www.example.org\r\n"
6347 "Connection: keep-alive\r\n\r\n"),
6350 MockRead data_reads[] = {
6351 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6352 MockRead("HTTP/1.0 200 OK\r\n"),
6353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6354 MockRead("Content-Length: 100\r\n\r\n"),
6355 MockRead(SYNCHRONOUS, OK),
6358 StaticSocketDataProvider ssl_bad_certificate(
6359 proxy_reads, arraysize(proxy_reads),
6360 proxy_writes, arraysize(proxy_writes));
6361 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6362 data_writes, arraysize(data_writes));
6363 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6364 SSLSocketDataProvider ssl(ASYNC, OK);
6366 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6367 session_deps_.socket_factory->AddSocketDataProvider(&data);
6368 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6369 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6371 TestCompletionCallback callback;
6373 for (int i = 0; i < 2; i++) {
6374 session_deps_.socket_factory->ResetNextMockIndexes();
6376 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6377 scoped_ptr<HttpTransaction> trans(
6378 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6380 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6381 EXPECT_EQ(ERR_IO_PENDING, rv);
6383 rv = callback.WaitForResult();
6384 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6386 rv = trans->RestartIgnoringLastError(callback.callback());
6387 EXPECT_EQ(ERR_IO_PENDING, rv);
6389 rv = callback.WaitForResult();
6390 EXPECT_EQ(OK, rv);
6392 const HttpResponseInfo* response = trans->GetResponseInfo();
6394 ASSERT_TRUE(response != NULL);
6395 EXPECT_EQ(100, response->headers->GetContentLength());
6400 // Test HTTPS connections to a site, going through an HTTPS proxy
6401 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6402 session_deps_.proxy_service.reset(
6403 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6404 TestNetLog net_log;
6405 session_deps_.net_log = &net_log;
6407 HttpRequestInfo request;
6408 request.method = "GET";
6409 request.url = GURL("https://www.example.org/");
6410 request.load_flags = 0;
6412 MockWrite data_writes[] = {
6413 MockWrite(
6414 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6415 "Host: www.example.org\r\n"
6416 "Proxy-Connection: keep-alive\r\n\r\n"),
6417 MockWrite(
6418 "GET / HTTP/1.1\r\n"
6419 "Host: www.example.org\r\n"
6420 "Connection: keep-alive\r\n\r\n"),
6423 MockRead data_reads[] = {
6424 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6425 MockRead("HTTP/1.1 200 OK\r\n"),
6426 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6427 MockRead("Content-Length: 100\r\n\r\n"),
6428 MockRead(SYNCHRONOUS, OK),
6431 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6432 data_writes, arraysize(data_writes));
6433 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6434 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6436 session_deps_.socket_factory->AddSocketDataProvider(&data);
6437 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6438 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6440 TestCompletionCallback callback;
6442 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6443 scoped_ptr<HttpTransaction> trans(
6444 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6446 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6447 EXPECT_EQ(ERR_IO_PENDING, rv);
6449 rv = callback.WaitForResult();
6450 EXPECT_EQ(OK, rv);
6451 const HttpResponseInfo* response = trans->GetResponseInfo();
6453 ASSERT_TRUE(response != NULL);
6455 EXPECT_TRUE(response->headers->IsKeepAlive());
6456 EXPECT_EQ(200, response->headers->response_code());
6457 EXPECT_EQ(100, response->headers->GetContentLength());
6458 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6460 LoadTimingInfo load_timing_info;
6461 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6462 TestLoadTimingNotReusedWithPac(load_timing_info,
6463 CONNECT_TIMING_HAS_SSL_TIMES);
6466 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6467 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6468 session_deps_.proxy_service.reset(
6469 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6470 TestNetLog net_log;
6471 session_deps_.net_log = &net_log;
6473 HttpRequestInfo request;
6474 request.method = "GET";
6475 request.url = GURL("https://www.example.org/");
6476 request.load_flags = 0;
6478 MockWrite data_writes[] = {
6479 MockWrite(
6480 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6481 "Host: www.example.org\r\n"
6482 "Proxy-Connection: keep-alive\r\n\r\n"),
6485 MockRead data_reads[] = {
6486 MockRead("HTTP/1.1 302 Redirect\r\n"),
6487 MockRead("Location: http://login.example.com/\r\n"),
6488 MockRead("Content-Length: 0\r\n\r\n"),
6489 MockRead(SYNCHRONOUS, OK),
6492 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6493 data_writes, arraysize(data_writes));
6494 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6496 session_deps_.socket_factory->AddSocketDataProvider(&data);
6497 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6499 TestCompletionCallback callback;
6501 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6502 scoped_ptr<HttpTransaction> trans(
6503 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6505 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6506 EXPECT_EQ(ERR_IO_PENDING, rv);
6508 rv = callback.WaitForResult();
6509 EXPECT_EQ(OK, rv);
6510 const HttpResponseInfo* response = trans->GetResponseInfo();
6512 ASSERT_TRUE(response != NULL);
6514 EXPECT_EQ(302, response->headers->response_code());
6515 std::string url;
6516 EXPECT_TRUE(response->headers->IsRedirect(&url));
6517 EXPECT_EQ("http://login.example.com/", url);
6519 // In the case of redirects from proxies, HttpNetworkTransaction returns
6520 // timing for the proxy connection instead of the connection to the host,
6521 // and no send / receive times.
6522 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6523 LoadTimingInfo load_timing_info;
6524 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6526 EXPECT_FALSE(load_timing_info.socket_reused);
6527 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6529 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6530 EXPECT_LE(load_timing_info.proxy_resolve_start,
6531 load_timing_info.proxy_resolve_end);
6532 EXPECT_LE(load_timing_info.proxy_resolve_end,
6533 load_timing_info.connect_timing.connect_start);
6534 ExpectConnectTimingHasTimes(
6535 load_timing_info.connect_timing,
6536 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6538 EXPECT_TRUE(load_timing_info.send_start.is_null());
6539 EXPECT_TRUE(load_timing_info.send_end.is_null());
6540 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6543 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6544 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6545 session_deps_.proxy_service.reset(
6546 ProxyService::CreateFixed("https://proxy:70"));
6548 HttpRequestInfo request;
6549 request.method = "GET";
6550 request.url = GURL("https://www.example.org/");
6551 request.load_flags = 0;
6553 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6554 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6555 scoped_ptr<SpdyFrame> goaway(
6556 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6557 MockWrite data_writes[] = {
6558 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6559 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
6562 static const char* const kExtraHeaders[] = {
6563 "location",
6564 "http://login.example.com/",
6566 scoped_ptr<SpdyFrame> resp(
6567 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6568 arraysize(kExtraHeaders)/2, 1));
6569 MockRead data_reads[] = {
6570 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
6573 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6574 arraysize(data_writes));
6575 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6576 proxy_ssl.SetNextProto(GetParam());
6578 session_deps_.socket_factory->AddSocketDataProvider(&data);
6579 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6581 TestCompletionCallback callback;
6583 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6584 scoped_ptr<HttpTransaction> trans(
6585 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6587 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6588 EXPECT_EQ(ERR_IO_PENDING, rv);
6590 rv = callback.WaitForResult();
6591 EXPECT_EQ(OK, rv);
6592 const HttpResponseInfo* response = trans->GetResponseInfo();
6594 ASSERT_TRUE(response != NULL);
6596 EXPECT_EQ(302, response->headers->response_code());
6597 std::string url;
6598 EXPECT_TRUE(response->headers->IsRedirect(&url));
6599 EXPECT_EQ("http://login.example.com/", url);
6602 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6603 TEST_P(HttpNetworkTransactionTest,
6604 ErrorResponseToHttpsConnectViaHttpsProxy) {
6605 session_deps_.proxy_service.reset(
6606 ProxyService::CreateFixed("https://proxy:70"));
6608 HttpRequestInfo request;
6609 request.method = "GET";
6610 request.url = GURL("https://www.example.org/");
6611 request.load_flags = 0;
6613 MockWrite data_writes[] = {
6614 MockWrite(
6615 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6616 "Host: www.example.org\r\n"
6617 "Proxy-Connection: keep-alive\r\n\r\n"),
6620 MockRead data_reads[] = {
6621 MockRead("HTTP/1.1 404 Not Found\r\n"),
6622 MockRead("Content-Length: 23\r\n\r\n"),
6623 MockRead("The host does not exist"),
6624 MockRead(SYNCHRONOUS, OK),
6627 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6628 data_writes, arraysize(data_writes));
6629 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6631 session_deps_.socket_factory->AddSocketDataProvider(&data);
6632 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6634 TestCompletionCallback callback;
6636 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6637 scoped_ptr<HttpTransaction> trans(
6638 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6640 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6641 EXPECT_EQ(ERR_IO_PENDING, rv);
6643 rv = callback.WaitForResult();
6644 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6646 // TODO(ttuttle): Anything else to check here?
6649 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6650 TEST_P(HttpNetworkTransactionTest,
6651 ErrorResponseToHttpsConnectViaSpdyProxy) {
6652 session_deps_.proxy_service.reset(
6653 ProxyService::CreateFixed("https://proxy:70"));
6655 HttpRequestInfo request;
6656 request.method = "GET";
6657 request.url = GURL("https://www.example.org/");
6658 request.load_flags = 0;
6660 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6661 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6662 scoped_ptr<SpdyFrame> rst(
6663 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6664 MockWrite data_writes[] = {
6665 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
6668 static const char* const kExtraHeaders[] = {
6669 "location",
6670 "http://login.example.com/",
6672 scoped_ptr<SpdyFrame> resp(
6673 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6674 arraysize(kExtraHeaders)/2, 1));
6675 scoped_ptr<SpdyFrame> body(
6676 spdy_util_.ConstructSpdyBodyFrame(
6677 1, "The host does not exist", 23, true));
6678 MockRead data_reads[] = {
6679 CreateMockRead(*resp.get(), 1),
6680 CreateMockRead(*body.get(), 2),
6681 MockRead(ASYNC, 0, 4), // EOF
6684 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6685 arraysize(data_writes));
6686 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6687 proxy_ssl.SetNextProto(GetParam());
6689 session_deps_.socket_factory->AddSocketDataProvider(&data);
6690 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6692 TestCompletionCallback callback;
6694 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6695 scoped_ptr<HttpTransaction> trans(
6696 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6698 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6699 EXPECT_EQ(ERR_IO_PENDING, rv);
6701 rv = callback.WaitForResult();
6702 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6704 // TODO(ttuttle): Anything else to check here?
6707 // Test the request-challenge-retry sequence for basic auth, through
6708 // a SPDY proxy over a single SPDY session.
6709 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6710 HttpRequestInfo request;
6711 request.method = "GET";
6712 request.url = GURL("https://www.example.org/");
6713 // when the no authentication data flag is set.
6714 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
6716 // Configure against https proxy server "myproxy:70".
6717 session_deps_.proxy_service.reset(
6718 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6719 BoundTestNetLog log;
6720 session_deps_.net_log = log.bound().net_log();
6721 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6723 // Since we have proxy, should try to establish tunnel.
6724 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
6725 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6726 scoped_ptr<SpdyFrame> rst(
6727 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6729 // After calling trans->RestartWithAuth(), this is the request we should
6730 // be issuing -- the final header line contains the credentials.
6731 const char* const kAuthCredentials[] = {
6732 "proxy-authorization", "Basic Zm9vOmJhcg==",
6734 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6735 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
6736 HostPortPair("www.example.org", 443)));
6737 // fetch https://www.example.org/ via HTTP
6738 const char get[] =
6739 "GET / HTTP/1.1\r\n"
6740 "Host: www.example.org\r\n"
6741 "Connection: keep-alive\r\n\r\n";
6742 scoped_ptr<SpdyFrame> wrapped_get(
6743 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6745 MockWrite spdy_writes[] = {
6746 CreateMockWrite(*req, 0, ASYNC),
6747 CreateMockWrite(*rst, 2, ASYNC),
6748 CreateMockWrite(*connect2, 3),
6749 CreateMockWrite(*wrapped_get, 5),
6752 // The proxy responds to the connect with a 407, using a persistent
6753 // connection.
6754 const char kAuthStatus[] = "407";
6755 const char* const kAuthChallenge[] = {
6756 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6758 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6759 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6761 scoped_ptr<SpdyFrame> conn_resp(
6762 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6763 const char resp[] = "HTTP/1.1 200 OK\r\n"
6764 "Content-Length: 5\r\n\r\n";
6766 scoped_ptr<SpdyFrame> wrapped_get_resp(
6767 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6768 scoped_ptr<SpdyFrame> wrapped_body(
6769 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6770 MockRead spdy_reads[] = {
6771 CreateMockRead(*conn_auth_resp, 1, ASYNC),
6772 CreateMockRead(*conn_resp, 4, ASYNC),
6773 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
6774 CreateMockRead(*wrapped_body, 7, ASYNC),
6775 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
6778 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6779 arraysize(spdy_writes));
6780 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6781 // Negotiate SPDY to the proxy
6782 SSLSocketDataProvider proxy(ASYNC, OK);
6783 proxy.SetNextProto(GetParam());
6784 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6785 // Vanilla SSL to the server
6786 SSLSocketDataProvider server(ASYNC, OK);
6787 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6789 TestCompletionCallback callback1;
6791 scoped_ptr<HttpTransaction> trans(
6792 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6794 int rv = trans->Start(&request, callback1.callback(), log.bound());
6795 EXPECT_EQ(ERR_IO_PENDING, rv);
6797 rv = callback1.WaitForResult();
6798 EXPECT_EQ(OK, rv);
6799 TestNetLogEntry::List entries;
6800 log.GetEntries(&entries);
6801 size_t pos = ExpectLogContainsSomewhere(
6802 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6803 NetLog::PHASE_NONE);
6804 ExpectLogContainsSomewhere(
6805 entries, pos,
6806 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6807 NetLog::PHASE_NONE);
6809 const HttpResponseInfo* response = trans->GetResponseInfo();
6810 ASSERT_TRUE(response != NULL);
6811 ASSERT_FALSE(response->headers.get() == NULL);
6812 EXPECT_EQ(407, response->headers->response_code());
6813 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6814 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6815 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6817 TestCompletionCallback callback2;
6819 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6820 callback2.callback());
6821 EXPECT_EQ(ERR_IO_PENDING, rv);
6823 rv = callback2.WaitForResult();
6824 EXPECT_EQ(OK, rv);
6826 response = trans->GetResponseInfo();
6827 ASSERT_TRUE(response != NULL);
6829 EXPECT_TRUE(response->headers->IsKeepAlive());
6830 EXPECT_EQ(200, response->headers->response_code());
6831 EXPECT_EQ(5, response->headers->GetContentLength());
6832 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6834 // The password prompt info should not be set.
6835 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6837 LoadTimingInfo load_timing_info;
6838 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6839 TestLoadTimingNotReusedWithPac(load_timing_info,
6840 CONNECT_TIMING_HAS_SSL_TIMES);
6842 trans.reset();
6843 session->CloseAllConnections();
6846 // Test that an explicitly trusted SPDY proxy can push a resource from an
6847 // origin that is different from that of its associated resource.
6848 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6849 HttpRequestInfo request;
6850 HttpRequestInfo push_request;
6852 request.method = "GET";
6853 request.url = GURL("http://www.example.org/");
6854 push_request.method = "GET";
6855 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6857 // Configure against https proxy server "myproxy:70".
6858 session_deps_.proxy_service.reset(
6859 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6860 BoundTestNetLog log;
6861 session_deps_.net_log = log.bound().net_log();
6863 // Enable cross-origin push.
6864 session_deps_.trusted_spdy_proxy = "myproxy:70";
6866 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6868 scoped_ptr<SpdyFrame> stream1_syn(
6869 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6871 MockWrite spdy_writes[] = {
6872 CreateMockWrite(*stream1_syn, 0, ASYNC),
6875 scoped_ptr<SpdyFrame>
6876 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6878 scoped_ptr<SpdyFrame>
6879 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6881 scoped_ptr<SpdyFrame>
6882 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6886 "http://www.another-origin.com/foo.dat"));
6887 const char kPushedData[] = "pushed";
6888 scoped_ptr<SpdyFrame> stream2_body(
6889 spdy_util_.ConstructSpdyBodyFrame(
6890 2, kPushedData, strlen(kPushedData), true));
6892 MockRead spdy_reads[] = {
6893 CreateMockRead(*stream1_reply, 1, ASYNC),
6894 CreateMockRead(*stream2_syn, 2, ASYNC),
6895 CreateMockRead(*stream1_body, 3, ASYNC),
6896 CreateMockRead(*stream2_body, 4, ASYNC),
6897 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
6900 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6901 arraysize(spdy_writes));
6902 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6903 // Negotiate SPDY to the proxy
6904 SSLSocketDataProvider proxy(ASYNC, OK);
6905 proxy.SetNextProto(GetParam());
6906 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6908 scoped_ptr<HttpTransaction> trans(
6909 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6910 TestCompletionCallback callback;
6911 int rv = trans->Start(&request, callback.callback(), log.bound());
6912 EXPECT_EQ(ERR_IO_PENDING, rv);
6914 rv = callback.WaitForResult();
6915 EXPECT_EQ(OK, rv);
6916 const HttpResponseInfo* response = trans->GetResponseInfo();
6918 scoped_ptr<HttpTransaction> push_trans(
6919 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6920 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6921 EXPECT_EQ(ERR_IO_PENDING, rv);
6923 rv = callback.WaitForResult();
6924 EXPECT_EQ(OK, rv);
6925 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6927 ASSERT_TRUE(response != NULL);
6928 EXPECT_TRUE(response->headers->IsKeepAlive());
6930 EXPECT_EQ(200, response->headers->response_code());
6931 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6933 std::string response_data;
6934 rv = ReadTransaction(trans.get(), &response_data);
6935 EXPECT_EQ(OK, rv);
6936 EXPECT_EQ("hello!", response_data);
6938 LoadTimingInfo load_timing_info;
6939 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6940 TestLoadTimingNotReusedWithPac(load_timing_info,
6941 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6943 // Verify the pushed stream.
6944 EXPECT_TRUE(push_response->headers.get() != NULL);
6945 EXPECT_EQ(200, push_response->headers->response_code());
6947 rv = ReadTransaction(push_trans.get(), &response_data);
6948 EXPECT_EQ(OK, rv);
6949 EXPECT_EQ("pushed", response_data);
6951 LoadTimingInfo push_load_timing_info;
6952 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6953 TestLoadTimingReusedWithPac(push_load_timing_info);
6954 // The transactions should share a socket ID, despite being for different
6955 // origins.
6956 EXPECT_EQ(load_timing_info.socket_log_id,
6957 push_load_timing_info.socket_log_id);
6959 trans.reset();
6960 push_trans.reset();
6961 session->CloseAllConnections();
6964 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6965 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6966 HttpRequestInfo request;
6968 request.method = "GET";
6969 request.url = GURL("http://www.example.org/");
6971 // Configure against https proxy server "myproxy:70".
6972 session_deps_.proxy_service.reset(
6973 ProxyService::CreateFixed("https://myproxy:70"));
6974 BoundTestNetLog log;
6975 session_deps_.net_log = log.bound().net_log();
6977 // Enable cross-origin push.
6978 session_deps_.trusted_spdy_proxy = "myproxy:70";
6980 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6982 scoped_ptr<SpdyFrame> stream1_syn(
6983 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6985 scoped_ptr<SpdyFrame> push_rst(
6986 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6988 MockWrite spdy_writes[] = {
6989 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
6992 scoped_ptr<SpdyFrame>
6993 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6995 scoped_ptr<SpdyFrame>
6996 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6998 scoped_ptr<SpdyFrame>
6999 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
7003 "https://www.another-origin.com/foo.dat"));
7005 MockRead spdy_reads[] = {
7006 CreateMockRead(*stream1_reply, 1, ASYNC),
7007 CreateMockRead(*stream2_syn, 2, ASYNC),
7008 CreateMockRead(*stream1_body, 4, ASYNC),
7009 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
7012 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7013 arraysize(spdy_writes));
7014 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7015 // Negotiate SPDY to the proxy
7016 SSLSocketDataProvider proxy(ASYNC, OK);
7017 proxy.SetNextProto(GetParam());
7018 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7020 scoped_ptr<HttpTransaction> trans(
7021 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7022 TestCompletionCallback callback;
7023 int rv = trans->Start(&request, callback.callback(), log.bound());
7024 EXPECT_EQ(ERR_IO_PENDING, rv);
7026 rv = callback.WaitForResult();
7027 EXPECT_EQ(OK, rv);
7028 const HttpResponseInfo* response = trans->GetResponseInfo();
7030 ASSERT_TRUE(response != NULL);
7031 EXPECT_TRUE(response->headers->IsKeepAlive());
7033 EXPECT_EQ(200, response->headers->response_code());
7034 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7036 std::string response_data;
7037 rv = ReadTransaction(trans.get(), &response_data);
7038 EXPECT_EQ(OK, rv);
7039 EXPECT_EQ("hello!", response_data);
7041 trans.reset();
7042 session->CloseAllConnections();
7045 // Test HTTPS connections to a site with a bad certificate, going through an
7046 // HTTPS proxy
7047 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
7048 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
7049 "https://proxy:70"));
7051 HttpRequestInfo request;
7052 request.method = "GET";
7053 request.url = GURL("https://www.example.org/");
7054 request.load_flags = 0;
7056 // Attempt to fetch the URL from a server with a bad cert
7057 MockWrite bad_cert_writes[] = {
7058 MockWrite(
7059 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7060 "Host: www.example.org\r\n"
7061 "Proxy-Connection: keep-alive\r\n\r\n"),
7064 MockRead bad_cert_reads[] = {
7065 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7066 MockRead(SYNCHRONOUS, OK)
7069 // Attempt to fetch the URL with a good cert
7070 MockWrite good_data_writes[] = {
7071 MockWrite(
7072 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7073 "Host: www.example.org\r\n"
7074 "Proxy-Connection: keep-alive\r\n\r\n"),
7075 MockWrite(
7076 "GET / HTTP/1.1\r\n"
7077 "Host: www.example.org\r\n"
7078 "Connection: keep-alive\r\n\r\n"),
7081 MockRead good_cert_reads[] = {
7082 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7083 MockRead("HTTP/1.0 200 OK\r\n"),
7084 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7085 MockRead("Content-Length: 100\r\n\r\n"),
7086 MockRead(SYNCHRONOUS, OK),
7089 StaticSocketDataProvider ssl_bad_certificate(
7090 bad_cert_reads, arraysize(bad_cert_reads),
7091 bad_cert_writes, arraysize(bad_cert_writes));
7092 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7093 good_data_writes, arraysize(good_data_writes));
7094 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7095 SSLSocketDataProvider ssl(ASYNC, OK);
7097 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7098 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7099 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7100 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7102 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7103 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7104 session_deps_.socket_factory->AddSocketDataProvider(&data);
7105 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7107 TestCompletionCallback callback;
7109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7110 scoped_ptr<HttpTransaction> trans(
7111 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7113 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7114 EXPECT_EQ(ERR_IO_PENDING, rv);
7116 rv = callback.WaitForResult();
7117 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7119 rv = trans->RestartIgnoringLastError(callback.callback());
7120 EXPECT_EQ(ERR_IO_PENDING, rv);
7122 rv = callback.WaitForResult();
7123 EXPECT_EQ(OK, rv);
7125 const HttpResponseInfo* response = trans->GetResponseInfo();
7127 ASSERT_TRUE(response != NULL);
7128 EXPECT_EQ(100, response->headers->GetContentLength());
7131 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
7132 HttpRequestInfo request;
7133 request.method = "GET";
7134 request.url = GURL("http://www.example.org/");
7135 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7136 "Chromium Ultra Awesome X Edition");
7138 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7139 scoped_ptr<HttpTransaction> trans(
7140 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7142 MockWrite data_writes[] = {
7143 MockWrite(
7144 "GET / HTTP/1.1\r\n"
7145 "Host: www.example.org\r\n"
7146 "Connection: keep-alive\r\n"
7147 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7150 // Lastly, the server responds with the actual content.
7151 MockRead data_reads[] = {
7152 MockRead("HTTP/1.0 200 OK\r\n"),
7153 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7154 MockRead("Content-Length: 100\r\n\r\n"),
7155 MockRead(SYNCHRONOUS, OK),
7158 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7159 data_writes, arraysize(data_writes));
7160 session_deps_.socket_factory->AddSocketDataProvider(&data);
7162 TestCompletionCallback callback;
7164 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7165 EXPECT_EQ(ERR_IO_PENDING, rv);
7167 rv = callback.WaitForResult();
7168 EXPECT_EQ(OK, rv);
7171 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
7172 HttpRequestInfo request;
7173 request.method = "GET";
7174 request.url = GURL("https://www.example.org/");
7175 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7176 "Chromium Ultra Awesome X Edition");
7178 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7179 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7180 scoped_ptr<HttpTransaction> trans(
7181 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7183 MockWrite data_writes[] = {
7184 MockWrite(
7185 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7186 "Host: www.example.org\r\n"
7187 "Proxy-Connection: keep-alive\r\n"
7188 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7190 MockRead data_reads[] = {
7191 // Return an error, so the transaction stops here (this test isn't
7192 // interested in the rest).
7193 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7194 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7195 MockRead("Proxy-Connection: close\r\n\r\n"),
7198 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7199 data_writes, arraysize(data_writes));
7200 session_deps_.socket_factory->AddSocketDataProvider(&data);
7202 TestCompletionCallback callback;
7204 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7205 EXPECT_EQ(ERR_IO_PENDING, rv);
7207 rv = callback.WaitForResult();
7208 EXPECT_EQ(OK, rv);
7211 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
7212 HttpRequestInfo request;
7213 request.method = "GET";
7214 request.url = GURL("http://www.example.org/");
7215 request.load_flags = 0;
7216 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7217 "http://the.previous.site.com/");
7219 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7220 scoped_ptr<HttpTransaction> trans(
7221 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7223 MockWrite data_writes[] = {
7224 MockWrite(
7225 "GET / HTTP/1.1\r\n"
7226 "Host: www.example.org\r\n"
7227 "Connection: keep-alive\r\n"
7228 "Referer: http://the.previous.site.com/\r\n\r\n"),
7231 // Lastly, the server responds with the actual content.
7232 MockRead data_reads[] = {
7233 MockRead("HTTP/1.0 200 OK\r\n"),
7234 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7235 MockRead("Content-Length: 100\r\n\r\n"),
7236 MockRead(SYNCHRONOUS, OK),
7239 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7240 data_writes, arraysize(data_writes));
7241 session_deps_.socket_factory->AddSocketDataProvider(&data);
7243 TestCompletionCallback callback;
7245 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7246 EXPECT_EQ(ERR_IO_PENDING, rv);
7248 rv = callback.WaitForResult();
7249 EXPECT_EQ(OK, rv);
7252 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
7253 HttpRequestInfo request;
7254 request.method = "POST";
7255 request.url = GURL("http://www.example.org/");
7257 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7258 scoped_ptr<HttpTransaction> trans(
7259 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7261 MockWrite data_writes[] = {
7262 MockWrite(
7263 "POST / HTTP/1.1\r\n"
7264 "Host: www.example.org\r\n"
7265 "Connection: keep-alive\r\n"
7266 "Content-Length: 0\r\n\r\n"),
7269 // Lastly, the server responds with the actual content.
7270 MockRead data_reads[] = {
7271 MockRead("HTTP/1.0 200 OK\r\n"),
7272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7273 MockRead("Content-Length: 100\r\n\r\n"),
7274 MockRead(SYNCHRONOUS, OK),
7277 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7278 data_writes, arraysize(data_writes));
7279 session_deps_.socket_factory->AddSocketDataProvider(&data);
7281 TestCompletionCallback callback;
7283 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7284 EXPECT_EQ(ERR_IO_PENDING, rv);
7286 rv = callback.WaitForResult();
7287 EXPECT_EQ(OK, rv);
7290 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
7291 HttpRequestInfo request;
7292 request.method = "PUT";
7293 request.url = GURL("http://www.example.org/");
7295 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7296 scoped_ptr<HttpTransaction> trans(
7297 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7299 MockWrite data_writes[] = {
7300 MockWrite(
7301 "PUT / HTTP/1.1\r\n"
7302 "Host: www.example.org\r\n"
7303 "Connection: keep-alive\r\n"
7304 "Content-Length: 0\r\n\r\n"),
7307 // Lastly, the server responds with the actual content.
7308 MockRead data_reads[] = {
7309 MockRead("HTTP/1.0 200 OK\r\n"),
7310 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7311 MockRead("Content-Length: 100\r\n\r\n"),
7312 MockRead(SYNCHRONOUS, OK),
7315 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7316 data_writes, arraysize(data_writes));
7317 session_deps_.socket_factory->AddSocketDataProvider(&data);
7319 TestCompletionCallback callback;
7321 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7322 EXPECT_EQ(ERR_IO_PENDING, rv);
7324 rv = callback.WaitForResult();
7325 EXPECT_EQ(OK, rv);
7328 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
7329 HttpRequestInfo request;
7330 request.method = "HEAD";
7331 request.url = GURL("http://www.example.org/");
7333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7334 scoped_ptr<HttpTransaction> trans(
7335 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7337 MockWrite data_writes[] = {
7338 MockWrite(
7339 "HEAD / HTTP/1.1\r\n"
7340 "Host: www.example.org\r\n"
7341 "Connection: keep-alive\r\n"
7342 "Content-Length: 0\r\n\r\n"),
7345 // Lastly, the server responds with the actual content.
7346 MockRead data_reads[] = {
7347 MockRead("HTTP/1.0 200 OK\r\n"),
7348 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7349 MockRead("Content-Length: 100\r\n\r\n"),
7350 MockRead(SYNCHRONOUS, OK),
7353 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7354 data_writes, arraysize(data_writes));
7355 session_deps_.socket_factory->AddSocketDataProvider(&data);
7357 TestCompletionCallback callback;
7359 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7360 EXPECT_EQ(ERR_IO_PENDING, rv);
7362 rv = callback.WaitForResult();
7363 EXPECT_EQ(OK, rv);
7366 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7367 HttpRequestInfo request;
7368 request.method = "GET";
7369 request.url = GURL("http://www.example.org/");
7370 request.load_flags = LOAD_BYPASS_CACHE;
7372 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7373 scoped_ptr<HttpTransaction> trans(
7374 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7376 MockWrite data_writes[] = {
7377 MockWrite(
7378 "GET / HTTP/1.1\r\n"
7379 "Host: www.example.org\r\n"
7380 "Connection: keep-alive\r\n"
7381 "Pragma: no-cache\r\n"
7382 "Cache-Control: no-cache\r\n\r\n"),
7385 // Lastly, the server responds with the actual content.
7386 MockRead data_reads[] = {
7387 MockRead("HTTP/1.0 200 OK\r\n"),
7388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7389 MockRead("Content-Length: 100\r\n\r\n"),
7390 MockRead(SYNCHRONOUS, OK),
7393 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7394 data_writes, arraysize(data_writes));
7395 session_deps_.socket_factory->AddSocketDataProvider(&data);
7397 TestCompletionCallback callback;
7399 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7400 EXPECT_EQ(ERR_IO_PENDING, rv);
7402 rv = callback.WaitForResult();
7403 EXPECT_EQ(OK, rv);
7406 TEST_P(HttpNetworkTransactionTest,
7407 BuildRequest_CacheControlValidateCache) {
7408 HttpRequestInfo request;
7409 request.method = "GET";
7410 request.url = GURL("http://www.example.org/");
7411 request.load_flags = LOAD_VALIDATE_CACHE;
7413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7414 scoped_ptr<HttpTransaction> trans(
7415 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7417 MockWrite data_writes[] = {
7418 MockWrite(
7419 "GET / HTTP/1.1\r\n"
7420 "Host: www.example.org\r\n"
7421 "Connection: keep-alive\r\n"
7422 "Cache-Control: max-age=0\r\n\r\n"),
7425 // Lastly, the server responds with the actual content.
7426 MockRead data_reads[] = {
7427 MockRead("HTTP/1.0 200 OK\r\n"),
7428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7429 MockRead("Content-Length: 100\r\n\r\n"),
7430 MockRead(SYNCHRONOUS, OK),
7433 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7434 data_writes, arraysize(data_writes));
7435 session_deps_.socket_factory->AddSocketDataProvider(&data);
7437 TestCompletionCallback callback;
7439 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7440 EXPECT_EQ(ERR_IO_PENDING, rv);
7442 rv = callback.WaitForResult();
7443 EXPECT_EQ(OK, rv);
7446 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7447 HttpRequestInfo request;
7448 request.method = "GET";
7449 request.url = GURL("http://www.example.org/");
7450 request.extra_headers.SetHeader("FooHeader", "Bar");
7452 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7453 scoped_ptr<HttpTransaction> trans(
7454 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7456 MockWrite data_writes[] = {
7457 MockWrite(
7458 "GET / HTTP/1.1\r\n"
7459 "Host: www.example.org\r\n"
7460 "Connection: keep-alive\r\n"
7461 "FooHeader: Bar\r\n\r\n"),
7464 // Lastly, the server responds with the actual content.
7465 MockRead data_reads[] = {
7466 MockRead("HTTP/1.0 200 OK\r\n"),
7467 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7468 MockRead("Content-Length: 100\r\n\r\n"),
7469 MockRead(SYNCHRONOUS, OK),
7472 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7473 data_writes, arraysize(data_writes));
7474 session_deps_.socket_factory->AddSocketDataProvider(&data);
7476 TestCompletionCallback callback;
7478 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7479 EXPECT_EQ(ERR_IO_PENDING, rv);
7481 rv = callback.WaitForResult();
7482 EXPECT_EQ(OK, rv);
7485 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7486 HttpRequestInfo request;
7487 request.method = "GET";
7488 request.url = GURL("http://www.example.org/");
7489 request.extra_headers.SetHeader("referer", "www.foo.com");
7490 request.extra_headers.SetHeader("hEllo", "Kitty");
7491 request.extra_headers.SetHeader("FoO", "bar");
7493 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7494 scoped_ptr<HttpTransaction> trans(
7495 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7497 MockWrite data_writes[] = {
7498 MockWrite(
7499 "GET / HTTP/1.1\r\n"
7500 "Host: www.example.org\r\n"
7501 "Connection: keep-alive\r\n"
7502 "referer: www.foo.com\r\n"
7503 "hEllo: Kitty\r\n"
7504 "FoO: bar\r\n\r\n"),
7507 // Lastly, the server responds with the actual content.
7508 MockRead data_reads[] = {
7509 MockRead("HTTP/1.0 200 OK\r\n"),
7510 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7511 MockRead("Content-Length: 100\r\n\r\n"),
7512 MockRead(SYNCHRONOUS, OK),
7515 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7516 data_writes, arraysize(data_writes));
7517 session_deps_.socket_factory->AddSocketDataProvider(&data);
7519 TestCompletionCallback callback;
7521 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7522 EXPECT_EQ(ERR_IO_PENDING, rv);
7524 rv = callback.WaitForResult();
7525 EXPECT_EQ(OK, rv);
7528 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7529 HttpRequestInfo request;
7530 request.method = "GET";
7531 request.url = GURL("http://www.example.org/");
7532 request.load_flags = 0;
7534 session_deps_.proxy_service.reset(
7535 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7536 TestNetLog net_log;
7537 session_deps_.net_log = &net_log;
7539 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7540 scoped_ptr<HttpTransaction> trans(
7541 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7543 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7544 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7546 MockWrite data_writes[] = {
7547 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7548 MockWrite(
7549 "GET / HTTP/1.1\r\n"
7550 "Host: www.example.org\r\n"
7551 "Connection: keep-alive\r\n\r\n")};
7553 MockRead data_reads[] = {
7554 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7555 MockRead("HTTP/1.0 200 OK\r\n"),
7556 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7557 MockRead("Payload"),
7558 MockRead(SYNCHRONOUS, OK)
7561 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7562 data_writes, arraysize(data_writes));
7563 session_deps_.socket_factory->AddSocketDataProvider(&data);
7565 TestCompletionCallback callback;
7567 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7568 EXPECT_EQ(ERR_IO_PENDING, rv);
7570 rv = callback.WaitForResult();
7571 EXPECT_EQ(OK, rv);
7573 const HttpResponseInfo* response = trans->GetResponseInfo();
7574 ASSERT_TRUE(response != NULL);
7576 LoadTimingInfo load_timing_info;
7577 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7578 TestLoadTimingNotReusedWithPac(load_timing_info,
7579 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7581 std::string response_text;
7582 rv = ReadTransaction(trans.get(), &response_text);
7583 EXPECT_EQ(OK, rv);
7584 EXPECT_EQ("Payload", response_text);
7587 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7588 HttpRequestInfo request;
7589 request.method = "GET";
7590 request.url = GURL("https://www.example.org/");
7591 request.load_flags = 0;
7593 session_deps_.proxy_service.reset(
7594 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7595 TestNetLog net_log;
7596 session_deps_.net_log = &net_log;
7598 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7599 scoped_ptr<HttpTransaction> trans(
7600 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7602 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7603 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7605 MockWrite data_writes[] = {
7606 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7607 arraysize(write_buffer)),
7608 MockWrite(
7609 "GET / HTTP/1.1\r\n"
7610 "Host: www.example.org\r\n"
7611 "Connection: keep-alive\r\n\r\n")};
7613 MockRead data_reads[] = {
7614 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7615 arraysize(read_buffer)),
7616 MockRead("HTTP/1.0 200 OK\r\n"),
7617 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7618 MockRead("Payload"),
7619 MockRead(SYNCHRONOUS, OK)
7622 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7623 data_writes, arraysize(data_writes));
7624 session_deps_.socket_factory->AddSocketDataProvider(&data);
7626 SSLSocketDataProvider ssl(ASYNC, OK);
7627 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7629 TestCompletionCallback callback;
7631 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7632 EXPECT_EQ(ERR_IO_PENDING, rv);
7634 rv = callback.WaitForResult();
7635 EXPECT_EQ(OK, rv);
7637 LoadTimingInfo load_timing_info;
7638 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7639 TestLoadTimingNotReusedWithPac(load_timing_info,
7640 CONNECT_TIMING_HAS_SSL_TIMES);
7642 const HttpResponseInfo* response = trans->GetResponseInfo();
7643 ASSERT_TRUE(response != NULL);
7645 std::string response_text;
7646 rv = ReadTransaction(trans.get(), &response_text);
7647 EXPECT_EQ(OK, rv);
7648 EXPECT_EQ("Payload", response_text);
7651 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7652 HttpRequestInfo request;
7653 request.method = "GET";
7654 request.url = GURL("http://www.example.org/");
7655 request.load_flags = 0;
7657 session_deps_.proxy_service.reset(
7658 ProxyService::CreateFixed("socks4://myproxy:1080"));
7659 TestNetLog net_log;
7660 session_deps_.net_log = &net_log;
7662 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7663 scoped_ptr<HttpTransaction> trans(
7664 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7666 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7667 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7669 MockWrite data_writes[] = {
7670 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7671 MockWrite(
7672 "GET / HTTP/1.1\r\n"
7673 "Host: www.example.org\r\n"
7674 "Connection: keep-alive\r\n\r\n")};
7676 MockRead data_reads[] = {
7677 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7678 MockRead("HTTP/1.0 200 OK\r\n"),
7679 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7680 MockRead("Payload"),
7681 MockRead(SYNCHRONOUS, OK)
7684 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7685 data_writes, arraysize(data_writes));
7686 session_deps_.socket_factory->AddSocketDataProvider(&data);
7688 TestCompletionCallback callback;
7690 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7691 EXPECT_EQ(ERR_IO_PENDING, rv);
7693 rv = callback.WaitForResult();
7694 EXPECT_EQ(OK, rv);
7696 const HttpResponseInfo* response = trans->GetResponseInfo();
7697 ASSERT_TRUE(response != NULL);
7699 LoadTimingInfo load_timing_info;
7700 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7701 TestLoadTimingNotReused(load_timing_info,
7702 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7704 std::string response_text;
7705 rv = ReadTransaction(trans.get(), &response_text);
7706 EXPECT_EQ(OK, rv);
7707 EXPECT_EQ("Payload", response_text);
7710 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7711 HttpRequestInfo request;
7712 request.method = "GET";
7713 request.url = GURL("http://www.example.org/");
7714 request.load_flags = 0;
7716 session_deps_.proxy_service.reset(
7717 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7718 TestNetLog net_log;
7719 session_deps_.net_log = &net_log;
7721 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7722 scoped_ptr<HttpTransaction> trans(
7723 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7725 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7726 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7727 const char kSOCKS5OkRequest[] = {
7728 0x05, // Version
7729 0x01, // Command (CONNECT)
7730 0x00, // Reserved.
7731 0x03, // Address type (DOMAINNAME).
7732 0x0F, // Length of domain (15)
7733 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7734 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7736 const char kSOCKS5OkResponse[] =
7737 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7739 MockWrite data_writes[] = {
7740 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7741 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7742 MockWrite(
7743 "GET / HTTP/1.1\r\n"
7744 "Host: www.example.org\r\n"
7745 "Connection: keep-alive\r\n\r\n")};
7747 MockRead data_reads[] = {
7748 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7749 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7750 MockRead("HTTP/1.0 200 OK\r\n"),
7751 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7752 MockRead("Payload"),
7753 MockRead(SYNCHRONOUS, OK)
7756 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7757 data_writes, arraysize(data_writes));
7758 session_deps_.socket_factory->AddSocketDataProvider(&data);
7760 TestCompletionCallback callback;
7762 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7763 EXPECT_EQ(ERR_IO_PENDING, rv);
7765 rv = callback.WaitForResult();
7766 EXPECT_EQ(OK, rv);
7768 const HttpResponseInfo* response = trans->GetResponseInfo();
7769 ASSERT_TRUE(response != NULL);
7771 LoadTimingInfo load_timing_info;
7772 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7773 TestLoadTimingNotReusedWithPac(load_timing_info,
7774 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7776 std::string response_text;
7777 rv = ReadTransaction(trans.get(), &response_text);
7778 EXPECT_EQ(OK, rv);
7779 EXPECT_EQ("Payload", response_text);
7782 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7783 HttpRequestInfo request;
7784 request.method = "GET";
7785 request.url = GURL("https://www.example.org/");
7786 request.load_flags = 0;
7788 session_deps_.proxy_service.reset(
7789 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7790 TestNetLog net_log;
7791 session_deps_.net_log = &net_log;
7793 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7794 scoped_ptr<HttpTransaction> trans(
7795 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7797 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7798 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7799 const unsigned char kSOCKS5OkRequest[] = {
7800 0x05, // Version
7801 0x01, // Command (CONNECT)
7802 0x00, // Reserved.
7803 0x03, // Address type (DOMAINNAME).
7804 0x0F, // Length of domain (15)
7805 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7806 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7809 const char kSOCKS5OkResponse[] =
7810 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7812 MockWrite data_writes[] = {
7813 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7814 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7815 arraysize(kSOCKS5OkRequest)),
7816 MockWrite(
7817 "GET / HTTP/1.1\r\n"
7818 "Host: www.example.org\r\n"
7819 "Connection: keep-alive\r\n\r\n")};
7821 MockRead data_reads[] = {
7822 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7823 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7824 MockRead("HTTP/1.0 200 OK\r\n"),
7825 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7826 MockRead("Payload"),
7827 MockRead(SYNCHRONOUS, OK)
7830 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7831 data_writes, arraysize(data_writes));
7832 session_deps_.socket_factory->AddSocketDataProvider(&data);
7834 SSLSocketDataProvider ssl(ASYNC, OK);
7835 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7837 TestCompletionCallback callback;
7839 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7840 EXPECT_EQ(ERR_IO_PENDING, rv);
7842 rv = callback.WaitForResult();
7843 EXPECT_EQ(OK, rv);
7845 const HttpResponseInfo* response = trans->GetResponseInfo();
7846 ASSERT_TRUE(response != NULL);
7848 LoadTimingInfo load_timing_info;
7849 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7850 TestLoadTimingNotReusedWithPac(load_timing_info,
7851 CONNECT_TIMING_HAS_SSL_TIMES);
7853 std::string response_text;
7854 rv = ReadTransaction(trans.get(), &response_text);
7855 EXPECT_EQ(OK, rv);
7856 EXPECT_EQ("Payload", response_text);
7859 namespace {
7861 // Tests that for connection endpoints the group names are correctly set.
7863 struct GroupNameTest {
7864 std::string proxy_server;
7865 std::string url;
7866 std::string expected_group_name;
7867 bool ssl;
7870 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7871 NextProto next_proto,
7872 SpdySessionDependencies* session_deps_) {
7873 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7875 base::WeakPtr<HttpServerProperties> http_server_properties =
7876 session->http_server_properties();
7877 AlternativeService alternative_service(
7878 AlternateProtocolFromNextProto(next_proto), "", 443);
7879 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
7880 http_server_properties->SetAlternativeService(
7881 HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
7882 expiration);
7884 return session;
7887 int GroupNameTransactionHelper(
7888 const std::string& url,
7889 const scoped_refptr<HttpNetworkSession>& session) {
7890 HttpRequestInfo request;
7891 request.method = "GET";
7892 request.url = GURL(url);
7893 request.load_flags = 0;
7895 scoped_ptr<HttpTransaction> trans(
7896 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7898 TestCompletionCallback callback;
7900 // We do not complete this request, the dtor will clean the transaction up.
7901 return trans->Start(&request, callback.callback(), BoundNetLog());
7904 } // namespace
7906 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7907 const GroupNameTest tests[] = {
7909 "", // unused
7910 "http://www.example.org/direct",
7911 "www.example.org:80",
7912 false,
7915 "", // unused
7916 "http://[2001:1418:13:1::25]/direct",
7917 "[2001:1418:13:1::25]:80",
7918 false,
7921 // SSL Tests
7923 "", // unused
7924 "https://www.example.org/direct_ssl",
7925 "ssl/www.example.org:443",
7926 true,
7929 "", // unused
7930 "https://[2001:1418:13:1::25]/direct",
7931 "ssl/[2001:1418:13:1::25]:443",
7932 true,
7935 "", // unused
7936 "http://host.with.alternate/direct",
7937 "ssl/host.with.alternate:443",
7938 true,
7942 session_deps_.use_alternate_protocols = true;
7944 for (size_t i = 0; i < arraysize(tests); ++i) {
7945 session_deps_.proxy_service.reset(
7946 ProxyService::CreateFixed(tests[i].proxy_server));
7947 scoped_refptr<HttpNetworkSession> session(
7948 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7950 HttpNetworkSessionPeer peer(session);
7951 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7952 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7953 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7954 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7955 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7956 new MockClientSocketPoolManager);
7957 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7958 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7959 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
7961 EXPECT_EQ(ERR_IO_PENDING,
7962 GroupNameTransactionHelper(tests[i].url, session));
7963 if (tests[i].ssl)
7964 EXPECT_EQ(tests[i].expected_group_name,
7965 ssl_conn_pool->last_group_name_received());
7966 else
7967 EXPECT_EQ(tests[i].expected_group_name,
7968 transport_conn_pool->last_group_name_received());
7973 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7974 const GroupNameTest tests[] = {
7976 "http_proxy",
7977 "http://www.example.org/http_proxy_normal",
7978 "www.example.org:80",
7979 false,
7982 // SSL Tests
7984 "http_proxy",
7985 "https://www.example.org/http_connect_ssl",
7986 "ssl/www.example.org:443",
7987 true,
7991 "http_proxy",
7992 "http://host.with.alternate/direct",
7993 "ssl/host.with.alternate:443",
7994 true,
7998 "http_proxy",
7999 "ftp://ftp.google.com/http_proxy_normal",
8000 "ftp/ftp.google.com:21",
8001 false,
8005 session_deps_.use_alternate_protocols = true;
8007 for (size_t i = 0; i < arraysize(tests); ++i) {
8008 session_deps_.proxy_service.reset(
8009 ProxyService::CreateFixed(tests[i].proxy_server));
8010 scoped_refptr<HttpNetworkSession> session(
8011 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8013 HttpNetworkSessionPeer peer(session);
8015 HostPortPair proxy_host("http_proxy", 80);
8016 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
8017 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
8018 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8019 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8021 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8022 new MockClientSocketPoolManager);
8023 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8024 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8025 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8027 EXPECT_EQ(ERR_IO_PENDING,
8028 GroupNameTransactionHelper(tests[i].url, session));
8029 if (tests[i].ssl)
8030 EXPECT_EQ(tests[i].expected_group_name,
8031 ssl_conn_pool->last_group_name_received());
8032 else
8033 EXPECT_EQ(tests[i].expected_group_name,
8034 http_proxy_pool->last_group_name_received());
8038 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
8039 const GroupNameTest tests[] = {
8041 "socks4://socks_proxy:1080",
8042 "http://www.example.org/socks4_direct",
8043 "socks4/www.example.org:80",
8044 false,
8047 "socks5://socks_proxy:1080",
8048 "http://www.example.org/socks5_direct",
8049 "socks5/www.example.org:80",
8050 false,
8053 // SSL Tests
8055 "socks4://socks_proxy:1080",
8056 "https://www.example.org/socks4_ssl",
8057 "socks4/ssl/www.example.org:443",
8058 true,
8061 "socks5://socks_proxy:1080",
8062 "https://www.example.org/socks5_ssl",
8063 "socks5/ssl/www.example.org:443",
8064 true,
8068 "socks4://socks_proxy:1080",
8069 "http://host.with.alternate/direct",
8070 "socks4/ssl/host.with.alternate:443",
8071 true,
8075 session_deps_.use_alternate_protocols = true;
8077 for (size_t i = 0; i < arraysize(tests); ++i) {
8078 session_deps_.proxy_service.reset(
8079 ProxyService::CreateFixed(tests[i].proxy_server));
8080 scoped_refptr<HttpNetworkSession> session(
8081 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8083 HttpNetworkSessionPeer peer(session);
8085 HostPortPair proxy_host("socks_proxy", 1080);
8086 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
8087 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
8088 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8089 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8091 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8092 new MockClientSocketPoolManager);
8093 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8094 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8095 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8097 scoped_ptr<HttpTransaction> trans(
8098 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8100 EXPECT_EQ(ERR_IO_PENDING,
8101 GroupNameTransactionHelper(tests[i].url, session));
8102 if (tests[i].ssl)
8103 EXPECT_EQ(tests[i].expected_group_name,
8104 ssl_conn_pool->last_group_name_received());
8105 else
8106 EXPECT_EQ(tests[i].expected_group_name,
8107 socks_conn_pool->last_group_name_received());
8111 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
8112 HttpRequestInfo request;
8113 request.method = "GET";
8114 request.url = GURL("http://www.example.org/");
8116 session_deps_.proxy_service.reset(
8117 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8119 // This simulates failure resolving all hostnames; that means we will fail
8120 // connecting to both proxies (myproxy:70 and foobar:80).
8121 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
8123 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8124 scoped_ptr<HttpTransaction> trans(
8125 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8127 TestCompletionCallback callback;
8129 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8130 EXPECT_EQ(ERR_IO_PENDING, rv);
8132 rv = callback.WaitForResult();
8133 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
8136 // Base test to make sure that when the load flags for a request specify to
8137 // bypass the cache, the DNS cache is not used.
8138 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8139 int load_flags) {
8140 // Issue a request, asking to bypass the cache(s).
8141 HttpRequestInfo request;
8142 request.method = "GET";
8143 request.load_flags = load_flags;
8144 request.url = GURL("http://www.example.org/");
8146 // Select a host resolver that does caching.
8147 session_deps_.host_resolver.reset(new MockCachingHostResolver);
8149 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8150 scoped_ptr<HttpTransaction> trans(
8151 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8153 // Warm up the host cache so it has an entry for "www.example.org".
8154 AddressList addrlist;
8155 TestCompletionCallback callback;
8156 int rv = session_deps_.host_resolver->Resolve(
8157 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8158 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8159 EXPECT_EQ(ERR_IO_PENDING, rv);
8160 rv = callback.WaitForResult();
8161 EXPECT_EQ(OK, rv);
8163 // Verify that it was added to host cache, by doing a subsequent async lookup
8164 // and confirming it completes synchronously.
8165 rv = session_deps_.host_resolver->Resolve(
8166 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8167 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8168 ASSERT_EQ(OK, rv);
8170 // Inject a failure the next time that "www.example.org" is resolved. This way
8171 // we can tell if the next lookup hit the cache, or the "network".
8172 // (cache --> success, "network" --> failure).
8173 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
8175 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8176 // first read -- this won't be reached as the host resolution will fail first.
8177 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
8178 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8179 session_deps_.socket_factory->AddSocketDataProvider(&data);
8181 // Run the request.
8182 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8183 ASSERT_EQ(ERR_IO_PENDING, rv);
8184 rv = callback.WaitForResult();
8186 // If we bypassed the cache, we would have gotten a failure while resolving
8187 // "www.example.org".
8188 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8191 // There are multiple load flags that should trigger the host cache bypass.
8192 // Test each in isolation:
8193 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
8194 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8197 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
8198 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8201 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
8202 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8205 // Make sure we can handle an error when writing the request.
8206 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
8207 HttpRequestInfo request;
8208 request.method = "GET";
8209 request.url = GURL("http://www.foo.com/");
8210 request.load_flags = 0;
8212 MockWrite write_failure[] = {
8213 MockWrite(ASYNC, ERR_CONNECTION_RESET),
8215 StaticSocketDataProvider data(NULL, 0,
8216 write_failure, arraysize(write_failure));
8217 session_deps_.socket_factory->AddSocketDataProvider(&data);
8218 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8220 TestCompletionCallback callback;
8222 scoped_ptr<HttpTransaction> trans(
8223 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8225 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8226 EXPECT_EQ(ERR_IO_PENDING, rv);
8228 rv = callback.WaitForResult();
8229 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
8232 // Check that a connection closed after the start of the headers finishes ok.
8233 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
8234 HttpRequestInfo request;
8235 request.method = "GET";
8236 request.url = GURL("http://www.foo.com/");
8237 request.load_flags = 0;
8239 MockRead data_reads[] = {
8240 MockRead("HTTP/1."),
8241 MockRead(SYNCHRONOUS, OK),
8244 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8245 session_deps_.socket_factory->AddSocketDataProvider(&data);
8246 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8248 TestCompletionCallback callback;
8250 scoped_ptr<HttpTransaction> trans(
8251 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8253 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8254 EXPECT_EQ(ERR_IO_PENDING, rv);
8256 rv = callback.WaitForResult();
8257 EXPECT_EQ(OK, rv);
8259 const HttpResponseInfo* response = trans->GetResponseInfo();
8260 ASSERT_TRUE(response != NULL);
8262 EXPECT_TRUE(response->headers.get() != NULL);
8263 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8265 std::string response_data;
8266 rv = ReadTransaction(trans.get(), &response_data);
8267 EXPECT_EQ(OK, rv);
8268 EXPECT_EQ("", response_data);
8271 // Make sure that a dropped connection while draining the body for auth
8272 // restart does the right thing.
8273 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
8274 HttpRequestInfo request;
8275 request.method = "GET";
8276 request.url = GURL("http://www.example.org/");
8277 request.load_flags = 0;
8279 MockWrite data_writes1[] = {
8280 MockWrite(
8281 "GET / HTTP/1.1\r\n"
8282 "Host: www.example.org\r\n"
8283 "Connection: keep-alive\r\n\r\n"),
8286 MockRead data_reads1[] = {
8287 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8288 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8289 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8290 MockRead("Content-Length: 14\r\n\r\n"),
8291 MockRead("Unauth"),
8292 MockRead(ASYNC, ERR_CONNECTION_RESET),
8295 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8296 data_writes1, arraysize(data_writes1));
8297 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8299 // After calling trans->RestartWithAuth(), this is the request we should
8300 // be issuing -- the final header line contains the credentials.
8301 MockWrite data_writes2[] = {
8302 MockWrite(
8303 "GET / HTTP/1.1\r\n"
8304 "Host: www.example.org\r\n"
8305 "Connection: keep-alive\r\n"
8306 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8309 // Lastly, the server responds with the actual content.
8310 MockRead data_reads2[] = {
8311 MockRead("HTTP/1.1 200 OK\r\n"),
8312 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8313 MockRead("Content-Length: 100\r\n\r\n"),
8314 MockRead(SYNCHRONOUS, OK),
8317 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8318 data_writes2, arraysize(data_writes2));
8319 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8320 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8322 TestCompletionCallback callback1;
8324 scoped_ptr<HttpTransaction> trans(
8325 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8327 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8328 EXPECT_EQ(ERR_IO_PENDING, rv);
8330 rv = callback1.WaitForResult();
8331 EXPECT_EQ(OK, rv);
8333 const HttpResponseInfo* response = trans->GetResponseInfo();
8334 ASSERT_TRUE(response != NULL);
8335 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8337 TestCompletionCallback callback2;
8339 rv = trans->RestartWithAuth(
8340 AuthCredentials(kFoo, kBar), callback2.callback());
8341 EXPECT_EQ(ERR_IO_PENDING, rv);
8343 rv = callback2.WaitForResult();
8344 EXPECT_EQ(OK, rv);
8346 response = trans->GetResponseInfo();
8347 ASSERT_TRUE(response != NULL);
8348 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8349 EXPECT_EQ(100, response->headers->GetContentLength());
8352 // Test HTTPS connections going through a proxy that sends extra data.
8353 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8354 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8356 HttpRequestInfo request;
8357 request.method = "GET";
8358 request.url = GURL("https://www.example.org/");
8359 request.load_flags = 0;
8361 MockRead proxy_reads[] = {
8362 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8363 MockRead(SYNCHRONOUS, OK)
8366 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8367 SSLSocketDataProvider ssl(ASYNC, OK);
8369 session_deps_.socket_factory->AddSocketDataProvider(&data);
8370 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8372 TestCompletionCallback callback;
8374 session_deps_.socket_factory->ResetNextMockIndexes();
8376 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8377 scoped_ptr<HttpTransaction> trans(
8378 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8380 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8381 EXPECT_EQ(ERR_IO_PENDING, rv);
8383 rv = callback.WaitForResult();
8384 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8387 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8388 HttpRequestInfo request;
8389 request.method = "GET";
8390 request.url = GURL("http://www.example.org/");
8391 request.load_flags = 0;
8393 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8394 scoped_ptr<HttpTransaction> trans(
8395 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8397 MockRead data_reads[] = {
8398 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8399 MockRead(SYNCHRONOUS, OK),
8402 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8403 session_deps_.socket_factory->AddSocketDataProvider(&data);
8405 TestCompletionCallback callback;
8407 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8408 EXPECT_EQ(ERR_IO_PENDING, rv);
8410 EXPECT_EQ(OK, callback.WaitForResult());
8412 const HttpResponseInfo* response = trans->GetResponseInfo();
8413 ASSERT_TRUE(response != NULL);
8415 EXPECT_TRUE(response->headers.get() != NULL);
8416 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8418 std::string response_data;
8419 rv = ReadTransaction(trans.get(), &response_data);
8420 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8423 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8424 base::FilePath temp_file_path;
8425 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8426 const uint64 kFakeSize = 100000; // file is actually blank
8427 UploadFileElementReader::ScopedOverridingContentLengthForTests
8428 overriding_content_length(kFakeSize);
8430 ScopedVector<UploadElementReader> element_readers;
8431 element_readers.push_back(
8432 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8433 temp_file_path, 0, kuint64max, base::Time()));
8434 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8436 HttpRequestInfo request;
8437 request.method = "POST";
8438 request.url = GURL("http://www.example.org/upload");
8439 request.upload_data_stream = &upload_data_stream;
8440 request.load_flags = 0;
8442 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8443 scoped_ptr<HttpTransaction> trans(
8444 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8446 MockRead data_reads[] = {
8447 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8448 MockRead("hello world"),
8449 MockRead(SYNCHRONOUS, OK),
8451 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8452 session_deps_.socket_factory->AddSocketDataProvider(&data);
8454 TestCompletionCallback callback;
8456 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8457 EXPECT_EQ(ERR_IO_PENDING, rv);
8459 rv = callback.WaitForResult();
8460 EXPECT_EQ(OK, rv);
8462 const HttpResponseInfo* response = trans->GetResponseInfo();
8463 ASSERT_TRUE(response != NULL);
8465 EXPECT_TRUE(response->headers.get() != NULL);
8466 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8468 std::string response_data;
8469 rv = ReadTransaction(trans.get(), &response_data);
8470 EXPECT_EQ(OK, rv);
8471 EXPECT_EQ("hello world", response_data);
8473 base::DeleteFile(temp_file_path, false);
8476 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8477 base::FilePath temp_file;
8478 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8479 std::string temp_file_content("Unreadable file.");
8480 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8481 temp_file_content.length()));
8482 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
8484 ScopedVector<UploadElementReader> element_readers;
8485 element_readers.push_back(
8486 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8487 temp_file, 0, kuint64max, base::Time()));
8488 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8490 HttpRequestInfo request;
8491 request.method = "POST";
8492 request.url = GURL("http://www.example.org/upload");
8493 request.upload_data_stream = &upload_data_stream;
8494 request.load_flags = 0;
8496 // If we try to upload an unreadable file, the transaction should fail.
8497 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8498 scoped_ptr<HttpTransaction> trans(
8499 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8501 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8502 session_deps_.socket_factory->AddSocketDataProvider(&data);
8504 TestCompletionCallback callback;
8506 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8507 EXPECT_EQ(ERR_IO_PENDING, rv);
8509 rv = callback.WaitForResult();
8510 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8512 base::DeleteFile(temp_file, false);
8515 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8516 class FakeUploadElementReader : public UploadElementReader {
8517 public:
8518 FakeUploadElementReader() {}
8519 ~FakeUploadElementReader() override {}
8521 const CompletionCallback& callback() const { return callback_; }
8523 // UploadElementReader overrides:
8524 int Init(const CompletionCallback& callback) override {
8525 callback_ = callback;
8526 return ERR_IO_PENDING;
8528 uint64 GetContentLength() const override { return 0; }
8529 uint64 BytesRemaining() const override { return 0; }
8530 int Read(IOBuffer* buf,
8531 int buf_length,
8532 const CompletionCallback& callback) override {
8533 return ERR_FAILED;
8536 private:
8537 CompletionCallback callback_;
8540 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8541 ScopedVector<UploadElementReader> element_readers;
8542 element_readers.push_back(fake_reader);
8543 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8545 HttpRequestInfo request;
8546 request.method = "POST";
8547 request.url = GURL("http://www.example.org/upload");
8548 request.upload_data_stream = &upload_data_stream;
8549 request.load_flags = 0;
8551 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8552 scoped_ptr<HttpTransaction> trans(
8553 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8555 StaticSocketDataProvider data;
8556 session_deps_.socket_factory->AddSocketDataProvider(&data);
8558 TestCompletionCallback callback;
8559 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8560 EXPECT_EQ(ERR_IO_PENDING, rv);
8561 base::MessageLoop::current()->RunUntilIdle();
8563 // Transaction is pending on request body initialization.
8564 ASSERT_FALSE(fake_reader->callback().is_null());
8566 // Return Init()'s result after the transaction gets destroyed.
8567 trans.reset();
8568 fake_reader->callback().Run(OK); // Should not crash.
8571 // Tests that changes to Auth realms are treated like auth rejections.
8572 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8574 HttpRequestInfo request;
8575 request.method = "GET";
8576 request.url = GURL("http://www.example.org/");
8577 request.load_flags = 0;
8579 // First transaction will request a resource and receive a Basic challenge
8580 // with realm="first_realm".
8581 MockWrite data_writes1[] = {
8582 MockWrite(
8583 "GET / HTTP/1.1\r\n"
8584 "Host: www.example.org\r\n"
8585 "Connection: keep-alive\r\n"
8586 "\r\n"),
8588 MockRead data_reads1[] = {
8589 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8590 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8591 "\r\n"),
8594 // After calling trans->RestartWithAuth(), provide an Authentication header
8595 // for first_realm. The server will reject and provide a challenge with
8596 // second_realm.
8597 MockWrite data_writes2[] = {
8598 MockWrite(
8599 "GET / HTTP/1.1\r\n"
8600 "Host: www.example.org\r\n"
8601 "Connection: keep-alive\r\n"
8602 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8603 "\r\n"),
8605 MockRead data_reads2[] = {
8606 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8607 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8608 "\r\n"),
8611 // This again fails, and goes back to first_realm. Make sure that the
8612 // entry is removed from cache.
8613 MockWrite data_writes3[] = {
8614 MockWrite(
8615 "GET / HTTP/1.1\r\n"
8616 "Host: www.example.org\r\n"
8617 "Connection: keep-alive\r\n"
8618 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8619 "\r\n"),
8621 MockRead data_reads3[] = {
8622 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8623 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8624 "\r\n"),
8627 // Try one last time (with the correct password) and get the resource.
8628 MockWrite data_writes4[] = {
8629 MockWrite(
8630 "GET / HTTP/1.1\r\n"
8631 "Host: www.example.org\r\n"
8632 "Connection: keep-alive\r\n"
8633 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8634 "\r\n"),
8636 MockRead data_reads4[] = {
8637 MockRead("HTTP/1.1 200 OK\r\n"
8638 "Content-Type: text/html; charset=iso-8859-1\r\n"
8639 "Content-Length: 5\r\n"
8640 "\r\n"
8641 "hello"),
8644 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8645 data_writes1, arraysize(data_writes1));
8646 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8647 data_writes2, arraysize(data_writes2));
8648 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8649 data_writes3, arraysize(data_writes3));
8650 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8651 data_writes4, arraysize(data_writes4));
8652 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8653 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8654 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8655 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8657 TestCompletionCallback callback1;
8659 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8660 scoped_ptr<HttpTransaction> trans(
8661 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8663 // Issue the first request with Authorize headers. There should be a
8664 // password prompt for first_realm waiting to be filled in after the
8665 // transaction completes.
8666 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8667 EXPECT_EQ(ERR_IO_PENDING, rv);
8668 rv = callback1.WaitForResult();
8669 EXPECT_EQ(OK, rv);
8670 const HttpResponseInfo* response = trans->GetResponseInfo();
8671 ASSERT_TRUE(response != NULL);
8672 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8673 ASSERT_FALSE(challenge == NULL);
8674 EXPECT_FALSE(challenge->is_proxy);
8675 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8676 EXPECT_EQ("first_realm", challenge->realm);
8677 EXPECT_EQ("basic", challenge->scheme);
8679 // Issue the second request with an incorrect password. There should be a
8680 // password prompt for second_realm waiting to be filled in after the
8681 // transaction completes.
8682 TestCompletionCallback callback2;
8683 rv = trans->RestartWithAuth(
8684 AuthCredentials(kFirst, kBaz), callback2.callback());
8685 EXPECT_EQ(ERR_IO_PENDING, rv);
8686 rv = callback2.WaitForResult();
8687 EXPECT_EQ(OK, rv);
8688 response = trans->GetResponseInfo();
8689 ASSERT_TRUE(response != NULL);
8690 challenge = response->auth_challenge.get();
8691 ASSERT_FALSE(challenge == NULL);
8692 EXPECT_FALSE(challenge->is_proxy);
8693 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8694 EXPECT_EQ("second_realm", challenge->realm);
8695 EXPECT_EQ("basic", challenge->scheme);
8697 // Issue the third request with another incorrect password. There should be
8698 // a password prompt for first_realm waiting to be filled in. If the password
8699 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8700 // first_realm was not correctly removed.
8701 TestCompletionCallback callback3;
8702 rv = trans->RestartWithAuth(
8703 AuthCredentials(kSecond, kFou), callback3.callback());
8704 EXPECT_EQ(ERR_IO_PENDING, rv);
8705 rv = callback3.WaitForResult();
8706 EXPECT_EQ(OK, rv);
8707 response = trans->GetResponseInfo();
8708 ASSERT_TRUE(response != NULL);
8709 challenge = response->auth_challenge.get();
8710 ASSERT_FALSE(challenge == NULL);
8711 EXPECT_FALSE(challenge->is_proxy);
8712 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8713 EXPECT_EQ("first_realm", challenge->realm);
8714 EXPECT_EQ("basic", challenge->scheme);
8716 // Issue the fourth request with the correct password and username.
8717 TestCompletionCallback callback4;
8718 rv = trans->RestartWithAuth(
8719 AuthCredentials(kFirst, kBar), callback4.callback());
8720 EXPECT_EQ(ERR_IO_PENDING, rv);
8721 rv = callback4.WaitForResult();
8722 EXPECT_EQ(OK, rv);
8723 response = trans->GetResponseInfo();
8724 ASSERT_TRUE(response != NULL);
8725 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8728 TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
8729 session_deps_.next_protos = SpdyNextProtos();
8730 session_deps_.use_alternate_protocols = true;
8732 std::string alternative_service_http_header =
8733 GetAlternativeServiceHttpHeader();
8735 MockRead data_reads[] = {
8736 MockRead("HTTP/1.1 200 OK\r\n"),
8737 MockRead(alternative_service_http_header.c_str()),
8738 MockRead("\r\n"),
8739 MockRead("hello world"),
8740 MockRead(SYNCHRONOUS, OK),
8743 HttpRequestInfo request;
8744 request.method = "GET";
8745 request.url = GURL("http://www.example.org/");
8746 request.load_flags = 0;
8748 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8750 session_deps_.socket_factory->AddSocketDataProvider(&data);
8752 TestCompletionCallback callback;
8754 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8755 scoped_ptr<HttpTransaction> trans(
8756 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8759 EXPECT_EQ(ERR_IO_PENDING, rv);
8761 HostPortPair http_host_port_pair("www.example.org", 80);
8762 HttpServerProperties& http_server_properties =
8763 *session->http_server_properties();
8764 AlternativeServiceVector alternative_service_vector =
8765 http_server_properties.GetAlternativeServices(http_host_port_pair);
8766 EXPECT_TRUE(alternative_service_vector.empty());
8768 EXPECT_EQ(OK, callback.WaitForResult());
8770 const HttpResponseInfo* response = trans->GetResponseInfo();
8771 ASSERT_TRUE(response != NULL);
8772 ASSERT_TRUE(response->headers.get() != NULL);
8773 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8774 EXPECT_FALSE(response->was_fetched_via_spdy);
8775 EXPECT_FALSE(response->was_npn_negotiated);
8777 std::string response_data;
8778 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8779 EXPECT_EQ("hello world", response_data);
8781 alternative_service_vector =
8782 http_server_properties.GetAlternativeServices(http_host_port_pair);
8783 ASSERT_EQ(1u, alternative_service_vector.size());
8784 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8785 alternative_service_vector[0].protocol);
8786 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
8787 EXPECT_EQ(443, alternative_service_vector[0].port);
8790 TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
8791 session_deps_.next_protos = SpdyNextProtos();
8792 session_deps_.use_alternate_protocols = true;
8794 MockRead data_reads[] = {
8795 MockRead("HTTP/1.1 200 OK\r\n"),
8796 MockRead("Alt-Svc: "),
8797 MockRead(GetAlternateProtocolFromParam()),
8798 MockRead("=\"www.example.com:443\";p=1.0,"),
8799 MockRead("quic=\":1234\"\r\n\r\n"),
8800 MockRead("hello world"),
8801 MockRead(SYNCHRONOUS, OK),
8804 HttpRequestInfo request;
8805 request.method = "GET";
8806 request.url = GURL("http://www.example.org/");
8807 request.load_flags = 0;
8809 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8811 session_deps_.socket_factory->AddSocketDataProvider(&data);
8813 TestCompletionCallback callback;
8815 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8816 scoped_ptr<HttpTransaction> trans(
8817 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8819 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8820 EXPECT_EQ(ERR_IO_PENDING, rv);
8822 HostPortPair http_host_port_pair("www.example.org", 80);
8823 HttpServerProperties& http_server_properties =
8824 *session->http_server_properties();
8825 AlternativeServiceVector alternative_service_vector =
8826 http_server_properties.GetAlternativeServices(http_host_port_pair);
8827 EXPECT_TRUE(alternative_service_vector.empty());
8829 EXPECT_EQ(OK, callback.WaitForResult());
8831 const HttpResponseInfo* response = trans->GetResponseInfo();
8832 ASSERT_TRUE(response != NULL);
8833 ASSERT_TRUE(response->headers.get() != NULL);
8834 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8835 EXPECT_FALSE(response->was_fetched_via_spdy);
8836 EXPECT_FALSE(response->was_npn_negotiated);
8838 std::string response_data;
8839 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8840 EXPECT_EQ("hello world", response_data);
8842 alternative_service_vector =
8843 http_server_properties.GetAlternativeServices(http_host_port_pair);
8844 ASSERT_EQ(2u, alternative_service_vector.size());
8845 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8846 alternative_service_vector[0].protocol);
8847 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
8848 EXPECT_EQ(443, alternative_service_vector[0].port);
8849 EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
8850 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
8851 EXPECT_EQ(1234, alternative_service_vector[1].port);
8854 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8855 session_deps_.next_protos = SpdyNextProtos();
8856 session_deps_.use_alternate_protocols = true;
8858 std::string alternate_protocol_http_header =
8859 GetAlternateProtocolHttpHeader();
8861 MockRead data_reads[] = {
8862 MockRead("HTTP/1.1 200 OK\r\n"),
8863 MockRead(alternate_protocol_http_header.c_str()),
8864 MockRead("\r\n"),
8865 MockRead("hello world"),
8866 MockRead(SYNCHRONOUS, OK),
8869 HttpRequestInfo request;
8870 request.method = "GET";
8871 request.url = GURL("http://www.example.org/");
8872 request.load_flags = 0;
8874 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8876 session_deps_.socket_factory->AddSocketDataProvider(&data);
8878 TestCompletionCallback callback;
8880 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8881 scoped_ptr<HttpTransaction> trans(
8882 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8884 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8885 EXPECT_EQ(ERR_IO_PENDING, rv);
8887 HostPortPair http_host_port_pair("www.example.org", 80);
8888 HttpServerProperties& http_server_properties =
8889 *session->http_server_properties();
8890 AlternativeServiceVector alternative_service_vector =
8891 http_server_properties.GetAlternativeServices(http_host_port_pair);
8892 EXPECT_TRUE(alternative_service_vector.empty());
8894 EXPECT_EQ(OK, callback.WaitForResult());
8896 const HttpResponseInfo* response = trans->GetResponseInfo();
8897 ASSERT_TRUE(response != NULL);
8898 ASSERT_TRUE(response->headers.get() != NULL);
8899 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8900 EXPECT_FALSE(response->was_fetched_via_spdy);
8901 EXPECT_FALSE(response->was_npn_negotiated);
8903 std::string response_data;
8904 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8905 EXPECT_EQ("hello world", response_data);
8907 alternative_service_vector =
8908 http_server_properties.GetAlternativeServices(http_host_port_pair);
8909 ASSERT_EQ(1u, alternative_service_vector.size());
8910 EXPECT_EQ(443, alternative_service_vector[0].port);
8911 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8912 alternative_service_vector[0].protocol);
8915 TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
8916 session_deps_.next_protos = SpdyNextProtos();
8917 session_deps_.use_alternate_protocols = true;
8919 MockRead data_reads[] = {
8920 MockRead("HTTP/1.1 200 OK\r\n"),
8921 MockRead("Alternate-Protocol: \r\n\r\n"),
8922 MockRead("hello world"),
8923 MockRead(SYNCHRONOUS, OK),
8926 HttpRequestInfo request;
8927 request.method = "GET";
8928 request.url = GURL("http://www.example.org/");
8929 request.load_flags = 0;
8931 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8933 session_deps_.socket_factory->AddSocketDataProvider(&data);
8935 TestCompletionCallback callback;
8937 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8939 HostPortPair http_host_port_pair("www.example.org", 80);
8940 HttpServerProperties& http_server_properties =
8941 *session->http_server_properties();
8942 AlternativeService alternative_service(QUIC, "", 80);
8943 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
8944 http_server_properties.SetAlternativeService(
8945 http_host_port_pair, alternative_service, 1.0, expiration);
8947 AlternativeServiceVector alternative_service_vector =
8948 http_server_properties.GetAlternativeServices(http_host_port_pair);
8949 ASSERT_EQ(1u, alternative_service_vector.size());
8950 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
8952 scoped_ptr<HttpTransaction> trans(
8953 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8955 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8956 EXPECT_EQ(ERR_IO_PENDING, rv);
8958 EXPECT_EQ(OK, callback.WaitForResult());
8960 const HttpResponseInfo* response = trans->GetResponseInfo();
8961 ASSERT_TRUE(response != NULL);
8962 ASSERT_TRUE(response->headers.get() != NULL);
8963 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8964 EXPECT_FALSE(response->was_fetched_via_spdy);
8965 EXPECT_FALSE(response->was_npn_negotiated);
8967 std::string response_data;
8968 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8969 EXPECT_EQ("hello world", response_data);
8971 alternative_service_vector =
8972 http_server_properties.GetAlternativeServices(http_host_port_pair);
8973 EXPECT_TRUE(alternative_service_vector.empty());
8976 TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
8977 session_deps_.next_protos = SpdyNextProtos();
8978 session_deps_.use_alternate_protocols = true;
8980 std::string alternative_service_http_header =
8981 GetAlternativeServiceHttpHeader();
8982 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
8984 MockRead data_reads[] = {
8985 MockRead("HTTP/1.1 200 OK\r\n"),
8986 MockRead(alternative_service_http_header.c_str()),
8987 MockRead(alternate_protocol_http_header.c_str()),
8988 MockRead("\r\n"),
8989 MockRead("hello world"),
8990 MockRead(SYNCHRONOUS, OK),
8993 HttpRequestInfo request;
8994 request.method = "GET";
8995 request.url = GURL("http://www.example.org/");
8996 request.load_flags = 0;
8998 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9000 session_deps_.socket_factory->AddSocketDataProvider(&data);
9002 TestCompletionCallback callback;
9004 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9005 scoped_ptr<HttpTransaction> trans(
9006 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9008 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9009 EXPECT_EQ(ERR_IO_PENDING, rv);
9011 HostPortPair http_host_port_pair("www.example.org", 80);
9012 HttpServerProperties& http_server_properties =
9013 *session->http_server_properties();
9014 AlternativeServiceVector alternative_service_vector =
9015 http_server_properties.GetAlternativeServices(http_host_port_pair);
9016 EXPECT_TRUE(alternative_service_vector.empty());
9018 EXPECT_EQ(OK, callback.WaitForResult());
9020 const HttpResponseInfo* response = trans->GetResponseInfo();
9021 ASSERT_TRUE(response != NULL);
9022 ASSERT_TRUE(response->headers.get() != NULL);
9023 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9024 EXPECT_FALSE(response->was_fetched_via_spdy);
9025 EXPECT_FALSE(response->was_npn_negotiated);
9027 std::string response_data;
9028 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9029 EXPECT_EQ("hello world", response_data);
9031 alternative_service_vector =
9032 http_server_properties.GetAlternativeServices(http_host_port_pair);
9033 ASSERT_EQ(1u, alternative_service_vector.size());
9034 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9035 alternative_service_vector[0].protocol);
9036 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9037 EXPECT_EQ(443, alternative_service_vector[0].port);
9040 TEST_P(HttpNetworkTransactionTest,
9041 MarkBrokenAlternateProtocolAndFallback) {
9042 session_deps_.use_alternate_protocols = true;
9044 HttpRequestInfo request;
9045 request.method = "GET";
9046 request.url = GURL("http://www.example.org/");
9047 request.load_flags = 0;
9049 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9050 StaticSocketDataProvider first_data;
9051 first_data.set_connect_data(mock_connect);
9052 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9054 MockRead data_reads[] = {
9055 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9056 MockRead("hello world"),
9057 MockRead(ASYNC, OK),
9059 StaticSocketDataProvider second_data(
9060 data_reads, arraysize(data_reads), NULL, 0);
9061 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9063 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9065 base::WeakPtr<HttpServerProperties> http_server_properties =
9066 session->http_server_properties();
9067 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
9068 // Port must be < 1024, or the header will be ignored (since initial port was
9069 // port 80 (another restricted port).
9070 const AlternativeService alternative_service(
9071 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9072 666); // Port is ignored by MockConnect anyway.
9073 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9074 http_server_properties->SetAlternativeService(
9075 host_port_pair, alternative_service, 1.0, expiration);
9077 scoped_ptr<HttpTransaction> trans(
9078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9079 TestCompletionCallback callback;
9081 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9082 EXPECT_EQ(ERR_IO_PENDING, rv);
9083 EXPECT_EQ(OK, callback.WaitForResult());
9085 const HttpResponseInfo* response = trans->GetResponseInfo();
9086 ASSERT_TRUE(response != NULL);
9087 ASSERT_TRUE(response->headers.get() != NULL);
9088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9090 std::string response_data;
9091 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9092 EXPECT_EQ("hello world", response_data);
9094 const AlternativeServiceVector alternative_service_vector =
9095 http_server_properties->GetAlternativeServices(host_port_pair);
9096 ASSERT_EQ(1u, alternative_service_vector.size());
9097 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
9098 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
9099 alternative_service_vector[0]));
9102 TEST_P(HttpNetworkTransactionTest,
9103 AlternateProtocolPortRestrictedBlocked) {
9104 // Ensure that we're not allowed to redirect traffic via an alternate
9105 // protocol to an unrestricted (port >= 1024) when the original traffic was
9106 // on a restricted port (port < 1024). Ensure that we can redirect in all
9107 // other cases.
9108 session_deps_.use_alternate_protocols = true;
9110 HttpRequestInfo restricted_port_request;
9111 restricted_port_request.method = "GET";
9112 restricted_port_request.url = GURL("http://www.example.org:1023/");
9113 restricted_port_request.load_flags = 0;
9115 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9116 StaticSocketDataProvider first_data;
9117 first_data.set_connect_data(mock_connect);
9118 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9120 MockRead data_reads[] = {
9121 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9122 MockRead("hello world"),
9123 MockRead(ASYNC, OK),
9125 StaticSocketDataProvider second_data(
9126 data_reads, arraysize(data_reads), NULL, 0);
9127 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9129 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9131 base::WeakPtr<HttpServerProperties> http_server_properties =
9132 session->http_server_properties();
9133 const int kUnrestrictedAlternatePort = 1024;
9134 AlternativeService alternative_service(
9135 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9136 kUnrestrictedAlternatePort);
9137 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9138 http_server_properties->SetAlternativeService(
9139 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9140 1.0, expiration);
9142 scoped_ptr<HttpTransaction> trans(
9143 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9144 TestCompletionCallback callback;
9146 int rv = trans->Start(
9147 &restricted_port_request,
9148 callback.callback(), BoundNetLog());
9149 EXPECT_EQ(ERR_IO_PENDING, rv);
9150 // Invalid change to unrestricted port should fail.
9151 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
9154 TEST_P(HttpNetworkTransactionTest,
9155 AlternateProtocolPortRestrictedPermitted) {
9156 // Ensure that we're allowed to redirect traffic via an alternate
9157 // protocol to an unrestricted (port >= 1024) when the original traffic was
9158 // on a restricted port (port < 1024) if we set
9159 // enable_user_alternate_protocol_ports.
9161 session_deps_.use_alternate_protocols = true;
9162 session_deps_.enable_user_alternate_protocol_ports = true;
9164 HttpRequestInfo restricted_port_request;
9165 restricted_port_request.method = "GET";
9166 restricted_port_request.url = GURL("http://www.example.org:1023/");
9167 restricted_port_request.load_flags = 0;
9169 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9170 StaticSocketDataProvider first_data;
9171 first_data.set_connect_data(mock_connect);
9172 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9174 MockRead data_reads[] = {
9175 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9176 MockRead("hello world"),
9177 MockRead(ASYNC, OK),
9179 StaticSocketDataProvider second_data(
9180 data_reads, arraysize(data_reads), NULL, 0);
9181 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9183 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9185 base::WeakPtr<HttpServerProperties> http_server_properties =
9186 session->http_server_properties();
9187 const int kUnrestrictedAlternatePort = 1024;
9188 AlternativeService alternative_service(
9189 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9190 kUnrestrictedAlternatePort);
9191 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9192 http_server_properties->SetAlternativeService(
9193 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9194 1.0, expiration);
9196 scoped_ptr<HttpTransaction> trans(
9197 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9198 TestCompletionCallback callback;
9200 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
9201 &restricted_port_request,
9202 callback.callback(), BoundNetLog()));
9203 // Change to unrestricted port should succeed.
9204 EXPECT_EQ(OK, callback.WaitForResult());
9207 TEST_P(HttpNetworkTransactionTest,
9208 AlternateProtocolPortRestrictedAllowed) {
9209 // Ensure that we're not allowed to redirect traffic via an alternate
9210 // protocol to an unrestricted (port >= 1024) when the original traffic was
9211 // on a restricted port (port < 1024). Ensure that we can redirect in all
9212 // other cases.
9213 session_deps_.use_alternate_protocols = true;
9215 HttpRequestInfo restricted_port_request;
9216 restricted_port_request.method = "GET";
9217 restricted_port_request.url = GURL("http://www.example.org:1023/");
9218 restricted_port_request.load_flags = 0;
9220 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9221 StaticSocketDataProvider first_data;
9222 first_data.set_connect_data(mock_connect);
9223 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9225 MockRead data_reads[] = {
9226 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9227 MockRead("hello world"),
9228 MockRead(ASYNC, OK),
9230 StaticSocketDataProvider second_data(
9231 data_reads, arraysize(data_reads), NULL, 0);
9232 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9234 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9236 base::WeakPtr<HttpServerProperties> http_server_properties =
9237 session->http_server_properties();
9238 const int kRestrictedAlternatePort = 80;
9239 AlternativeService alternative_service(
9240 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9241 kRestrictedAlternatePort);
9242 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9243 http_server_properties->SetAlternativeService(
9244 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9245 1.0, expiration);
9247 scoped_ptr<HttpTransaction> trans(
9248 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9249 TestCompletionCallback callback;
9251 int rv = trans->Start(
9252 &restricted_port_request,
9253 callback.callback(), BoundNetLog());
9254 EXPECT_EQ(ERR_IO_PENDING, rv);
9255 // Valid change to restricted port should pass.
9256 EXPECT_EQ(OK, callback.WaitForResult());
9259 TEST_P(HttpNetworkTransactionTest,
9260 AlternateProtocolPortUnrestrictedAllowed1) {
9261 // Ensure that we're not allowed to redirect traffic via an alternate
9262 // protocol to an unrestricted (port >= 1024) when the original traffic was
9263 // on a restricted port (port < 1024). Ensure that we can redirect in all
9264 // other cases.
9265 session_deps_.use_alternate_protocols = true;
9267 HttpRequestInfo unrestricted_port_request;
9268 unrestricted_port_request.method = "GET";
9269 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9270 unrestricted_port_request.load_flags = 0;
9272 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9273 StaticSocketDataProvider first_data;
9274 first_data.set_connect_data(mock_connect);
9275 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9277 MockRead data_reads[] = {
9278 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9279 MockRead("hello world"),
9280 MockRead(ASYNC, OK),
9282 StaticSocketDataProvider second_data(
9283 data_reads, arraysize(data_reads), NULL, 0);
9284 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9286 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9288 base::WeakPtr<HttpServerProperties> http_server_properties =
9289 session->http_server_properties();
9290 const int kRestrictedAlternatePort = 80;
9291 AlternativeService alternative_service(
9292 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9293 kRestrictedAlternatePort);
9294 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9295 http_server_properties->SetAlternativeService(
9296 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9297 1.0, expiration);
9299 scoped_ptr<HttpTransaction> trans(
9300 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9301 TestCompletionCallback callback;
9303 int rv = trans->Start(
9304 &unrestricted_port_request, callback.callback(), BoundNetLog());
9305 EXPECT_EQ(ERR_IO_PENDING, rv);
9306 // Valid change to restricted port should pass.
9307 EXPECT_EQ(OK, callback.WaitForResult());
9310 TEST_P(HttpNetworkTransactionTest,
9311 AlternateProtocolPortUnrestrictedAllowed2) {
9312 // Ensure that we're not allowed to redirect traffic via an alternate
9313 // protocol to an unrestricted (port >= 1024) when the original traffic was
9314 // on a restricted port (port < 1024). Ensure that we can redirect in all
9315 // other cases.
9316 session_deps_.use_alternate_protocols = true;
9318 HttpRequestInfo unrestricted_port_request;
9319 unrestricted_port_request.method = "GET";
9320 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9321 unrestricted_port_request.load_flags = 0;
9323 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9324 StaticSocketDataProvider first_data;
9325 first_data.set_connect_data(mock_connect);
9326 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9328 MockRead data_reads[] = {
9329 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9330 MockRead("hello world"),
9331 MockRead(ASYNC, OK),
9333 StaticSocketDataProvider second_data(
9334 data_reads, arraysize(data_reads), NULL, 0);
9335 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9337 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9339 base::WeakPtr<HttpServerProperties> http_server_properties =
9340 session->http_server_properties();
9341 const int kUnrestrictedAlternatePort = 1025;
9342 AlternativeService alternative_service(
9343 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9344 kUnrestrictedAlternatePort);
9345 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9346 http_server_properties->SetAlternativeService(
9347 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9348 1.0, expiration);
9350 scoped_ptr<HttpTransaction> trans(
9351 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9352 TestCompletionCallback callback;
9354 int rv = trans->Start(
9355 &unrestricted_port_request, callback.callback(), BoundNetLog());
9356 EXPECT_EQ(ERR_IO_PENDING, rv);
9357 // Valid change to an unrestricted port should pass.
9358 EXPECT_EQ(OK, callback.WaitForResult());
9361 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
9362 // Ensure that we're not allowed to redirect traffic via an alternate
9363 // protocol to an unsafe port, and that we resume the second
9364 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9365 session_deps_.use_alternate_protocols = true;
9367 HttpRequestInfo request;
9368 request.method = "GET";
9369 request.url = GURL("http://www.example.org/");
9370 request.load_flags = 0;
9372 // The alternate protocol request will error out before we attempt to connect,
9373 // so only the standard HTTP request will try to connect.
9374 MockRead data_reads[] = {
9375 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9376 MockRead("hello world"),
9377 MockRead(ASYNC, OK),
9379 StaticSocketDataProvider data(
9380 data_reads, arraysize(data_reads), NULL, 0);
9381 session_deps_.socket_factory->AddSocketDataProvider(&data);
9383 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9385 base::WeakPtr<HttpServerProperties> http_server_properties =
9386 session->http_server_properties();
9387 const int kUnsafePort = 7;
9388 AlternativeService alternative_service(
9389 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9390 kUnsafePort);
9391 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9392 http_server_properties->SetAlternativeService(
9393 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
9395 scoped_ptr<HttpTransaction> trans(
9396 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9397 TestCompletionCallback callback;
9399 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9400 EXPECT_EQ(ERR_IO_PENDING, rv);
9401 // The HTTP request should succeed.
9402 EXPECT_EQ(OK, callback.WaitForResult());
9404 // Disable alternate protocol before the asserts.
9405 // HttpStreamFactory::set_use_alternate_protocols(false);
9407 const HttpResponseInfo* response = trans->GetResponseInfo();
9408 ASSERT_TRUE(response != NULL);
9409 ASSERT_TRUE(response->headers.get() != NULL);
9410 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9412 std::string response_data;
9413 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9414 EXPECT_EQ("hello world", response_data);
9417 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
9418 session_deps_.use_alternate_protocols = true;
9419 session_deps_.next_protos = SpdyNextProtos();
9421 HttpRequestInfo request;
9422 request.method = "GET";
9423 request.url = GURL("http://www.example.org/");
9424 request.load_flags = 0;
9426 std::string alternate_protocol_http_header =
9427 GetAlternateProtocolHttpHeader();
9429 MockRead data_reads[] = {
9430 MockRead("HTTP/1.1 200 OK\r\n"),
9431 MockRead(alternate_protocol_http_header.c_str()),
9432 MockRead("\r\n"),
9433 MockRead("hello world"),
9434 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9435 MockRead(ASYNC, OK)};
9437 StaticSocketDataProvider first_transaction(
9438 data_reads, arraysize(data_reads), NULL, 0);
9439 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9441 SSLSocketDataProvider ssl(ASYNC, OK);
9442 ssl.SetNextProto(GetParam());
9443 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9444 ASSERT_TRUE(ssl.cert.get());
9445 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9447 scoped_ptr<SpdyFrame> req(
9448 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9449 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9451 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9452 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9453 MockRead spdy_reads[] = {
9454 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9457 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9458 arraysize(spdy_writes));
9459 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9461 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9462 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9463 NULL, 0, NULL, 0);
9464 hanging_non_alternate_protocol_socket.set_connect_data(
9465 never_finishing_connect);
9466 session_deps_.socket_factory->AddSocketDataProvider(
9467 &hanging_non_alternate_protocol_socket);
9469 TestCompletionCallback callback;
9471 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9472 scoped_ptr<HttpTransaction> trans(
9473 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9475 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9476 EXPECT_EQ(ERR_IO_PENDING, rv);
9477 EXPECT_EQ(OK, callback.WaitForResult());
9479 const HttpResponseInfo* response = trans->GetResponseInfo();
9480 ASSERT_TRUE(response != NULL);
9481 ASSERT_TRUE(response->headers.get() != NULL);
9482 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9484 std::string response_data;
9485 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9486 EXPECT_EQ("hello world", response_data);
9488 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9490 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9491 EXPECT_EQ(ERR_IO_PENDING, rv);
9492 EXPECT_EQ(OK, callback.WaitForResult());
9494 response = trans->GetResponseInfo();
9495 ASSERT_TRUE(response != NULL);
9496 ASSERT_TRUE(response->headers.get() != NULL);
9497 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9498 EXPECT_TRUE(response->was_fetched_via_spdy);
9499 EXPECT_TRUE(response->was_npn_negotiated);
9501 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9502 EXPECT_EQ("hello!", response_data);
9505 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
9506 session_deps_.use_alternate_protocols = true;
9507 session_deps_.next_protos = SpdyNextProtos();
9509 HttpRequestInfo request;
9510 request.method = "GET";
9511 request.url = GURL("http://www.example.org/");
9512 request.load_flags = 0;
9514 std::string alternate_protocol_http_header =
9515 GetAlternateProtocolHttpHeader();
9517 MockRead data_reads[] = {
9518 MockRead("HTTP/1.1 200 OK\r\n"),
9519 MockRead(alternate_protocol_http_header.c_str()),
9520 MockRead("\r\n"),
9521 MockRead("hello world"),
9522 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9523 MockRead(ASYNC, OK),
9526 StaticSocketDataProvider first_transaction(
9527 data_reads, arraysize(data_reads), NULL, 0);
9528 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9529 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9531 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9532 StaticSocketDataProvider hanging_socket(
9533 NULL, 0, NULL, 0);
9534 hanging_socket.set_connect_data(never_finishing_connect);
9535 // Socket 2 and 3 are the hanging Alternate-Protocol and
9536 // non-Alternate-Protocol jobs from the 2nd transaction.
9537 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9538 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9540 SSLSocketDataProvider ssl(ASYNC, OK);
9541 ssl.SetNextProto(GetParam());
9542 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9543 ASSERT_TRUE(ssl.cert.get());
9544 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9546 scoped_ptr<SpdyFrame> req1(
9547 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9548 scoped_ptr<SpdyFrame> req2(
9549 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9550 MockWrite spdy_writes[] = {
9551 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
9553 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9554 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
9555 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9556 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9557 MockRead spdy_reads[] = {
9558 CreateMockRead(*resp1, 2),
9559 CreateMockRead(*data1, 3),
9560 CreateMockRead(*resp2, 4),
9561 CreateMockRead(*data2, 5),
9562 MockRead(ASYNC, 0, 6),
9565 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9566 arraysize(spdy_writes));
9567 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9568 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9570 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9571 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9573 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9574 TestCompletionCallback callback1;
9575 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9577 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
9578 EXPECT_EQ(ERR_IO_PENDING, rv);
9579 EXPECT_EQ(OK, callback1.WaitForResult());
9581 const HttpResponseInfo* response = trans1.GetResponseInfo();
9582 ASSERT_TRUE(response != NULL);
9583 ASSERT_TRUE(response->headers.get() != NULL);
9584 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9586 std::string response_data;
9587 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9588 EXPECT_EQ("hello world", response_data);
9590 TestCompletionCallback callback2;
9591 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9592 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
9593 EXPECT_EQ(ERR_IO_PENDING, rv);
9595 TestCompletionCallback callback3;
9596 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
9597 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
9598 EXPECT_EQ(ERR_IO_PENDING, rv);
9600 EXPECT_EQ(OK, callback2.WaitForResult());
9601 EXPECT_EQ(OK, callback3.WaitForResult());
9603 response = trans2.GetResponseInfo();
9604 ASSERT_TRUE(response != NULL);
9605 ASSERT_TRUE(response->headers.get() != NULL);
9606 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9607 EXPECT_TRUE(response->was_fetched_via_spdy);
9608 EXPECT_TRUE(response->was_npn_negotiated);
9609 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9610 EXPECT_EQ("hello!", response_data);
9612 response = trans3.GetResponseInfo();
9613 ASSERT_TRUE(response != NULL);
9614 ASSERT_TRUE(response->headers.get() != NULL);
9615 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9616 EXPECT_TRUE(response->was_fetched_via_spdy);
9617 EXPECT_TRUE(response->was_npn_negotiated);
9618 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9619 EXPECT_EQ("hello!", response_data);
9622 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9623 session_deps_.use_alternate_protocols = true;
9624 session_deps_.next_protos = SpdyNextProtos();
9626 HttpRequestInfo request;
9627 request.method = "GET";
9628 request.url = GURL("http://www.example.org/");
9629 request.load_flags = 0;
9631 std::string alternate_protocol_http_header =
9632 GetAlternateProtocolHttpHeader();
9634 MockRead data_reads[] = {
9635 MockRead("HTTP/1.1 200 OK\r\n"),
9636 MockRead(alternate_protocol_http_header.c_str()),
9637 MockRead("\r\n"),
9638 MockRead("hello world"),
9639 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9640 MockRead(ASYNC, OK),
9643 StaticSocketDataProvider first_transaction(
9644 data_reads, arraysize(data_reads), NULL, 0);
9645 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9647 SSLSocketDataProvider ssl(ASYNC, OK);
9648 ssl.SetNextProto(GetParam());
9649 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9651 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9652 StaticSocketDataProvider hanging_alternate_protocol_socket(
9653 NULL, 0, NULL, 0);
9654 hanging_alternate_protocol_socket.set_connect_data(
9655 never_finishing_connect);
9656 session_deps_.socket_factory->AddSocketDataProvider(
9657 &hanging_alternate_protocol_socket);
9659 // 2nd request is just a copy of the first one, over HTTP again.
9660 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9662 TestCompletionCallback callback;
9664 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9665 scoped_ptr<HttpTransaction> trans(
9666 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9668 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9669 EXPECT_EQ(ERR_IO_PENDING, rv);
9670 EXPECT_EQ(OK, callback.WaitForResult());
9672 const HttpResponseInfo* response = trans->GetResponseInfo();
9673 ASSERT_TRUE(response != NULL);
9674 ASSERT_TRUE(response->headers.get() != NULL);
9675 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9677 std::string response_data;
9678 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9679 EXPECT_EQ("hello world", response_data);
9681 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9683 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9684 EXPECT_EQ(ERR_IO_PENDING, rv);
9685 EXPECT_EQ(OK, callback.WaitForResult());
9687 response = trans->GetResponseInfo();
9688 ASSERT_TRUE(response != NULL);
9689 ASSERT_TRUE(response->headers.get() != NULL);
9690 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9691 EXPECT_FALSE(response->was_fetched_via_spdy);
9692 EXPECT_FALSE(response->was_npn_negotiated);
9694 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9695 EXPECT_EQ("hello world", response_data);
9698 class CapturingProxyResolver : public ProxyResolver {
9699 public:
9700 CapturingProxyResolver() {}
9701 ~CapturingProxyResolver() override {}
9703 int GetProxyForURL(const GURL& url,
9704 ProxyInfo* results,
9705 const CompletionCallback& callback,
9706 RequestHandle* request,
9707 const BoundNetLog& net_log) override {
9708 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9709 HostPortPair("myproxy", 80));
9710 results->UseProxyServer(proxy_server);
9711 resolved_.push_back(url);
9712 return OK;
9715 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
9717 LoadState GetLoadState(RequestHandle request) const override {
9718 NOTREACHED();
9719 return LOAD_STATE_IDLE;
9722 const std::vector<GURL>& resolved() const { return resolved_; }
9724 private:
9725 std::vector<GURL> resolved_;
9727 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9730 class CapturingProxyResolverFactory : public ProxyResolverFactory {
9731 public:
9732 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
9733 : ProxyResolverFactory(false), resolver_(resolver) {}
9735 int CreateProxyResolver(
9736 const scoped_refptr<ProxyResolverScriptData>& pac_script,
9737 scoped_ptr<ProxyResolver>* resolver,
9738 const net::CompletionCallback& callback,
9739 scoped_ptr<Request>* request) override {
9740 resolver->reset(new ForwardingProxyResolver(resolver_));
9741 return OK;
9744 private:
9745 ProxyResolver* resolver_;
9748 TEST_P(HttpNetworkTransactionTest,
9749 UseAlternateProtocolForTunneledNpnSpdy) {
9750 session_deps_.use_alternate_protocols = true;
9751 session_deps_.next_protos = SpdyNextProtos();
9753 ProxyConfig proxy_config;
9754 proxy_config.set_auto_detect(true);
9755 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9757 CapturingProxyResolver capturing_proxy_resolver;
9758 session_deps_.proxy_service.reset(new ProxyService(
9759 new ProxyConfigServiceFixed(proxy_config),
9760 make_scoped_ptr(
9761 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
9762 NULL));
9763 TestNetLog net_log;
9764 session_deps_.net_log = &net_log;
9766 HttpRequestInfo request;
9767 request.method = "GET";
9768 request.url = GURL("http://www.example.org/");
9769 request.load_flags = 0;
9771 std::string alternate_protocol_http_header =
9772 GetAlternateProtocolHttpHeader();
9774 MockRead data_reads[] = {
9775 MockRead("HTTP/1.1 200 OK\r\n"),
9776 MockRead(alternate_protocol_http_header.c_str()),
9777 MockRead("\r\n"),
9778 MockRead("hello world"),
9779 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9780 MockRead(ASYNC, OK),
9783 StaticSocketDataProvider first_transaction(
9784 data_reads, arraysize(data_reads), NULL, 0);
9785 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9787 SSLSocketDataProvider ssl(ASYNC, OK);
9788 ssl.SetNextProto(GetParam());
9789 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9790 ASSERT_TRUE(ssl.cert.get());
9791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9793 scoped_ptr<SpdyFrame> req(
9794 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9795 MockWrite spdy_writes[] = {
9796 MockWrite(ASYNC, 0,
9797 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9798 "Host: www.example.org\r\n"
9799 "Proxy-Connection: keep-alive\r\n\r\n"),
9800 CreateMockWrite(*req, 2),
9803 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9805 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9806 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9807 MockRead spdy_reads[] = {
9808 MockRead(ASYNC, 1, kCONNECTResponse),
9809 CreateMockRead(*resp.get(), 3),
9810 CreateMockRead(*data.get(), 4),
9811 MockRead(ASYNC, ERR_IO_PENDING, 5),
9814 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9815 arraysize(spdy_writes));
9816 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9818 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9819 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9820 NULL, 0, NULL, 0);
9821 hanging_non_alternate_protocol_socket.set_connect_data(
9822 never_finishing_connect);
9823 session_deps_.socket_factory->AddSocketDataProvider(
9824 &hanging_non_alternate_protocol_socket);
9826 TestCompletionCallback callback;
9828 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9829 scoped_ptr<HttpTransaction> trans(
9830 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9832 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9833 EXPECT_EQ(ERR_IO_PENDING, rv);
9834 EXPECT_EQ(OK, callback.WaitForResult());
9836 const HttpResponseInfo* response = trans->GetResponseInfo();
9837 ASSERT_TRUE(response != NULL);
9838 ASSERT_TRUE(response->headers.get() != NULL);
9839 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9840 EXPECT_FALSE(response->was_fetched_via_spdy);
9841 EXPECT_FALSE(response->was_npn_negotiated);
9843 std::string response_data;
9844 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9845 EXPECT_EQ("hello world", response_data);
9847 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9849 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9850 EXPECT_EQ(ERR_IO_PENDING, rv);
9851 EXPECT_EQ(OK, callback.WaitForResult());
9853 response = trans->GetResponseInfo();
9854 ASSERT_TRUE(response != NULL);
9855 ASSERT_TRUE(response->headers.get() != NULL);
9856 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9857 EXPECT_TRUE(response->was_fetched_via_spdy);
9858 EXPECT_TRUE(response->was_npn_negotiated);
9860 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9861 EXPECT_EQ("hello!", response_data);
9862 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
9863 EXPECT_EQ("http://www.example.org/",
9864 capturing_proxy_resolver.resolved()[0].spec());
9865 EXPECT_EQ("https://www.example.org/",
9866 capturing_proxy_resolver.resolved()[1].spec());
9868 LoadTimingInfo load_timing_info;
9869 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9870 TestLoadTimingNotReusedWithPac(load_timing_info,
9871 CONNECT_TIMING_HAS_SSL_TIMES);
9874 TEST_P(HttpNetworkTransactionTest,
9875 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9876 session_deps_.use_alternate_protocols = true;
9877 session_deps_.next_protos = SpdyNextProtos();
9879 HttpRequestInfo request;
9880 request.method = "GET";
9881 request.url = GURL("http://www.example.org/");
9882 request.load_flags = 0;
9884 std::string alternate_protocol_http_header =
9885 GetAlternateProtocolHttpHeader();
9887 MockRead data_reads[] = {
9888 MockRead("HTTP/1.1 200 OK\r\n"),
9889 MockRead(alternate_protocol_http_header.c_str()),
9890 MockRead("\r\n"),
9891 MockRead("hello world"),
9892 MockRead(ASYNC, OK),
9895 StaticSocketDataProvider first_transaction(
9896 data_reads, arraysize(data_reads), NULL, 0);
9897 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9899 SSLSocketDataProvider ssl(ASYNC, OK);
9900 ssl.SetNextProto(GetParam());
9901 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9902 ASSERT_TRUE(ssl.cert.get());
9903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9905 scoped_ptr<SpdyFrame> req(
9906 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9907 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9909 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9910 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9911 MockRead spdy_reads[] = {
9912 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9915 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9916 arraysize(spdy_writes));
9917 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9919 TestCompletionCallback callback;
9921 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9923 scoped_ptr<HttpTransaction> trans(
9924 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9926 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9927 EXPECT_EQ(ERR_IO_PENDING, rv);
9928 EXPECT_EQ(OK, callback.WaitForResult());
9930 const HttpResponseInfo* response = trans->GetResponseInfo();
9931 ASSERT_TRUE(response != NULL);
9932 ASSERT_TRUE(response->headers.get() != NULL);
9933 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9935 std::string response_data;
9936 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9937 EXPECT_EQ("hello world", response_data);
9939 // Set up an initial SpdySession in the pool to reuse.
9940 HostPortPair host_port_pair("www.example.org", 443);
9941 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9942 PRIVACY_MODE_DISABLED);
9943 base::WeakPtr<SpdySession> spdy_session =
9944 CreateSecureSpdySession(session, key, BoundNetLog());
9946 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9948 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9949 EXPECT_EQ(ERR_IO_PENDING, rv);
9950 EXPECT_EQ(OK, callback.WaitForResult());
9952 response = trans->GetResponseInfo();
9953 ASSERT_TRUE(response != NULL);
9954 ASSERT_TRUE(response->headers.get() != NULL);
9955 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9956 EXPECT_TRUE(response->was_fetched_via_spdy);
9957 EXPECT_TRUE(response->was_npn_negotiated);
9959 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9960 EXPECT_EQ("hello!", response_data);
9963 // GenerateAuthToken is a mighty big test.
9964 // It tests all permutation of GenerateAuthToken behavior:
9965 // - Synchronous and Asynchronous completion.
9966 // - OK or error on completion.
9967 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9968 // - HTTP or HTTPS backend (to include proxy tunneling).
9969 // - Non-authenticating and authenticating backend.
9971 // In all, there are 44 reasonable permuations (for example, if there are
9972 // problems generating an auth token for an authenticating proxy, we don't
9973 // need to test all permutations of the backend server).
9975 // The test proceeds by going over each of the configuration cases, and
9976 // potentially running up to three rounds in each of the tests. The TestConfig
9977 // specifies both the configuration for the test as well as the expectations
9978 // for the results.
9979 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9980 static const char kServer[] = "http://www.example.com";
9981 static const char kSecureServer[] = "https://www.example.com";
9982 static const char kProxy[] = "myproxy:70";
9983 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9985 enum AuthTiming {
9986 AUTH_NONE,
9987 AUTH_SYNC,
9988 AUTH_ASYNC,
9991 const MockWrite kGet(
9992 "GET / HTTP/1.1\r\n"
9993 "Host: www.example.com\r\n"
9994 "Connection: keep-alive\r\n\r\n");
9995 const MockWrite kGetProxy(
9996 "GET http://www.example.com/ HTTP/1.1\r\n"
9997 "Host: www.example.com\r\n"
9998 "Proxy-Connection: keep-alive\r\n\r\n");
9999 const MockWrite kGetAuth(
10000 "GET / HTTP/1.1\r\n"
10001 "Host: www.example.com\r\n"
10002 "Connection: keep-alive\r\n"
10003 "Authorization: auth_token\r\n\r\n");
10004 const MockWrite kGetProxyAuth(
10005 "GET http://www.example.com/ HTTP/1.1\r\n"
10006 "Host: www.example.com\r\n"
10007 "Proxy-Connection: keep-alive\r\n"
10008 "Proxy-Authorization: auth_token\r\n\r\n");
10009 const MockWrite kGetAuthThroughProxy(
10010 "GET http://www.example.com/ HTTP/1.1\r\n"
10011 "Host: www.example.com\r\n"
10012 "Proxy-Connection: keep-alive\r\n"
10013 "Authorization: auth_token\r\n\r\n");
10014 const MockWrite kGetAuthWithProxyAuth(
10015 "GET http://www.example.com/ HTTP/1.1\r\n"
10016 "Host: www.example.com\r\n"
10017 "Proxy-Connection: keep-alive\r\n"
10018 "Proxy-Authorization: auth_token\r\n"
10019 "Authorization: auth_token\r\n\r\n");
10020 const MockWrite kConnect(
10021 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10022 "Host: www.example.com\r\n"
10023 "Proxy-Connection: keep-alive\r\n\r\n");
10024 const MockWrite kConnectProxyAuth(
10025 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10026 "Host: www.example.com\r\n"
10027 "Proxy-Connection: keep-alive\r\n"
10028 "Proxy-Authorization: auth_token\r\n\r\n");
10030 const MockRead kSuccess(
10031 "HTTP/1.1 200 OK\r\n"
10032 "Content-Type: text/html; charset=iso-8859-1\r\n"
10033 "Content-Length: 3\r\n\r\n"
10034 "Yes");
10035 const MockRead kFailure(
10036 "Should not be called.");
10037 const MockRead kServerChallenge(
10038 "HTTP/1.1 401 Unauthorized\r\n"
10039 "WWW-Authenticate: Mock realm=server\r\n"
10040 "Content-Type: text/html; charset=iso-8859-1\r\n"
10041 "Content-Length: 14\r\n\r\n"
10042 "Unauthorized\r\n");
10043 const MockRead kProxyChallenge(
10044 "HTTP/1.1 407 Unauthorized\r\n"
10045 "Proxy-Authenticate: Mock realm=proxy\r\n"
10046 "Proxy-Connection: close\r\n"
10047 "Content-Type: text/html; charset=iso-8859-1\r\n"
10048 "Content-Length: 14\r\n\r\n"
10049 "Unauthorized\r\n");
10050 const MockRead kProxyConnected(
10051 "HTTP/1.1 200 Connection Established\r\n\r\n");
10053 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10054 // no constructors, but the C++ compiler on Windows warns about
10055 // unspecified data in compound literals. So, moved to using constructors,
10056 // and TestRound's created with the default constructor should not be used.
10057 struct TestRound {
10058 TestRound()
10059 : expected_rv(ERR_UNEXPECTED),
10060 extra_write(NULL),
10061 extra_read(NULL) {
10063 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10064 int expected_rv_arg)
10065 : write(write_arg),
10066 read(read_arg),
10067 expected_rv(expected_rv_arg),
10068 extra_write(NULL),
10069 extra_read(NULL) {
10071 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10072 int expected_rv_arg, const MockWrite* extra_write_arg,
10073 const MockRead* extra_read_arg)
10074 : write(write_arg),
10075 read(read_arg),
10076 expected_rv(expected_rv_arg),
10077 extra_write(extra_write_arg),
10078 extra_read(extra_read_arg) {
10080 MockWrite write;
10081 MockRead read;
10082 int expected_rv;
10083 const MockWrite* extra_write;
10084 const MockRead* extra_read;
10087 static const int kNoSSL = 500;
10089 struct TestConfig {
10090 const char* const proxy_url;
10091 AuthTiming proxy_auth_timing;
10092 int proxy_auth_rv;
10093 const char* const server_url;
10094 AuthTiming server_auth_timing;
10095 int server_auth_rv;
10096 int num_auth_rounds;
10097 int first_ssl_round;
10098 TestRound rounds[3];
10099 } test_configs[] = {
10100 // Non-authenticating HTTP server with a direct connection.
10101 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10102 { TestRound(kGet, kSuccess, OK)}},
10103 // Authenticating HTTP server with a direct connection.
10104 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10105 { TestRound(kGet, kServerChallenge, OK),
10106 TestRound(kGetAuth, kSuccess, OK)}},
10107 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10108 { TestRound(kGet, kServerChallenge, OK),
10109 TestRound(kGetAuth, kFailure, kAuthErr)}},
10110 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10111 { TestRound(kGet, kServerChallenge, OK),
10112 TestRound(kGetAuth, kSuccess, OK)}},
10113 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10114 { TestRound(kGet, kServerChallenge, OK),
10115 TestRound(kGetAuth, kFailure, kAuthErr)}},
10116 // Non-authenticating HTTP server through a non-authenticating proxy.
10117 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10118 { TestRound(kGetProxy, kSuccess, OK)}},
10119 // Authenticating HTTP server through a non-authenticating proxy.
10120 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10121 { TestRound(kGetProxy, kServerChallenge, OK),
10122 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10123 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10124 { TestRound(kGetProxy, kServerChallenge, OK),
10125 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10126 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10127 { TestRound(kGetProxy, kServerChallenge, OK),
10128 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10129 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10130 { TestRound(kGetProxy, kServerChallenge, OK),
10131 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10132 // Non-authenticating HTTP server through an authenticating proxy.
10133 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10134 { TestRound(kGetProxy, kProxyChallenge, OK),
10135 TestRound(kGetProxyAuth, kSuccess, OK)}},
10136 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10137 { TestRound(kGetProxy, kProxyChallenge, OK),
10138 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10139 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10140 { TestRound(kGetProxy, kProxyChallenge, OK),
10141 TestRound(kGetProxyAuth, kSuccess, OK)}},
10142 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10143 { TestRound(kGetProxy, kProxyChallenge, OK),
10144 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10145 // Authenticating HTTP server through an authenticating proxy.
10146 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10147 { TestRound(kGetProxy, kProxyChallenge, OK),
10148 TestRound(kGetProxyAuth, kServerChallenge, OK),
10149 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10150 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10151 { TestRound(kGetProxy, kProxyChallenge, OK),
10152 TestRound(kGetProxyAuth, kServerChallenge, OK),
10153 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10154 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10155 { TestRound(kGetProxy, kProxyChallenge, OK),
10156 TestRound(kGetProxyAuth, kServerChallenge, OK),
10157 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10158 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10159 { TestRound(kGetProxy, kProxyChallenge, OK),
10160 TestRound(kGetProxyAuth, kServerChallenge, OK),
10161 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10162 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10163 { TestRound(kGetProxy, kProxyChallenge, OK),
10164 TestRound(kGetProxyAuth, kServerChallenge, OK),
10165 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10166 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10167 { TestRound(kGetProxy, kProxyChallenge, OK),
10168 TestRound(kGetProxyAuth, kServerChallenge, OK),
10169 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10170 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10171 { TestRound(kGetProxy, kProxyChallenge, OK),
10172 TestRound(kGetProxyAuth, kServerChallenge, OK),
10173 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10174 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10175 { TestRound(kGetProxy, kProxyChallenge, OK),
10176 TestRound(kGetProxyAuth, kServerChallenge, OK),
10177 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10178 // Non-authenticating HTTPS server with a direct connection.
10179 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10180 { TestRound(kGet, kSuccess, OK)}},
10181 // Authenticating HTTPS server with a direct connection.
10182 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10183 { TestRound(kGet, kServerChallenge, OK),
10184 TestRound(kGetAuth, kSuccess, OK)}},
10185 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10186 { TestRound(kGet, kServerChallenge, OK),
10187 TestRound(kGetAuth, kFailure, kAuthErr)}},
10188 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10189 { TestRound(kGet, kServerChallenge, OK),
10190 TestRound(kGetAuth, kSuccess, OK)}},
10191 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10192 { TestRound(kGet, kServerChallenge, OK),
10193 TestRound(kGetAuth, kFailure, kAuthErr)}},
10194 // Non-authenticating HTTPS server with a non-authenticating proxy.
10195 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10196 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
10197 // Authenticating HTTPS server through a non-authenticating proxy.
10198 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10199 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10200 TestRound(kGetAuth, kSuccess, OK)}},
10201 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10202 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10203 TestRound(kGetAuth, kFailure, kAuthErr)}},
10204 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10205 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10206 TestRound(kGetAuth, kSuccess, OK)}},
10207 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10208 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10209 TestRound(kGetAuth, kFailure, kAuthErr)}},
10210 // Non-Authenticating HTTPS server through an authenticating proxy.
10211 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10212 { TestRound(kConnect, kProxyChallenge, OK),
10213 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10214 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10215 { TestRound(kConnect, kProxyChallenge, OK),
10216 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10217 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10218 { TestRound(kConnect, kProxyChallenge, OK),
10219 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10220 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10221 { TestRound(kConnect, kProxyChallenge, OK),
10222 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10223 // Authenticating HTTPS server through an authenticating proxy.
10224 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10225 { TestRound(kConnect, kProxyChallenge, OK),
10226 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10227 &kGet, &kServerChallenge),
10228 TestRound(kGetAuth, kSuccess, OK)}},
10229 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10230 { TestRound(kConnect, kProxyChallenge, OK),
10231 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10232 &kGet, &kServerChallenge),
10233 TestRound(kGetAuth, kFailure, kAuthErr)}},
10234 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10235 { TestRound(kConnect, kProxyChallenge, OK),
10236 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10237 &kGet, &kServerChallenge),
10238 TestRound(kGetAuth, kSuccess, OK)}},
10239 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10240 { TestRound(kConnect, kProxyChallenge, OK),
10241 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10242 &kGet, &kServerChallenge),
10243 TestRound(kGetAuth, kFailure, kAuthErr)}},
10244 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10245 { TestRound(kConnect, kProxyChallenge, OK),
10246 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10247 &kGet, &kServerChallenge),
10248 TestRound(kGetAuth, kSuccess, OK)}},
10249 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10250 { TestRound(kConnect, kProxyChallenge, OK),
10251 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10252 &kGet, &kServerChallenge),
10253 TestRound(kGetAuth, kFailure, kAuthErr)}},
10254 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10255 { TestRound(kConnect, kProxyChallenge, OK),
10256 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10257 &kGet, &kServerChallenge),
10258 TestRound(kGetAuth, kSuccess, OK)}},
10259 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10260 { TestRound(kConnect, kProxyChallenge, OK),
10261 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10262 &kGet, &kServerChallenge),
10263 TestRound(kGetAuth, kFailure, kAuthErr)}},
10266 for (size_t i = 0; i < arraysize(test_configs); ++i) {
10267 HttpAuthHandlerMock::Factory* auth_factory(
10268 new HttpAuthHandlerMock::Factory());
10269 session_deps_.http_auth_handler_factory.reset(auth_factory);
10270 const TestConfig& test_config = test_configs[i];
10272 // Set up authentication handlers as necessary.
10273 if (test_config.proxy_auth_timing != AUTH_NONE) {
10274 for (int n = 0; n < 2; n++) {
10275 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10276 std::string auth_challenge = "Mock realm=proxy";
10277 GURL origin(test_config.proxy_url);
10278 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10279 auth_challenge.end());
10280 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
10281 origin, BoundNetLog());
10282 auth_handler->SetGenerateExpectation(
10283 test_config.proxy_auth_timing == AUTH_ASYNC,
10284 test_config.proxy_auth_rv);
10285 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10288 if (test_config.server_auth_timing != AUTH_NONE) {
10289 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10290 std::string auth_challenge = "Mock realm=server";
10291 GURL origin(test_config.server_url);
10292 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10293 auth_challenge.end());
10294 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10295 origin, BoundNetLog());
10296 auth_handler->SetGenerateExpectation(
10297 test_config.server_auth_timing == AUTH_ASYNC,
10298 test_config.server_auth_rv);
10299 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10301 if (test_config.proxy_url) {
10302 session_deps_.proxy_service.reset(
10303 ProxyService::CreateFixed(test_config.proxy_url));
10304 } else {
10305 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10308 HttpRequestInfo request;
10309 request.method = "GET";
10310 request.url = GURL(test_config.server_url);
10311 request.load_flags = 0;
10313 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10314 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10316 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
10318 std::vector<std::vector<MockRead>> mock_reads(1);
10319 std::vector<std::vector<MockWrite>> mock_writes(1);
10320 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10321 const TestRound& read_write_round = test_config.rounds[round];
10323 // Set up expected reads and writes.
10324 mock_reads.back().push_back(read_write_round.read);
10325 mock_writes.back().push_back(read_write_round.write);
10327 // kProxyChallenge uses Proxy-Connection: close which means that the
10328 // socket is closed and a new one will be created for the next request.
10329 if (read_write_round.read.data == kProxyChallenge.data &&
10330 read_write_round.write.data != kConnect.data) {
10331 mock_reads.push_back(std::vector<MockRead>());
10332 mock_writes.push_back(std::vector<MockWrite>());
10335 if (read_write_round.extra_read) {
10336 mock_reads.back().push_back(*read_write_round.extra_read);
10338 if (read_write_round.extra_write) {
10339 mock_writes.back().push_back(*read_write_round.extra_write);
10342 // Add an SSL sequence if necessary.
10343 if (round >= test_config.first_ssl_round)
10344 session_deps_.socket_factory->AddSSLSocketDataProvider(
10345 &ssl_socket_data_provider);
10348 ScopedVector<StaticSocketDataProvider> data_providers;
10349 for (size_t i = 0; i < mock_reads.size(); ++i) {
10350 data_providers.push_back(new StaticSocketDataProvider(
10351 vector_as_array(&mock_reads[i]), mock_reads[i].size(),
10352 vector_as_array(&mock_writes[i]), mock_writes[i].size()));
10353 session_deps_.socket_factory->AddSocketDataProvider(
10354 data_providers.back());
10357 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10358 const TestRound& read_write_round = test_config.rounds[round];
10359 // Start or restart the transaction.
10360 TestCompletionCallback callback;
10361 int rv;
10362 if (round == 0) {
10363 rv = trans.Start(&request, callback.callback(), BoundNetLog());
10364 } else {
10365 rv = trans.RestartWithAuth(
10366 AuthCredentials(kFoo, kBar), callback.callback());
10368 if (rv == ERR_IO_PENDING)
10369 rv = callback.WaitForResult();
10371 // Compare results with expected data.
10372 EXPECT_EQ(read_write_round.expected_rv, rv);
10373 const HttpResponseInfo* response = trans.GetResponseInfo();
10374 if (read_write_round.expected_rv != OK) {
10375 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
10376 continue;
10378 if (round + 1 < test_config.num_auth_rounds) {
10379 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10380 } else {
10381 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10387 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
10388 // Do multi-round authentication and make sure it works correctly.
10389 HttpAuthHandlerMock::Factory* auth_factory(
10390 new HttpAuthHandlerMock::Factory());
10391 session_deps_.http_auth_handler_factory.reset(auth_factory);
10392 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10393 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
10394 session_deps_.host_resolver->set_synchronous_mode(true);
10396 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10397 auth_handler->set_connection_based(true);
10398 std::string auth_challenge = "Mock realm=server";
10399 GURL origin("http://www.example.com");
10400 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10401 auth_challenge.end());
10402 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10403 origin, BoundNetLog());
10404 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10406 int rv = OK;
10407 const HttpResponseInfo* response = NULL;
10408 HttpRequestInfo request;
10409 request.method = "GET";
10410 request.url = origin;
10411 request.load_flags = 0;
10413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10415 // Use a TCP Socket Pool with only one connection per group. This is used
10416 // to validate that the TCP socket is not released to the pool between
10417 // each round of multi-round authentication.
10418 HttpNetworkSessionPeer session_peer(session);
10419 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
10420 50, // Max sockets for pool
10421 1, // Max sockets per group
10422 session_deps_.host_resolver.get(),
10423 session_deps_.socket_factory.get(),
10424 session_deps_.net_log);
10425 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
10426 new MockClientSocketPoolManager);
10427 mock_pool_manager->SetTransportSocketPool(transport_pool);
10428 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
10430 scoped_ptr<HttpTransaction> trans(
10431 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10432 TestCompletionCallback callback;
10434 const MockWrite kGet(
10435 "GET / HTTP/1.1\r\n"
10436 "Host: www.example.com\r\n"
10437 "Connection: keep-alive\r\n\r\n");
10438 const MockWrite kGetAuth(
10439 "GET / HTTP/1.1\r\n"
10440 "Host: www.example.com\r\n"
10441 "Connection: keep-alive\r\n"
10442 "Authorization: auth_token\r\n\r\n");
10444 const MockRead kServerChallenge(
10445 "HTTP/1.1 401 Unauthorized\r\n"
10446 "WWW-Authenticate: Mock realm=server\r\n"
10447 "Content-Type: text/html; charset=iso-8859-1\r\n"
10448 "Content-Length: 14\r\n\r\n"
10449 "Unauthorized\r\n");
10450 const MockRead kSuccess(
10451 "HTTP/1.1 200 OK\r\n"
10452 "Content-Type: text/html; charset=iso-8859-1\r\n"
10453 "Content-Length: 3\r\n\r\n"
10454 "Yes");
10456 MockWrite writes[] = {
10457 // First round
10458 kGet,
10459 // Second round
10460 kGetAuth,
10461 // Third round
10462 kGetAuth,
10463 // Fourth round
10464 kGetAuth,
10465 // Competing request
10466 kGet,
10468 MockRead reads[] = {
10469 // First round
10470 kServerChallenge,
10471 // Second round
10472 kServerChallenge,
10473 // Third round
10474 kServerChallenge,
10475 // Fourth round
10476 kSuccess,
10477 // Competing response
10478 kSuccess,
10480 StaticSocketDataProvider data_provider(reads, arraysize(reads),
10481 writes, arraysize(writes));
10482 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10484 const char kSocketGroup[] = "www.example.com:80";
10486 // First round of authentication.
10487 auth_handler->SetGenerateExpectation(false, OK);
10488 rv = trans->Start(&request, callback.callback(), BoundNetLog());
10489 if (rv == ERR_IO_PENDING)
10490 rv = callback.WaitForResult();
10491 EXPECT_EQ(OK, rv);
10492 response = trans->GetResponseInfo();
10493 ASSERT_TRUE(response != NULL);
10494 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10495 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10497 // In between rounds, another request comes in for the same domain.
10498 // It should not be able to grab the TCP socket that trans has already
10499 // claimed.
10500 scoped_ptr<HttpTransaction> trans_compete(
10501 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10502 TestCompletionCallback callback_compete;
10503 rv = trans_compete->Start(
10504 &request, callback_compete.callback(), BoundNetLog());
10505 EXPECT_EQ(ERR_IO_PENDING, rv);
10506 // callback_compete.WaitForResult at this point would stall forever,
10507 // since the HttpNetworkTransaction does not release the request back to
10508 // the pool until after authentication completes.
10510 // Second round of authentication.
10511 auth_handler->SetGenerateExpectation(false, OK);
10512 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), 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 // Third round of authentication.
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 // Fourth round of authentication, which completes successfully.
10533 auth_handler->SetGenerateExpectation(false, OK);
10534 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10535 if (rv == ERR_IO_PENDING)
10536 rv = callback.WaitForResult();
10537 EXPECT_EQ(OK, rv);
10538 response = trans->GetResponseInfo();
10539 ASSERT_TRUE(response != NULL);
10540 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10541 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10543 // Read the body since the fourth round was successful. This will also
10544 // release the socket back to the pool.
10545 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
10546 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10547 if (rv == ERR_IO_PENDING)
10548 rv = callback.WaitForResult();
10549 EXPECT_EQ(3, rv);
10550 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10551 EXPECT_EQ(0, rv);
10552 // There are still 0 idle sockets, since the trans_compete transaction
10553 // will be handed it immediately after trans releases it to the group.
10554 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10556 // The competing request can now finish. Wait for the headers and then
10557 // read the body.
10558 rv = callback_compete.WaitForResult();
10559 EXPECT_EQ(OK, rv);
10560 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10561 if (rv == ERR_IO_PENDING)
10562 rv = callback.WaitForResult();
10563 EXPECT_EQ(3, rv);
10564 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10565 EXPECT_EQ(0, rv);
10567 // Finally, the socket is released to the group.
10568 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10571 // This tests the case that a request is issued via http instead of spdy after
10572 // npn is negotiated.
10573 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
10574 session_deps_.use_alternate_protocols = true;
10575 NextProtoVector next_protos;
10576 next_protos.push_back(kProtoHTTP11);
10577 session_deps_.next_protos = next_protos;
10579 HttpRequestInfo request;
10580 request.method = "GET";
10581 request.url = GURL("https://www.example.org/");
10582 request.load_flags = 0;
10584 MockWrite data_writes[] = {
10585 MockWrite(
10586 "GET / HTTP/1.1\r\n"
10587 "Host: www.example.org\r\n"
10588 "Connection: keep-alive\r\n\r\n"),
10591 std::string alternate_protocol_http_header =
10592 GetAlternateProtocolHttpHeader();
10594 MockRead data_reads[] = {
10595 MockRead("HTTP/1.1 200 OK\r\n"),
10596 MockRead(alternate_protocol_http_header.c_str()),
10597 MockRead("\r\n"),
10598 MockRead("hello world"),
10599 MockRead(SYNCHRONOUS, OK),
10602 SSLSocketDataProvider ssl(ASYNC, OK);
10603 ssl.SetNextProto(kProtoHTTP11);
10605 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10607 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
10608 data_writes, arraysize(data_writes));
10609 session_deps_.socket_factory->AddSocketDataProvider(&data);
10611 TestCompletionCallback callback;
10613 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10614 scoped_ptr<HttpTransaction> trans(
10615 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10617 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10619 EXPECT_EQ(ERR_IO_PENDING, rv);
10620 EXPECT_EQ(OK, callback.WaitForResult());
10622 const HttpResponseInfo* response = trans->GetResponseInfo();
10623 ASSERT_TRUE(response != NULL);
10624 ASSERT_TRUE(response->headers.get() != NULL);
10625 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10627 std::string response_data;
10628 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10629 EXPECT_EQ("hello world", response_data);
10631 EXPECT_FALSE(response->was_fetched_via_spdy);
10632 EXPECT_TRUE(response->was_npn_negotiated);
10635 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
10636 // Simulate the SSL handshake completing with an NPN negotiation
10637 // followed by an immediate server closing of the socket.
10638 // Fix crash: http://crbug.com/46369
10639 session_deps_.use_alternate_protocols = true;
10640 session_deps_.next_protos = SpdyNextProtos();
10642 HttpRequestInfo request;
10643 request.method = "GET";
10644 request.url = GURL("https://www.example.org/");
10645 request.load_flags = 0;
10647 SSLSocketDataProvider ssl(ASYNC, OK);
10648 ssl.SetNextProto(GetParam());
10649 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10651 scoped_ptr<SpdyFrame> req(
10652 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10653 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
10655 MockRead spdy_reads[] = {
10656 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10659 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10660 arraysize(spdy_writes));
10661 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10663 TestCompletionCallback callback;
10665 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10666 scoped_ptr<HttpTransaction> trans(
10667 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10669 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10670 EXPECT_EQ(ERR_IO_PENDING, rv);
10671 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10674 // A subclass of HttpAuthHandlerMock that records the request URL when
10675 // it gets it. This is needed since the auth handler may get destroyed
10676 // before we get a chance to query it.
10677 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10678 public:
10679 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10681 ~UrlRecordingHttpAuthHandlerMock() override {}
10683 protected:
10684 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10685 const HttpRequestInfo* request,
10686 const CompletionCallback& callback,
10687 std::string* auth_token) override {
10688 *url_ = request->url;
10689 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10690 credentials, request, callback, auth_token);
10693 private:
10694 GURL* url_;
10697 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10698 // This test ensures that the URL passed into the proxy is upgraded
10699 // to https when doing an Alternate Protocol upgrade.
10700 session_deps_.use_alternate_protocols = true;
10701 session_deps_.next_protos = SpdyNextProtos();
10703 session_deps_.proxy_service.reset(
10704 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10705 TestNetLog net_log;
10706 session_deps_.net_log = &net_log;
10707 GURL request_url;
10709 HttpAuthHandlerMock::Factory* auth_factory =
10710 new HttpAuthHandlerMock::Factory();
10711 UrlRecordingHttpAuthHandlerMock* auth_handler =
10712 new UrlRecordingHttpAuthHandlerMock(&request_url);
10713 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10714 auth_factory->set_do_init_from_challenge(true);
10715 session_deps_.http_auth_handler_factory.reset(auth_factory);
10718 HttpRequestInfo request;
10719 request.method = "GET";
10720 request.url = GURL("http://www.example.org");
10721 request.load_flags = 0;
10723 // First round goes unauthenticated through the proxy.
10724 MockWrite data_writes_1[] = {
10725 MockWrite(
10726 "GET http://www.example.org/ HTTP/1.1\r\n"
10727 "Host: www.example.org\r\n"
10728 "Proxy-Connection: keep-alive\r\n"
10729 "\r\n"),
10731 MockRead data_reads_1[] = {
10732 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10733 MockRead("HTTP/1.1 200 OK\r\n"),
10734 MockRead("Alternate-Protocol: 443:"),
10735 MockRead(GetAlternateProtocolFromParam()),
10736 MockRead("\r\n"),
10737 MockRead("Proxy-Connection: close\r\n"),
10738 MockRead("\r\n"),
10740 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10741 data_writes_1, arraysize(data_writes_1));
10743 // Second round tries to tunnel to www.example.org due to the
10744 // Alternate-Protocol announcement in the first round. It fails due
10745 // to a proxy authentication challenge.
10746 // After the failure, a tunnel is established to www.example.org using
10747 // Proxy-Authorization headers. There is then a SPDY request round.
10749 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10750 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10751 // does a Disconnect and Connect on the same socket, rather than trying
10752 // to obtain a new one.
10754 // NOTE: Originally, the proxy response to the second CONNECT request
10755 // simply returned another 407 so the unit test could skip the SSL connection
10756 // establishment and SPDY framing issues. Alas, the
10757 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10758 // complicated to set up expectations for than the SPDY session.
10760 scoped_ptr<SpdyFrame> req(
10761 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10762 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10763 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10765 MockWrite data_writes_2[] = {
10766 // First connection attempt without Proxy-Authorization.
10767 MockWrite(ASYNC, 0,
10768 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10769 "Host: www.example.org\r\n"
10770 "Proxy-Connection: keep-alive\r\n"
10771 "\r\n"),
10773 // Second connection attempt with Proxy-Authorization.
10774 MockWrite(ASYNC, 2,
10775 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10776 "Host: www.example.org\r\n"
10777 "Proxy-Connection: keep-alive\r\n"
10778 "Proxy-Authorization: auth_token\r\n"
10779 "\r\n"),
10781 // SPDY request
10782 CreateMockWrite(*req, 4),
10784 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10785 "Proxy-Authenticate: Mock\r\n"
10786 "Proxy-Connection: close\r\n"
10787 "\r\n");
10788 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10789 MockRead data_reads_2[] = {
10790 // First connection attempt fails
10791 MockRead(ASYNC, kRejectConnectResponse,
10792 arraysize(kRejectConnectResponse) - 1, 1),
10794 // Second connection attempt passes
10795 MockRead(ASYNC, kAcceptConnectResponse,
10796 arraysize(kAcceptConnectResponse) - 1, 3),
10798 // SPDY response
10799 CreateMockRead(*resp.get(), 5),
10800 CreateMockRead(*data.get(), 6),
10801 MockRead(ASYNC, 0, 0, 7),
10803 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
10804 data_writes_2, arraysize(data_writes_2));
10806 SSLSocketDataProvider ssl(ASYNC, OK);
10807 ssl.SetNextProto(GetParam());
10808 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10809 ASSERT_TRUE(ssl.cert.get());
10811 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10812 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10813 NULL, 0, NULL, 0);
10814 hanging_non_alternate_protocol_socket.set_connect_data(
10815 never_finishing_connect);
10817 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10818 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10819 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10820 session_deps_.socket_factory->AddSocketDataProvider(
10821 &hanging_non_alternate_protocol_socket);
10822 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10824 // First round should work and provide the Alternate-Protocol state.
10825 TestCompletionCallback callback_1;
10826 scoped_ptr<HttpTransaction> trans_1(
10827 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10828 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10829 EXPECT_EQ(ERR_IO_PENDING, rv);
10830 EXPECT_EQ(OK, callback_1.WaitForResult());
10832 // Second round should attempt a tunnel connect and get an auth challenge.
10833 TestCompletionCallback callback_2;
10834 scoped_ptr<HttpTransaction> trans_2(
10835 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10836 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10837 EXPECT_EQ(ERR_IO_PENDING, rv);
10838 EXPECT_EQ(OK, callback_2.WaitForResult());
10839 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10840 ASSERT_TRUE(response != NULL);
10841 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10843 // Restart with auth. Tunnel should work and response received.
10844 TestCompletionCallback callback_3;
10845 rv = trans_2->RestartWithAuth(
10846 AuthCredentials(kFoo, kBar), callback_3.callback());
10847 EXPECT_EQ(ERR_IO_PENDING, rv);
10848 EXPECT_EQ(OK, callback_3.WaitForResult());
10850 // After all that work, these two lines (or actually, just the scheme) are
10851 // what this test is all about. Make sure it happens correctly.
10852 EXPECT_EQ("https", request_url.scheme());
10853 EXPECT_EQ("www.example.org", request_url.host());
10855 LoadTimingInfo load_timing_info;
10856 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10857 TestLoadTimingNotReusedWithPac(load_timing_info,
10858 CONNECT_TIMING_HAS_SSL_TIMES);
10861 // Test that if we cancel the transaction as the connection is completing, that
10862 // everything tears down correctly.
10863 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10864 // Setup everything about the connection to complete synchronously, so that
10865 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10866 // for is the callback from the HttpStreamRequest.
10867 // Then cancel the transaction.
10868 // Verify that we don't crash.
10869 MockConnect mock_connect(SYNCHRONOUS, OK);
10870 MockRead data_reads[] = {
10871 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10872 MockRead(SYNCHRONOUS, "hello world"),
10873 MockRead(SYNCHRONOUS, OK),
10876 HttpRequestInfo request;
10877 request.method = "GET";
10878 request.url = GURL("http://www.example.org/");
10879 request.load_flags = 0;
10881 session_deps_.host_resolver->set_synchronous_mode(true);
10882 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10883 scoped_ptr<HttpTransaction> trans(
10884 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10886 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10887 data.set_connect_data(mock_connect);
10888 session_deps_.socket_factory->AddSocketDataProvider(&data);
10890 TestCompletionCallback callback;
10892 BoundTestNetLog log;
10893 int rv = trans->Start(&request, callback.callback(), log.bound());
10894 EXPECT_EQ(ERR_IO_PENDING, rv);
10895 trans.reset(); // Cancel the transaction here.
10897 base::MessageLoop::current()->RunUntilIdle();
10900 // Test that if a transaction is cancelled after receiving the headers, the
10901 // stream is drained properly and added back to the socket pool. The main
10902 // purpose of this test is to make sure that an HttpStreamParser can be read
10903 // from after the HttpNetworkTransaction and the objects it owns have been
10904 // deleted.
10905 // See http://crbug.com/368418
10906 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10907 MockRead data_reads[] = {
10908 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10909 MockRead(ASYNC, "Content-Length: 2\r\n"),
10910 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10911 MockRead(ASYNC, "1"),
10912 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10913 // HttpNetworkTransaction has been deleted.
10914 MockRead(ASYNC, "2"),
10915 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10917 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10918 session_deps_.socket_factory->AddSocketDataProvider(&data);
10920 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10923 HttpRequestInfo request;
10924 request.method = "GET";
10925 request.url = GURL("http://www.example.org/");
10926 request.load_flags = 0;
10928 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10929 TestCompletionCallback callback;
10931 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10932 EXPECT_EQ(ERR_IO_PENDING, rv);
10933 callback.WaitForResult();
10935 const HttpResponseInfo* response = trans.GetResponseInfo();
10936 ASSERT_TRUE(response != NULL);
10937 EXPECT_TRUE(response->headers.get() != NULL);
10938 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10940 // The transaction and HttpRequestInfo are deleted.
10943 // Let the HttpResponseBodyDrainer drain the socket.
10944 base::MessageLoop::current()->RunUntilIdle();
10946 // Socket should now be idle, waiting to be reused.
10947 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
10950 // Test a basic GET request through a proxy.
10951 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10952 session_deps_.proxy_service.reset(
10953 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10954 BoundTestNetLog log;
10955 session_deps_.net_log = log.bound().net_log();
10956 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10958 HttpRequestInfo request;
10959 request.method = "GET";
10960 request.url = GURL("http://www.example.org/");
10962 MockWrite data_writes1[] = {
10963 MockWrite(
10964 "GET http://www.example.org/ HTTP/1.1\r\n"
10965 "Host: www.example.org\r\n"
10966 "Proxy-Connection: keep-alive\r\n\r\n"),
10969 MockRead data_reads1[] = {
10970 MockRead("HTTP/1.1 200 OK\r\n"),
10971 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10972 MockRead("Content-Length: 100\r\n\r\n"),
10973 MockRead(SYNCHRONOUS, OK),
10976 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10977 data_writes1, arraysize(data_writes1));
10978 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10980 TestCompletionCallback callback1;
10982 scoped_ptr<HttpTransaction> trans(
10983 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10984 BeforeProxyHeadersSentHandler proxy_headers_handler;
10985 trans->SetBeforeProxyHeadersSentCallback(
10986 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
10987 base::Unretained(&proxy_headers_handler)));
10989 int rv = trans->Start(&request, callback1.callback(), log.bound());
10990 EXPECT_EQ(ERR_IO_PENDING, rv);
10992 rv = callback1.WaitForResult();
10993 EXPECT_EQ(OK, rv);
10995 const HttpResponseInfo* response = trans->GetResponseInfo();
10996 ASSERT_TRUE(response != NULL);
10998 EXPECT_TRUE(response->headers->IsKeepAlive());
10999 EXPECT_EQ(200, response->headers->response_code());
11000 EXPECT_EQ(100, response->headers->GetContentLength());
11001 EXPECT_TRUE(response->was_fetched_via_proxy);
11002 EXPECT_TRUE(
11003 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
11004 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
11005 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
11006 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11008 LoadTimingInfo load_timing_info;
11009 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11010 TestLoadTimingNotReusedWithPac(load_timing_info,
11011 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11014 // Test a basic HTTPS GET request through a proxy.
11015 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
11016 session_deps_.proxy_service.reset(
11017 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11018 BoundTestNetLog log;
11019 session_deps_.net_log = log.bound().net_log();
11020 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11022 HttpRequestInfo request;
11023 request.method = "GET";
11024 request.url = GURL("https://www.example.org/");
11026 // Since we have proxy, should try to establish tunnel.
11027 MockWrite data_writes1[] = {
11028 MockWrite(
11029 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11030 "Host: www.example.org\r\n"
11031 "Proxy-Connection: keep-alive\r\n\r\n"),
11033 MockWrite(
11034 "GET / HTTP/1.1\r\n"
11035 "Host: www.example.org\r\n"
11036 "Connection: keep-alive\r\n\r\n"),
11039 MockRead data_reads1[] = {
11040 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11042 MockRead("HTTP/1.1 200 OK\r\n"),
11043 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11044 MockRead("Content-Length: 100\r\n\r\n"),
11045 MockRead(SYNCHRONOUS, OK),
11048 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11049 data_writes1, arraysize(data_writes1));
11050 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11051 SSLSocketDataProvider ssl(ASYNC, OK);
11052 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11054 TestCompletionCallback callback1;
11056 scoped_ptr<HttpTransaction> trans(
11057 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11059 int rv = trans->Start(&request, callback1.callback(), log.bound());
11060 EXPECT_EQ(ERR_IO_PENDING, rv);
11062 rv = callback1.WaitForResult();
11063 EXPECT_EQ(OK, rv);
11064 TestNetLogEntry::List entries;
11065 log.GetEntries(&entries);
11066 size_t pos = ExpectLogContainsSomewhere(
11067 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11068 NetLog::PHASE_NONE);
11069 ExpectLogContainsSomewhere(
11070 entries, pos,
11071 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11072 NetLog::PHASE_NONE);
11074 const HttpResponseInfo* response = trans->GetResponseInfo();
11075 ASSERT_TRUE(response != NULL);
11077 EXPECT_TRUE(response->headers->IsKeepAlive());
11078 EXPECT_EQ(200, response->headers->response_code());
11079 EXPECT_EQ(100, response->headers->GetContentLength());
11080 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11081 EXPECT_TRUE(response->was_fetched_via_proxy);
11082 EXPECT_TRUE(
11083 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
11085 LoadTimingInfo load_timing_info;
11086 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11087 TestLoadTimingNotReusedWithPac(load_timing_info,
11088 CONNECT_TIMING_HAS_SSL_TIMES);
11091 // Test a basic HTTPS GET request through a proxy, but the server hangs up
11092 // while establishing the tunnel.
11093 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
11094 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
11095 BoundTestNetLog log;
11096 session_deps_.net_log = log.bound().net_log();
11097 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11099 HttpRequestInfo request;
11100 request.method = "GET";
11101 request.url = GURL("https://www.example.org/");
11103 // Since we have proxy, should try to establish tunnel.
11104 MockWrite data_writes1[] = {
11105 MockWrite(
11106 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11107 "Host: www.example.org\r\n"
11108 "Proxy-Connection: keep-alive\r\n\r\n"),
11110 MockWrite(
11111 "GET / HTTP/1.1\r\n"
11112 "Host: www.example.org\r\n"
11113 "Connection: keep-alive\r\n\r\n"),
11116 MockRead data_reads1[] = {
11117 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
11118 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11119 MockRead(ASYNC, 0, 0), // EOF
11122 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11123 data_writes1, arraysize(data_writes1));
11124 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11125 SSLSocketDataProvider ssl(ASYNC, OK);
11126 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11128 TestCompletionCallback callback1;
11130 scoped_ptr<HttpTransaction> trans(
11131 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11133 int rv = trans->Start(&request, callback1.callback(), log.bound());
11134 EXPECT_EQ(ERR_IO_PENDING, rv);
11136 rv = callback1.WaitForResult();
11137 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
11138 TestNetLogEntry::List entries;
11139 log.GetEntries(&entries);
11140 size_t pos = ExpectLogContainsSomewhere(
11141 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11142 NetLog::PHASE_NONE);
11143 ExpectLogContainsSomewhere(
11144 entries, pos,
11145 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11146 NetLog::PHASE_NONE);
11149 // Test for crbug.com/55424.
11150 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
11151 scoped_ptr<SpdyFrame> req(
11152 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11153 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
11155 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11156 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
11157 MockRead spdy_reads[] = {
11158 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
11161 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11162 arraysize(spdy_writes));
11163 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11165 SSLSocketDataProvider ssl(ASYNC, OK);
11166 ssl.SetNextProto(GetParam());
11167 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11169 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11171 // Set up an initial SpdySession in the pool to reuse.
11172 HostPortPair host_port_pair("www.example.org", 443);
11173 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
11174 PRIVACY_MODE_DISABLED);
11175 base::WeakPtr<SpdySession> spdy_session =
11176 CreateInsecureSpdySession(session, key, BoundNetLog());
11178 HttpRequestInfo request;
11179 request.method = "GET";
11180 request.url = GURL("https://www.example.org/");
11181 request.load_flags = 0;
11183 // This is the important line that marks this as a preconnect.
11184 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
11186 scoped_ptr<HttpTransaction> trans(
11187 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11189 TestCompletionCallback callback;
11190 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11191 EXPECT_EQ(ERR_IO_PENDING, rv);
11192 EXPECT_EQ(OK, callback.WaitForResult());
11195 // Given a net error, cause that error to be returned from the first Write()
11196 // call and verify that the HttpTransaction fails with that error.
11197 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11198 int error, IoMode mode) {
11199 HttpRequestInfo request_info;
11200 request_info.url = GURL("https://www.example.com/");
11201 request_info.method = "GET";
11202 request_info.load_flags = LOAD_NORMAL;
11204 SSLSocketDataProvider ssl_data(mode, OK);
11205 MockWrite data_writes[] = {
11206 MockWrite(mode, error),
11208 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
11209 session_deps_.socket_factory->AddSocketDataProvider(&data);
11210 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
11212 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11213 scoped_ptr<HttpTransaction> trans(
11214 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11216 TestCompletionCallback callback;
11217 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11218 if (rv == ERR_IO_PENDING)
11219 rv = callback.WaitForResult();
11220 ASSERT_EQ(error, rv);
11223 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
11224 // Just check a grab bag of cert errors.
11225 static const int kErrors[] = {
11226 ERR_CERT_COMMON_NAME_INVALID,
11227 ERR_CERT_AUTHORITY_INVALID,
11228 ERR_CERT_DATE_INVALID,
11230 for (size_t i = 0; i < arraysize(kErrors); i++) {
11231 CheckErrorIsPassedBack(kErrors[i], ASYNC);
11232 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
11236 // Ensure that a client certificate is removed from the SSL client auth
11237 // cache when:
11238 // 1) No proxy is involved.
11239 // 2) TLS False Start is disabled.
11240 // 3) The initial TLS handshake requests a client certificate.
11241 // 4) The client supplies an invalid/unacceptable certificate.
11242 TEST_P(HttpNetworkTransactionTest,
11243 ClientAuthCertCache_Direct_NoFalseStart) {
11244 HttpRequestInfo request_info;
11245 request_info.url = GURL("https://www.example.com/");
11246 request_info.method = "GET";
11247 request_info.load_flags = LOAD_NORMAL;
11249 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11250 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11252 // [ssl_]data1 contains the data for the first SSL handshake. When a
11253 // CertificateRequest is received for the first time, the handshake will
11254 // be aborted to allow the caller to provide a certificate.
11255 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11256 ssl_data1.cert_request_info = cert_request.get();
11257 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11258 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11259 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11261 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11262 // False Start is not being used, the result of the SSL handshake will be
11263 // returned as part of the SSLClientSocket::Connect() call. This test
11264 // matches the result of a server sending a handshake_failure alert,
11265 // rather than a Finished message, because it requires a client
11266 // certificate and none was supplied.
11267 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11268 ssl_data2.cert_request_info = cert_request.get();
11269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11270 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11271 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11273 // [ssl_]data3 contains the data for the third SSL handshake. When a
11274 // connection to a server fails during an SSL handshake,
11275 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11276 // connection was attempted with TLSv1.2. This is transparent to the caller
11277 // of the HttpNetworkTransaction. Because this test failure is due to
11278 // requiring a client certificate, this fallback handshake should also
11279 // fail.
11280 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11281 ssl_data3.cert_request_info = cert_request.get();
11282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11283 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11284 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11286 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11287 // connection to a server fails during an SSL handshake,
11288 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11289 // connection was attempted with TLSv1.1. This is transparent to the caller
11290 // of the HttpNetworkTransaction. Because this test failure is due to
11291 // requiring a client certificate, this fallback handshake should also
11292 // fail.
11293 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11294 ssl_data4.cert_request_info = cert_request.get();
11295 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11296 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
11297 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11299 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11300 scoped_ptr<HttpTransaction> trans(
11301 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11303 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11304 TestCompletionCallback callback;
11305 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11306 ASSERT_EQ(ERR_IO_PENDING, rv);
11308 // Complete the SSL handshake, which should abort due to requiring a
11309 // client certificate.
11310 rv = callback.WaitForResult();
11311 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11313 // Indicate that no certificate should be supplied. From the perspective
11314 // of SSLClientCertCache, NULL is just as meaningful as a real
11315 // certificate, so this is the same as supply a
11316 // legitimate-but-unacceptable certificate.
11317 rv = trans->RestartWithCertificate(NULL, callback.callback());
11318 ASSERT_EQ(ERR_IO_PENDING, rv);
11320 // Ensure the certificate was added to the client auth cache before
11321 // allowing the connection to continue restarting.
11322 scoped_refptr<X509Certificate> client_cert;
11323 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11324 HostPortPair("www.example.com", 443), &client_cert));
11325 ASSERT_EQ(NULL, client_cert.get());
11327 // Restart the handshake. This will consume ssl_data2, which fails, and
11328 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11329 // The result code is checked against what ssl_data4 should return.
11330 rv = callback.WaitForResult();
11331 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11333 // Ensure that the client certificate is removed from the cache on a
11334 // handshake failure.
11335 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11336 HostPortPair("www.example.com", 443), &client_cert));
11339 // Ensure that a client certificate is removed from the SSL client auth
11340 // cache when:
11341 // 1) No proxy is involved.
11342 // 2) TLS False Start is enabled.
11343 // 3) The initial TLS handshake requests a client certificate.
11344 // 4) The client supplies an invalid/unacceptable certificate.
11345 TEST_P(HttpNetworkTransactionTest,
11346 ClientAuthCertCache_Direct_FalseStart) {
11347 HttpRequestInfo request_info;
11348 request_info.url = GURL("https://www.example.com/");
11349 request_info.method = "GET";
11350 request_info.load_flags = LOAD_NORMAL;
11352 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11353 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11355 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11356 // return successfully after reading up to the peer's Certificate message.
11357 // This is to allow the caller to call SSLClientSocket::Write(), which can
11358 // enqueue application data to be sent in the same packet as the
11359 // ChangeCipherSpec and Finished messages.
11360 // The actual handshake will be finished when SSLClientSocket::Read() is
11361 // called, which expects to process the peer's ChangeCipherSpec and
11362 // Finished messages. If there was an error negotiating with the peer,
11363 // such as due to the peer requiring a client certificate when none was
11364 // supplied, the alert sent by the peer won't be processed until Read() is
11365 // called.
11367 // Like the non-False Start case, when a client certificate is requested by
11368 // the peer, the handshake is aborted during the Connect() call.
11369 // [ssl_]data1 represents the initial SSL handshake with the peer.
11370 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11371 ssl_data1.cert_request_info = cert_request.get();
11372 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11373 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11374 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11376 // When a client certificate is supplied, Connect() will not be aborted
11377 // when the peer requests the certificate. Instead, the handshake will
11378 // artificially succeed, allowing the caller to write the HTTP request to
11379 // the socket. The handshake messages are not processed until Read() is
11380 // called, which then detects that the handshake was aborted, due to the
11381 // peer sending a handshake_failure because it requires a client
11382 // certificate.
11383 SSLSocketDataProvider ssl_data2(ASYNC, OK);
11384 ssl_data2.cert_request_info = cert_request.get();
11385 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11386 MockRead data2_reads[] = {
11387 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
11389 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
11390 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11392 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11393 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11394 // TLSv1. It has the same behaviour as [ssl_]data2.
11395 SSLSocketDataProvider ssl_data3(ASYNC, OK);
11396 ssl_data3.cert_request_info = cert_request.get();
11397 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11398 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
11399 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11401 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11402 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11403 SSLSocketDataProvider ssl_data4(ASYNC, OK);
11404 ssl_data4.cert_request_info = cert_request.get();
11405 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11406 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
11407 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11409 // Need one more if TLSv1.2 is enabled.
11410 SSLSocketDataProvider ssl_data5(ASYNC, OK);
11411 ssl_data5.cert_request_info = cert_request.get();
11412 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11413 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
11414 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11416 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11417 scoped_ptr<HttpTransaction> trans(
11418 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11420 // Begin the initial SSL handshake.
11421 TestCompletionCallback callback;
11422 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11423 ASSERT_EQ(ERR_IO_PENDING, rv);
11425 // Complete the SSL handshake, which should abort due to requiring a
11426 // client certificate.
11427 rv = callback.WaitForResult();
11428 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11430 // Indicate that no certificate should be supplied. From the perspective
11431 // of SSLClientCertCache, NULL is just as meaningful as a real
11432 // certificate, so this is the same as supply a
11433 // legitimate-but-unacceptable certificate.
11434 rv = trans->RestartWithCertificate(NULL, callback.callback());
11435 ASSERT_EQ(ERR_IO_PENDING, rv);
11437 // Ensure the certificate was added to the client auth cache before
11438 // allowing the connection to continue restarting.
11439 scoped_refptr<X509Certificate> client_cert;
11440 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11441 HostPortPair("www.example.com", 443), &client_cert));
11442 ASSERT_EQ(NULL, client_cert.get());
11444 // Restart the handshake. This will consume ssl_data2, which fails, and
11445 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11446 // The result code is checked against what ssl_data4 should return.
11447 rv = callback.WaitForResult();
11448 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11450 // Ensure that the client certificate is removed from the cache on a
11451 // handshake failure.
11452 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11453 HostPortPair("www.example.com", 443), &client_cert));
11456 // Ensure that a client certificate is removed from the SSL client auth
11457 // cache when:
11458 // 1) An HTTPS proxy is involved.
11459 // 3) The HTTPS proxy requests a client certificate.
11460 // 4) The client supplies an invalid/unacceptable certificate for the
11461 // proxy.
11462 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11463 // then for connecting to an HTTP endpoint.
11464 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
11465 session_deps_.proxy_service.reset(
11466 ProxyService::CreateFixed("https://proxy:70"));
11467 BoundTestNetLog log;
11468 session_deps_.net_log = log.bound().net_log();
11470 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11471 cert_request->host_and_port = HostPortPair("proxy", 70);
11473 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11474 // [ssl_]data[1-3]. Rather than represending the endpoint
11475 // (www.example.com:443), they represent failures with the HTTPS proxy
11476 // (proxy:70).
11477 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11478 ssl_data1.cert_request_info = cert_request.get();
11479 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11480 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11481 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11483 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11484 ssl_data2.cert_request_info = cert_request.get();
11485 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11486 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11487 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11489 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11490 #if 0
11491 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11492 ssl_data3.cert_request_info = cert_request.get();
11493 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11494 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11495 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11496 #endif
11498 HttpRequestInfo requests[2];
11499 requests[0].url = GURL("https://www.example.com/");
11500 requests[0].method = "GET";
11501 requests[0].load_flags = LOAD_NORMAL;
11503 requests[1].url = GURL("http://www.example.com/");
11504 requests[1].method = "GET";
11505 requests[1].load_flags = LOAD_NORMAL;
11507 for (size_t i = 0; i < arraysize(requests); ++i) {
11508 session_deps_.socket_factory->ResetNextMockIndexes();
11509 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11510 scoped_ptr<HttpNetworkTransaction> trans(
11511 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11513 // Begin the SSL handshake with the proxy.
11514 TestCompletionCallback callback;
11515 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
11516 ASSERT_EQ(ERR_IO_PENDING, rv);
11518 // Complete the SSL handshake, which should abort due to requiring a
11519 // client certificate.
11520 rv = callback.WaitForResult();
11521 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11523 // Indicate that no certificate should be supplied. From the perspective
11524 // of SSLClientCertCache, NULL is just as meaningful as a real
11525 // certificate, so this is the same as supply a
11526 // legitimate-but-unacceptable certificate.
11527 rv = trans->RestartWithCertificate(NULL, callback.callback());
11528 ASSERT_EQ(ERR_IO_PENDING, rv);
11530 // Ensure the certificate was added to the client auth cache before
11531 // allowing the connection to continue restarting.
11532 scoped_refptr<X509Certificate> client_cert;
11533 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11534 HostPortPair("proxy", 70), &client_cert));
11535 ASSERT_EQ(NULL, client_cert.get());
11536 // Ensure the certificate was NOT cached for the endpoint. This only
11537 // applies to HTTPS requests, but is fine to check for HTTP requests.
11538 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11539 HostPortPair("www.example.com", 443), &client_cert));
11541 // Restart the handshake. This will consume ssl_data2, which fails, and
11542 // then consume ssl_data3, which should also fail. The result code is
11543 // checked against what ssl_data3 should return.
11544 rv = callback.WaitForResult();
11545 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
11547 // Now that the new handshake has failed, ensure that the client
11548 // certificate was removed from the client auth cache.
11549 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11550 HostPortPair("proxy", 70), &client_cert));
11551 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11552 HostPortPair("www.example.com", 443), &client_cert));
11556 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
11557 session_deps_.use_alternate_protocols = true;
11558 session_deps_.next_protos = SpdyNextProtos();
11560 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11561 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11562 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11563 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11564 pool_peer.DisableDomainAuthenticationVerification();
11566 SSLSocketDataProvider ssl(ASYNC, OK);
11567 ssl.SetNextProto(GetParam());
11568 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11570 scoped_ptr<SpdyFrame> host1_req(
11571 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11572 scoped_ptr<SpdyFrame> host2_req(
11573 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11574 MockWrite spdy_writes[] = {
11575 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11577 scoped_ptr<SpdyFrame> host1_resp(
11578 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11579 scoped_ptr<SpdyFrame> host1_resp_body(
11580 spdy_util_.ConstructSpdyBodyFrame(1, true));
11581 scoped_ptr<SpdyFrame> host2_resp(
11582 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11583 scoped_ptr<SpdyFrame> host2_resp_body(
11584 spdy_util_.ConstructSpdyBodyFrame(3, true));
11585 MockRead spdy_reads[] = {
11586 CreateMockRead(*host1_resp, 1),
11587 CreateMockRead(*host1_resp_body, 2),
11588 CreateMockRead(*host2_resp, 4),
11589 CreateMockRead(*host2_resp_body, 5),
11590 MockRead(ASYNC, 0, 6),
11593 IPAddressNumber ip;
11594 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11595 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11596 MockConnect connect(ASYNC, OK, peer_addr);
11597 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11598 spdy_writes, arraysize(spdy_writes));
11599 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11601 TestCompletionCallback callback;
11602 HttpRequestInfo request1;
11603 request1.method = "GET";
11604 request1.url = GURL("https://www.example.org/");
11605 request1.load_flags = 0;
11606 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11608 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11609 EXPECT_EQ(ERR_IO_PENDING, rv);
11610 EXPECT_EQ(OK, callback.WaitForResult());
11612 const HttpResponseInfo* response = trans1.GetResponseInfo();
11613 ASSERT_TRUE(response != NULL);
11614 ASSERT_TRUE(response->headers.get() != NULL);
11615 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11617 std::string response_data;
11618 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11619 EXPECT_EQ("hello!", response_data);
11621 // Preload www.gmail.com into HostCache.
11622 HostPortPair host_port("www.gmail.com", 443);
11623 HostResolver::RequestInfo resolve_info(host_port);
11624 AddressList ignored;
11625 rv = session_deps_.host_resolver->Resolve(resolve_info,
11626 DEFAULT_PRIORITY,
11627 &ignored,
11628 callback.callback(),
11629 NULL,
11630 BoundNetLog());
11631 EXPECT_EQ(ERR_IO_PENDING, rv);
11632 rv = callback.WaitForResult();
11633 EXPECT_EQ(OK, rv);
11635 HttpRequestInfo request2;
11636 request2.method = "GET";
11637 request2.url = GURL("https://www.gmail.com/");
11638 request2.load_flags = 0;
11639 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11641 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11642 EXPECT_EQ(ERR_IO_PENDING, rv);
11643 EXPECT_EQ(OK, callback.WaitForResult());
11645 response = trans2.GetResponseInfo();
11646 ASSERT_TRUE(response != NULL);
11647 ASSERT_TRUE(response->headers.get() != NULL);
11648 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11649 EXPECT_TRUE(response->was_fetched_via_spdy);
11650 EXPECT_TRUE(response->was_npn_negotiated);
11651 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11652 EXPECT_EQ("hello!", response_data);
11655 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11656 session_deps_.use_alternate_protocols = true;
11657 session_deps_.next_protos = SpdyNextProtos();
11659 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11660 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11661 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11662 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11663 pool_peer.DisableDomainAuthenticationVerification();
11665 SSLSocketDataProvider ssl(ASYNC, OK);
11666 ssl.SetNextProto(GetParam());
11667 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11669 scoped_ptr<SpdyFrame> host1_req(
11670 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11671 scoped_ptr<SpdyFrame> host2_req(
11672 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11673 MockWrite spdy_writes[] = {
11674 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11676 scoped_ptr<SpdyFrame> host1_resp(
11677 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11678 scoped_ptr<SpdyFrame> host1_resp_body(
11679 spdy_util_.ConstructSpdyBodyFrame(1, true));
11680 scoped_ptr<SpdyFrame> host2_resp(
11681 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11682 scoped_ptr<SpdyFrame> host2_resp_body(
11683 spdy_util_.ConstructSpdyBodyFrame(3, true));
11684 MockRead spdy_reads[] = {
11685 CreateMockRead(*host1_resp, 1),
11686 CreateMockRead(*host1_resp_body, 2),
11687 CreateMockRead(*host2_resp, 4),
11688 CreateMockRead(*host2_resp_body, 5),
11689 MockRead(ASYNC, 0, 6),
11692 IPAddressNumber ip;
11693 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11694 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11695 MockConnect connect(ASYNC, OK, peer_addr);
11696 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11697 spdy_writes, arraysize(spdy_writes));
11698 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11700 TestCompletionCallback callback;
11701 HttpRequestInfo request1;
11702 request1.method = "GET";
11703 request1.url = GURL("https://www.example.org/");
11704 request1.load_flags = 0;
11705 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11707 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11708 EXPECT_EQ(ERR_IO_PENDING, rv);
11709 EXPECT_EQ(OK, callback.WaitForResult());
11711 const HttpResponseInfo* response = trans1.GetResponseInfo();
11712 ASSERT_TRUE(response != NULL);
11713 ASSERT_TRUE(response->headers.get() != NULL);
11714 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11716 std::string response_data;
11717 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11718 EXPECT_EQ("hello!", response_data);
11720 HttpRequestInfo request2;
11721 request2.method = "GET";
11722 request2.url = GURL("https://www.gmail.com/");
11723 request2.load_flags = 0;
11724 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11726 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11727 EXPECT_EQ(ERR_IO_PENDING, rv);
11728 EXPECT_EQ(OK, callback.WaitForResult());
11730 response = trans2.GetResponseInfo();
11731 ASSERT_TRUE(response != NULL);
11732 ASSERT_TRUE(response->headers.get() != NULL);
11733 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11734 EXPECT_TRUE(response->was_fetched_via_spdy);
11735 EXPECT_TRUE(response->was_npn_negotiated);
11736 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11737 EXPECT_EQ("hello!", response_data);
11740 class OneTimeCachingHostResolver : public HostResolver {
11741 public:
11742 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11743 : host_port_(host_port) {}
11744 ~OneTimeCachingHostResolver() override {}
11746 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11748 // HostResolver methods:
11749 int Resolve(const RequestInfo& info,
11750 RequestPriority priority,
11751 AddressList* addresses,
11752 const CompletionCallback& callback,
11753 RequestHandle* out_req,
11754 const BoundNetLog& net_log) override {
11755 return host_resolver_.Resolve(
11756 info, priority, addresses, callback, out_req, net_log);
11759 int ResolveFromCache(const RequestInfo& info,
11760 AddressList* addresses,
11761 const BoundNetLog& net_log) override {
11762 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11763 if (rv == OK && info.host_port_pair().Equals(host_port_))
11764 host_resolver_.GetHostCache()->clear();
11765 return rv;
11768 void CancelRequest(RequestHandle req) override {
11769 host_resolver_.CancelRequest(req);
11772 MockCachingHostResolver* GetMockHostResolver() {
11773 return &host_resolver_;
11776 private:
11777 MockCachingHostResolver host_resolver_;
11778 const HostPortPair host_port_;
11781 TEST_P(HttpNetworkTransactionTest,
11782 UseIPConnectionPoolingWithHostCacheExpiration) {
11783 session_deps_.use_alternate_protocols = true;
11784 session_deps_.next_protos = SpdyNextProtos();
11786 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11787 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11788 HttpNetworkSession::Params params =
11789 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11790 params.host_resolver = &host_resolver;
11791 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11792 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11793 pool_peer.DisableDomainAuthenticationVerification();
11795 SSLSocketDataProvider ssl(ASYNC, OK);
11796 ssl.SetNextProto(GetParam());
11797 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11799 scoped_ptr<SpdyFrame> host1_req(
11800 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11801 scoped_ptr<SpdyFrame> host2_req(
11802 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11803 MockWrite spdy_writes[] = {
11804 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11806 scoped_ptr<SpdyFrame> host1_resp(
11807 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11808 scoped_ptr<SpdyFrame> host1_resp_body(
11809 spdy_util_.ConstructSpdyBodyFrame(1, true));
11810 scoped_ptr<SpdyFrame> host2_resp(
11811 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11812 scoped_ptr<SpdyFrame> host2_resp_body(
11813 spdy_util_.ConstructSpdyBodyFrame(3, true));
11814 MockRead spdy_reads[] = {
11815 CreateMockRead(*host1_resp, 1),
11816 CreateMockRead(*host1_resp_body, 2),
11817 CreateMockRead(*host2_resp, 4),
11818 CreateMockRead(*host2_resp_body, 5),
11819 MockRead(ASYNC, 0, 6),
11822 IPAddressNumber ip;
11823 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11824 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11825 MockConnect connect(ASYNC, OK, peer_addr);
11826 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11827 spdy_writes, arraysize(spdy_writes));
11828 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11830 TestCompletionCallback callback;
11831 HttpRequestInfo request1;
11832 request1.method = "GET";
11833 request1.url = GURL("https://www.example.org/");
11834 request1.load_flags = 0;
11835 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11837 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11838 EXPECT_EQ(ERR_IO_PENDING, rv);
11839 EXPECT_EQ(OK, callback.WaitForResult());
11841 const HttpResponseInfo* response = trans1.GetResponseInfo();
11842 ASSERT_TRUE(response != NULL);
11843 ASSERT_TRUE(response->headers.get() != NULL);
11844 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11846 std::string response_data;
11847 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11848 EXPECT_EQ("hello!", response_data);
11850 // Preload cache entries into HostCache.
11851 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11852 AddressList ignored;
11853 rv = host_resolver.Resolve(resolve_info,
11854 DEFAULT_PRIORITY,
11855 &ignored,
11856 callback.callback(),
11857 NULL,
11858 BoundNetLog());
11859 EXPECT_EQ(ERR_IO_PENDING, rv);
11860 rv = callback.WaitForResult();
11861 EXPECT_EQ(OK, rv);
11863 HttpRequestInfo request2;
11864 request2.method = "GET";
11865 request2.url = GURL("https://www.gmail.com/");
11866 request2.load_flags = 0;
11867 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11869 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11870 EXPECT_EQ(ERR_IO_PENDING, rv);
11871 EXPECT_EQ(OK, callback.WaitForResult());
11873 response = trans2.GetResponseInfo();
11874 ASSERT_TRUE(response != NULL);
11875 ASSERT_TRUE(response->headers.get() != NULL);
11876 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11877 EXPECT_TRUE(response->was_fetched_via_spdy);
11878 EXPECT_TRUE(response->was_npn_negotiated);
11879 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11880 EXPECT_EQ("hello!", response_data);
11883 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11884 const std::string https_url = "https://www.example.org:8080/";
11885 const std::string http_url = "http://www.example.org:8080/";
11887 // SPDY GET for HTTPS URL
11888 scoped_ptr<SpdyFrame> req1(
11889 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11891 MockWrite writes1[] = {
11892 CreateMockWrite(*req1, 0),
11895 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11896 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11897 MockRead reads1[] = {
11898 CreateMockRead(*resp1, 1),
11899 CreateMockRead(*body1, 2),
11900 MockRead(ASYNC, ERR_IO_PENDING, 3)
11903 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
11904 arraysize(writes1));
11905 MockConnect connect_data1(ASYNC, OK);
11906 data1.set_connect_data(connect_data1);
11908 // HTTP GET for the HTTP URL
11909 MockWrite writes2[] = {
11910 MockWrite(ASYNC, 0,
11911 "GET / HTTP/1.1\r\n"
11912 "Host: www.example.org:8080\r\n"
11913 "Connection: keep-alive\r\n\r\n"),
11916 MockRead reads2[] = {
11917 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11918 MockRead(ASYNC, 2, "hello"),
11919 MockRead(ASYNC, OK, 3),
11922 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
11923 arraysize(writes2));
11925 SSLSocketDataProvider ssl(ASYNC, OK);
11926 ssl.SetNextProto(GetParam());
11927 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11928 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11929 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11931 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11933 // Start the first transaction to set up the SpdySession
11934 HttpRequestInfo request1;
11935 request1.method = "GET";
11936 request1.url = GURL(https_url);
11937 request1.load_flags = 0;
11938 HttpNetworkTransaction trans1(LOWEST, session.get());
11939 TestCompletionCallback callback1;
11940 EXPECT_EQ(ERR_IO_PENDING,
11941 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11942 base::MessageLoop::current()->RunUntilIdle();
11944 EXPECT_EQ(OK, callback1.WaitForResult());
11945 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11947 // Now, start the HTTP request
11948 HttpRequestInfo request2;
11949 request2.method = "GET";
11950 request2.url = GURL(http_url);
11951 request2.load_flags = 0;
11952 HttpNetworkTransaction trans2(MEDIUM, session.get());
11953 TestCompletionCallback callback2;
11954 EXPECT_EQ(ERR_IO_PENDING,
11955 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11956 base::MessageLoop::current()->RunUntilIdle();
11958 EXPECT_EQ(OK, callback2.WaitForResult());
11959 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11962 class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
11963 public:
11964 void Run(bool pooling, bool valid) {
11965 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
11966 443);
11967 HostPortPair alternative("www.example.org", 443);
11969 base::FilePath certs_dir = GetTestCertsDirectory();
11970 scoped_refptr<X509Certificate> cert(
11971 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
11972 ASSERT_TRUE(cert.get());
11973 bool common_name_fallback_used;
11974 EXPECT_EQ(valid,
11975 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
11976 EXPECT_TRUE(
11977 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
11978 SSLSocketDataProvider ssl(ASYNC, OK);
11979 ssl.SetNextProto(GetParam());
11980 ssl.cert = cert;
11981 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11983 // If pooling, then start a request to alternative first to create a
11984 // SpdySession.
11985 std::string url0 = "https://www.example.org:443";
11986 // Second request to origin, which has an alternative service, and could
11987 // open a connection to the alternative host or pool to the existing one.
11988 std::string url1("https://");
11989 url1.append(origin.host());
11990 url1.append(":443");
11992 scoped_ptr<SpdyFrame> req0;
11993 scoped_ptr<SpdyFrame> req1;
11994 scoped_ptr<SpdyFrame> resp0;
11995 scoped_ptr<SpdyFrame> body0;
11996 scoped_ptr<SpdyFrame> resp1;
11997 scoped_ptr<SpdyFrame> body1;
11998 std::vector<MockWrite> writes;
11999 std::vector<MockRead> reads;
12001 if (pooling) {
12002 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
12003 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
12005 writes.push_back(CreateMockWrite(*req0, 0));
12006 writes.push_back(CreateMockWrite(*req1, 3));
12008 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12009 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12010 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12011 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
12013 reads.push_back(CreateMockRead(*resp0, 1));
12014 reads.push_back(CreateMockRead(*body0, 2));
12015 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
12016 reads.push_back(CreateMockRead(*resp1, 5));
12017 reads.push_back(CreateMockRead(*body1, 6));
12018 reads.push_back(MockRead(ASYNC, OK, 7));
12019 } else {
12020 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
12022 writes.push_back(CreateMockWrite(*req1, 0));
12024 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12025 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12027 reads.push_back(CreateMockRead(*resp1, 1));
12028 reads.push_back(CreateMockRead(*body1, 2));
12029 reads.push_back(MockRead(ASYNC, OK, 3));
12032 SequencedSocketData data(vector_as_array(&reads), reads.size(),
12033 vector_as_array(&writes), writes.size());
12034 session_deps_.socket_factory->AddSocketDataProvider(&data);
12036 // Connection to the origin fails.
12037 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12038 StaticSocketDataProvider data_refused;
12039 data_refused.set_connect_data(mock_connect);
12040 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12042 session_deps_.use_alternate_protocols = true;
12043 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12044 base::WeakPtr<HttpServerProperties> http_server_properties =
12045 session->http_server_properties();
12046 AlternativeService alternative_service(
12047 AlternateProtocolFromNextProto(GetParam()), alternative);
12048 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12049 http_server_properties->SetAlternativeService(origin, alternative_service,
12050 1.0, expiration);
12052 // First request to alternative.
12053 if (pooling) {
12054 scoped_ptr<HttpTransaction> trans0(
12055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12056 HttpRequestInfo request0;
12057 request0.method = "GET";
12058 request0.url = GURL(url0);
12059 request0.load_flags = 0;
12060 TestCompletionCallback callback0;
12062 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
12063 EXPECT_EQ(ERR_IO_PENDING, rv);
12064 rv = callback0.WaitForResult();
12065 EXPECT_EQ(OK, rv);
12068 // Second request to origin.
12069 scoped_ptr<HttpTransaction> trans1(
12070 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12071 HttpRequestInfo request1;
12072 request1.method = "GET";
12073 request1.url = GURL(url1);
12074 request1.load_flags = 0;
12075 TestCompletionCallback callback1;
12077 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12078 EXPECT_EQ(ERR_IO_PENDING, rv);
12079 base::MessageLoop::current()->RunUntilIdle();
12080 if (data.IsReadPaused()) {
12081 data.CompleteRead();
12083 rv = callback1.WaitForResult();
12084 if (valid) {
12085 EXPECT_EQ(OK, rv);
12086 } else {
12087 if (pooling) {
12088 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12089 } else {
12090 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
12096 INSTANTIATE_TEST_CASE_P(NextProto,
12097 AltSvcCertificateVerificationTest,
12098 testing::Values(kProtoSPDY31,
12099 kProtoHTTP2_14,
12100 kProtoHTTP2));
12102 // The alternative service host must exhibit a certificate that is valid for the
12103 // origin host. Test that this is enforced when pooling to an existing
12104 // connection.
12105 TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
12106 Run(true, true);
12109 TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
12110 Run(true, false);
12113 // The alternative service host must exhibit a certificate that is valid for the
12114 // origin host. Test that this is enforced when opening a new connection.
12115 TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
12116 Run(false, true);
12119 TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
12120 Run(false, false);
12123 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12124 // with the alternative server. That connection should not be used.
12125 TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
12126 HostPortPair origin("origin.example.org", 443);
12127 HostPortPair alternative("alternative.example.org", 443);
12129 // Negotiate HTTP/1.1 with alternative.example.org.
12130 SSLSocketDataProvider ssl(ASYNC, OK);
12131 ssl.SetNextProto(kProtoHTTP11);
12132 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12134 // No data should be read from the alternative, because HTTP/1.1 is
12135 // negotiated.
12136 StaticSocketDataProvider data;
12137 session_deps_.socket_factory->AddSocketDataProvider(&data);
12139 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12140 // negotiated. In order to test this, a failed connection to the origin is
12141 // mocked. This way the request relies on the alternate Job.
12142 StaticSocketDataProvider data_refused;
12143 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12144 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12146 // Set up alternative service for origin.
12147 session_deps_.use_alternate_protocols = true;
12148 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12149 base::WeakPtr<HttpServerProperties> http_server_properties =
12150 session->http_server_properties();
12151 AlternativeService alternative_service(
12152 AlternateProtocolFromNextProto(GetParam()), alternative);
12153 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12154 http_server_properties->SetAlternativeService(origin, alternative_service,
12155 1.0, expiration);
12157 scoped_ptr<HttpTransaction> trans(
12158 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12159 HttpRequestInfo request;
12160 request.method = "GET";
12161 request.url = GURL("https://origin.example.org:443");
12162 request.load_flags = 0;
12163 TestCompletionCallback callback;
12165 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12166 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12167 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12168 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
12171 // A request to a server with an alternative service fires two Jobs: one to the
12172 // origin, and an alternate one to the alternative server. If the former
12173 // succeeds, the request should succeed, even if the latter fails because
12174 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12175 TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
12176 HostPortPair origin("origin.example.org", 443);
12177 HostPortPair alternative("alternative.example.org", 443);
12179 // Negotiate HTTP/1.1 with alternative.
12180 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
12181 alternative_ssl.SetNextProto(kProtoHTTP11);
12182 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
12184 // No data should be read from the alternative, because HTTP/1.1 is
12185 // negotiated.
12186 StaticSocketDataProvider data;
12187 session_deps_.socket_factory->AddSocketDataProvider(&data);
12189 // Negotiate HTTP/1.1 with origin.
12190 SSLSocketDataProvider origin_ssl(ASYNC, OK);
12191 origin_ssl.SetNextProto(kProtoHTTP11);
12192 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
12194 MockWrite http_writes[] = {
12195 MockWrite(
12196 "GET / HTTP/1.1\r\n"
12197 "Host: origin.example.org\r\n"
12198 "Connection: keep-alive\r\n\r\n"),
12199 MockWrite(
12200 "GET /second HTTP/1.1\r\n"
12201 "Host: origin.example.org\r\n"
12202 "Connection: keep-alive\r\n\r\n"),
12205 MockRead http_reads[] = {
12206 MockRead("HTTP/1.1 200 OK\r\n"),
12207 MockRead("Content-Type: text/html\r\n"),
12208 MockRead("Content-Length: 6\r\n\r\n"),
12209 MockRead("foobar"),
12210 MockRead("HTTP/1.1 200 OK\r\n"),
12211 MockRead("Content-Type: text/html\r\n"),
12212 MockRead("Content-Length: 7\r\n\r\n"),
12213 MockRead("another"),
12215 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12216 http_writes, arraysize(http_writes));
12217 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12219 // Set up alternative service for origin.
12220 session_deps_.use_alternate_protocols = true;
12221 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12222 base::WeakPtr<HttpServerProperties> http_server_properties =
12223 session->http_server_properties();
12224 AlternativeService alternative_service(
12225 AlternateProtocolFromNextProto(GetParam()), alternative);
12226 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12227 http_server_properties->SetAlternativeService(origin, alternative_service,
12228 1.0, expiration);
12230 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
12231 HttpRequestInfo request1;
12232 request1.method = "GET";
12233 request1.url = GURL("https://origin.example.org:443");
12234 request1.load_flags = 0;
12235 TestCompletionCallback callback1;
12237 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
12238 rv = callback1.GetResult(rv);
12239 EXPECT_EQ(OK, rv);
12241 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
12242 ASSERT_TRUE(response1 != nullptr);
12243 ASSERT_TRUE(response1->headers.get() != nullptr);
12244 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12246 std::string response_data1;
12247 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
12248 EXPECT_EQ("foobar", response_data1);
12250 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12251 // for alternative service.
12252 EXPECT_TRUE(
12253 http_server_properties->IsAlternativeServiceBroken(alternative_service));
12255 // Since |alternative_service| is broken, a second transaction to origin
12256 // should not start an alternate Job. It should pool to existing connection
12257 // to origin.
12258 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
12259 HttpRequestInfo request2;
12260 request2.method = "GET";
12261 request2.url = GURL("https://origin.example.org:443/second");
12262 request2.load_flags = 0;
12263 TestCompletionCallback callback2;
12265 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
12266 rv = callback2.GetResult(rv);
12267 EXPECT_EQ(OK, rv);
12269 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
12270 ASSERT_TRUE(response2 != nullptr);
12271 ASSERT_TRUE(response2->headers.get() != nullptr);
12272 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
12274 std::string response_data2;
12275 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
12276 EXPECT_EQ("another", response_data2);
12279 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12280 // HTTP/1.1 socket open to the alternative server. That socket should not be
12281 // used.
12282 TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
12283 HostPortPair origin("origin.example.org", 443);
12284 HostPortPair alternative("alternative.example.org", 443);
12285 std::string origin_url = "https://origin.example.org:443";
12286 std::string alternative_url = "https://alternative.example.org:443";
12288 // Negotiate HTTP/1.1 with alternative.example.org.
12289 SSLSocketDataProvider ssl(ASYNC, OK);
12290 ssl.SetNextProto(kProtoHTTP11);
12291 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12293 // HTTP/1.1 data for |request1| and |request2|.
12294 MockWrite http_writes[] = {
12295 MockWrite(
12296 "GET / HTTP/1.1\r\n"
12297 "Host: alternative.example.org\r\n"
12298 "Connection: keep-alive\r\n\r\n"),
12299 MockWrite(
12300 "GET / HTTP/1.1\r\n"
12301 "Host: alternative.example.org\r\n"
12302 "Connection: keep-alive\r\n\r\n"),
12305 MockRead http_reads[] = {
12306 MockRead(
12307 "HTTP/1.1 200 OK\r\n"
12308 "Content-Type: text/html; charset=iso-8859-1\r\n"
12309 "Content-Length: 40\r\n\r\n"
12310 "first HTTP/1.1 response from alternative"),
12311 MockRead(
12312 "HTTP/1.1 200 OK\r\n"
12313 "Content-Type: text/html; charset=iso-8859-1\r\n"
12314 "Content-Length: 41\r\n\r\n"
12315 "second HTTP/1.1 response from alternative"),
12317 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12318 http_writes, arraysize(http_writes));
12319 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12321 // This test documents that an alternate Job should not pool to an already
12322 // existing HTTP/1.1 connection. In order to test this, a failed connection
12323 // to the origin is mocked. This way |request2| relies on the alternate Job.
12324 StaticSocketDataProvider data_refused;
12325 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12326 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12328 // Set up alternative service for origin.
12329 session_deps_.use_alternate_protocols = true;
12330 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12331 base::WeakPtr<HttpServerProperties> http_server_properties =
12332 session->http_server_properties();
12333 AlternativeService alternative_service(
12334 AlternateProtocolFromNextProto(GetParam()), alternative);
12335 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12336 http_server_properties->SetAlternativeService(origin, alternative_service,
12337 1.0, expiration);
12339 // First transaction to alternative to open an HTTP/1.1 socket.
12340 scoped_ptr<HttpTransaction> trans1(
12341 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12342 HttpRequestInfo request1;
12343 request1.method = "GET";
12344 request1.url = GURL(alternative_url);
12345 request1.load_flags = 0;
12346 TestCompletionCallback callback1;
12348 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12349 EXPECT_EQ(OK, callback1.GetResult(rv));
12350 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12351 ASSERT_TRUE(response1);
12352 ASSERT_TRUE(response1->headers.get());
12353 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12354 EXPECT_TRUE(response1->was_npn_negotiated);
12355 EXPECT_FALSE(response1->was_fetched_via_spdy);
12356 std::string response_data1;
12357 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
12358 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
12360 // Request for origin.example.org, which has an alternative service. This
12361 // will start two Jobs: the alternative looks for connections to pool to,
12362 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12363 // open other connections to alternative server. The Job to origin fails, so
12364 // this request fails.
12365 scoped_ptr<HttpTransaction> trans2(
12366 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12367 HttpRequestInfo request2;
12368 request2.method = "GET";
12369 request2.url = GURL(origin_url);
12370 request2.load_flags = 0;
12371 TestCompletionCallback callback2;
12373 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
12374 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
12376 // Another transaction to alternative. This is to test that the HTTP/1.1
12377 // socket is still open and in the pool.
12378 scoped_ptr<HttpTransaction> trans3(
12379 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12380 HttpRequestInfo request3;
12381 request3.method = "GET";
12382 request3.url = GURL(alternative_url);
12383 request3.load_flags = 0;
12384 TestCompletionCallback callback3;
12386 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
12387 EXPECT_EQ(OK, callback3.GetResult(rv));
12388 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
12389 ASSERT_TRUE(response3);
12390 ASSERT_TRUE(response3->headers.get());
12391 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
12392 EXPECT_TRUE(response3->was_npn_negotiated);
12393 EXPECT_FALSE(response3->was_fetched_via_spdy);
12394 std::string response_data3;
12395 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
12396 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
12399 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
12400 const std::string https_url = "https://www.example.org:8080/";
12401 const std::string http_url = "http://www.example.org:8080/";
12403 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12404 const HostPortPair host_port_pair("www.example.org", 8080);
12405 scoped_ptr<SpdyFrame> connect(
12406 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
12407 scoped_ptr<SpdyFrame> req1(
12408 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
12409 scoped_ptr<SpdyFrame> wrapped_req1(
12410 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
12412 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12413 SpdyHeaderBlock req2_block;
12414 req2_block[spdy_util_.GetMethodKey()] = "GET";
12415 req2_block[spdy_util_.GetPathKey()] = "/";
12416 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
12417 req2_block[spdy_util_.GetSchemeKey()] = "http";
12418 spdy_util_.MaybeAddVersionHeader(&req2_block);
12419 scoped_ptr<SpdyFrame> req2(
12420 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
12422 MockWrite writes1[] = {
12423 CreateMockWrite(*connect, 0),
12424 CreateMockWrite(*wrapped_req1, 2),
12425 CreateMockWrite(*req2, 5),
12428 scoped_ptr<SpdyFrame> conn_resp(
12429 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12430 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12431 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12432 scoped_ptr<SpdyFrame> wrapped_resp1(
12433 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
12434 scoped_ptr<SpdyFrame> wrapped_body1(
12435 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
12436 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12437 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
12438 MockRead reads1[] = {
12439 CreateMockRead(*conn_resp, 1),
12440 CreateMockRead(*wrapped_resp1, 3),
12441 CreateMockRead(*wrapped_body1, 4),
12442 CreateMockRead(*resp2, 6),
12443 CreateMockRead(*body2, 7),
12444 MockRead(ASYNC, ERR_IO_PENDING, 8)
12447 DeterministicSocketData data1(reads1, arraysize(reads1),
12448 writes1, arraysize(writes1));
12449 MockConnect connect_data1(ASYNC, OK);
12450 data1.set_connect_data(connect_data1);
12452 session_deps_.proxy_service.reset(
12453 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12454 TestNetLog log;
12455 session_deps_.net_log = &log;
12456 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12457 ssl1.SetNextProto(GetParam());
12458 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12459 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12460 ssl2.SetNextProto(GetParam());
12461 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12462 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
12464 scoped_refptr<HttpNetworkSession> session(
12465 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12467 // Start the first transaction to set up the SpdySession
12468 HttpRequestInfo request1;
12469 request1.method = "GET";
12470 request1.url = GURL(https_url);
12471 request1.load_flags = 0;
12472 HttpNetworkTransaction trans1(LOWEST, session.get());
12473 TestCompletionCallback callback1;
12474 EXPECT_EQ(ERR_IO_PENDING,
12475 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12476 base::MessageLoop::current()->RunUntilIdle();
12477 data1.RunFor(4);
12479 EXPECT_EQ(OK, callback1.WaitForResult());
12480 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12482 LoadTimingInfo load_timing_info1;
12483 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
12484 TestLoadTimingNotReusedWithPac(load_timing_info1,
12485 CONNECT_TIMING_HAS_SSL_TIMES);
12487 // Now, start the HTTP request
12488 HttpRequestInfo request2;
12489 request2.method = "GET";
12490 request2.url = GURL(http_url);
12491 request2.load_flags = 0;
12492 HttpNetworkTransaction trans2(MEDIUM, session.get());
12493 TestCompletionCallback callback2;
12494 EXPECT_EQ(ERR_IO_PENDING,
12495 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12496 base::MessageLoop::current()->RunUntilIdle();
12497 data1.RunFor(3);
12499 EXPECT_EQ(OK, callback2.WaitForResult());
12500 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12502 LoadTimingInfo load_timing_info2;
12503 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
12504 // The established SPDY sessions is considered reused by the HTTP request.
12505 TestLoadTimingReusedWithPac(load_timing_info2);
12506 // HTTP requests over a SPDY session should have a different connection
12507 // socket_log_id than requests over a tunnel.
12508 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
12511 // Test that in the case where we have a SPDY session to a SPDY proxy
12512 // that we do not pool other origins that resolve to the same IP when
12513 // the certificate does not match the new origin.
12514 // http://crbug.com/134690
12515 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
12516 const std::string url1 = "http://www.example.org/";
12517 const std::string url2 = "https://news.example.org/";
12518 const std::string ip_addr = "1.2.3.4";
12520 // SPDY GET for HTTP URL (through SPDY proxy)
12521 scoped_ptr<SpdyHeaderBlock> headers(
12522 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12523 scoped_ptr<SpdyFrame> req1(
12524 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
12526 MockWrite writes1[] = {
12527 CreateMockWrite(*req1, 0),
12530 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12531 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12532 MockRead reads1[] = {
12533 CreateMockRead(*resp1, 1),
12534 CreateMockRead(*body1, 2),
12535 MockRead(ASYNC, OK, 3) // EOF
12538 scoped_ptr<DeterministicSocketData> data1(
12539 new DeterministicSocketData(reads1, arraysize(reads1),
12540 writes1, arraysize(writes1)));
12541 IPAddressNumber ip;
12542 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
12543 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12544 MockConnect connect_data1(ASYNC, OK, peer_addr);
12545 data1->set_connect_data(connect_data1);
12547 // SPDY GET for HTTPS URL (direct)
12548 scoped_ptr<SpdyFrame> req2(
12549 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
12551 MockWrite writes2[] = {
12552 CreateMockWrite(*req2, 0),
12555 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12556 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12557 MockRead reads2[] = {
12558 CreateMockRead(*resp2, 1),
12559 CreateMockRead(*body2, 2),
12560 MockRead(ASYNC, OK, 3) // EOF
12563 scoped_ptr<DeterministicSocketData> data2(
12564 new DeterministicSocketData(reads2, arraysize(reads2),
12565 writes2, arraysize(writes2)));
12566 MockConnect connect_data2(ASYNC, OK);
12567 data2->set_connect_data(connect_data2);
12569 // Set up a proxy config that sends HTTP requests to a proxy, and
12570 // all others direct.
12571 ProxyConfig proxy_config;
12572 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
12573 session_deps_.proxy_service.reset(new ProxyService(
12574 new ProxyConfigServiceFixed(proxy_config), nullptr, NULL));
12576 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12577 ssl1.SetNextProto(GetParam());
12578 // Load a valid cert. Note, that this does not need to
12579 // be valid for proxy because the MockSSLClientSocket does
12580 // not actually verify it. But SpdySession will use this
12581 // to see if it is valid for the new origin
12582 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12583 ASSERT_TRUE(ssl1.cert.get());
12584 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12585 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12586 data1.get());
12588 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12589 ssl2.SetNextProto(GetParam());
12590 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12591 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12592 data2.get());
12594 session_deps_.host_resolver.reset(new MockCachingHostResolver());
12595 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
12596 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
12598 scoped_refptr<HttpNetworkSession> session(
12599 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12601 // Start the first transaction to set up the SpdySession
12602 HttpRequestInfo request1;
12603 request1.method = "GET";
12604 request1.url = GURL(url1);
12605 request1.load_flags = 0;
12606 HttpNetworkTransaction trans1(LOWEST, session.get());
12607 TestCompletionCallback callback1;
12608 ASSERT_EQ(ERR_IO_PENDING,
12609 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12610 data1->RunFor(3);
12612 ASSERT_TRUE(callback1.have_result());
12613 EXPECT_EQ(OK, callback1.WaitForResult());
12614 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12616 // Now, start the HTTP request
12617 HttpRequestInfo request2;
12618 request2.method = "GET";
12619 request2.url = GURL(url2);
12620 request2.load_flags = 0;
12621 HttpNetworkTransaction trans2(MEDIUM, session.get());
12622 TestCompletionCallback callback2;
12623 EXPECT_EQ(ERR_IO_PENDING,
12624 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12625 base::MessageLoop::current()->RunUntilIdle();
12626 data2->RunFor(3);
12628 ASSERT_TRUE(callback2.have_result());
12629 EXPECT_EQ(OK, callback2.WaitForResult());
12630 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12633 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12634 // error) in SPDY session, removes the socket from pool and closes the SPDY
12635 // session. Verify that new url's from the same HttpNetworkSession (and a new
12636 // SpdySession) do work. http://crbug.com/224701
12637 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
12638 const std::string https_url = "https://www.example.org/";
12640 MockRead reads1[] = {
12641 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
12644 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
12646 scoped_ptr<SpdyFrame> req2(
12647 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
12648 MockWrite writes2[] = {
12649 CreateMockWrite(*req2, 0),
12652 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12653 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12654 MockRead reads2[] = {
12655 CreateMockRead(*resp2, 1),
12656 CreateMockRead(*body2, 2),
12657 MockRead(ASYNC, OK, 3) // EOF
12660 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
12661 arraysize(writes2));
12663 SSLSocketDataProvider ssl1(ASYNC, OK);
12664 ssl1.SetNextProto(GetParam());
12665 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12666 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12668 SSLSocketDataProvider ssl2(ASYNC, OK);
12669 ssl2.SetNextProto(GetParam());
12670 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12671 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12673 scoped_refptr<HttpNetworkSession> session(
12674 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
12676 // Start the first transaction to set up the SpdySession and verify that
12677 // connection was closed.
12678 HttpRequestInfo request1;
12679 request1.method = "GET";
12680 request1.url = GURL(https_url);
12681 request1.load_flags = 0;
12682 HttpNetworkTransaction trans1(MEDIUM, session.get());
12683 TestCompletionCallback callback1;
12684 EXPECT_EQ(ERR_IO_PENDING,
12685 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12686 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
12688 // Now, start the second request and make sure it succeeds.
12689 HttpRequestInfo request2;
12690 request2.method = "GET";
12691 request2.url = GURL(https_url);
12692 request2.load_flags = 0;
12693 HttpNetworkTransaction trans2(MEDIUM, session.get());
12694 TestCompletionCallback callback2;
12695 EXPECT_EQ(ERR_IO_PENDING,
12696 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12698 ASSERT_EQ(OK, callback2.WaitForResult());
12699 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12702 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
12703 session_deps_.next_protos = SpdyNextProtos();
12704 ClientSocketPoolManager::set_max_sockets_per_group(
12705 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12706 ClientSocketPoolManager::set_max_sockets_per_pool(
12707 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12709 // Use two different hosts with different IPs so they don't get pooled.
12710 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
12711 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
12712 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12714 SSLSocketDataProvider ssl1(ASYNC, OK);
12715 ssl1.SetNextProto(GetParam());
12716 SSLSocketDataProvider ssl2(ASYNC, OK);
12717 ssl2.SetNextProto(GetParam());
12718 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12719 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12721 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
12722 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
12723 MockWrite spdy1_writes[] = {
12724 CreateMockWrite(*host1_req, 0),
12726 scoped_ptr<SpdyFrame> host1_resp(
12727 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12728 scoped_ptr<SpdyFrame> host1_resp_body(
12729 spdy_util_.ConstructSpdyBodyFrame(1, true));
12730 MockRead spdy1_reads[] = {
12731 CreateMockRead(*host1_resp, 1),
12732 CreateMockRead(*host1_resp_body, 2),
12733 MockRead(ASYNC, ERR_IO_PENDING, 3),
12736 scoped_ptr<SequencedSocketData> spdy1_data(
12737 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
12738 arraysize(spdy1_writes)));
12739 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
12741 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
12742 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
12743 MockWrite spdy2_writes[] = {
12744 CreateMockWrite(*host2_req, 0),
12746 scoped_ptr<SpdyFrame> host2_resp(
12747 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12748 scoped_ptr<SpdyFrame> host2_resp_body(
12749 spdy_util_.ConstructSpdyBodyFrame(1, true));
12750 MockRead spdy2_reads[] = {
12751 CreateMockRead(*host2_resp, 1),
12752 CreateMockRead(*host2_resp_body, 2),
12753 MockRead(ASYNC, ERR_IO_PENDING, 3),
12756 scoped_ptr<SequencedSocketData> spdy2_data(
12757 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
12758 arraysize(spdy2_writes)));
12759 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
12761 MockWrite http_write[] = {
12762 MockWrite("GET / HTTP/1.1\r\n"
12763 "Host: www.a.com\r\n"
12764 "Connection: keep-alive\r\n\r\n"),
12767 MockRead http_read[] = {
12768 MockRead("HTTP/1.1 200 OK\r\n"),
12769 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12770 MockRead("Content-Length: 6\r\n\r\n"),
12771 MockRead("hello!"),
12773 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
12774 http_write, arraysize(http_write));
12775 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12777 HostPortPair host_port_pair_a("www.a.com", 443);
12778 SpdySessionKey spdy_session_key_a(
12779 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12780 EXPECT_FALSE(
12781 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12783 TestCompletionCallback callback;
12784 HttpRequestInfo request1;
12785 request1.method = "GET";
12786 request1.url = GURL("https://www.a.com/");
12787 request1.load_flags = 0;
12788 scoped_ptr<HttpNetworkTransaction> trans(
12789 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12791 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
12792 EXPECT_EQ(ERR_IO_PENDING, rv);
12793 EXPECT_EQ(OK, callback.WaitForResult());
12795 const HttpResponseInfo* response = trans->GetResponseInfo();
12796 ASSERT_TRUE(response != NULL);
12797 ASSERT_TRUE(response->headers.get() != NULL);
12798 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12799 EXPECT_TRUE(response->was_fetched_via_spdy);
12800 EXPECT_TRUE(response->was_npn_negotiated);
12802 std::string response_data;
12803 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12804 EXPECT_EQ("hello!", response_data);
12805 trans.reset();
12806 EXPECT_TRUE(
12807 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12809 HostPortPair host_port_pair_b("www.b.com", 443);
12810 SpdySessionKey spdy_session_key_b(
12811 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12812 EXPECT_FALSE(
12813 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12814 HttpRequestInfo request2;
12815 request2.method = "GET";
12816 request2.url = GURL("https://www.b.com/");
12817 request2.load_flags = 0;
12818 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12820 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
12821 EXPECT_EQ(ERR_IO_PENDING, rv);
12822 EXPECT_EQ(OK, callback.WaitForResult());
12824 response = trans->GetResponseInfo();
12825 ASSERT_TRUE(response != NULL);
12826 ASSERT_TRUE(response->headers.get() != NULL);
12827 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12828 EXPECT_TRUE(response->was_fetched_via_spdy);
12829 EXPECT_TRUE(response->was_npn_negotiated);
12830 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12831 EXPECT_EQ("hello!", response_data);
12832 EXPECT_FALSE(
12833 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12834 EXPECT_TRUE(
12835 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12837 HostPortPair host_port_pair_a1("www.a.com", 80);
12838 SpdySessionKey spdy_session_key_a1(
12839 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12840 EXPECT_FALSE(
12841 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
12842 HttpRequestInfo request3;
12843 request3.method = "GET";
12844 request3.url = GURL("http://www.a.com/");
12845 request3.load_flags = 0;
12846 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12848 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
12849 EXPECT_EQ(ERR_IO_PENDING, rv);
12850 EXPECT_EQ(OK, callback.WaitForResult());
12852 response = trans->GetResponseInfo();
12853 ASSERT_TRUE(response != NULL);
12854 ASSERT_TRUE(response->headers.get() != NULL);
12855 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12856 EXPECT_FALSE(response->was_fetched_via_spdy);
12857 EXPECT_FALSE(response->was_npn_negotiated);
12858 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12859 EXPECT_EQ("hello!", response_data);
12860 EXPECT_FALSE(
12861 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12862 EXPECT_FALSE(
12863 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12866 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
12867 HttpRequestInfo request;
12868 request.method = "GET";
12869 request.url = GURL("http://www.example.org/");
12870 request.load_flags = 0;
12872 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12873 scoped_ptr<HttpTransaction> trans(
12874 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12876 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
12877 StaticSocketDataProvider data;
12878 data.set_connect_data(mock_connect);
12879 session_deps_.socket_factory->AddSocketDataProvider(&data);
12881 TestCompletionCallback callback;
12883 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12884 EXPECT_EQ(ERR_IO_PENDING, rv);
12886 rv = callback.WaitForResult();
12887 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12889 // We don't care whether this succeeds or fails, but it shouldn't crash.
12890 HttpRequestHeaders request_headers;
12891 trans->GetFullRequestHeaders(&request_headers);
12893 ConnectionAttempts attempts;
12894 trans->GetConnectionAttempts(&attempts);
12895 ASSERT_EQ(1u, attempts.size());
12896 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12899 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
12900 HttpRequestInfo request;
12901 request.method = "GET";
12902 request.url = GURL("http://www.example.org/");
12903 request.load_flags = 0;
12905 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12906 scoped_ptr<HttpTransaction> trans(
12907 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12909 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12910 StaticSocketDataProvider data;
12911 data.set_connect_data(mock_connect);
12912 session_deps_.socket_factory->AddSocketDataProvider(&data);
12914 TestCompletionCallback callback;
12916 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12917 EXPECT_EQ(ERR_IO_PENDING, rv);
12919 rv = callback.WaitForResult();
12920 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12922 // We don't care whether this succeeds or fails, but it shouldn't crash.
12923 HttpRequestHeaders request_headers;
12924 trans->GetFullRequestHeaders(&request_headers);
12926 ConnectionAttempts attempts;
12927 trans->GetConnectionAttempts(&attempts);
12928 ASSERT_EQ(1u, attempts.size());
12929 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
12932 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
12933 HttpRequestInfo request;
12934 request.method = "GET";
12935 request.url = GURL("http://www.example.org/");
12936 request.load_flags = 0;
12938 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12939 scoped_ptr<HttpTransaction> trans(
12940 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12942 MockWrite data_writes[] = {
12943 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12945 MockRead data_reads[] = {
12946 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12949 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12950 data_writes, arraysize(data_writes));
12951 session_deps_.socket_factory->AddSocketDataProvider(&data);
12953 TestCompletionCallback callback;
12955 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12956 EXPECT_EQ(ERR_IO_PENDING, rv);
12958 rv = callback.WaitForResult();
12959 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12961 HttpRequestHeaders request_headers;
12962 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12963 EXPECT_TRUE(request_headers.HasHeader("Host"));
12966 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
12967 HttpRequestInfo request;
12968 request.method = "GET";
12969 request.url = GURL("http://www.example.org/");
12970 request.load_flags = 0;
12972 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12973 scoped_ptr<HttpTransaction> trans(
12974 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12976 MockWrite data_writes[] = {
12977 MockWrite(ASYNC, ERR_CONNECTION_RESET),
12979 MockRead data_reads[] = {
12980 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12983 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12984 data_writes, arraysize(data_writes));
12985 session_deps_.socket_factory->AddSocketDataProvider(&data);
12987 TestCompletionCallback callback;
12989 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12990 EXPECT_EQ(ERR_IO_PENDING, rv);
12992 rv = callback.WaitForResult();
12993 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12995 HttpRequestHeaders request_headers;
12996 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12997 EXPECT_TRUE(request_headers.HasHeader("Host"));
13000 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
13001 HttpRequestInfo request;
13002 request.method = "GET";
13003 request.url = GURL("http://www.example.org/");
13004 request.load_flags = 0;
13006 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13007 scoped_ptr<HttpTransaction> trans(
13008 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13010 MockWrite data_writes[] = {
13011 MockWrite(
13012 "GET / HTTP/1.1\r\n"
13013 "Host: www.example.org\r\n"
13014 "Connection: keep-alive\r\n\r\n"),
13016 MockRead data_reads[] = {
13017 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
13020 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13021 data_writes, arraysize(data_writes));
13022 session_deps_.socket_factory->AddSocketDataProvider(&data);
13024 TestCompletionCallback callback;
13026 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13027 EXPECT_EQ(ERR_IO_PENDING, rv);
13029 rv = callback.WaitForResult();
13030 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13032 HttpRequestHeaders request_headers;
13033 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13034 EXPECT_TRUE(request_headers.HasHeader("Host"));
13037 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
13038 HttpRequestInfo request;
13039 request.method = "GET";
13040 request.url = GURL("http://www.example.org/");
13041 request.load_flags = 0;
13043 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13044 scoped_ptr<HttpTransaction> trans(
13045 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13047 MockWrite data_writes[] = {
13048 MockWrite(
13049 "GET / HTTP/1.1\r\n"
13050 "Host: www.example.org\r\n"
13051 "Connection: keep-alive\r\n\r\n"),
13053 MockRead data_reads[] = {
13054 MockRead(ASYNC, ERR_CONNECTION_RESET),
13057 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13058 data_writes, arraysize(data_writes));
13059 session_deps_.socket_factory->AddSocketDataProvider(&data);
13061 TestCompletionCallback callback;
13063 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13064 EXPECT_EQ(ERR_IO_PENDING, rv);
13066 rv = callback.WaitForResult();
13067 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13069 HttpRequestHeaders request_headers;
13070 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13071 EXPECT_TRUE(request_headers.HasHeader("Host"));
13074 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
13075 HttpRequestInfo request;
13076 request.method = "GET";
13077 request.url = GURL("http://www.example.org/");
13078 request.load_flags = 0;
13079 request.extra_headers.SetHeader("X-Foo", "bar");
13081 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13082 scoped_ptr<HttpTransaction> trans(
13083 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13085 MockWrite data_writes[] = {
13086 MockWrite(
13087 "GET / HTTP/1.1\r\n"
13088 "Host: www.example.org\r\n"
13089 "Connection: keep-alive\r\n"
13090 "X-Foo: bar\r\n\r\n"),
13092 MockRead data_reads[] = {
13093 MockRead("HTTP/1.1 200 OK\r\n"
13094 "Content-Length: 5\r\n\r\n"
13095 "hello"),
13096 MockRead(ASYNC, ERR_UNEXPECTED),
13099 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13100 data_writes, arraysize(data_writes));
13101 session_deps_.socket_factory->AddSocketDataProvider(&data);
13103 TestCompletionCallback callback;
13105 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13106 EXPECT_EQ(ERR_IO_PENDING, rv);
13108 rv = callback.WaitForResult();
13109 EXPECT_EQ(OK, rv);
13111 HttpRequestHeaders request_headers;
13112 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13113 std::string foo;
13114 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
13115 EXPECT_EQ("bar", foo);
13118 namespace {
13120 // Fake HttpStream that simply records calls to SetPriority().
13121 class FakeStream : public HttpStream,
13122 public base::SupportsWeakPtr<FakeStream> {
13123 public:
13124 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
13125 ~FakeStream() override {}
13127 RequestPriority priority() const { return priority_; }
13129 int InitializeStream(const HttpRequestInfo* request_info,
13130 RequestPriority priority,
13131 const BoundNetLog& net_log,
13132 const CompletionCallback& callback) override {
13133 return ERR_IO_PENDING;
13136 int SendRequest(const HttpRequestHeaders& request_headers,
13137 HttpResponseInfo* response,
13138 const CompletionCallback& callback) override {
13139 ADD_FAILURE();
13140 return ERR_UNEXPECTED;
13143 int ReadResponseHeaders(const CompletionCallback& callback) override {
13144 ADD_FAILURE();
13145 return ERR_UNEXPECTED;
13148 int ReadResponseBody(IOBuffer* buf,
13149 int buf_len,
13150 const CompletionCallback& callback) override {
13151 ADD_FAILURE();
13152 return ERR_UNEXPECTED;
13155 void Close(bool not_reusable) override {}
13157 bool IsResponseBodyComplete() const override {
13158 ADD_FAILURE();
13159 return false;
13162 bool CanFindEndOfResponse() const override { return false; }
13164 bool IsConnectionReused() const override {
13165 ADD_FAILURE();
13166 return false;
13169 void SetConnectionReused() override { ADD_FAILURE(); }
13171 bool IsConnectionReusable() const override {
13172 ADD_FAILURE();
13173 return false;
13176 int64 GetTotalReceivedBytes() const override {
13177 ADD_FAILURE();
13178 return 0;
13181 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13182 ADD_FAILURE();
13183 return false;
13186 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
13188 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13189 ADD_FAILURE();
13192 bool IsSpdyHttpStream() const override {
13193 ADD_FAILURE();
13194 return false;
13197 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
13199 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13201 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
13203 HttpStream* RenewStreamForAuth() override { return NULL; }
13205 private:
13206 RequestPriority priority_;
13208 DISALLOW_COPY_AND_ASSIGN(FakeStream);
13211 // Fake HttpStreamRequest that simply records calls to SetPriority()
13212 // and vends FakeStreams with its current priority.
13213 class FakeStreamRequest : public HttpStreamRequest,
13214 public base::SupportsWeakPtr<FakeStreamRequest> {
13215 public:
13216 FakeStreamRequest(RequestPriority priority,
13217 HttpStreamRequest::Delegate* delegate)
13218 : priority_(priority),
13219 delegate_(delegate),
13220 websocket_stream_create_helper_(NULL) {}
13222 FakeStreamRequest(RequestPriority priority,
13223 HttpStreamRequest::Delegate* delegate,
13224 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
13225 : priority_(priority),
13226 delegate_(delegate),
13227 websocket_stream_create_helper_(create_helper) {}
13229 ~FakeStreamRequest() override {}
13231 RequestPriority priority() const { return priority_; }
13233 const WebSocketHandshakeStreamBase::CreateHelper*
13234 websocket_stream_create_helper() const {
13235 return websocket_stream_create_helper_;
13238 // Create a new FakeStream and pass it to the request's
13239 // delegate. Returns a weak pointer to the FakeStream.
13240 base::WeakPtr<FakeStream> FinishStreamRequest() {
13241 FakeStream* fake_stream = new FakeStream(priority_);
13242 // Do this before calling OnStreamReady() as OnStreamReady() may
13243 // immediately delete |fake_stream|.
13244 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
13245 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
13246 return weak_stream;
13249 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
13250 ADD_FAILURE();
13251 return ERR_UNEXPECTED;
13254 LoadState GetLoadState() const override {
13255 ADD_FAILURE();
13256 return LoadState();
13259 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13261 bool was_npn_negotiated() const override { return false; }
13263 NextProto protocol_negotiated() const override { return kProtoUnknown; }
13265 bool using_spdy() const override { return false; }
13267 const ConnectionAttempts& connection_attempts() const override {
13268 static ConnectionAttempts no_attempts;
13269 return no_attempts;
13272 private:
13273 RequestPriority priority_;
13274 HttpStreamRequest::Delegate* const delegate_;
13275 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
13277 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
13280 // Fake HttpStreamFactory that vends FakeStreamRequests.
13281 class FakeStreamFactory : public HttpStreamFactory {
13282 public:
13283 FakeStreamFactory() {}
13284 ~FakeStreamFactory() override {}
13286 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13287 // RequestStream() (which may be NULL if it was destroyed already).
13288 base::WeakPtr<FakeStreamRequest> last_stream_request() {
13289 return last_stream_request_;
13292 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
13293 RequestPriority priority,
13294 const SSLConfig& server_ssl_config,
13295 const SSLConfig& proxy_ssl_config,
13296 HttpStreamRequest::Delegate* delegate,
13297 const BoundNetLog& net_log) override {
13298 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
13299 last_stream_request_ = fake_request->AsWeakPtr();
13300 return fake_request;
13303 HttpStreamRequest* RequestWebSocketHandshakeStream(
13304 const HttpRequestInfo& info,
13305 RequestPriority priority,
13306 const SSLConfig& server_ssl_config,
13307 const SSLConfig& proxy_ssl_config,
13308 HttpStreamRequest::Delegate* delegate,
13309 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
13310 const BoundNetLog& net_log) override {
13311 FakeStreamRequest* fake_request =
13312 new FakeStreamRequest(priority, delegate, create_helper);
13313 last_stream_request_ = fake_request->AsWeakPtr();
13314 return fake_request;
13317 void PreconnectStreams(int num_streams,
13318 const HttpRequestInfo& info,
13319 const SSLConfig& server_ssl_config,
13320 const SSLConfig& proxy_ssl_config) override {
13321 ADD_FAILURE();
13324 const HostMappingRules* GetHostMappingRules() const override {
13325 ADD_FAILURE();
13326 return NULL;
13329 private:
13330 base::WeakPtr<FakeStreamRequest> last_stream_request_;
13332 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
13335 // TODO(ricea): Maybe unify this with the one in
13336 // url_request_http_job_unittest.cc ?
13337 class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
13338 public:
13339 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
13340 bool using_proxy)
13341 : state_(connection.release(), using_proxy) {}
13343 // Fake implementation of HttpStreamBase methods.
13344 // This ends up being quite "real" because this object has to really send data
13345 // on the mock socket. It might be easier to use the real implementation, but
13346 // the fact that the WebSocket code is not compiled on iOS makes that
13347 // difficult.
13348 int InitializeStream(const HttpRequestInfo* request_info,
13349 RequestPriority priority,
13350 const BoundNetLog& net_log,
13351 const CompletionCallback& callback) override {
13352 state_.Initialize(request_info, priority, net_log, callback);
13353 return OK;
13356 int SendRequest(const HttpRequestHeaders& request_headers,
13357 HttpResponseInfo* response,
13358 const CompletionCallback& callback) override {
13359 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
13360 response, callback);
13363 int ReadResponseHeaders(const CompletionCallback& callback) override {
13364 return parser()->ReadResponseHeaders(callback);
13367 int ReadResponseBody(IOBuffer* buf,
13368 int buf_len,
13369 const CompletionCallback& callback) override {
13370 NOTREACHED();
13371 return ERR_IO_PENDING;
13374 void Close(bool not_reusable) override {
13375 if (parser())
13376 parser()->Close(true);
13379 bool IsResponseBodyComplete() const override {
13380 NOTREACHED();
13381 return false;
13384 bool CanFindEndOfResponse() const override {
13385 return parser()->CanFindEndOfResponse();
13388 bool IsConnectionReused() const override {
13389 NOTREACHED();
13390 return false;
13392 void SetConnectionReused() override { NOTREACHED(); }
13394 bool IsConnectionReusable() const override {
13395 NOTREACHED();
13396 return false;
13399 int64 GetTotalReceivedBytes() const override {
13400 NOTREACHED();
13401 return 0;
13404 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13405 NOTREACHED();
13406 return false;
13409 void GetSSLInfo(SSLInfo* ssl_info) override {}
13411 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13412 NOTREACHED();
13415 bool IsSpdyHttpStream() const override {
13416 NOTREACHED();
13417 return false;
13420 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
13422 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
13424 UploadProgress GetUploadProgress() const override {
13425 NOTREACHED();
13426 return UploadProgress();
13429 HttpStream* RenewStreamForAuth() override {
13430 NOTREACHED();
13431 return nullptr;
13434 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13435 scoped_ptr<WebSocketStream> Upgrade() override {
13436 NOTREACHED();
13437 return scoped_ptr<WebSocketStream>();
13440 private:
13441 HttpStreamParser* parser() const { return state_.parser(); }
13442 HttpBasicState state_;
13444 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
13447 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13448 // worth doing.
13449 class FakeWebSocketStreamCreateHelper :
13450 public WebSocketHandshakeStreamBase::CreateHelper {
13451 public:
13452 WebSocketHandshakeStreamBase* CreateBasicStream(
13453 scoped_ptr<ClientSocketHandle> connection,
13454 bool using_proxy) override {
13455 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
13456 using_proxy);
13459 WebSocketHandshakeStreamBase* CreateSpdyStream(
13460 const base::WeakPtr<SpdySession>& session,
13461 bool use_relative_url) override {
13462 NOTREACHED();
13463 return NULL;
13466 ~FakeWebSocketStreamCreateHelper() override {}
13468 virtual scoped_ptr<WebSocketStream> Upgrade() {
13469 NOTREACHED();
13470 return scoped_ptr<WebSocketStream>();
13474 } // namespace
13476 // Make sure that HttpNetworkTransaction passes on its priority to its
13477 // stream request on start.
13478 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
13479 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13480 HttpNetworkSessionPeer peer(session);
13481 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13482 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13484 HttpNetworkTransaction trans(LOW, session.get());
13486 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
13488 HttpRequestInfo request;
13489 TestCompletionCallback callback;
13490 EXPECT_EQ(ERR_IO_PENDING,
13491 trans.Start(&request, callback.callback(), BoundNetLog()));
13493 base::WeakPtr<FakeStreamRequest> fake_request =
13494 fake_factory->last_stream_request();
13495 ASSERT_TRUE(fake_request != NULL);
13496 EXPECT_EQ(LOW, fake_request->priority());
13499 // Make sure that HttpNetworkTransaction passes on its priority
13500 // updates to its stream request.
13501 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
13502 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13503 HttpNetworkSessionPeer peer(session);
13504 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13505 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13507 HttpNetworkTransaction trans(LOW, session.get());
13509 HttpRequestInfo request;
13510 TestCompletionCallback callback;
13511 EXPECT_EQ(ERR_IO_PENDING,
13512 trans.Start(&request, callback.callback(), BoundNetLog()));
13514 base::WeakPtr<FakeStreamRequest> fake_request =
13515 fake_factory->last_stream_request();
13516 ASSERT_TRUE(fake_request != NULL);
13517 EXPECT_EQ(LOW, fake_request->priority());
13519 trans.SetPriority(LOWEST);
13520 ASSERT_TRUE(fake_request != NULL);
13521 EXPECT_EQ(LOWEST, fake_request->priority());
13524 // Make sure that HttpNetworkTransaction passes on its priority
13525 // updates to its stream.
13526 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
13527 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13528 HttpNetworkSessionPeer peer(session);
13529 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13530 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13532 HttpNetworkTransaction trans(LOW, session.get());
13534 HttpRequestInfo request;
13535 TestCompletionCallback callback;
13536 EXPECT_EQ(ERR_IO_PENDING,
13537 trans.Start(&request, callback.callback(), BoundNetLog()));
13539 base::WeakPtr<FakeStreamRequest> fake_request =
13540 fake_factory->last_stream_request();
13541 ASSERT_TRUE(fake_request != NULL);
13542 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
13543 ASSERT_TRUE(fake_stream != NULL);
13544 EXPECT_EQ(LOW, fake_stream->priority());
13546 trans.SetPriority(LOWEST);
13547 EXPECT_EQ(LOWEST, fake_stream->priority());
13550 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
13551 // The same logic needs to be tested for both ws: and wss: schemes, but this
13552 // test is already parameterised on NextProto, so it uses a loop to verify
13553 // that the different schemes work.
13554 std::string test_cases[] = {"ws://www.example.org/",
13555 "wss://www.example.org/"};
13556 for (size_t i = 0; i < arraysize(test_cases); ++i) {
13557 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13558 HttpNetworkSessionPeer peer(session);
13559 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13560 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13561 peer.SetHttpStreamFactoryForWebSocket(
13562 scoped_ptr<HttpStreamFactory>(fake_factory));
13564 HttpNetworkTransaction trans(LOW, session.get());
13565 trans.SetWebSocketHandshakeStreamCreateHelper(
13566 &websocket_stream_create_helper);
13568 HttpRequestInfo request;
13569 TestCompletionCallback callback;
13570 request.method = "GET";
13571 request.url = GURL(test_cases[i]);
13573 EXPECT_EQ(ERR_IO_PENDING,
13574 trans.Start(&request, callback.callback(), BoundNetLog()));
13576 base::WeakPtr<FakeStreamRequest> fake_request =
13577 fake_factory->last_stream_request();
13578 ASSERT_TRUE(fake_request != NULL);
13579 EXPECT_EQ(&websocket_stream_create_helper,
13580 fake_request->websocket_stream_create_helper());
13584 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13585 // if the transport socket pool is stalled on the global socket limit.
13586 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
13587 ClientSocketPoolManager::set_max_sockets_per_group(
13588 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13589 ClientSocketPoolManager::set_max_sockets_per_pool(
13590 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13592 // Set up SSL request.
13594 HttpRequestInfo ssl_request;
13595 ssl_request.method = "GET";
13596 ssl_request.url = GURL("https://www.example.org/");
13598 MockWrite ssl_writes[] = {
13599 MockWrite(
13600 "GET / HTTP/1.1\r\n"
13601 "Host: www.example.org\r\n"
13602 "Connection: keep-alive\r\n\r\n"),
13604 MockRead ssl_reads[] = {
13605 MockRead("HTTP/1.1 200 OK\r\n"),
13606 MockRead("Content-Length: 11\r\n\r\n"),
13607 MockRead("hello world"),
13608 MockRead(SYNCHRONOUS, OK),
13610 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
13611 ssl_writes, arraysize(ssl_writes));
13612 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13614 SSLSocketDataProvider ssl(ASYNC, OK);
13615 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13617 // Set up HTTP request.
13619 HttpRequestInfo http_request;
13620 http_request.method = "GET";
13621 http_request.url = GURL("http://www.example.org/");
13623 MockWrite http_writes[] = {
13624 MockWrite(
13625 "GET / HTTP/1.1\r\n"
13626 "Host: www.example.org\r\n"
13627 "Connection: keep-alive\r\n\r\n"),
13629 MockRead http_reads[] = {
13630 MockRead("HTTP/1.1 200 OK\r\n"),
13631 MockRead("Content-Length: 7\r\n\r\n"),
13632 MockRead("falafel"),
13633 MockRead(SYNCHRONOUS, OK),
13635 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13636 http_writes, arraysize(http_writes));
13637 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13639 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13641 // Start the SSL request.
13642 TestCompletionCallback ssl_callback;
13643 scoped_ptr<HttpTransaction> ssl_trans(
13644 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13645 ASSERT_EQ(ERR_IO_PENDING,
13646 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
13647 BoundNetLog()));
13649 // Start the HTTP request. Pool should stall.
13650 TestCompletionCallback http_callback;
13651 scoped_ptr<HttpTransaction> http_trans(
13652 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13653 ASSERT_EQ(ERR_IO_PENDING,
13654 http_trans->Start(&http_request, http_callback.callback(),
13655 BoundNetLog()));
13656 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13658 // Wait for response from SSL request.
13659 ASSERT_EQ(OK, ssl_callback.WaitForResult());
13660 std::string response_data;
13661 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
13662 EXPECT_EQ("hello world", response_data);
13664 // The SSL socket should automatically be closed, so the HTTP request can
13665 // start.
13666 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13667 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
13669 // The HTTP request can now complete.
13670 ASSERT_EQ(OK, http_callback.WaitForResult());
13671 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13672 EXPECT_EQ("falafel", response_data);
13674 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13677 // Tests that when a SSL connection is established but there's no corresponding
13678 // request that needs it, the new socket is closed if the transport socket pool
13679 // is stalled on the global socket limit.
13680 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
13681 ClientSocketPoolManager::set_max_sockets_per_group(
13682 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13683 ClientSocketPoolManager::set_max_sockets_per_pool(
13684 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13686 // Set up an ssl request.
13688 HttpRequestInfo ssl_request;
13689 ssl_request.method = "GET";
13690 ssl_request.url = GURL("https://www.foopy.com/");
13692 // No data will be sent on the SSL socket.
13693 StaticSocketDataProvider ssl_data;
13694 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13696 SSLSocketDataProvider ssl(ASYNC, OK);
13697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13699 // Set up HTTP request.
13701 HttpRequestInfo http_request;
13702 http_request.method = "GET";
13703 http_request.url = GURL("http://www.example.org/");
13705 MockWrite http_writes[] = {
13706 MockWrite(
13707 "GET / HTTP/1.1\r\n"
13708 "Host: www.example.org\r\n"
13709 "Connection: keep-alive\r\n\r\n"),
13711 MockRead http_reads[] = {
13712 MockRead("HTTP/1.1 200 OK\r\n"),
13713 MockRead("Content-Length: 7\r\n\r\n"),
13714 MockRead("falafel"),
13715 MockRead(SYNCHRONOUS, OK),
13717 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13718 http_writes, arraysize(http_writes));
13719 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13721 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13723 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13724 // cancelled when a normal transaction is cancelled.
13725 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
13726 SSLConfig ssl_config;
13727 session->ssl_config_service()->GetSSLConfig(&ssl_config);
13728 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
13729 ssl_config);
13730 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13732 // Start the HTTP request. Pool should stall.
13733 TestCompletionCallback http_callback;
13734 scoped_ptr<HttpTransaction> http_trans(
13735 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13736 ASSERT_EQ(ERR_IO_PENDING,
13737 http_trans->Start(&http_request, http_callback.callback(),
13738 BoundNetLog()));
13739 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13741 // The SSL connection will automatically be closed once the connection is
13742 // established, to let the HTTP request start.
13743 ASSERT_EQ(OK, http_callback.WaitForResult());
13744 std::string response_data;
13745 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13746 EXPECT_EQ("falafel", response_data);
13748 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13751 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
13752 ScopedVector<UploadElementReader> element_readers;
13753 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13754 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13756 HttpRequestInfo request;
13757 request.method = "POST";
13758 request.url = GURL("http://www.foo.com/");
13759 request.upload_data_stream = &upload_data_stream;
13760 request.load_flags = 0;
13762 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13763 scoped_ptr<HttpTransaction> trans(
13764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13765 // Send headers successfully, but get an error while sending the body.
13766 MockWrite data_writes[] = {
13767 MockWrite("POST / HTTP/1.1\r\n"
13768 "Host: www.foo.com\r\n"
13769 "Connection: keep-alive\r\n"
13770 "Content-Length: 3\r\n\r\n"),
13771 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13774 MockRead data_reads[] = {
13775 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13776 MockRead("hello world"),
13777 MockRead(SYNCHRONOUS, OK),
13779 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13780 arraysize(data_writes));
13781 session_deps_.socket_factory->AddSocketDataProvider(&data);
13783 TestCompletionCallback callback;
13785 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13786 EXPECT_EQ(ERR_IO_PENDING, rv);
13788 rv = callback.WaitForResult();
13789 EXPECT_EQ(OK, rv);
13791 const HttpResponseInfo* response = trans->GetResponseInfo();
13792 ASSERT_TRUE(response != NULL);
13794 EXPECT_TRUE(response->headers.get() != NULL);
13795 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13797 std::string response_data;
13798 rv = ReadTransaction(trans.get(), &response_data);
13799 EXPECT_EQ(OK, rv);
13800 EXPECT_EQ("hello world", response_data);
13803 // This test makes sure the retry logic doesn't trigger when reading an error
13804 // response from a server that rejected a POST with a CONNECTION_RESET.
13805 TEST_P(HttpNetworkTransactionTest,
13806 PostReadsErrorResponseAfterResetOnReusedSocket) {
13807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13808 MockWrite data_writes[] = {
13809 MockWrite("GET / HTTP/1.1\r\n"
13810 "Host: www.foo.com\r\n"
13811 "Connection: keep-alive\r\n\r\n"),
13812 MockWrite("POST / HTTP/1.1\r\n"
13813 "Host: www.foo.com\r\n"
13814 "Connection: keep-alive\r\n"
13815 "Content-Length: 3\r\n\r\n"),
13816 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13819 MockRead data_reads[] = {
13820 MockRead("HTTP/1.1 200 Peachy\r\n"
13821 "Content-Length: 14\r\n\r\n"),
13822 MockRead("first response"),
13823 MockRead("HTTP/1.1 400 Not OK\r\n"
13824 "Content-Length: 15\r\n\r\n"),
13825 MockRead("second response"),
13826 MockRead(SYNCHRONOUS, OK),
13828 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13829 arraysize(data_writes));
13830 session_deps_.socket_factory->AddSocketDataProvider(&data);
13832 TestCompletionCallback callback;
13833 HttpRequestInfo request1;
13834 request1.method = "GET";
13835 request1.url = GURL("http://www.foo.com/");
13836 request1.load_flags = 0;
13838 scoped_ptr<HttpTransaction> trans1(
13839 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13840 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
13841 EXPECT_EQ(ERR_IO_PENDING, rv);
13843 rv = callback.WaitForResult();
13844 EXPECT_EQ(OK, rv);
13846 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13847 ASSERT_TRUE(response1 != NULL);
13849 EXPECT_TRUE(response1->headers.get() != NULL);
13850 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
13852 std::string response_data1;
13853 rv = ReadTransaction(trans1.get(), &response_data1);
13854 EXPECT_EQ(OK, rv);
13855 EXPECT_EQ("first response", response_data1);
13856 // Delete the transaction to release the socket back into the socket pool.
13857 trans1.reset();
13859 ScopedVector<UploadElementReader> element_readers;
13860 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13861 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13863 HttpRequestInfo request2;
13864 request2.method = "POST";
13865 request2.url = GURL("http://www.foo.com/");
13866 request2.upload_data_stream = &upload_data_stream;
13867 request2.load_flags = 0;
13869 scoped_ptr<HttpTransaction> trans2(
13870 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13871 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
13872 EXPECT_EQ(ERR_IO_PENDING, rv);
13874 rv = callback.WaitForResult();
13875 EXPECT_EQ(OK, rv);
13877 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
13878 ASSERT_TRUE(response2 != NULL);
13880 EXPECT_TRUE(response2->headers.get() != NULL);
13881 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
13883 std::string response_data2;
13884 rv = ReadTransaction(trans2.get(), &response_data2);
13885 EXPECT_EQ(OK, rv);
13886 EXPECT_EQ("second response", response_data2);
13889 TEST_P(HttpNetworkTransactionTest,
13890 PostReadsErrorResponseAfterResetPartialBodySent) {
13891 ScopedVector<UploadElementReader> element_readers;
13892 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13893 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13895 HttpRequestInfo request;
13896 request.method = "POST";
13897 request.url = GURL("http://www.foo.com/");
13898 request.upload_data_stream = &upload_data_stream;
13899 request.load_flags = 0;
13901 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13902 scoped_ptr<HttpTransaction> trans(
13903 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13904 // Send headers successfully, but get an error while sending the body.
13905 MockWrite data_writes[] = {
13906 MockWrite("POST / HTTP/1.1\r\n"
13907 "Host: www.foo.com\r\n"
13908 "Connection: keep-alive\r\n"
13909 "Content-Length: 3\r\n\r\n"
13910 "fo"),
13911 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13914 MockRead data_reads[] = {
13915 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13916 MockRead("hello world"),
13917 MockRead(SYNCHRONOUS, OK),
13919 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13920 arraysize(data_writes));
13921 session_deps_.socket_factory->AddSocketDataProvider(&data);
13923 TestCompletionCallback callback;
13925 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13926 EXPECT_EQ(ERR_IO_PENDING, rv);
13928 rv = callback.WaitForResult();
13929 EXPECT_EQ(OK, rv);
13931 const HttpResponseInfo* response = trans->GetResponseInfo();
13932 ASSERT_TRUE(response != NULL);
13934 EXPECT_TRUE(response->headers.get() != NULL);
13935 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13937 std::string response_data;
13938 rv = ReadTransaction(trans.get(), &response_data);
13939 EXPECT_EQ(OK, rv);
13940 EXPECT_EQ("hello world", response_data);
13943 // This tests the more common case than the previous test, where headers and
13944 // body are not merged into a single request.
13945 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
13946 ScopedVector<UploadElementReader> element_readers;
13947 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13948 ChunkedUploadDataStream upload_data_stream(0);
13950 HttpRequestInfo request;
13951 request.method = "POST";
13952 request.url = GURL("http://www.foo.com/");
13953 request.upload_data_stream = &upload_data_stream;
13954 request.load_flags = 0;
13956 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13957 scoped_ptr<HttpTransaction> trans(
13958 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13959 // Send headers successfully, but get an error while sending the body.
13960 MockWrite data_writes[] = {
13961 MockWrite("POST / HTTP/1.1\r\n"
13962 "Host: www.foo.com\r\n"
13963 "Connection: keep-alive\r\n"
13964 "Transfer-Encoding: chunked\r\n\r\n"),
13965 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13968 MockRead data_reads[] = {
13969 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13970 MockRead("hello world"),
13971 MockRead(SYNCHRONOUS, OK),
13973 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13974 arraysize(data_writes));
13975 session_deps_.socket_factory->AddSocketDataProvider(&data);
13977 TestCompletionCallback callback;
13979 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13980 EXPECT_EQ(ERR_IO_PENDING, rv);
13981 // Make sure the headers are sent before adding a chunk. This ensures that
13982 // they can't be merged with the body in a single send. Not currently
13983 // necessary since a chunked body is never merged with headers, but this makes
13984 // the test more future proof.
13985 base::RunLoop().RunUntilIdle();
13987 upload_data_stream.AppendData("last chunk", 10, true);
13989 rv = callback.WaitForResult();
13990 EXPECT_EQ(OK, rv);
13992 const HttpResponseInfo* response = trans->GetResponseInfo();
13993 ASSERT_TRUE(response != NULL);
13995 EXPECT_TRUE(response->headers.get() != NULL);
13996 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13998 std::string response_data;
13999 rv = ReadTransaction(trans.get(), &response_data);
14000 EXPECT_EQ(OK, rv);
14001 EXPECT_EQ("hello world", response_data);
14004 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
14005 ScopedVector<UploadElementReader> element_readers;
14006 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14007 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14009 HttpRequestInfo request;
14010 request.method = "POST";
14011 request.url = GURL("http://www.foo.com/");
14012 request.upload_data_stream = &upload_data_stream;
14013 request.load_flags = 0;
14015 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14016 scoped_ptr<HttpTransaction> trans(
14017 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14019 MockWrite data_writes[] = {
14020 MockWrite("POST / HTTP/1.1\r\n"
14021 "Host: www.foo.com\r\n"
14022 "Connection: keep-alive\r\n"
14023 "Content-Length: 3\r\n\r\n"),
14024 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14027 MockRead data_reads[] = {
14028 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14029 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14030 MockRead("hello world"),
14031 MockRead(SYNCHRONOUS, OK),
14033 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14034 arraysize(data_writes));
14035 session_deps_.socket_factory->AddSocketDataProvider(&data);
14037 TestCompletionCallback callback;
14039 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14040 EXPECT_EQ(ERR_IO_PENDING, rv);
14042 rv = callback.WaitForResult();
14043 EXPECT_EQ(OK, rv);
14045 const HttpResponseInfo* response = trans->GetResponseInfo();
14046 ASSERT_TRUE(response != NULL);
14048 EXPECT_TRUE(response->headers.get() != NULL);
14049 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14051 std::string response_data;
14052 rv = ReadTransaction(trans.get(), &response_data);
14053 EXPECT_EQ(OK, rv);
14054 EXPECT_EQ("hello world", response_data);
14057 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
14058 ScopedVector<UploadElementReader> element_readers;
14059 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14060 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14062 HttpRequestInfo request;
14063 request.method = "POST";
14064 request.url = GURL("http://www.foo.com/");
14065 request.upload_data_stream = &upload_data_stream;
14066 request.load_flags = 0;
14068 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14069 scoped_ptr<HttpTransaction> trans(
14070 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14071 // Send headers successfully, but get an error while sending the body.
14072 MockWrite data_writes[] = {
14073 MockWrite("POST / HTTP/1.1\r\n"
14074 "Host: www.foo.com\r\n"
14075 "Connection: keep-alive\r\n"
14076 "Content-Length: 3\r\n\r\n"),
14077 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14080 MockRead data_reads[] = {
14081 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14082 MockRead("hello world"),
14083 MockRead(SYNCHRONOUS, OK),
14085 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14086 arraysize(data_writes));
14087 session_deps_.socket_factory->AddSocketDataProvider(&data);
14089 TestCompletionCallback callback;
14091 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14092 EXPECT_EQ(ERR_IO_PENDING, rv);
14094 rv = callback.WaitForResult();
14095 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14098 TEST_P(HttpNetworkTransactionTest,
14099 PostIgnoresNonErrorResponseAfterResetAnd100) {
14100 ScopedVector<UploadElementReader> element_readers;
14101 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14102 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14104 HttpRequestInfo request;
14105 request.method = "POST";
14106 request.url = GURL("http://www.foo.com/");
14107 request.upload_data_stream = &upload_data_stream;
14108 request.load_flags = 0;
14110 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14111 scoped_ptr<HttpTransaction> trans(
14112 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14113 // Send headers successfully, but get an error while sending the body.
14114 MockWrite data_writes[] = {
14115 MockWrite("POST / HTTP/1.1\r\n"
14116 "Host: www.foo.com\r\n"
14117 "Connection: keep-alive\r\n"
14118 "Content-Length: 3\r\n\r\n"),
14119 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14122 MockRead data_reads[] = {
14123 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14124 MockRead("HTTP/1.0 302 Redirect\r\n"),
14125 MockRead("Location: http://somewhere-else.com/\r\n"),
14126 MockRead("Content-Length: 0\r\n\r\n"),
14127 MockRead(SYNCHRONOUS, OK),
14129 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14130 arraysize(data_writes));
14131 session_deps_.socket_factory->AddSocketDataProvider(&data);
14133 TestCompletionCallback callback;
14135 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14136 EXPECT_EQ(ERR_IO_PENDING, rv);
14138 rv = callback.WaitForResult();
14139 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14142 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
14143 ScopedVector<UploadElementReader> element_readers;
14144 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14145 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14147 HttpRequestInfo request;
14148 request.method = "POST";
14149 request.url = GURL("http://www.foo.com/");
14150 request.upload_data_stream = &upload_data_stream;
14151 request.load_flags = 0;
14153 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14154 scoped_ptr<HttpTransaction> trans(
14155 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14156 // Send headers successfully, but get an error while sending the body.
14157 MockWrite data_writes[] = {
14158 MockWrite("POST / HTTP/1.1\r\n"
14159 "Host: www.foo.com\r\n"
14160 "Connection: keep-alive\r\n"
14161 "Content-Length: 3\r\n\r\n"),
14162 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14165 MockRead data_reads[] = {
14166 MockRead("HTTP 0.9 rocks!"),
14167 MockRead(SYNCHRONOUS, OK),
14169 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14170 arraysize(data_writes));
14171 session_deps_.socket_factory->AddSocketDataProvider(&data);
14173 TestCompletionCallback callback;
14175 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14176 EXPECT_EQ(ERR_IO_PENDING, rv);
14178 rv = callback.WaitForResult();
14179 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14182 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
14183 ScopedVector<UploadElementReader> element_readers;
14184 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14185 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14187 HttpRequestInfo request;
14188 request.method = "POST";
14189 request.url = GURL("http://www.foo.com/");
14190 request.upload_data_stream = &upload_data_stream;
14191 request.load_flags = 0;
14193 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14194 scoped_ptr<HttpTransaction> trans(
14195 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14196 // Send headers successfully, but get an error while sending the body.
14197 MockWrite data_writes[] = {
14198 MockWrite("POST / HTTP/1.1\r\n"
14199 "Host: www.foo.com\r\n"
14200 "Connection: keep-alive\r\n"
14201 "Content-Length: 3\r\n\r\n"),
14202 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14205 MockRead data_reads[] = {
14206 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14207 MockRead(SYNCHRONOUS, OK),
14209 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14210 arraysize(data_writes));
14211 session_deps_.socket_factory->AddSocketDataProvider(&data);
14213 TestCompletionCallback callback;
14215 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14216 EXPECT_EQ(ERR_IO_PENDING, rv);
14218 rv = callback.WaitForResult();
14219 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14222 // Verify that proxy headers are not sent to the destination server when
14223 // establishing a tunnel for a secure WebSocket connection.
14224 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
14225 HttpRequestInfo request;
14226 request.method = "GET";
14227 request.url = GURL("wss://www.example.org/");
14228 AddWebSocketHeaders(&request.extra_headers);
14230 // Configure against proxy server "myproxy:70".
14231 session_deps_.proxy_service.reset(
14232 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14234 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14236 // Since a proxy is configured, try to establish a tunnel.
14237 MockWrite data_writes[] = {
14238 MockWrite(
14239 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14240 "Host: www.example.org\r\n"
14241 "Proxy-Connection: keep-alive\r\n\r\n"),
14243 // After calling trans->RestartWithAuth(), this is the request we should
14244 // be issuing -- the final header line contains the credentials.
14245 MockWrite(
14246 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14247 "Host: www.example.org\r\n"
14248 "Proxy-Connection: keep-alive\r\n"
14249 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14251 MockWrite(
14252 "GET / HTTP/1.1\r\n"
14253 "Host: www.example.org\r\n"
14254 "Connection: Upgrade\r\n"
14255 "Upgrade: websocket\r\n"
14256 "Origin: http://www.example.org\r\n"
14257 "Sec-WebSocket-Version: 13\r\n"
14258 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14261 // The proxy responds to the connect with a 407, using a persistent
14262 // connection.
14263 MockRead data_reads[] = {
14264 // No credentials.
14265 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14266 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14267 MockRead("Proxy-Connection: close\r\n\r\n"),
14269 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14271 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14272 MockRead("Upgrade: websocket\r\n"),
14273 MockRead("Connection: Upgrade\r\n"),
14274 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14277 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14278 arraysize(data_writes));
14279 session_deps_.socket_factory->AddSocketDataProvider(&data);
14280 SSLSocketDataProvider ssl(ASYNC, OK);
14281 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14283 scoped_ptr<HttpTransaction> trans(
14284 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14285 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14286 trans->SetWebSocketHandshakeStreamCreateHelper(
14287 &websocket_stream_create_helper);
14290 TestCompletionCallback callback;
14292 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14293 EXPECT_EQ(ERR_IO_PENDING, rv);
14295 rv = callback.WaitForResult();
14296 EXPECT_EQ(OK, rv);
14299 const HttpResponseInfo* response = trans->GetResponseInfo();
14300 ASSERT_TRUE(response);
14301 ASSERT_TRUE(response->headers.get());
14302 EXPECT_EQ(407, response->headers->response_code());
14305 TestCompletionCallback callback;
14307 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
14308 callback.callback());
14309 EXPECT_EQ(ERR_IO_PENDING, rv);
14311 rv = callback.WaitForResult();
14312 EXPECT_EQ(OK, rv);
14315 response = trans->GetResponseInfo();
14316 ASSERT_TRUE(response);
14317 ASSERT_TRUE(response->headers.get());
14319 EXPECT_EQ(101, response->headers->response_code());
14321 trans.reset();
14322 session->CloseAllConnections();
14325 // Verify that proxy headers are not sent to the destination server when
14326 // establishing a tunnel for an insecure WebSocket connection.
14327 // This requires the authentication info to be injected into the auth cache
14328 // due to crbug.com/395064
14329 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14330 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
14331 HttpRequestInfo request;
14332 request.method = "GET";
14333 request.url = GURL("ws://www.example.org/");
14334 AddWebSocketHeaders(&request.extra_headers);
14336 // Configure against proxy server "myproxy:70".
14337 session_deps_.proxy_service.reset(
14338 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14342 MockWrite data_writes[] = {
14343 // Try to establish a tunnel for the WebSocket connection, with
14344 // credentials. Because WebSockets have a separate set of socket pools,
14345 // they cannot and will not use the same TCP/IP connection as the
14346 // preflight HTTP request.
14347 MockWrite(
14348 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14349 "Host: www.example.org:80\r\n"
14350 "Proxy-Connection: keep-alive\r\n"
14351 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14353 MockWrite(
14354 "GET / HTTP/1.1\r\n"
14355 "Host: www.example.org\r\n"
14356 "Connection: Upgrade\r\n"
14357 "Upgrade: websocket\r\n"
14358 "Origin: http://www.example.org\r\n"
14359 "Sec-WebSocket-Version: 13\r\n"
14360 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14363 MockRead data_reads[] = {
14364 // HTTP CONNECT with credentials.
14365 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14367 // WebSocket connection established inside tunnel.
14368 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14369 MockRead("Upgrade: websocket\r\n"),
14370 MockRead("Connection: Upgrade\r\n"),
14371 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14374 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14375 arraysize(data_writes));
14376 session_deps_.socket_factory->AddSocketDataProvider(&data);
14378 session->http_auth_cache()->Add(
14379 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
14380 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
14382 scoped_ptr<HttpTransaction> trans(
14383 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14384 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14385 trans->SetWebSocketHandshakeStreamCreateHelper(
14386 &websocket_stream_create_helper);
14388 TestCompletionCallback callback;
14390 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14391 EXPECT_EQ(ERR_IO_PENDING, rv);
14393 rv = callback.WaitForResult();
14394 EXPECT_EQ(OK, rv);
14396 const HttpResponseInfo* response = trans->GetResponseInfo();
14397 ASSERT_TRUE(response);
14398 ASSERT_TRUE(response->headers.get());
14400 EXPECT_EQ(101, response->headers->response_code());
14402 trans.reset();
14403 session->CloseAllConnections();
14406 } // namespace net