Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blob14bda39448d3534d25d6c6b5e742fb08a47b8f07
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 <stdint.h>
11 #include <string>
12 #include <vector>
14 #include "base/basictypes.h"
15 #include "base/compiler_specific.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/json/json_writer.h"
19 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/weak_ptr.h"
22 #include "base/run_loop.h"
23 #include "base/stl_util.h"
24 #include "base/strings/string_util.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/test/test_file_util.h"
27 #include "base/thread_task_runner_handle.h"
28 #include "net/base/auth.h"
29 #include "net/base/chunked_upload_data_stream.h"
30 #include "net/base/completion_callback.h"
31 #include "net/base/elements_upload_data_stream.h"
32 #include "net/base/load_timing_info.h"
33 #include "net/base/load_timing_info_test_util.h"
34 #include "net/base/net_errors.h"
35 #include "net/base/request_priority.h"
36 #include "net/base/test_completion_callback.h"
37 #include "net/base/test_data_directory.h"
38 #include "net/base/upload_bytes_element_reader.h"
39 #include "net/base/upload_file_element_reader.h"
40 #include "net/cert/mock_cert_verifier.h"
41 #include "net/dns/host_cache.h"
42 #include "net/dns/mock_host_resolver.h"
43 #include "net/http/http_auth_challenge_tokenizer.h"
44 #include "net/http/http_auth_handler_digest.h"
45 #include "net/http/http_auth_handler_mock.h"
46 #include "net/http/http_auth_handler_ntlm.h"
47 #include "net/http/http_basic_state.h"
48 #include "net/http/http_basic_stream.h"
49 #include "net/http/http_network_session.h"
50 #include "net/http/http_network_session_peer.h"
51 #include "net/http/http_request_headers.h"
52 #include "net/http/http_server_properties_impl.h"
53 #include "net/http/http_stream.h"
54 #include "net/http/http_stream_factory.h"
55 #include "net/http/http_stream_parser.h"
56 #include "net/http/http_transaction_test_util.h"
57 #include "net/log/net_log.h"
58 #include "net/log/test_net_log.h"
59 #include "net/log/test_net_log_entry.h"
60 #include "net/log/test_net_log_util.h"
61 #include "net/proxy/mock_proxy_resolver.h"
62 #include "net/proxy/proxy_config_service_fixed.h"
63 #include "net/proxy/proxy_info.h"
64 #include "net/proxy/proxy_resolver.h"
65 #include "net/proxy/proxy_service.h"
66 #include "net/socket/client_socket_factory.h"
67 #include "net/socket/client_socket_pool_manager.h"
68 #include "net/socket/connection_attempts.h"
69 #include "net/socket/mock_client_socket_pool_manager.h"
70 #include "net/socket/next_proto.h"
71 #include "net/socket/socket_test_util.h"
72 #include "net/socket/ssl_client_socket.h"
73 #include "net/spdy/spdy_framer.h"
74 #include "net/spdy/spdy_session.h"
75 #include "net/spdy/spdy_session_pool.h"
76 #include "net/spdy/spdy_test_util_common.h"
77 #include "net/ssl/ssl_cert_request_info.h"
78 #include "net/ssl/ssl_config_service.h"
79 #include "net/ssl/ssl_config_service_defaults.h"
80 #include "net/ssl/ssl_info.h"
81 #include "net/test/cert_test_util.h"
82 #include "net/websockets/websocket_handshake_stream_base.h"
83 #include "testing/gtest/include/gtest/gtest.h"
84 #include "testing/platform_test.h"
85 #include "url/gurl.h"
87 using base::ASCIIToUTF16;
89 //-----------------------------------------------------------------------------
91 namespace net {
93 namespace {
95 const base::string16 kBar(ASCIIToUTF16("bar"));
96 const base::string16 kBar2(ASCIIToUTF16("bar2"));
97 const base::string16 kBar3(ASCIIToUTF16("bar3"));
98 const base::string16 kBaz(ASCIIToUTF16("baz"));
99 const base::string16 kFirst(ASCIIToUTF16("first"));
100 const base::string16 kFoo(ASCIIToUTF16("foo"));
101 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
102 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
103 const base::string16 kFou(ASCIIToUTF16("fou"));
104 const base::string16 kSecond(ASCIIToUTF16("second"));
105 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
106 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
108 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
109 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
110 ->IdleSocketCount();
113 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
114 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
115 ->IdleSocketCount();
118 bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
119 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
120 ->IsStalled();
123 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
124 // a JSONified list of headers as a single string. Uses single quotes instead
125 // of double quotes for easier comparison. Returns false on failure.
126 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
127 if (!params)
128 return false;
129 base::ListValue* header_list;
130 if (!params->GetList("headers", &header_list))
131 return false;
132 std::string double_quote_headers;
133 base::JSONWriter::Write(*header_list, &double_quote_headers);
134 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
135 return true;
138 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
139 // used.
140 void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
141 EXPECT_TRUE(load_timing_info.socket_reused);
142 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
144 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
145 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
147 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
148 EXPECT_FALSE(load_timing_info.send_start.is_null());
150 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
152 // Set at a higher level.
153 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
154 EXPECT_TRUE(load_timing_info.request_start.is_null());
155 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
158 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
159 // used.
160 void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
161 int connect_timing_flags) {
162 EXPECT_FALSE(load_timing_info.socket_reused);
163 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
165 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
166 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
168 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
169 connect_timing_flags);
170 EXPECT_LE(load_timing_info.connect_timing.connect_end,
171 load_timing_info.send_start);
173 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
175 // Set at a higher level.
176 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
177 EXPECT_TRUE(load_timing_info.request_start.is_null());
178 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
181 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
182 // used.
183 void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
184 EXPECT_TRUE(load_timing_info.socket_reused);
185 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
187 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
189 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
190 EXPECT_LE(load_timing_info.proxy_resolve_start,
191 load_timing_info.proxy_resolve_end);
192 EXPECT_LE(load_timing_info.proxy_resolve_end,
193 load_timing_info.send_start);
194 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
196 // Set at a higher level.
197 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
198 EXPECT_TRUE(load_timing_info.request_start.is_null());
199 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
202 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
203 // used.
204 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
205 int connect_timing_flags) {
206 EXPECT_FALSE(load_timing_info.socket_reused);
207 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
209 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
210 EXPECT_LE(load_timing_info.proxy_resolve_start,
211 load_timing_info.proxy_resolve_end);
212 EXPECT_LE(load_timing_info.proxy_resolve_end,
213 load_timing_info.connect_timing.connect_start);
214 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
215 connect_timing_flags);
216 EXPECT_LE(load_timing_info.connect_timing.connect_end,
217 load_timing_info.send_start);
219 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
221 // Set at a higher level.
222 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
223 EXPECT_TRUE(load_timing_info.request_start.is_null());
224 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
227 void AddWebSocketHeaders(HttpRequestHeaders* headers) {
228 headers->SetHeader("Connection", "Upgrade");
229 headers->SetHeader("Upgrade", "websocket");
230 headers->SetHeader("Origin", "http://www.example.org");
231 headers->SetHeader("Sec-WebSocket-Version", "13");
232 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
235 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
236 return SpdySessionDependencies::SpdyCreateSession(session_deps);
239 } // namespace
241 class HttpNetworkTransactionTest
242 : public PlatformTest,
243 public ::testing::WithParamInterface<NextProto> {
244 public:
245 virtual ~HttpNetworkTransactionTest() {
246 // Important to restore the per-pool limit first, since the pool limit must
247 // always be greater than group limit, and the tests reduce both limits.
248 ClientSocketPoolManager::set_max_sockets_per_pool(
249 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
250 ClientSocketPoolManager::set_max_sockets_per_group(
251 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
254 protected:
255 HttpNetworkTransactionTest()
256 : spdy_util_(GetParam()),
257 session_deps_(GetParam()),
258 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
259 HttpNetworkSession::NORMAL_SOCKET_POOL)),
260 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
261 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
264 struct SimpleGetHelperResult {
265 int rv;
266 std::string status_line;
267 std::string response_data;
268 int64 totalReceivedBytes;
269 LoadTimingInfo load_timing_info;
270 ConnectionAttempts connection_attempts;
273 void SetUp() override {
274 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
275 base::MessageLoop::current()->RunUntilIdle();
278 void TearDown() override {
279 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
280 base::MessageLoop::current()->RunUntilIdle();
281 // Empty the current queue.
282 base::MessageLoop::current()->RunUntilIdle();
283 PlatformTest::TearDown();
284 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
285 base::MessageLoop::current()->RunUntilIdle();
288 const char* GetAlternateProtocolFromParam() {
289 return
290 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
293 std::string GetAlternativeServiceHttpHeader() {
294 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
295 "=\"www.example.com:443\"\r\n";
298 std::string GetAlternateProtocolHttpHeader() {
299 return std::string("Alternate-Protocol: 443:") +
300 GetAlternateProtocolFromParam() + "\r\n";
303 // Either |write_failure| specifies a write failure or |read_failure|
304 // specifies a read failure when using a reused socket. In either case, the
305 // failure should cause the network transaction to resend the request, and the
306 // other argument should be NULL.
307 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
308 const MockRead* read_failure);
310 // Either |write_failure| specifies a write failure or |read_failure|
311 // specifies a read failure when using a reused socket. In either case, the
312 // failure should cause the network transaction to resend the request, and the
313 // other argument should be NULL.
314 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
315 const MockRead* read_failure,
316 bool use_spdy);
318 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
319 size_t data_count) {
320 SimpleGetHelperResult out;
322 HttpRequestInfo request;
323 request.method = "GET";
324 request.url = GURL("http://www.example.org/");
325 request.load_flags = 0;
327 BoundTestNetLog log;
328 session_deps_.net_log = log.bound().net_log();
329 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
330 scoped_ptr<HttpTransaction> trans(
331 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
333 for (size_t i = 0; i < data_count; ++i) {
334 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
337 TestCompletionCallback callback;
339 EXPECT_TRUE(log.bound().IsCapturing());
340 int rv = trans->Start(&request, callback.callback(), log.bound());
341 EXPECT_EQ(ERR_IO_PENDING, rv);
343 out.rv = callback.WaitForResult();
345 // Even in the failure cases that use this function, connections are always
346 // successfully established before the error.
347 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
348 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
350 if (out.rv != OK)
351 return out;
353 const HttpResponseInfo* response = trans->GetResponseInfo();
354 // Can't use ASSERT_* inside helper functions like this, so
355 // return an error.
356 if (response == NULL || response->headers.get() == NULL) {
357 out.rv = ERR_UNEXPECTED;
358 return out;
360 out.status_line = response->headers->GetStatusLine();
362 EXPECT_EQ("127.0.0.1", response->socket_address.host());
363 EXPECT_EQ(80, response->socket_address.port());
365 rv = ReadTransaction(trans.get(), &out.response_data);
366 EXPECT_EQ(OK, rv);
368 TestNetLogEntry::List entries;
369 log.GetEntries(&entries);
370 size_t pos = ExpectLogContainsSomewhere(
371 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
372 NetLog::PHASE_NONE);
373 ExpectLogContainsSomewhere(
374 entries, pos,
375 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
376 NetLog::PHASE_NONE);
378 std::string line;
379 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
380 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
382 HttpRequestHeaders request_headers;
383 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
384 std::string value;
385 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
386 EXPECT_EQ("www.example.org", value);
387 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
388 EXPECT_EQ("keep-alive", value);
390 std::string response_headers;
391 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
392 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
393 response_headers);
395 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
396 trans->GetConnectionAttempts(&out.connection_attempts);
397 return out;
400 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
401 size_t reads_count) {
402 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
403 StaticSocketDataProvider* data[] = { &reads };
404 return SimpleGetHelperForData(data, 1);
407 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
408 int64 size = 0;
409 for (size_t i = 0; i < reads_count; ++i)
410 size += data_reads[i].data_len;
411 return size;
414 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
415 int expected_status);
417 void ConnectStatusHelper(const MockRead& status);
419 void BypassHostCacheOnRefreshHelper(int load_flags);
421 void CheckErrorIsPassedBack(int error, IoMode mode);
423 SpdyTestUtil spdy_util_;
424 SpdySessionDependencies session_deps_;
426 // Original socket limits. Some tests set these. Safest to always restore
427 // them once each test has been run.
428 int old_max_group_sockets_;
429 int old_max_pool_sockets_;
432 INSTANTIATE_TEST_CASE_P(NextProto,
433 HttpNetworkTransactionTest,
434 testing::Values(kProtoSPDY31,
435 kProtoHTTP2));
437 namespace {
439 class BeforeNetworkStartHandler {
440 public:
441 explicit BeforeNetworkStartHandler(bool defer)
442 : defer_on_before_network_start_(defer),
443 observed_before_network_start_(false) {}
445 void OnBeforeNetworkStart(bool* defer) {
446 *defer = defer_on_before_network_start_;
447 observed_before_network_start_ = true;
450 bool observed_before_network_start() const {
451 return observed_before_network_start_;
454 private:
455 const bool defer_on_before_network_start_;
456 bool observed_before_network_start_;
458 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
461 class BeforeProxyHeadersSentHandler {
462 public:
463 BeforeProxyHeadersSentHandler()
464 : observed_before_proxy_headers_sent_(false) {}
466 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
467 HttpRequestHeaders* request_headers) {
468 observed_before_proxy_headers_sent_ = true;
469 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
472 bool observed_before_proxy_headers_sent() const {
473 return observed_before_proxy_headers_sent_;
476 std::string observed_proxy_server_uri() const {
477 return observed_proxy_server_uri_;
480 private:
481 bool observed_before_proxy_headers_sent_;
482 std::string observed_proxy_server_uri_;
484 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
487 // Fill |str| with a long header list that consumes >= |size| bytes.
488 void FillLargeHeadersString(std::string* str, int size) {
489 const char row[] =
490 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
491 const int sizeof_row = strlen(row);
492 const int num_rows = static_cast<int>(
493 ceil(static_cast<float>(size) / sizeof_row));
494 const int sizeof_data = num_rows * sizeof_row;
495 DCHECK(sizeof_data >= size);
496 str->reserve(sizeof_data);
498 for (int i = 0; i < num_rows; ++i)
499 str->append(row, sizeof_row);
502 #if defined(NTLM_PORTABLE)
503 // Alternative functions that eliminate randomness and dependency on the local
504 // host name so that the generated NTLM messages are reproducible.
505 void MockGenerateRandom1(uint8* output, size_t n) {
506 static const uint8 bytes[] = {
507 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
509 static size_t current_byte = 0;
510 for (size_t i = 0; i < n; ++i) {
511 output[i] = bytes[current_byte++];
512 current_byte %= arraysize(bytes);
516 void MockGenerateRandom2(uint8* output, size_t n) {
517 static const uint8 bytes[] = {
518 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
519 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
521 static size_t current_byte = 0;
522 for (size_t i = 0; i < n; ++i) {
523 output[i] = bytes[current_byte++];
524 current_byte %= arraysize(bytes);
528 std::string MockGetHostName() {
529 return "WTC-WIN7";
531 #endif // defined(NTLM_PORTABLE)
533 template<typename ParentPool>
534 class CaptureGroupNameSocketPool : public ParentPool {
535 public:
536 CaptureGroupNameSocketPool(HostResolver* host_resolver,
537 CertVerifier* cert_verifier);
539 const std::string last_group_name_received() const {
540 return last_group_name_;
543 int RequestSocket(const std::string& group_name,
544 const void* socket_params,
545 RequestPriority priority,
546 ClientSocketHandle* handle,
547 const CompletionCallback& callback,
548 const BoundNetLog& net_log) override {
549 last_group_name_ = group_name;
550 return ERR_IO_PENDING;
552 void CancelRequest(const std::string& group_name,
553 ClientSocketHandle* handle) override {}
554 void ReleaseSocket(const std::string& group_name,
555 scoped_ptr<StreamSocket> socket,
556 int id) override {}
557 void CloseIdleSockets() override {}
558 int IdleSocketCount() const override { return 0; }
559 int IdleSocketCountInGroup(const std::string& group_name) const override {
560 return 0;
562 LoadState GetLoadState(const std::string& group_name,
563 const ClientSocketHandle* handle) const override {
564 return LOAD_STATE_IDLE;
566 base::TimeDelta ConnectionTimeout() const override {
567 return base::TimeDelta();
570 private:
571 std::string last_group_name_;
574 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
575 CaptureGroupNameTransportSocketPool;
576 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
577 CaptureGroupNameHttpProxySocketPool;
578 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
579 CaptureGroupNameSOCKSSocketPool;
580 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
581 CaptureGroupNameSSLSocketPool;
583 template <typename ParentPool>
584 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
585 HostResolver* host_resolver,
586 CertVerifier* /* cert_verifier */)
587 : ParentPool(0, 0, host_resolver, NULL, NULL) {
590 template <>
591 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
592 HostResolver* /* host_resolver */,
593 CertVerifier* /* cert_verifier */)
594 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
597 template <>
598 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
599 HostResolver* /* host_resolver */,
600 CertVerifier* cert_verifier)
601 : SSLClientSocketPool(0,
603 cert_verifier,
604 NULL,
605 NULL,
606 NULL,
607 NULL,
608 std::string(),
609 NULL,
610 NULL,
611 NULL,
612 NULL,
613 NULL,
614 NULL) {
617 //-----------------------------------------------------------------------------
619 // Helper functions for validating that AuthChallengeInfo's are correctly
620 // configured for common cases.
621 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
622 if (!auth_challenge)
623 return false;
624 EXPECT_FALSE(auth_challenge->is_proxy);
625 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
626 EXPECT_EQ("MyRealm1", auth_challenge->realm);
627 EXPECT_EQ("basic", auth_challenge->scheme);
628 return true;
631 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
632 if (!auth_challenge)
633 return false;
634 EXPECT_TRUE(auth_challenge->is_proxy);
635 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
636 EXPECT_EQ("MyRealm1", auth_challenge->realm);
637 EXPECT_EQ("basic", auth_challenge->scheme);
638 return true;
641 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
642 if (!auth_challenge)
643 return false;
644 EXPECT_FALSE(auth_challenge->is_proxy);
645 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
646 EXPECT_EQ("digestive", auth_challenge->realm);
647 EXPECT_EQ("digest", auth_challenge->scheme);
648 return true;
651 #if defined(NTLM_PORTABLE)
652 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
653 if (!auth_challenge)
654 return false;
655 EXPECT_FALSE(auth_challenge->is_proxy);
656 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
657 EXPECT_EQ(std::string(), auth_challenge->realm);
658 EXPECT_EQ("ntlm", auth_challenge->scheme);
659 return true;
661 #endif // defined(NTLM_PORTABLE)
663 } // namespace
665 TEST_P(HttpNetworkTransactionTest, Basic) {
666 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
667 scoped_ptr<HttpTransaction> trans(
668 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
671 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
672 MockRead data_reads[] = {
673 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
674 MockRead("hello world"),
675 MockRead(SYNCHRONOUS, OK),
677 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
678 arraysize(data_reads));
679 EXPECT_EQ(OK, out.rv);
680 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
681 EXPECT_EQ("hello world", out.response_data);
682 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
683 EXPECT_EQ(reads_size, out.totalReceivedBytes);
684 EXPECT_EQ(0u, out.connection_attempts.size());
687 // Response with no status line.
688 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
689 MockRead data_reads[] = {
690 MockRead("hello world"),
691 MockRead(SYNCHRONOUS, OK),
693 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
694 arraysize(data_reads));
695 EXPECT_EQ(OK, out.rv);
696 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
697 EXPECT_EQ("hello world", out.response_data);
698 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
699 EXPECT_EQ(reads_size, out.totalReceivedBytes);
702 // Allow up to 4 bytes of junk to precede status line.
703 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
704 MockRead data_reads[] = {
705 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
706 MockRead(SYNCHRONOUS, OK),
708 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
709 arraysize(data_reads));
710 EXPECT_EQ(OK, out.rv);
711 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
712 EXPECT_EQ("DATA", out.response_data);
713 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
714 EXPECT_EQ(reads_size, out.totalReceivedBytes);
717 // Allow up to 4 bytes of junk to precede status line.
718 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
719 MockRead data_reads[] = {
720 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
721 MockRead(SYNCHRONOUS, OK),
723 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
724 arraysize(data_reads));
725 EXPECT_EQ(OK, out.rv);
726 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
727 EXPECT_EQ("DATA", out.response_data);
728 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
729 EXPECT_EQ(reads_size, out.totalReceivedBytes);
732 // Beyond 4 bytes of slop and it should fail to find a status line.
733 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
734 MockRead data_reads[] = {
735 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
736 MockRead(SYNCHRONOUS, OK),
738 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
739 arraysize(data_reads));
740 EXPECT_EQ(OK, out.rv);
741 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
742 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
743 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
744 EXPECT_EQ(reads_size, out.totalReceivedBytes);
747 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
748 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
749 MockRead data_reads[] = {
750 MockRead("\n"),
751 MockRead("\n"),
752 MockRead("Q"),
753 MockRead("J"),
754 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
755 MockRead(SYNCHRONOUS, OK),
757 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
758 arraysize(data_reads));
759 EXPECT_EQ(OK, out.rv);
760 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
761 EXPECT_EQ("DATA", out.response_data);
762 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
763 EXPECT_EQ(reads_size, out.totalReceivedBytes);
766 // Close the connection before enough bytes to have a status line.
767 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
768 MockRead data_reads[] = {
769 MockRead("HTT"),
770 MockRead(SYNCHRONOUS, OK),
772 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
773 arraysize(data_reads));
774 EXPECT_EQ(OK, out.rv);
775 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
776 EXPECT_EQ("HTT", out.response_data);
777 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
778 EXPECT_EQ(reads_size, out.totalReceivedBytes);
781 // Simulate a 204 response, lacking a Content-Length header, sent over a
782 // persistent connection. The response should still terminate since a 204
783 // cannot have a response body.
784 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
785 char junk[] = "junk";
786 MockRead data_reads[] = {
787 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
788 MockRead(junk), // Should not be read!!
789 MockRead(SYNCHRONOUS, OK),
791 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
792 arraysize(data_reads));
793 EXPECT_EQ(OK, out.rv);
794 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
795 EXPECT_EQ("", out.response_data);
796 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
797 int64 response_size = reads_size - strlen(junk);
798 EXPECT_EQ(response_size, out.totalReceivedBytes);
801 // A simple request using chunked encoding with some extra data after.
802 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
803 std::string final_chunk = "0\r\n\r\n";
804 std::string extra_data = "HTTP/1.1 200 OK\r\n";
805 std::string last_read = final_chunk + extra_data;
806 MockRead data_reads[] = {
807 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
808 MockRead("5\r\nHello\r\n"),
809 MockRead("1\r\n"),
810 MockRead(" \r\n"),
811 MockRead("5\r\nworld\r\n"),
812 MockRead(last_read.data()),
813 MockRead(SYNCHRONOUS, OK),
815 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
816 arraysize(data_reads));
817 EXPECT_EQ(OK, out.rv);
818 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
819 EXPECT_EQ("Hello world", out.response_data);
820 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
821 int64 response_size = reads_size - extra_data.size();
822 EXPECT_EQ(response_size, out.totalReceivedBytes);
825 // Next tests deal with http://crbug.com/56344.
827 TEST_P(HttpNetworkTransactionTest,
828 MultipleContentLengthHeadersNoTransferEncoding) {
829 MockRead data_reads[] = {
830 MockRead("HTTP/1.1 200 OK\r\n"),
831 MockRead("Content-Length: 10\r\n"),
832 MockRead("Content-Length: 5\r\n\r\n"),
834 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
835 arraysize(data_reads));
836 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
839 TEST_P(HttpNetworkTransactionTest,
840 DuplicateContentLengthHeadersNoTransferEncoding) {
841 MockRead data_reads[] = {
842 MockRead("HTTP/1.1 200 OK\r\n"),
843 MockRead("Content-Length: 5\r\n"),
844 MockRead("Content-Length: 5\r\n\r\n"),
845 MockRead("Hello"),
847 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
848 arraysize(data_reads));
849 EXPECT_EQ(OK, out.rv);
850 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
851 EXPECT_EQ("Hello", out.response_data);
854 TEST_P(HttpNetworkTransactionTest,
855 ComplexContentLengthHeadersNoTransferEncoding) {
856 // More than 2 dupes.
858 MockRead data_reads[] = {
859 MockRead("HTTP/1.1 200 OK\r\n"),
860 MockRead("Content-Length: 5\r\n"),
861 MockRead("Content-Length: 5\r\n"),
862 MockRead("Content-Length: 5\r\n\r\n"),
863 MockRead("Hello"),
865 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
866 arraysize(data_reads));
867 EXPECT_EQ(OK, out.rv);
868 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
869 EXPECT_EQ("Hello", out.response_data);
871 // HTTP/1.0
873 MockRead data_reads[] = {
874 MockRead("HTTP/1.0 200 OK\r\n"),
875 MockRead("Content-Length: 5\r\n"),
876 MockRead("Content-Length: 5\r\n"),
877 MockRead("Content-Length: 5\r\n\r\n"),
878 MockRead("Hello"),
880 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
881 arraysize(data_reads));
882 EXPECT_EQ(OK, out.rv);
883 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
884 EXPECT_EQ("Hello", out.response_data);
886 // 2 dupes and one mismatched.
888 MockRead data_reads[] = {
889 MockRead("HTTP/1.1 200 OK\r\n"),
890 MockRead("Content-Length: 10\r\n"),
891 MockRead("Content-Length: 10\r\n"),
892 MockRead("Content-Length: 5\r\n\r\n"),
894 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
895 arraysize(data_reads));
896 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
900 TEST_P(HttpNetworkTransactionTest,
901 MultipleContentLengthHeadersTransferEncoding) {
902 MockRead data_reads[] = {
903 MockRead("HTTP/1.1 200 OK\r\n"),
904 MockRead("Content-Length: 666\r\n"),
905 MockRead("Content-Length: 1337\r\n"),
906 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
907 MockRead("5\r\nHello\r\n"),
908 MockRead("1\r\n"),
909 MockRead(" \r\n"),
910 MockRead("5\r\nworld\r\n"),
911 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
912 MockRead(SYNCHRONOUS, OK),
914 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
915 arraysize(data_reads));
916 EXPECT_EQ(OK, out.rv);
917 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
918 EXPECT_EQ("Hello world", out.response_data);
921 // Next tests deal with http://crbug.com/98895.
923 // Checks that a single Content-Disposition header results in no error.
924 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
925 MockRead data_reads[] = {
926 MockRead("HTTP/1.1 200 OK\r\n"),
927 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
928 MockRead("Content-Length: 5\r\n\r\n"),
929 MockRead("Hello"),
931 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
932 arraysize(data_reads));
933 EXPECT_EQ(OK, out.rv);
934 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
935 EXPECT_EQ("Hello", out.response_data);
938 // Checks that two identical Content-Disposition headers result in no error.
939 TEST_P(HttpNetworkTransactionTest,
940 TwoIdenticalContentDispositionHeaders) {
941 MockRead data_reads[] = {
942 MockRead("HTTP/1.1 200 OK\r\n"),
943 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
944 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
945 MockRead("Content-Length: 5\r\n\r\n"),
946 MockRead("Hello"),
948 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
949 arraysize(data_reads));
950 EXPECT_EQ(OK, out.rv);
951 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
952 EXPECT_EQ("Hello", out.response_data);
955 // Checks that two distinct Content-Disposition headers result in an error.
956 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
957 MockRead data_reads[] = {
958 MockRead("HTTP/1.1 200 OK\r\n"),
959 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
960 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
961 MockRead("Content-Length: 5\r\n\r\n"),
962 MockRead("Hello"),
964 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
965 arraysize(data_reads));
966 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
969 // Checks that two identical Location headers result in no error.
970 // Also tests Location header behavior.
971 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
972 MockRead data_reads[] = {
973 MockRead("HTTP/1.1 302 Redirect\r\n"),
974 MockRead("Location: http://good.com/\r\n"),
975 MockRead("Location: http://good.com/\r\n"),
976 MockRead("Content-Length: 0\r\n\r\n"),
977 MockRead(SYNCHRONOUS, OK),
980 HttpRequestInfo request;
981 request.method = "GET";
982 request.url = GURL("http://redirect.com/");
983 request.load_flags = 0;
985 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
986 scoped_ptr<HttpTransaction> trans(
987 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
989 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
990 session_deps_.socket_factory->AddSocketDataProvider(&data);
992 TestCompletionCallback callback;
994 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
995 EXPECT_EQ(ERR_IO_PENDING, rv);
997 EXPECT_EQ(OK, callback.WaitForResult());
999 const HttpResponseInfo* response = trans->GetResponseInfo();
1000 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
1001 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1002 std::string url;
1003 EXPECT_TRUE(response->headers->IsRedirect(&url));
1004 EXPECT_EQ("http://good.com/", url);
1005 EXPECT_TRUE(response->proxy_server.IsEmpty());
1008 // Checks that two distinct Location headers result in an error.
1009 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
1010 MockRead data_reads[] = {
1011 MockRead("HTTP/1.1 302 Redirect\r\n"),
1012 MockRead("Location: http://good.com/\r\n"),
1013 MockRead("Location: http://evil.com/\r\n"),
1014 MockRead("Content-Length: 0\r\n\r\n"),
1015 MockRead(SYNCHRONOUS, OK),
1017 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1018 arraysize(data_reads));
1019 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1022 // Do a request using the HEAD method. Verify that we don't try to read the
1023 // message body (since HEAD has none).
1024 TEST_P(HttpNetworkTransactionTest, Head) {
1025 HttpRequestInfo request;
1026 request.method = "HEAD";
1027 request.url = GURL("http://www.example.org/");
1028 request.load_flags = 0;
1030 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1031 scoped_ptr<HttpTransaction> trans(
1032 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1033 BeforeProxyHeadersSentHandler proxy_headers_handler;
1034 trans->SetBeforeProxyHeadersSentCallback(
1035 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1036 base::Unretained(&proxy_headers_handler)));
1038 MockWrite data_writes1[] = {
1039 MockWrite("HEAD / HTTP/1.1\r\n"
1040 "Host: www.example.org\r\n"
1041 "Connection: keep-alive\r\n\r\n"),
1043 MockRead data_reads1[] = {
1044 MockRead("HTTP/1.1 404 Not Found\r\n"),
1045 MockRead("Server: Blah\r\n"),
1046 MockRead("Content-Length: 1234\r\n\r\n"),
1048 // No response body because the test stops reading here.
1049 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1052 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1053 data_writes1, arraysize(data_writes1));
1054 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1056 TestCompletionCallback callback1;
1058 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1059 EXPECT_EQ(ERR_IO_PENDING, rv);
1061 rv = callback1.WaitForResult();
1062 EXPECT_EQ(OK, rv);
1064 const HttpResponseInfo* response = trans->GetResponseInfo();
1065 ASSERT_TRUE(response != NULL);
1067 // Check that the headers got parsed.
1068 EXPECT_TRUE(response->headers.get() != NULL);
1069 EXPECT_EQ(1234, response->headers->GetContentLength());
1070 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1071 EXPECT_TRUE(response->proxy_server.IsEmpty());
1072 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1074 std::string server_header;
1075 void* iter = NULL;
1076 bool has_server_header = response->headers->EnumerateHeader(
1077 &iter, "Server", &server_header);
1078 EXPECT_TRUE(has_server_header);
1079 EXPECT_EQ("Blah", server_header);
1081 // Reading should give EOF right away, since there is no message body
1082 // (despite non-zero content-length).
1083 std::string response_data;
1084 rv = ReadTransaction(trans.get(), &response_data);
1085 EXPECT_EQ(OK, rv);
1086 EXPECT_EQ("", response_data);
1089 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1090 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1092 MockRead data_reads[] = {
1093 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1094 MockRead("hello"),
1095 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1096 MockRead("world"),
1097 MockRead(SYNCHRONOUS, OK),
1099 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1100 session_deps_.socket_factory->AddSocketDataProvider(&data);
1102 const char* const kExpectedResponseData[] = {
1103 "hello", "world"
1106 for (int i = 0; i < 2; ++i) {
1107 HttpRequestInfo request;
1108 request.method = "GET";
1109 request.url = GURL("http://www.example.org/");
1110 request.load_flags = 0;
1112 scoped_ptr<HttpTransaction> trans(
1113 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1115 TestCompletionCallback callback;
1117 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1118 EXPECT_EQ(ERR_IO_PENDING, rv);
1120 rv = callback.WaitForResult();
1121 EXPECT_EQ(OK, rv);
1123 const HttpResponseInfo* response = trans->GetResponseInfo();
1124 ASSERT_TRUE(response != NULL);
1126 EXPECT_TRUE(response->headers.get() != NULL);
1127 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1128 EXPECT_TRUE(response->proxy_server.IsEmpty());
1130 std::string response_data;
1131 rv = ReadTransaction(trans.get(), &response_data);
1132 EXPECT_EQ(OK, rv);
1133 EXPECT_EQ(kExpectedResponseData[i], response_data);
1137 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1138 ScopedVector<UploadElementReader> element_readers;
1139 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1140 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
1142 HttpRequestInfo request;
1143 request.method = "POST";
1144 request.url = GURL("http://www.foo.com/");
1145 request.upload_data_stream = &upload_data_stream;
1146 request.load_flags = 0;
1148 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1149 scoped_ptr<HttpTransaction> trans(
1150 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1152 MockRead data_reads[] = {
1153 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1154 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1155 MockRead("hello world"),
1156 MockRead(SYNCHRONOUS, OK),
1158 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1159 session_deps_.socket_factory->AddSocketDataProvider(&data);
1161 TestCompletionCallback callback;
1163 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1164 EXPECT_EQ(ERR_IO_PENDING, rv);
1166 rv = callback.WaitForResult();
1167 EXPECT_EQ(OK, rv);
1169 const HttpResponseInfo* response = trans->GetResponseInfo();
1170 ASSERT_TRUE(response != NULL);
1172 EXPECT_TRUE(response->headers.get() != NULL);
1173 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1175 std::string response_data;
1176 rv = ReadTransaction(trans.get(), &response_data);
1177 EXPECT_EQ(OK, rv);
1178 EXPECT_EQ("hello world", response_data);
1181 // This test is almost the same as Ignores100 above, but the response contains
1182 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1183 // HTTP/1.1 and the two status headers are read in one read.
1184 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1185 HttpRequestInfo request;
1186 request.method = "GET";
1187 request.url = GURL("http://www.foo.com/");
1188 request.load_flags = 0;
1190 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1191 scoped_ptr<HttpTransaction> trans(
1192 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1194 MockRead data_reads[] = {
1195 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1196 "HTTP/1.1 200 OK\r\n\r\n"),
1197 MockRead("hello world"),
1198 MockRead(SYNCHRONOUS, OK),
1200 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1201 session_deps_.socket_factory->AddSocketDataProvider(&data);
1203 TestCompletionCallback callback;
1205 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1206 EXPECT_EQ(ERR_IO_PENDING, rv);
1208 rv = callback.WaitForResult();
1209 EXPECT_EQ(OK, rv);
1211 const HttpResponseInfo* response = trans->GetResponseInfo();
1212 ASSERT_TRUE(response != NULL);
1214 EXPECT_TRUE(response->headers.get() != NULL);
1215 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1217 std::string response_data;
1218 rv = ReadTransaction(trans.get(), &response_data);
1219 EXPECT_EQ(OK, rv);
1220 EXPECT_EQ("hello world", response_data);
1223 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1224 HttpRequestInfo request;
1225 request.method = "POST";
1226 request.url = GURL("http://www.foo.com/");
1227 request.load_flags = 0;
1229 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1230 scoped_ptr<HttpTransaction> trans(
1231 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1233 MockRead data_reads[] = {
1234 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1235 MockRead(ASYNC, 0),
1237 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1238 session_deps_.socket_factory->AddSocketDataProvider(&data);
1240 TestCompletionCallback callback;
1242 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1243 EXPECT_EQ(ERR_IO_PENDING, rv);
1245 rv = callback.WaitForResult();
1246 EXPECT_EQ(OK, rv);
1248 std::string response_data;
1249 rv = ReadTransaction(trans.get(), &response_data);
1250 EXPECT_EQ(OK, rv);
1251 EXPECT_EQ("", response_data);
1254 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1255 HttpRequestInfo request;
1256 request.method = "POST";
1257 request.url = GURL("http://www.foo.com/");
1258 request.load_flags = 0;
1260 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1261 scoped_ptr<HttpTransaction> trans(
1262 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1264 MockRead data_reads[] = {
1265 MockRead(ASYNC, 0),
1267 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1268 session_deps_.socket_factory->AddSocketDataProvider(&data);
1270 TestCompletionCallback callback;
1272 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1273 EXPECT_EQ(ERR_IO_PENDING, rv);
1275 rv = callback.WaitForResult();
1276 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1279 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1280 const MockWrite* write_failure,
1281 const MockRead* read_failure) {
1282 HttpRequestInfo request;
1283 request.method = "GET";
1284 request.url = GURL("http://www.foo.com/");
1285 request.load_flags = 0;
1287 TestNetLog net_log;
1288 session_deps_.net_log = &net_log;
1289 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1291 // Written data for successfully sending both requests.
1292 MockWrite data1_writes[] = {
1293 MockWrite("GET / HTTP/1.1\r\n"
1294 "Host: www.foo.com\r\n"
1295 "Connection: keep-alive\r\n\r\n"),
1296 MockWrite("GET / HTTP/1.1\r\n"
1297 "Host: www.foo.com\r\n"
1298 "Connection: keep-alive\r\n\r\n")
1301 // Read results for the first request.
1302 MockRead data1_reads[] = {
1303 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1304 MockRead("hello"),
1305 MockRead(ASYNC, OK),
1308 if (write_failure) {
1309 ASSERT_FALSE(read_failure);
1310 data1_writes[1] = *write_failure;
1311 } else {
1312 ASSERT_TRUE(read_failure);
1313 data1_reads[2] = *read_failure;
1316 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1317 data1_writes, arraysize(data1_writes));
1318 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1320 MockRead data2_reads[] = {
1321 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1322 MockRead("world"),
1323 MockRead(ASYNC, OK),
1325 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1326 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1328 const char* const kExpectedResponseData[] = {
1329 "hello", "world"
1332 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1333 for (int i = 0; i < 2; ++i) {
1334 TestCompletionCallback callback;
1336 scoped_ptr<HttpTransaction> trans(
1337 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1339 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1340 EXPECT_EQ(ERR_IO_PENDING, rv);
1342 rv = callback.WaitForResult();
1343 EXPECT_EQ(OK, rv);
1345 LoadTimingInfo load_timing_info;
1346 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1347 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1348 if (i == 0) {
1349 first_socket_log_id = load_timing_info.socket_log_id;
1350 } else {
1351 // The second request should be using a new socket.
1352 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1355 const HttpResponseInfo* response = trans->GetResponseInfo();
1356 ASSERT_TRUE(response != NULL);
1358 EXPECT_TRUE(response->headers.get() != NULL);
1359 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1361 std::string response_data;
1362 rv = ReadTransaction(trans.get(), &response_data);
1363 EXPECT_EQ(OK, rv);
1364 EXPECT_EQ(kExpectedResponseData[i], response_data);
1368 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1369 const MockWrite* write_failure,
1370 const MockRead* read_failure,
1371 bool use_spdy) {
1372 HttpRequestInfo request;
1373 request.method = "GET";
1374 request.url = GURL("https://www.foo.com/");
1375 request.load_flags = 0;
1377 TestNetLog net_log;
1378 session_deps_.net_log = &net_log;
1379 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1381 SSLSocketDataProvider ssl1(ASYNC, OK);
1382 SSLSocketDataProvider ssl2(ASYNC, OK);
1383 if (use_spdy) {
1384 ssl1.SetNextProto(GetParam());
1385 ssl2.SetNextProto(GetParam());
1387 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1388 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1390 // SPDY versions of the request and response.
1391 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1392 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1393 scoped_ptr<SpdyFrame> spdy_response(
1394 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1395 scoped_ptr<SpdyFrame> spdy_data(
1396 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1398 // HTTP/1.1 versions of the request and response.
1399 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1400 "Host: www.foo.com\r\n"
1401 "Connection: keep-alive\r\n\r\n";
1402 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1403 const char kHttpData[] = "hello";
1405 std::vector<MockRead> data1_reads;
1406 std::vector<MockWrite> data1_writes;
1407 if (write_failure) {
1408 ASSERT_FALSE(read_failure);
1409 data1_writes.push_back(*write_failure);
1410 data1_reads.push_back(MockRead(ASYNC, OK));
1411 } else {
1412 ASSERT_TRUE(read_failure);
1413 if (use_spdy) {
1414 data1_writes.push_back(CreateMockWrite(*spdy_request));
1415 } else {
1416 data1_writes.push_back(MockWrite(kHttpRequest));
1418 data1_reads.push_back(*read_failure);
1421 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1422 &data1_writes[0], data1_writes.size());
1423 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1425 std::vector<MockRead> data2_reads;
1426 std::vector<MockWrite> data2_writes;
1428 if (use_spdy) {
1429 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1431 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1432 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1433 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1434 } else {
1435 data2_writes.push_back(
1436 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1438 data2_reads.push_back(
1439 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1440 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1441 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1443 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1444 &data2_writes[0], data2_writes.size());
1445 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1447 // Preconnect a socket.
1448 SSLConfig ssl_config;
1449 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1450 session->GetNextProtos(&ssl_config.next_protos);
1451 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1452 ssl_config);
1453 // Wait for the preconnect to complete.
1454 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1455 base::RunLoop().RunUntilIdle();
1456 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1458 // Make the request.
1459 TestCompletionCallback callback;
1461 scoped_ptr<HttpTransaction> trans(
1462 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1464 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1465 EXPECT_EQ(ERR_IO_PENDING, rv);
1467 rv = callback.WaitForResult();
1468 EXPECT_EQ(OK, rv);
1470 LoadTimingInfo load_timing_info;
1471 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1472 TestLoadTimingNotReused(
1473 load_timing_info,
1474 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1476 const HttpResponseInfo* response = trans->GetResponseInfo();
1477 ASSERT_TRUE(response != NULL);
1479 EXPECT_TRUE(response->headers.get() != NULL);
1480 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1482 std::string response_data;
1483 rv = ReadTransaction(trans.get(), &response_data);
1484 EXPECT_EQ(OK, rv);
1485 EXPECT_EQ(kHttpData, response_data);
1488 TEST_P(HttpNetworkTransactionTest,
1489 KeepAliveConnectionNotConnectedOnWrite) {
1490 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1491 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1494 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1495 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1496 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1499 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1500 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1501 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1504 // Make sure that on a 408 response (Request Timeout), the request is retried,
1505 // if the socket was a reused keep alive socket.
1506 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1507 MockRead read_failure(SYNCHRONOUS,
1508 "HTTP/1.1 408 Request Timeout\r\n"
1509 "Connection: Keep-Alive\r\n"
1510 "Content-Length: 6\r\n\r\n"
1511 "Pickle");
1512 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1515 TEST_P(HttpNetworkTransactionTest,
1516 PreconnectErrorNotConnectedOnWrite) {
1517 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1518 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1521 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1522 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1523 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1526 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1527 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1528 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1531 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1532 MockRead read_failure(ASYNC, OK); // EOF
1533 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1536 // Make sure that on a 408 response (Request Timeout), the request is retried,
1537 // if the socket was a preconnected (UNUSED_IDLE) socket.
1538 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1539 MockRead read_failure(SYNCHRONOUS,
1540 "HTTP/1.1 408 Request Timeout\r\n"
1541 "Connection: Keep-Alive\r\n"
1542 "Content-Length: 6\r\n\r\n"
1543 "Pickle");
1544 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1545 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1548 TEST_P(HttpNetworkTransactionTest,
1549 SpdyPreconnectErrorNotConnectedOnWrite) {
1550 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1551 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1554 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1555 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1556 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1559 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1560 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1561 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1564 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1565 MockRead read_failure(ASYNC, OK); // EOF
1566 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1569 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1570 HttpRequestInfo request;
1571 request.method = "GET";
1572 request.url = GURL("http://www.example.org/");
1573 request.load_flags = 0;
1575 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1576 scoped_ptr<HttpTransaction> trans(
1577 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1579 MockRead data_reads[] = {
1580 MockRead(ASYNC, ERR_CONNECTION_RESET),
1581 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1582 MockRead("hello world"),
1583 MockRead(SYNCHRONOUS, OK),
1585 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1586 session_deps_.socket_factory->AddSocketDataProvider(&data);
1588 TestCompletionCallback callback;
1590 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1591 EXPECT_EQ(ERR_IO_PENDING, rv);
1593 rv = callback.WaitForResult();
1594 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1597 // What do various browsers do when the server closes a non-keepalive
1598 // connection without sending any response header or body?
1600 // IE7: error page
1601 // Safari 3.1.2 (Windows): error page
1602 // Firefox 3.0.1: blank page
1603 // Opera 9.52: after five attempts, blank page
1604 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1605 // Us: error page (EMPTY_RESPONSE)
1606 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1607 MockRead data_reads[] = {
1608 MockRead(SYNCHRONOUS, OK), // EOF
1609 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1610 MockRead("hello world"),
1611 MockRead(SYNCHRONOUS, OK),
1613 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1614 arraysize(data_reads));
1615 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1618 // Test that network access can be deferred and resumed.
1619 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1620 HttpRequestInfo request;
1621 request.method = "GET";
1622 request.url = GURL("http://www.example.org/");
1623 request.load_flags = 0;
1625 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1626 scoped_ptr<HttpTransaction> trans(
1627 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1629 // Defer on OnBeforeNetworkStart.
1630 BeforeNetworkStartHandler net_start_handler(true); // defer
1631 trans->SetBeforeNetworkStartCallback(
1632 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1633 base::Unretained(&net_start_handler)));
1635 MockRead data_reads[] = {
1636 MockRead("HTTP/1.0 200 OK\r\n"),
1637 MockRead("Content-Length: 5\r\n\r\n"),
1638 MockRead("hello"),
1639 MockRead(SYNCHRONOUS, 0),
1641 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1642 session_deps_.socket_factory->AddSocketDataProvider(&data);
1644 TestCompletionCallback callback;
1646 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1647 EXPECT_EQ(ERR_IO_PENDING, rv);
1648 base::MessageLoop::current()->RunUntilIdle();
1650 // Should have deferred for network start.
1651 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1652 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1654 trans->ResumeNetworkStart();
1655 rv = callback.WaitForResult();
1656 EXPECT_EQ(OK, rv);
1657 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1659 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1660 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1661 if (rv == ERR_IO_PENDING)
1662 rv = callback.WaitForResult();
1663 EXPECT_EQ(5, rv);
1664 trans.reset();
1667 // Test that network use can be deferred and canceled.
1668 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1669 HttpRequestInfo request;
1670 request.method = "GET";
1671 request.url = GURL("http://www.example.org/");
1672 request.load_flags = 0;
1674 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1675 scoped_ptr<HttpTransaction> trans(
1676 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1678 // Defer on OnBeforeNetworkStart.
1679 BeforeNetworkStartHandler net_start_handler(true); // defer
1680 trans->SetBeforeNetworkStartCallback(
1681 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1682 base::Unretained(&net_start_handler)));
1684 TestCompletionCallback callback;
1686 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1687 EXPECT_EQ(ERR_IO_PENDING, rv);
1688 base::MessageLoop::current()->RunUntilIdle();
1690 // Should have deferred for network start.
1691 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1692 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1695 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1696 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1697 // destructor in such situations.
1698 // See http://crbug.com/154712 and http://crbug.com/156609.
1699 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1700 HttpRequestInfo request;
1701 request.method = "GET";
1702 request.url = GURL("http://www.example.org/");
1703 request.load_flags = 0;
1705 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1706 scoped_ptr<HttpTransaction> trans(
1707 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1709 MockRead data_reads[] = {
1710 MockRead("HTTP/1.0 200 OK\r\n"),
1711 MockRead("Connection: keep-alive\r\n"),
1712 MockRead("Content-Length: 100\r\n\r\n"),
1713 MockRead("hello"),
1714 MockRead(SYNCHRONOUS, 0),
1716 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1717 session_deps_.socket_factory->AddSocketDataProvider(&data);
1719 TestCompletionCallback callback;
1721 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1722 EXPECT_EQ(ERR_IO_PENDING, rv);
1724 rv = callback.WaitForResult();
1725 EXPECT_EQ(OK, rv);
1727 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1728 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1729 if (rv == ERR_IO_PENDING)
1730 rv = callback.WaitForResult();
1731 EXPECT_EQ(5, rv);
1732 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1733 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1735 trans.reset();
1736 base::MessageLoop::current()->RunUntilIdle();
1737 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1740 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1741 HttpRequestInfo request;
1742 request.method = "GET";
1743 request.url = GURL("http://www.example.org/");
1744 request.load_flags = 0;
1746 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1747 scoped_ptr<HttpTransaction> trans(
1748 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1750 MockRead data_reads[] = {
1751 MockRead("HTTP/1.0 200 OK\r\n"),
1752 MockRead("Connection: keep-alive\r\n"),
1753 MockRead("Content-Length: 100\r\n\r\n"),
1754 MockRead(SYNCHRONOUS, 0),
1756 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1757 session_deps_.socket_factory->AddSocketDataProvider(&data);
1759 TestCompletionCallback callback;
1761 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1762 EXPECT_EQ(ERR_IO_PENDING, rv);
1764 rv = callback.WaitForResult();
1765 EXPECT_EQ(OK, rv);
1767 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1768 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1769 if (rv == ERR_IO_PENDING)
1770 rv = callback.WaitForResult();
1771 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1773 trans.reset();
1774 base::MessageLoop::current()->RunUntilIdle();
1775 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1778 // Test that we correctly reuse a keep-alive connection after not explicitly
1779 // reading the body.
1780 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1781 HttpRequestInfo request;
1782 request.method = "GET";
1783 request.url = GURL("http://www.foo.com/");
1784 request.load_flags = 0;
1786 TestNetLog net_log;
1787 session_deps_.net_log = &net_log;
1788 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1790 // Note that because all these reads happen in the same
1791 // StaticSocketDataProvider, it shows that the same socket is being reused for
1792 // all transactions.
1793 MockRead data1_reads[] = {
1794 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1795 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1796 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1797 MockRead("HTTP/1.1 302 Found\r\n"
1798 "Content-Length: 0\r\n\r\n"),
1799 MockRead("HTTP/1.1 302 Found\r\n"
1800 "Content-Length: 5\r\n\r\n"
1801 "hello"),
1802 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1803 "Content-Length: 0\r\n\r\n"),
1804 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1805 "Content-Length: 5\r\n\r\n"
1806 "hello"),
1807 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1808 MockRead("hello"),
1810 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1811 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1813 MockRead data2_reads[] = {
1814 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1816 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1817 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1819 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1820 std::string response_lines[kNumUnreadBodies];
1822 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1823 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1824 TestCompletionCallback callback;
1826 scoped_ptr<HttpTransaction> trans(
1827 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1829 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1830 EXPECT_EQ(ERR_IO_PENDING, rv);
1832 rv = callback.WaitForResult();
1833 EXPECT_EQ(OK, rv);
1835 LoadTimingInfo load_timing_info;
1836 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1837 if (i == 0) {
1838 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1839 first_socket_log_id = load_timing_info.socket_log_id;
1840 } else {
1841 TestLoadTimingReused(load_timing_info);
1842 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1845 const HttpResponseInfo* response = trans->GetResponseInfo();
1846 ASSERT_TRUE(response != NULL);
1848 ASSERT_TRUE(response->headers.get() != NULL);
1849 response_lines[i] = response->headers->GetStatusLine();
1851 // We intentionally don't read the response bodies.
1854 const char* const kStatusLines[] = {
1855 "HTTP/1.1 204 No Content",
1856 "HTTP/1.1 205 Reset Content",
1857 "HTTP/1.1 304 Not Modified",
1858 "HTTP/1.1 302 Found",
1859 "HTTP/1.1 302 Found",
1860 "HTTP/1.1 301 Moved Permanently",
1861 "HTTP/1.1 301 Moved Permanently",
1864 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1865 "forgot to update kStatusLines");
1867 for (int i = 0; i < kNumUnreadBodies; ++i)
1868 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1870 TestCompletionCallback callback;
1871 scoped_ptr<HttpTransaction> trans(
1872 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1873 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1874 EXPECT_EQ(ERR_IO_PENDING, rv);
1875 rv = callback.WaitForResult();
1876 EXPECT_EQ(OK, rv);
1877 const HttpResponseInfo* response = trans->GetResponseInfo();
1878 ASSERT_TRUE(response != NULL);
1879 ASSERT_TRUE(response->headers.get() != NULL);
1880 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1881 std::string response_data;
1882 rv = ReadTransaction(trans.get(), &response_data);
1883 EXPECT_EQ(OK, rv);
1884 EXPECT_EQ("hello", response_data);
1887 // Test the request-challenge-retry sequence for basic auth.
1888 // (basic auth is the easiest to mock, because it has no randomness).
1889 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1890 HttpRequestInfo request;
1891 request.method = "GET";
1892 request.url = GURL("http://www.example.org/");
1893 request.load_flags = 0;
1895 TestNetLog log;
1896 session_deps_.net_log = &log;
1897 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1898 scoped_ptr<HttpTransaction> trans(
1899 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1901 MockWrite data_writes1[] = {
1902 MockWrite(
1903 "GET / HTTP/1.1\r\n"
1904 "Host: www.example.org\r\n"
1905 "Connection: keep-alive\r\n\r\n"),
1908 MockRead data_reads1[] = {
1909 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1910 // Give a couple authenticate options (only the middle one is actually
1911 // supported).
1912 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1913 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1914 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1915 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1916 // Large content-length -- won't matter, as connection will be reset.
1917 MockRead("Content-Length: 10000\r\n\r\n"),
1918 MockRead(SYNCHRONOUS, ERR_FAILED),
1921 // After calling trans->RestartWithAuth(), this is the request we should
1922 // be issuing -- the final header line contains the credentials.
1923 MockWrite data_writes2[] = {
1924 MockWrite(
1925 "GET / HTTP/1.1\r\n"
1926 "Host: www.example.org\r\n"
1927 "Connection: keep-alive\r\n"
1928 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1931 // Lastly, the server responds with the actual content.
1932 MockRead data_reads2[] = {
1933 MockRead("HTTP/1.0 200 OK\r\n"),
1934 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1935 MockRead("Content-Length: 100\r\n\r\n"),
1936 MockRead(SYNCHRONOUS, OK),
1939 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1940 data_writes1, arraysize(data_writes1));
1941 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1942 data_writes2, arraysize(data_writes2));
1943 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1944 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1946 TestCompletionCallback callback1;
1948 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1949 EXPECT_EQ(ERR_IO_PENDING, rv);
1951 rv = callback1.WaitForResult();
1952 EXPECT_EQ(OK, rv);
1954 LoadTimingInfo load_timing_info1;
1955 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1956 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1958 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1959 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1961 const HttpResponseInfo* response = trans->GetResponseInfo();
1962 ASSERT_TRUE(response != NULL);
1963 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1965 TestCompletionCallback callback2;
1967 rv = trans->RestartWithAuth(
1968 AuthCredentials(kFoo, kBar), callback2.callback());
1969 EXPECT_EQ(ERR_IO_PENDING, rv);
1971 rv = callback2.WaitForResult();
1972 EXPECT_EQ(OK, rv);
1974 LoadTimingInfo load_timing_info2;
1975 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1976 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1977 // The load timing after restart should have a new socket ID, and times after
1978 // those of the first load timing.
1979 EXPECT_LE(load_timing_info1.receive_headers_end,
1980 load_timing_info2.connect_timing.connect_start);
1981 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1983 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1984 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1986 response = trans->GetResponseInfo();
1987 ASSERT_TRUE(response != NULL);
1988 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1989 EXPECT_EQ(100, response->headers->GetContentLength());
1992 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1993 HttpRequestInfo request;
1994 request.method = "GET";
1995 request.url = GURL("http://www.example.org/");
1996 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
1998 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1999 scoped_ptr<HttpTransaction> trans(
2000 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2002 MockWrite data_writes[] = {
2003 MockWrite(
2004 "GET / HTTP/1.1\r\n"
2005 "Host: www.example.org\r\n"
2006 "Connection: keep-alive\r\n\r\n"),
2009 MockRead data_reads[] = {
2010 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2011 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2012 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2013 // Large content-length -- won't matter, as connection will be reset.
2014 MockRead("Content-Length: 10000\r\n\r\n"),
2015 MockRead(SYNCHRONOUS, ERR_FAILED),
2018 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2019 data_writes, arraysize(data_writes));
2020 session_deps_.socket_factory->AddSocketDataProvider(&data);
2021 TestCompletionCallback callback;
2023 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2024 EXPECT_EQ(ERR_IO_PENDING, rv);
2026 rv = callback.WaitForResult();
2027 EXPECT_EQ(0, rv);
2029 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2030 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2032 const HttpResponseInfo* response = trans->GetResponseInfo();
2033 ASSERT_TRUE(response != NULL);
2034 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2037 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2038 // connection.
2039 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2040 HttpRequestInfo request;
2041 request.method = "GET";
2042 request.url = GURL("http://www.example.org/");
2043 request.load_flags = 0;
2045 TestNetLog log;
2046 session_deps_.net_log = &log;
2047 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2049 MockWrite data_writes1[] = {
2050 MockWrite(
2051 "GET / HTTP/1.1\r\n"
2052 "Host: www.example.org\r\n"
2053 "Connection: keep-alive\r\n\r\n"),
2055 // After calling trans->RestartWithAuth(), this is the request we should
2056 // be issuing -- the final header line contains the credentials.
2057 MockWrite(
2058 "GET / HTTP/1.1\r\n"
2059 "Host: www.example.org\r\n"
2060 "Connection: keep-alive\r\n"
2061 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2064 MockRead data_reads1[] = {
2065 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2066 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2067 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2068 MockRead("Content-Length: 14\r\n\r\n"),
2069 MockRead("Unauthorized\r\n"),
2071 // Lastly, the server responds with the actual content.
2072 MockRead("HTTP/1.1 200 OK\r\n"),
2073 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2074 MockRead("Content-Length: 5\r\n\r\n"),
2075 MockRead("Hello"),
2078 // If there is a regression where we disconnect a Keep-Alive
2079 // connection during an auth roundtrip, we'll end up reading this.
2080 MockRead data_reads2[] = {
2081 MockRead(SYNCHRONOUS, ERR_FAILED),
2084 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2085 data_writes1, arraysize(data_writes1));
2086 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2087 NULL, 0);
2088 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2089 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2091 TestCompletionCallback callback1;
2093 scoped_ptr<HttpTransaction> trans(
2094 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2095 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2096 EXPECT_EQ(ERR_IO_PENDING, rv);
2098 rv = callback1.WaitForResult();
2099 EXPECT_EQ(OK, rv);
2101 LoadTimingInfo load_timing_info1;
2102 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2103 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2105 const HttpResponseInfo* response = trans->GetResponseInfo();
2106 ASSERT_TRUE(response != NULL);
2107 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2109 TestCompletionCallback callback2;
2111 rv = trans->RestartWithAuth(
2112 AuthCredentials(kFoo, kBar), callback2.callback());
2113 EXPECT_EQ(ERR_IO_PENDING, rv);
2115 rv = callback2.WaitForResult();
2116 EXPECT_EQ(OK, rv);
2118 LoadTimingInfo load_timing_info2;
2119 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2120 TestLoadTimingReused(load_timing_info2);
2121 // The load timing after restart should have the same socket ID, and times
2122 // those of the first load timing.
2123 EXPECT_LE(load_timing_info1.receive_headers_end,
2124 load_timing_info2.send_start);
2125 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2127 response = trans->GetResponseInfo();
2128 ASSERT_TRUE(response != NULL);
2129 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2130 EXPECT_EQ(5, response->headers->GetContentLength());
2132 std::string response_data;
2133 rv = ReadTransaction(trans.get(), &response_data);
2134 EXPECT_EQ(OK, rv);
2135 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2136 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2139 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2140 // connection and with no response body to drain.
2141 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2142 HttpRequestInfo request;
2143 request.method = "GET";
2144 request.url = GURL("http://www.example.org/");
2145 request.load_flags = 0;
2147 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2149 MockWrite data_writes1[] = {
2150 MockWrite(
2151 "GET / HTTP/1.1\r\n"
2152 "Host: www.example.org\r\n"
2153 "Connection: keep-alive\r\n\r\n"),
2155 // After calling trans->RestartWithAuth(), this is the request we should
2156 // be issuing -- the final header line contains the credentials.
2157 MockWrite(
2158 "GET / HTTP/1.1\r\n"
2159 "Host: www.example.org\r\n"
2160 "Connection: keep-alive\r\n"
2161 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2164 MockRead data_reads1[] = {
2165 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2166 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2167 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2169 // Lastly, the server responds with the actual content.
2170 MockRead("HTTP/1.1 200 OK\r\n"),
2171 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2172 MockRead("Content-Length: 5\r\n\r\n"),
2173 MockRead("hello"),
2176 // An incorrect reconnect would cause this to be read.
2177 MockRead data_reads2[] = {
2178 MockRead(SYNCHRONOUS, ERR_FAILED),
2181 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2182 data_writes1, arraysize(data_writes1));
2183 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2184 NULL, 0);
2185 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2186 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2188 TestCompletionCallback callback1;
2190 scoped_ptr<HttpTransaction> trans(
2191 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2192 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2193 EXPECT_EQ(ERR_IO_PENDING, rv);
2195 rv = callback1.WaitForResult();
2196 EXPECT_EQ(OK, rv);
2198 const HttpResponseInfo* response = trans->GetResponseInfo();
2199 ASSERT_TRUE(response != NULL);
2200 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2202 TestCompletionCallback callback2;
2204 rv = trans->RestartWithAuth(
2205 AuthCredentials(kFoo, kBar), callback2.callback());
2206 EXPECT_EQ(ERR_IO_PENDING, rv);
2208 rv = callback2.WaitForResult();
2209 EXPECT_EQ(OK, rv);
2211 response = trans->GetResponseInfo();
2212 ASSERT_TRUE(response != NULL);
2213 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2214 EXPECT_EQ(5, response->headers->GetContentLength());
2217 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2218 // connection and with a large response body to drain.
2219 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2220 HttpRequestInfo request;
2221 request.method = "GET";
2222 request.url = GURL("http://www.example.org/");
2223 request.load_flags = 0;
2225 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2227 MockWrite data_writes1[] = {
2228 MockWrite(
2229 "GET / HTTP/1.1\r\n"
2230 "Host: www.example.org\r\n"
2231 "Connection: keep-alive\r\n\r\n"),
2233 // After calling trans->RestartWithAuth(), this is the request we should
2234 // be issuing -- the final header line contains the credentials.
2235 MockWrite(
2236 "GET / HTTP/1.1\r\n"
2237 "Host: www.example.org\r\n"
2238 "Connection: keep-alive\r\n"
2239 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2242 // Respond with 5 kb of response body.
2243 std::string large_body_string("Unauthorized");
2244 large_body_string.append(5 * 1024, ' ');
2245 large_body_string.append("\r\n");
2247 MockRead data_reads1[] = {
2248 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2249 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2251 // 5134 = 12 + 5 * 1024 + 2
2252 MockRead("Content-Length: 5134\r\n\r\n"),
2253 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2255 // Lastly, the server responds with the actual content.
2256 MockRead("HTTP/1.1 200 OK\r\n"),
2257 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2258 MockRead("Content-Length: 5\r\n\r\n"),
2259 MockRead("hello"),
2262 // An incorrect reconnect would cause this to be read.
2263 MockRead data_reads2[] = {
2264 MockRead(SYNCHRONOUS, ERR_FAILED),
2267 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2268 data_writes1, arraysize(data_writes1));
2269 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2270 NULL, 0);
2271 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2272 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2274 TestCompletionCallback callback1;
2276 scoped_ptr<HttpTransaction> trans(
2277 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2278 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2279 EXPECT_EQ(ERR_IO_PENDING, rv);
2281 rv = callback1.WaitForResult();
2282 EXPECT_EQ(OK, rv);
2284 const HttpResponseInfo* response = trans->GetResponseInfo();
2285 ASSERT_TRUE(response != NULL);
2286 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2288 TestCompletionCallback callback2;
2290 rv = trans->RestartWithAuth(
2291 AuthCredentials(kFoo, kBar), callback2.callback());
2292 EXPECT_EQ(ERR_IO_PENDING, rv);
2294 rv = callback2.WaitForResult();
2295 EXPECT_EQ(OK, rv);
2297 response = trans->GetResponseInfo();
2298 ASSERT_TRUE(response != NULL);
2299 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2300 EXPECT_EQ(5, response->headers->GetContentLength());
2303 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2304 // connection, but the server gets impatient and closes the connection.
2305 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2306 HttpRequestInfo request;
2307 request.method = "GET";
2308 request.url = GURL("http://www.example.org/");
2309 request.load_flags = 0;
2311 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2313 MockWrite data_writes1[] = {
2314 MockWrite(
2315 "GET / HTTP/1.1\r\n"
2316 "Host: www.example.org\r\n"
2317 "Connection: keep-alive\r\n\r\n"),
2318 // This simulates the seemingly successful write to a closed connection
2319 // if the bug is not fixed.
2320 MockWrite(
2321 "GET / HTTP/1.1\r\n"
2322 "Host: www.example.org\r\n"
2323 "Connection: keep-alive\r\n"
2324 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2327 MockRead data_reads1[] = {
2328 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2329 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2330 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2331 MockRead("Content-Length: 14\r\n\r\n"),
2332 // Tell MockTCPClientSocket to simulate the server closing the connection.
2333 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2334 MockRead("Unauthorized\r\n"),
2335 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2338 // After calling trans->RestartWithAuth(), this is the request we should
2339 // be issuing -- the final header line contains the credentials.
2340 MockWrite data_writes2[] = {
2341 MockWrite(
2342 "GET / HTTP/1.1\r\n"
2343 "Host: www.example.org\r\n"
2344 "Connection: keep-alive\r\n"
2345 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2348 // Lastly, the server responds with the actual content.
2349 MockRead data_reads2[] = {
2350 MockRead("HTTP/1.1 200 OK\r\n"),
2351 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2352 MockRead("Content-Length: 5\r\n\r\n"),
2353 MockRead("hello"),
2356 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2357 data_writes1, arraysize(data_writes1));
2358 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2359 data_writes2, arraysize(data_writes2));
2360 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2361 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2363 TestCompletionCallback callback1;
2365 scoped_ptr<HttpTransaction> trans(
2366 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2367 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2368 EXPECT_EQ(ERR_IO_PENDING, rv);
2370 rv = callback1.WaitForResult();
2371 EXPECT_EQ(OK, rv);
2373 const HttpResponseInfo* response = trans->GetResponseInfo();
2374 ASSERT_TRUE(response != NULL);
2375 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2377 TestCompletionCallback callback2;
2379 rv = trans->RestartWithAuth(
2380 AuthCredentials(kFoo, kBar), callback2.callback());
2381 EXPECT_EQ(ERR_IO_PENDING, rv);
2383 rv = callback2.WaitForResult();
2384 EXPECT_EQ(OK, rv);
2386 response = trans->GetResponseInfo();
2387 ASSERT_TRUE(response != NULL);
2388 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2389 EXPECT_EQ(5, response->headers->GetContentLength());
2392 // Test the request-challenge-retry sequence for basic auth, over a connection
2393 // that requires a restart when setting up an SSL tunnel.
2394 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2395 HttpRequestInfo request;
2396 request.method = "GET";
2397 request.url = GURL("https://www.example.org/");
2398 // when the no authentication data flag is set.
2399 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2401 // Configure against proxy server "myproxy:70".
2402 session_deps_.proxy_service.reset(
2403 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2404 BoundTestNetLog log;
2405 session_deps_.net_log = log.bound().net_log();
2406 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2408 // Since we have proxy, should try to establish tunnel.
2409 MockWrite data_writes1[] = {
2410 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2411 "Host: www.example.org\r\n"
2412 "Proxy-Connection: keep-alive\r\n\r\n"),
2415 // The proxy responds to the connect with a 407, using a non-persistent
2416 // connection.
2417 MockRead data_reads1[] = {
2418 // No credentials.
2419 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2420 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2423 // Since the first connection couldn't be reused, need to establish another
2424 // once given credentials.
2425 MockWrite data_writes2[] = {
2426 // After calling trans->RestartWithAuth(), this is the request we should
2427 // be issuing -- the final header line contains the credentials.
2428 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2429 "Host: www.example.org\r\n"
2430 "Proxy-Connection: keep-alive\r\n"
2431 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2433 MockWrite("GET / HTTP/1.1\r\n"
2434 "Host: www.example.org\r\n"
2435 "Connection: keep-alive\r\n\r\n"),
2438 MockRead data_reads2[] = {
2439 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2441 MockRead("HTTP/1.1 200 OK\r\n"),
2442 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2443 MockRead("Content-Length: 5\r\n\r\n"),
2444 MockRead(SYNCHRONOUS, "hello"),
2447 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2448 data_writes1, arraysize(data_writes1));
2449 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2450 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2451 data_writes2, arraysize(data_writes2));
2452 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2453 SSLSocketDataProvider ssl(ASYNC, OK);
2454 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2456 TestCompletionCallback callback1;
2458 scoped_ptr<HttpTransaction> trans(
2459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2461 int rv = trans->Start(&request, callback1.callback(), log.bound());
2462 EXPECT_EQ(ERR_IO_PENDING, rv);
2464 rv = callback1.WaitForResult();
2465 EXPECT_EQ(OK, rv);
2466 TestNetLogEntry::List entries;
2467 log.GetEntries(&entries);
2468 size_t pos = ExpectLogContainsSomewhere(
2469 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2470 NetLog::PHASE_NONE);
2471 ExpectLogContainsSomewhere(
2472 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2473 NetLog::PHASE_NONE);
2475 const HttpResponseInfo* response = trans->GetResponseInfo();
2476 ASSERT_TRUE(response != NULL);
2477 EXPECT_FALSE(response->headers->IsKeepAlive());
2478 ASSERT_FALSE(response->headers.get() == NULL);
2479 EXPECT_EQ(407, response->headers->response_code());
2480 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2481 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2483 LoadTimingInfo load_timing_info;
2484 // CONNECT requests and responses are handled at the connect job level, so
2485 // the transaction does not yet have a connection.
2486 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2488 TestCompletionCallback callback2;
2490 rv =
2491 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2492 EXPECT_EQ(ERR_IO_PENDING, rv);
2494 rv = callback2.WaitForResult();
2495 EXPECT_EQ(OK, rv);
2497 response = trans->GetResponseInfo();
2498 ASSERT_TRUE(response != NULL);
2500 EXPECT_TRUE(response->headers->IsKeepAlive());
2501 EXPECT_EQ(200, response->headers->response_code());
2502 EXPECT_EQ(5, response->headers->GetContentLength());
2503 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2505 // The password prompt info should not be set.
2506 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2508 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2509 TestLoadTimingNotReusedWithPac(load_timing_info,
2510 CONNECT_TIMING_HAS_SSL_TIMES);
2512 trans.reset();
2513 session->CloseAllConnections();
2516 // Test the request-challenge-retry sequence for basic auth, over a connection
2517 // that requires a restart when setting up an SSL tunnel.
2518 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
2519 HttpRequestInfo request;
2520 request.method = "GET";
2521 request.url = GURL("https://www.example.org/");
2522 // when the no authentication data flag is set.
2523 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2525 // Configure against proxy server "myproxy:70".
2526 session_deps_.proxy_service.reset(
2527 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2528 BoundTestNetLog log;
2529 session_deps_.net_log = log.bound().net_log();
2530 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2532 // Since we have proxy, should try to establish tunnel.
2533 MockWrite data_writes1[] = {
2534 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2535 "Host: www.example.org\r\n"
2536 "Proxy-Connection: keep-alive\r\n\r\n"),
2539 // The proxy responds to the connect with a 407, using a non-persistent
2540 // connection.
2541 MockRead data_reads1[] = {
2542 // No credentials.
2543 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2544 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2545 MockRead("Proxy-Connection: close\r\n\r\n"),
2548 MockWrite data_writes2[] = {
2549 // After calling trans->RestartWithAuth(), this is the request we should
2550 // be issuing -- the final header line contains the credentials.
2551 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2552 "Host: www.example.org\r\n"
2553 "Proxy-Connection: keep-alive\r\n"
2554 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2556 MockWrite("GET / HTTP/1.1\r\n"
2557 "Host: www.example.org\r\n"
2558 "Connection: keep-alive\r\n\r\n"),
2561 MockRead data_reads2[] = {
2562 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2564 MockRead("HTTP/1.1 200 OK\r\n"),
2565 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2566 MockRead("Content-Length: 5\r\n\r\n"),
2567 MockRead(SYNCHRONOUS, "hello"),
2570 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2571 data_writes1, arraysize(data_writes1));
2572 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2573 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2574 data_writes2, arraysize(data_writes2));
2575 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2576 SSLSocketDataProvider ssl(ASYNC, OK);
2577 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2579 TestCompletionCallback callback1;
2581 scoped_ptr<HttpTransaction> trans(
2582 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2584 int rv = trans->Start(&request, callback1.callback(), log.bound());
2585 EXPECT_EQ(ERR_IO_PENDING, rv);
2587 rv = callback1.WaitForResult();
2588 EXPECT_EQ(OK, rv);
2589 TestNetLogEntry::List entries;
2590 log.GetEntries(&entries);
2591 size_t pos = ExpectLogContainsSomewhere(
2592 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2593 NetLog::PHASE_NONE);
2594 ExpectLogContainsSomewhere(
2595 entries, pos,
2596 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2597 NetLog::PHASE_NONE);
2599 const HttpResponseInfo* response = trans->GetResponseInfo();
2600 ASSERT_TRUE(response != NULL);
2601 EXPECT_FALSE(response->headers->IsKeepAlive());
2602 ASSERT_FALSE(response->headers.get() == NULL);
2603 EXPECT_EQ(407, response->headers->response_code());
2604 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2605 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2607 LoadTimingInfo load_timing_info;
2608 // CONNECT requests and responses are handled at the connect job level, so
2609 // the transaction does not yet have a connection.
2610 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2612 TestCompletionCallback callback2;
2614 rv = trans->RestartWithAuth(
2615 AuthCredentials(kFoo, kBar), callback2.callback());
2616 EXPECT_EQ(ERR_IO_PENDING, rv);
2618 rv = callback2.WaitForResult();
2619 EXPECT_EQ(OK, rv);
2621 response = trans->GetResponseInfo();
2622 ASSERT_TRUE(response != NULL);
2624 EXPECT_TRUE(response->headers->IsKeepAlive());
2625 EXPECT_EQ(200, response->headers->response_code());
2626 EXPECT_EQ(5, response->headers->GetContentLength());
2627 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2629 // The password prompt info should not be set.
2630 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2632 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2633 TestLoadTimingNotReusedWithPac(load_timing_info,
2634 CONNECT_TIMING_HAS_SSL_TIMES);
2636 trans.reset();
2637 session->CloseAllConnections();
2640 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2641 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2642 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2643 HttpRequestInfo request;
2644 request.method = "GET";
2645 request.url = GURL("https://www.example.org/");
2646 // Ensure that proxy authentication is attempted even
2647 // when the no authentication data flag is set.
2648 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2650 // Configure against proxy server "myproxy:70".
2651 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2652 BoundTestNetLog log;
2653 session_deps_.net_log = log.bound().net_log();
2654 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2656 scoped_ptr<HttpTransaction> trans(
2657 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2659 // Since we have proxy, should try to establish tunnel.
2660 MockWrite data_writes1[] = {
2661 MockWrite(
2662 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2663 "Host: www.example.org\r\n"
2664 "Proxy-Connection: keep-alive\r\n\r\n"),
2666 // After calling trans->RestartWithAuth(), this is the request we should
2667 // be issuing -- the final header line contains the credentials.
2668 MockWrite(
2669 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2670 "Host: www.example.org\r\n"
2671 "Proxy-Connection: keep-alive\r\n"
2672 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2675 // The proxy responds to the connect with a 407, using a persistent
2676 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2677 MockRead data_reads1[] = {
2678 // No credentials.
2679 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2680 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2681 MockRead("Proxy-Connection: keep-alive\r\n"),
2682 MockRead("Content-Length: 10\r\n\r\n"),
2683 MockRead("0123456789"),
2685 // Wrong credentials (wrong password).
2686 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2687 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2688 MockRead("Proxy-Connection: keep-alive\r\n"),
2689 MockRead("Content-Length: 10\r\n\r\n"),
2690 // No response body because the test stops reading here.
2691 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2694 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2695 data_writes1, arraysize(data_writes1));
2696 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2698 TestCompletionCallback callback1;
2700 int rv = trans->Start(&request, callback1.callback(), log.bound());
2701 EXPECT_EQ(ERR_IO_PENDING, rv);
2703 rv = callback1.WaitForResult();
2704 EXPECT_EQ(OK, rv);
2705 TestNetLogEntry::List entries;
2706 log.GetEntries(&entries);
2707 size_t pos = ExpectLogContainsSomewhere(
2708 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2709 NetLog::PHASE_NONE);
2710 ExpectLogContainsSomewhere(
2711 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2712 NetLog::PHASE_NONE);
2714 const HttpResponseInfo* response = trans->GetResponseInfo();
2715 ASSERT_TRUE(response);
2716 ASSERT_TRUE(response->headers);
2717 EXPECT_TRUE(response->headers->IsKeepAlive());
2718 EXPECT_EQ(407, response->headers->response_code());
2719 EXPECT_EQ(10, response->headers->GetContentLength());
2720 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2721 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2723 TestCompletionCallback callback2;
2725 // Wrong password (should be "bar").
2726 rv =
2727 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2728 EXPECT_EQ(ERR_IO_PENDING, rv);
2730 rv = callback2.WaitForResult();
2731 EXPECT_EQ(OK, rv);
2733 response = trans->GetResponseInfo();
2734 ASSERT_TRUE(response);
2735 ASSERT_TRUE(response->headers);
2736 EXPECT_TRUE(response->headers->IsKeepAlive());
2737 EXPECT_EQ(407, response->headers->response_code());
2738 EXPECT_EQ(10, response->headers->GetContentLength());
2739 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2740 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2742 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2743 // out of scope.
2744 session->CloseAllConnections();
2747 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2748 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2749 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
2750 HttpRequestInfo request;
2751 request.method = "GET";
2752 request.url = GURL("https://www.example.org/");
2753 // Ensure that proxy authentication is attempted even
2754 // when the no authentication data flag is set.
2755 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2757 // Configure against proxy server "myproxy:70".
2758 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2759 BoundTestNetLog log;
2760 session_deps_.net_log = log.bound().net_log();
2761 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2763 scoped_ptr<HttpTransaction> trans(
2764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2766 // Since we have proxy, should try to establish tunnel.
2767 MockWrite data_writes1[] = {
2768 MockWrite(
2769 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2770 "Host: www.example.org\r\n"
2771 "Proxy-Connection: keep-alive\r\n\r\n"),
2773 // After calling trans->RestartWithAuth(), this is the request we should
2774 // be issuing -- the final header line contains the credentials.
2775 MockWrite(
2776 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2777 "Host: www.example.org\r\n"
2778 "Proxy-Connection: keep-alive\r\n"
2779 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2782 // The proxy responds to the connect with a 407, using a persistent
2783 // connection.
2784 MockRead data_reads1[] = {
2785 // No credentials.
2786 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2787 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2788 MockRead("Content-Length: 10\r\n\r\n"),
2789 MockRead("0123456789"),
2791 // Wrong credentials (wrong password).
2792 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2793 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2794 MockRead("Content-Length: 10\r\n\r\n"),
2795 // No response body because the test stops reading here.
2796 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2799 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2800 data_writes1, arraysize(data_writes1));
2801 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2803 TestCompletionCallback callback1;
2805 int rv = trans->Start(&request, callback1.callback(), log.bound());
2806 EXPECT_EQ(ERR_IO_PENDING, rv);
2808 rv = callback1.WaitForResult();
2809 EXPECT_EQ(OK, rv);
2810 TestNetLogEntry::List entries;
2811 log.GetEntries(&entries);
2812 size_t pos = ExpectLogContainsSomewhere(
2813 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2814 NetLog::PHASE_NONE);
2815 ExpectLogContainsSomewhere(
2816 entries, pos,
2817 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2818 NetLog::PHASE_NONE);
2820 const HttpResponseInfo* response = trans->GetResponseInfo();
2821 ASSERT_TRUE(response);
2822 ASSERT_TRUE(response->headers);
2823 EXPECT_TRUE(response->headers->IsKeepAlive());
2824 EXPECT_EQ(407, response->headers->response_code());
2825 EXPECT_EQ(10, response->headers->GetContentLength());
2826 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2827 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2829 TestCompletionCallback callback2;
2831 // Wrong password (should be "bar").
2832 rv = trans->RestartWithAuth(
2833 AuthCredentials(kFoo, kBaz), callback2.callback());
2834 EXPECT_EQ(ERR_IO_PENDING, rv);
2836 rv = callback2.WaitForResult();
2837 EXPECT_EQ(OK, rv);
2839 response = trans->GetResponseInfo();
2840 ASSERT_TRUE(response);
2841 ASSERT_TRUE(response->headers);
2842 EXPECT_TRUE(response->headers->IsKeepAlive());
2843 EXPECT_EQ(407, response->headers->response_code());
2844 EXPECT_EQ(10, response->headers->GetContentLength());
2845 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2846 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2848 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2849 // out of scope.
2850 session->CloseAllConnections();
2853 // Test the case a proxy closes a socket while the challenge body is being
2854 // drained.
2855 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
2856 HttpRequestInfo request;
2857 request.method = "GET";
2858 request.url = GURL("https://www.example.org/");
2859 // Ensure that proxy authentication is attempted even
2860 // when the no authentication data flag is set.
2861 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2863 // Configure against proxy server "myproxy:70".
2864 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2867 scoped_ptr<HttpTransaction> trans(
2868 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2870 // Since we have proxy, should try to establish tunnel.
2871 MockWrite data_writes1[] = {
2872 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2873 "Host: www.example.org\r\n"
2874 "Proxy-Connection: keep-alive\r\n\r\n"),
2877 // The proxy responds to the connect with a 407, using a persistent
2878 // connection.
2879 MockRead data_reads1[] = {
2880 // No credentials.
2881 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2882 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2883 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
2884 // Server hands up in the middle of the body.
2885 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
2888 MockWrite data_writes2[] = {
2889 // After calling trans->RestartWithAuth(), this is the request we should
2890 // be issuing -- the final header line contains the credentials.
2891 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2892 "Host: www.example.org\r\n"
2893 "Proxy-Connection: keep-alive\r\n"
2894 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2896 MockWrite("GET / HTTP/1.1\r\n"
2897 "Host: www.example.org\r\n"
2898 "Connection: keep-alive\r\n\r\n"),
2901 MockRead data_reads2[] = {
2902 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2904 MockRead("HTTP/1.1 200 OK\r\n"),
2905 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2906 MockRead("Content-Length: 5\r\n\r\n"),
2907 MockRead(SYNCHRONOUS, "hello"),
2910 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2911 data_writes1, arraysize(data_writes1));
2912 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2913 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2914 data_writes2, arraysize(data_writes2));
2915 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2916 SSLSocketDataProvider ssl(ASYNC, OK);
2917 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2919 TestCompletionCallback callback;
2921 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2922 EXPECT_EQ(OK, callback.GetResult(rv));
2924 const HttpResponseInfo* response = trans->GetResponseInfo();
2925 ASSERT_TRUE(response);
2926 ASSERT_TRUE(response->headers);
2927 EXPECT_TRUE(response->headers->IsKeepAlive());
2928 EXPECT_EQ(407, response->headers->response_code());
2929 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2931 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
2932 EXPECT_EQ(OK, callback.GetResult(rv));
2934 response = trans->GetResponseInfo();
2935 ASSERT_TRUE(response);
2936 ASSERT_TRUE(response->headers);
2937 EXPECT_TRUE(response->headers->IsKeepAlive());
2938 EXPECT_EQ(200, response->headers->response_code());
2939 std::string body;
2940 EXPECT_EQ(OK, ReadTransaction(trans.get(), &body));
2941 EXPECT_EQ("hello", body);
2944 // Test that we don't read the response body when we fail to establish a tunnel,
2945 // even if the user cancels the proxy's auth attempt.
2946 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2947 HttpRequestInfo request;
2948 request.method = "GET";
2949 request.url = GURL("https://www.example.org/");
2950 request.load_flags = 0;
2952 // Configure against proxy server "myproxy:70".
2953 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2955 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2957 scoped_ptr<HttpTransaction> trans(
2958 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2960 // Since we have proxy, should try to establish tunnel.
2961 MockWrite data_writes[] = {
2962 MockWrite(
2963 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2964 "Host: www.example.org\r\n"
2965 "Proxy-Connection: keep-alive\r\n\r\n"),
2968 // The proxy responds to the connect with a 407.
2969 MockRead data_reads[] = {
2970 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2971 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2972 MockRead("Content-Length: 10\r\n\r\n"),
2973 MockRead("0123456789"), // Should not be reached.
2974 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
2977 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2978 data_writes, arraysize(data_writes));
2979 session_deps_.socket_factory->AddSocketDataProvider(&data);
2981 TestCompletionCallback callback;
2983 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2984 EXPECT_EQ(ERR_IO_PENDING, rv);
2986 rv = callback.WaitForResult();
2987 EXPECT_EQ(OK, rv);
2989 const HttpResponseInfo* response = trans->GetResponseInfo();
2990 ASSERT_TRUE(response);
2991 ASSERT_TRUE(response->headers);
2992 EXPECT_TRUE(response->headers->IsKeepAlive());
2993 EXPECT_EQ(407, response->headers->response_code());
2994 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2996 std::string response_data;
2997 rv = ReadTransaction(trans.get(), &response_data);
2998 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3000 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3001 session->CloseAllConnections();
3004 // Test that we don't pass extraneous headers from the proxy's response to the
3005 // caller when the proxy responds to CONNECT with 407.
3006 TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
3007 HttpRequestInfo request;
3008 request.method = "GET";
3009 request.url = GURL("https://www.example.org/");
3010 request.load_flags = 0;
3012 // Configure against proxy server "myproxy:70".
3013 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3015 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3017 scoped_ptr<HttpTransaction> trans(
3018 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3020 // Since we have proxy, should try to establish tunnel.
3021 MockWrite data_writes[] = {
3022 MockWrite(
3023 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3024 "Host: www.example.org\r\n"
3025 "Proxy-Connection: keep-alive\r\n\r\n"),
3028 // The proxy responds to the connect with a 407.
3029 MockRead data_reads[] = {
3030 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3031 MockRead("X-Foo: bar\r\n"),
3032 MockRead("Set-Cookie: foo=bar\r\n"),
3033 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3034 MockRead("Content-Length: 10\r\n\r\n"),
3035 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3038 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
3039 arraysize(data_writes));
3040 session_deps_.socket_factory->AddSocketDataProvider(&data);
3042 TestCompletionCallback callback;
3044 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3045 EXPECT_EQ(ERR_IO_PENDING, rv);
3047 rv = callback.WaitForResult();
3048 EXPECT_EQ(OK, rv);
3050 const HttpResponseInfo* response = trans->GetResponseInfo();
3051 ASSERT_TRUE(response);
3052 ASSERT_TRUE(response->headers);
3053 EXPECT_TRUE(response->headers->IsKeepAlive());
3054 EXPECT_EQ(407, response->headers->response_code());
3055 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3056 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
3057 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
3059 std::string response_data;
3060 rv = ReadTransaction(trans.get(), &response_data);
3061 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3063 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3064 session->CloseAllConnections();
3067 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3068 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
3069 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
3070 HttpRequestInfo request;
3071 request.method = "GET";
3072 request.url = GURL("http://www.example.org/");
3073 request.load_flags = 0;
3075 // We are using a DIRECT connection (i.e. no proxy) for this session.
3076 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3077 scoped_ptr<HttpTransaction> trans(
3078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3080 MockWrite data_writes1[] = {
3081 MockWrite(
3082 "GET / HTTP/1.1\r\n"
3083 "Host: www.example.org\r\n"
3084 "Connection: keep-alive\r\n\r\n"),
3087 MockRead data_reads1[] = {
3088 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3089 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3090 // Large content-length -- won't matter, as connection will be reset.
3091 MockRead("Content-Length: 10000\r\n\r\n"),
3092 MockRead(SYNCHRONOUS, ERR_FAILED),
3095 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3096 data_writes1, arraysize(data_writes1));
3097 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3099 TestCompletionCallback callback;
3101 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3102 EXPECT_EQ(ERR_IO_PENDING, rv);
3104 rv = callback.WaitForResult();
3105 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3108 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3109 // through a non-authenticating proxy. The request should fail with
3110 // ERR_UNEXPECTED_PROXY_AUTH.
3111 // Note that it is impossible to detect if an HTTP server returns a 407 through
3112 // a non-authenticating proxy - there is nothing to indicate whether the
3113 // response came from the proxy or the server, so it is treated as if the proxy
3114 // issued the challenge.
3115 TEST_P(HttpNetworkTransactionTest,
3116 HttpsServerRequestsProxyAuthThroughProxy) {
3117 HttpRequestInfo request;
3118 request.method = "GET";
3119 request.url = GURL("https://www.example.org/");
3121 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3122 BoundTestNetLog log;
3123 session_deps_.net_log = log.bound().net_log();
3124 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3126 // Since we have proxy, should try to establish tunnel.
3127 MockWrite data_writes1[] = {
3128 MockWrite(
3129 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3130 "Host: www.example.org\r\n"
3131 "Proxy-Connection: keep-alive\r\n\r\n"),
3133 MockWrite(
3134 "GET / HTTP/1.1\r\n"
3135 "Host: www.example.org\r\n"
3136 "Connection: keep-alive\r\n\r\n"),
3139 MockRead data_reads1[] = {
3140 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3142 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3143 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3144 MockRead("\r\n"),
3145 MockRead(SYNCHRONOUS, OK),
3148 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3149 data_writes1, arraysize(data_writes1));
3150 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3151 SSLSocketDataProvider ssl(ASYNC, OK);
3152 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3154 TestCompletionCallback callback1;
3156 scoped_ptr<HttpTransaction> trans(
3157 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3159 int rv = trans->Start(&request, callback1.callback(), log.bound());
3160 EXPECT_EQ(ERR_IO_PENDING, rv);
3162 rv = callback1.WaitForResult();
3163 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3164 TestNetLogEntry::List entries;
3165 log.GetEntries(&entries);
3166 size_t pos = ExpectLogContainsSomewhere(
3167 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3168 NetLog::PHASE_NONE);
3169 ExpectLogContainsSomewhere(
3170 entries, pos,
3171 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3172 NetLog::PHASE_NONE);
3175 // Test the load timing for HTTPS requests with an HTTP proxy.
3176 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
3177 HttpRequestInfo request1;
3178 request1.method = "GET";
3179 request1.url = GURL("https://www.example.org/1");
3181 HttpRequestInfo request2;
3182 request2.method = "GET";
3183 request2.url = GURL("https://www.example.org/2");
3185 // Configure against proxy server "myproxy:70".
3186 session_deps_.proxy_service.reset(
3187 ProxyService::CreateFixed("PROXY myproxy:70"));
3188 BoundTestNetLog log;
3189 session_deps_.net_log = log.bound().net_log();
3190 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3192 // Since we have proxy, should try to establish tunnel.
3193 MockWrite data_writes1[] = {
3194 MockWrite(
3195 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3196 "Host: www.example.org\r\n"
3197 "Proxy-Connection: keep-alive\r\n\r\n"),
3199 MockWrite(
3200 "GET /1 HTTP/1.1\r\n"
3201 "Host: www.example.org\r\n"
3202 "Connection: keep-alive\r\n\r\n"),
3204 MockWrite(
3205 "GET /2 HTTP/1.1\r\n"
3206 "Host: www.example.org\r\n"
3207 "Connection: keep-alive\r\n\r\n"),
3210 // The proxy responds to the connect with a 407, using a persistent
3211 // connection.
3212 MockRead data_reads1[] = {
3213 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3215 MockRead("HTTP/1.1 200 OK\r\n"),
3216 MockRead("Content-Length: 1\r\n\r\n"),
3217 MockRead(SYNCHRONOUS, "1"),
3219 MockRead("HTTP/1.1 200 OK\r\n"),
3220 MockRead("Content-Length: 2\r\n\r\n"),
3221 MockRead(SYNCHRONOUS, "22"),
3224 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3225 data_writes1, arraysize(data_writes1));
3226 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3227 SSLSocketDataProvider ssl(ASYNC, OK);
3228 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3230 TestCompletionCallback callback1;
3231 scoped_ptr<HttpTransaction> trans1(
3232 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3234 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3235 EXPECT_EQ(ERR_IO_PENDING, rv);
3237 rv = callback1.WaitForResult();
3238 EXPECT_EQ(OK, rv);
3240 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3241 ASSERT_TRUE(response1 != NULL);
3242 ASSERT_TRUE(response1->headers.get() != NULL);
3243 EXPECT_EQ(1, response1->headers->GetContentLength());
3245 LoadTimingInfo load_timing_info1;
3246 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3247 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3249 trans1.reset();
3251 TestCompletionCallback callback2;
3252 scoped_ptr<HttpTransaction> trans2(
3253 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3255 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3256 EXPECT_EQ(ERR_IO_PENDING, rv);
3258 rv = callback2.WaitForResult();
3259 EXPECT_EQ(OK, rv);
3261 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3262 ASSERT_TRUE(response2 != NULL);
3263 ASSERT_TRUE(response2->headers.get() != NULL);
3264 EXPECT_EQ(2, response2->headers->GetContentLength());
3266 LoadTimingInfo load_timing_info2;
3267 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3268 TestLoadTimingReused(load_timing_info2);
3270 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3272 trans2.reset();
3273 session->CloseAllConnections();
3276 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3277 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
3278 HttpRequestInfo request1;
3279 request1.method = "GET";
3280 request1.url = GURL("https://www.example.org/1");
3282 HttpRequestInfo request2;
3283 request2.method = "GET";
3284 request2.url = GURL("https://www.example.org/2");
3286 // Configure against proxy server "myproxy:70".
3287 session_deps_.proxy_service.reset(
3288 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3289 BoundTestNetLog log;
3290 session_deps_.net_log = log.bound().net_log();
3291 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3293 // Since we have proxy, should try to establish tunnel.
3294 MockWrite data_writes1[] = {
3295 MockWrite(
3296 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3297 "Host: www.example.org\r\n"
3298 "Proxy-Connection: keep-alive\r\n\r\n"),
3300 MockWrite(
3301 "GET /1 HTTP/1.1\r\n"
3302 "Host: www.example.org\r\n"
3303 "Connection: keep-alive\r\n\r\n"),
3305 MockWrite(
3306 "GET /2 HTTP/1.1\r\n"
3307 "Host: www.example.org\r\n"
3308 "Connection: keep-alive\r\n\r\n"),
3311 // The proxy responds to the connect with a 407, using a persistent
3312 // connection.
3313 MockRead data_reads1[] = {
3314 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3316 MockRead("HTTP/1.1 200 OK\r\n"),
3317 MockRead("Content-Length: 1\r\n\r\n"),
3318 MockRead(SYNCHRONOUS, "1"),
3320 MockRead("HTTP/1.1 200 OK\r\n"),
3321 MockRead("Content-Length: 2\r\n\r\n"),
3322 MockRead(SYNCHRONOUS, "22"),
3325 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3326 data_writes1, arraysize(data_writes1));
3327 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3328 SSLSocketDataProvider ssl(ASYNC, OK);
3329 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3331 TestCompletionCallback callback1;
3332 scoped_ptr<HttpTransaction> trans1(
3333 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3335 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3336 EXPECT_EQ(ERR_IO_PENDING, rv);
3338 rv = callback1.WaitForResult();
3339 EXPECT_EQ(OK, rv);
3341 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3342 ASSERT_TRUE(response1 != NULL);
3343 ASSERT_TRUE(response1->headers.get() != NULL);
3344 EXPECT_EQ(1, response1->headers->GetContentLength());
3346 LoadTimingInfo load_timing_info1;
3347 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3348 TestLoadTimingNotReusedWithPac(load_timing_info1,
3349 CONNECT_TIMING_HAS_SSL_TIMES);
3351 trans1.reset();
3353 TestCompletionCallback callback2;
3354 scoped_ptr<HttpTransaction> trans2(
3355 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3357 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3358 EXPECT_EQ(ERR_IO_PENDING, rv);
3360 rv = callback2.WaitForResult();
3361 EXPECT_EQ(OK, rv);
3363 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3364 ASSERT_TRUE(response2 != NULL);
3365 ASSERT_TRUE(response2->headers.get() != NULL);
3366 EXPECT_EQ(2, response2->headers->GetContentLength());
3368 LoadTimingInfo load_timing_info2;
3369 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3370 TestLoadTimingReusedWithPac(load_timing_info2);
3372 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3374 trans2.reset();
3375 session->CloseAllConnections();
3378 // Test a simple get through an HTTPS Proxy.
3379 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
3380 HttpRequestInfo request;
3381 request.method = "GET";
3382 request.url = GURL("http://www.example.org/");
3384 // Configure against https proxy server "proxy:70".
3385 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3386 "https://proxy:70"));
3387 BoundTestNetLog log;
3388 session_deps_.net_log = log.bound().net_log();
3389 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3391 // Since we have proxy, should use full url
3392 MockWrite data_writes1[] = {
3393 MockWrite(
3394 "GET http://www.example.org/ HTTP/1.1\r\n"
3395 "Host: www.example.org\r\n"
3396 "Proxy-Connection: keep-alive\r\n\r\n"),
3399 MockRead data_reads1[] = {
3400 MockRead("HTTP/1.1 200 OK\r\n"),
3401 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3402 MockRead("Content-Length: 100\r\n\r\n"),
3403 MockRead(SYNCHRONOUS, OK),
3406 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3407 data_writes1, arraysize(data_writes1));
3408 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3409 SSLSocketDataProvider ssl(ASYNC, OK);
3410 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3412 TestCompletionCallback callback1;
3414 scoped_ptr<HttpTransaction> trans(
3415 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3417 int rv = trans->Start(&request, callback1.callback(), log.bound());
3418 EXPECT_EQ(ERR_IO_PENDING, rv);
3420 rv = callback1.WaitForResult();
3421 EXPECT_EQ(OK, rv);
3423 LoadTimingInfo load_timing_info;
3424 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3425 TestLoadTimingNotReused(load_timing_info,
3426 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3428 const HttpResponseInfo* response = trans->GetResponseInfo();
3429 ASSERT_TRUE(response != NULL);
3431 EXPECT_TRUE(response->headers->IsKeepAlive());
3432 EXPECT_EQ(200, response->headers->response_code());
3433 EXPECT_EQ(100, response->headers->GetContentLength());
3434 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3436 // The password prompt info should not be set.
3437 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3440 // Test a SPDY get through an HTTPS Proxy.
3441 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3442 HttpRequestInfo request;
3443 request.method = "GET";
3444 request.url = GURL("http://www.example.org/");
3445 request.load_flags = 0;
3447 // Configure against https proxy server "proxy:70".
3448 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3449 "https://proxy:70"));
3450 BoundTestNetLog log;
3451 session_deps_.net_log = log.bound().net_log();
3452 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3454 // fetch http://www.example.org/ via SPDY
3455 scoped_ptr<SpdyFrame> req(
3456 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3457 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3459 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3460 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3461 MockRead spdy_reads[] = {
3462 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3465 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3466 arraysize(spdy_writes));
3467 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3469 SSLSocketDataProvider ssl(ASYNC, OK);
3470 ssl.SetNextProto(GetParam());
3471 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3473 TestCompletionCallback callback1;
3475 scoped_ptr<HttpTransaction> trans(
3476 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3478 int rv = trans->Start(&request, callback1.callback(), log.bound());
3479 EXPECT_EQ(ERR_IO_PENDING, rv);
3481 rv = callback1.WaitForResult();
3482 EXPECT_EQ(OK, rv);
3484 LoadTimingInfo load_timing_info;
3485 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3486 TestLoadTimingNotReused(load_timing_info,
3487 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3489 const HttpResponseInfo* response = trans->GetResponseInfo();
3490 ASSERT_TRUE(response != NULL);
3491 ASSERT_TRUE(response->headers.get() != NULL);
3492 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3494 std::string response_data;
3495 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3496 EXPECT_EQ(kUploadData, response_data);
3499 // Verifies that a session which races and wins against the owning transaction
3500 // (completing prior to host resolution), doesn't fail the transaction.
3501 // Regression test for crbug.com/334413.
3502 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3503 HttpRequestInfo request;
3504 request.method = "GET";
3505 request.url = GURL("http://www.example.org/");
3506 request.load_flags = 0;
3508 // Configure SPDY proxy server "proxy:70".
3509 session_deps_.proxy_service.reset(
3510 ProxyService::CreateFixed("https://proxy:70"));
3511 BoundTestNetLog log;
3512 session_deps_.net_log = log.bound().net_log();
3513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3515 // Fetch http://www.example.org/ through the SPDY proxy.
3516 scoped_ptr<SpdyFrame> req(
3517 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3518 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
3520 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3521 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3522 MockRead spdy_reads[] = {
3523 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
3526 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3527 arraysize(spdy_writes));
3528 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3530 SSLSocketDataProvider ssl(ASYNC, OK);
3531 ssl.SetNextProto(GetParam());
3532 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3534 TestCompletionCallback callback1;
3536 scoped_ptr<HttpTransaction> trans(
3537 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3539 // Stall the hostname resolution begun by the transaction.
3540 session_deps_.host_resolver->set_synchronous_mode(false);
3541 session_deps_.host_resolver->set_ondemand_mode(true);
3543 int rv = trans->Start(&request, callback1.callback(), log.bound());
3544 EXPECT_EQ(ERR_IO_PENDING, rv);
3546 // Race a session to the proxy, which completes first.
3547 session_deps_.host_resolver->set_ondemand_mode(false);
3548 SpdySessionKey key(
3549 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3550 base::WeakPtr<SpdySession> spdy_session =
3551 CreateSecureSpdySession(session, key, log.bound());
3553 // Unstall the resolution begun by the transaction.
3554 session_deps_.host_resolver->set_ondemand_mode(true);
3555 session_deps_.host_resolver->ResolveAllPending();
3557 EXPECT_FALSE(callback1.have_result());
3558 rv = callback1.WaitForResult();
3559 EXPECT_EQ(OK, rv);
3561 const HttpResponseInfo* response = trans->GetResponseInfo();
3562 ASSERT_TRUE(response != NULL);
3563 ASSERT_TRUE(response->headers.get() != NULL);
3564 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3566 std::string response_data;
3567 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3568 EXPECT_EQ(kUploadData, response_data);
3571 // Test a SPDY get through an HTTPS Proxy.
3572 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3573 HttpRequestInfo request;
3574 request.method = "GET";
3575 request.url = GURL("http://www.example.org/");
3576 request.load_flags = 0;
3578 // Configure against https proxy server "myproxy:70".
3579 session_deps_.proxy_service.reset(
3580 ProxyService::CreateFixed("https://myproxy:70"));
3581 BoundTestNetLog log;
3582 session_deps_.net_log = log.bound().net_log();
3583 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3585 // The first request will be a bare GET, the second request will be a
3586 // GET with a Proxy-Authorization header.
3587 scoped_ptr<SpdyFrame> req_get(
3588 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3589 const char* const kExtraAuthorizationHeaders[] = {
3590 "proxy-authorization", "Basic Zm9vOmJhcg=="
3592 scoped_ptr<SpdyFrame> req_get_authorization(
3593 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3594 arraysize(kExtraAuthorizationHeaders) / 2,
3595 false,
3597 LOWEST,
3598 false));
3599 MockWrite spdy_writes[] = {
3600 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
3603 // The first response is a 407 proxy authentication challenge, and the second
3604 // response will be a 200 response since the second request includes a valid
3605 // Authorization header.
3606 const char* const kExtraAuthenticationHeaders[] = {
3607 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3609 scoped_ptr<SpdyFrame> resp_authentication(
3610 spdy_util_.ConstructSpdySynReplyError(
3611 "407 Proxy Authentication Required",
3612 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3613 1));
3614 scoped_ptr<SpdyFrame> body_authentication(
3615 spdy_util_.ConstructSpdyBodyFrame(1, true));
3616 scoped_ptr<SpdyFrame> resp_data(
3617 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3618 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3619 MockRead spdy_reads[] = {
3620 CreateMockRead(*resp_authentication, 1),
3621 CreateMockRead(*body_authentication, 2),
3622 CreateMockRead(*resp_data, 4),
3623 CreateMockRead(*body_data, 5),
3624 MockRead(ASYNC, 0, 6),
3627 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3628 arraysize(spdy_writes));
3629 session_deps_.socket_factory->AddSocketDataProvider(&data);
3631 SSLSocketDataProvider ssl(ASYNC, OK);
3632 ssl.SetNextProto(GetParam());
3633 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3635 TestCompletionCallback callback1;
3637 scoped_ptr<HttpTransaction> trans(
3638 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3640 int rv = trans->Start(&request, callback1.callback(), log.bound());
3641 EXPECT_EQ(ERR_IO_PENDING, rv);
3643 rv = callback1.WaitForResult();
3644 EXPECT_EQ(OK, rv);
3646 const HttpResponseInfo* const response = trans->GetResponseInfo();
3648 ASSERT_TRUE(response != NULL);
3649 ASSERT_TRUE(response->headers.get() != NULL);
3650 EXPECT_EQ(407, response->headers->response_code());
3651 EXPECT_TRUE(response->was_fetched_via_spdy);
3652 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3654 TestCompletionCallback callback2;
3656 rv = trans->RestartWithAuth(
3657 AuthCredentials(kFoo, kBar), callback2.callback());
3658 EXPECT_EQ(ERR_IO_PENDING, rv);
3660 rv = callback2.WaitForResult();
3661 EXPECT_EQ(OK, rv);
3663 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3665 ASSERT_TRUE(response_restart != NULL);
3666 ASSERT_TRUE(response_restart->headers.get() != NULL);
3667 EXPECT_EQ(200, response_restart->headers->response_code());
3668 // The password prompt info should not be set.
3669 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3672 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3673 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3674 HttpRequestInfo request;
3675 request.method = "GET";
3676 request.url = GURL("https://www.example.org/");
3677 request.load_flags = 0;
3679 // Configure against https proxy server "proxy:70".
3680 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3681 "https://proxy:70"));
3682 BoundTestNetLog log;
3683 session_deps_.net_log = log.bound().net_log();
3684 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3686 scoped_ptr<HttpTransaction> trans(
3687 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3689 // CONNECT to www.example.org:443 via SPDY
3690 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3691 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3692 // fetch https://www.example.org/ via HTTP
3694 const char get[] =
3695 "GET / HTTP/1.1\r\n"
3696 "Host: www.example.org\r\n"
3697 "Connection: keep-alive\r\n\r\n";
3698 scoped_ptr<SpdyFrame> wrapped_get(
3699 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3700 scoped_ptr<SpdyFrame> conn_resp(
3701 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3702 const char resp[] = "HTTP/1.1 200 OK\r\n"
3703 "Content-Length: 10\r\n\r\n";
3704 scoped_ptr<SpdyFrame> wrapped_get_resp(
3705 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3706 scoped_ptr<SpdyFrame> wrapped_body(
3707 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3708 scoped_ptr<SpdyFrame> window_update(
3709 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3711 MockWrite spdy_writes[] = {
3712 CreateMockWrite(*connect, 0),
3713 CreateMockWrite(*wrapped_get, 2),
3714 CreateMockWrite(*window_update, 6),
3717 MockRead spdy_reads[] = {
3718 CreateMockRead(*conn_resp, 1, ASYNC),
3719 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
3720 CreateMockRead(*wrapped_body, 4, ASYNC),
3721 CreateMockRead(*wrapped_body, 5, ASYNC),
3722 MockRead(ASYNC, 0, 7),
3725 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3726 arraysize(spdy_writes));
3727 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3729 SSLSocketDataProvider ssl(ASYNC, OK);
3730 ssl.SetNextProto(GetParam());
3731 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3732 SSLSocketDataProvider ssl2(ASYNC, OK);
3733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3735 TestCompletionCallback callback1;
3737 int rv = trans->Start(&request, callback1.callback(), log.bound());
3738 EXPECT_EQ(ERR_IO_PENDING, rv);
3740 rv = callback1.WaitForResult();
3741 ASSERT_EQ(OK, rv);
3743 LoadTimingInfo load_timing_info;
3744 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3745 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3747 const HttpResponseInfo* response = trans->GetResponseInfo();
3748 ASSERT_TRUE(response != NULL);
3749 ASSERT_TRUE(response->headers.get() != NULL);
3750 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3752 std::string response_data;
3753 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3754 EXPECT_EQ("1234567890", response_data);
3757 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3758 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3759 HttpRequestInfo request;
3760 request.method = "GET";
3761 request.url = GURL("https://www.example.org/");
3762 request.load_flags = 0;
3764 // Configure against https proxy server "proxy:70".
3765 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3766 "https://proxy:70"));
3767 BoundTestNetLog log;
3768 session_deps_.net_log = log.bound().net_log();
3769 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3771 scoped_ptr<HttpTransaction> trans(
3772 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3774 // CONNECT to www.example.org:443 via SPDY
3775 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3776 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3777 // fetch https://www.example.org/ via SPDY
3778 const char kMyUrl[] = "https://www.example.org/";
3779 scoped_ptr<SpdyFrame> get(
3780 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3781 scoped_ptr<SpdyFrame> wrapped_get(
3782 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3783 scoped_ptr<SpdyFrame> conn_resp(
3784 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3785 scoped_ptr<SpdyFrame> get_resp(
3786 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3787 scoped_ptr<SpdyFrame> wrapped_get_resp(
3788 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3789 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3790 scoped_ptr<SpdyFrame> wrapped_body(
3791 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3792 scoped_ptr<SpdyFrame> window_update_get_resp(
3793 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3794 scoped_ptr<SpdyFrame> window_update_body(
3795 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3797 MockWrite spdy_writes[] = {
3798 CreateMockWrite(*connect, 0),
3799 CreateMockWrite(*wrapped_get, 2),
3800 CreateMockWrite(*window_update_get_resp, 6),
3801 CreateMockWrite(*window_update_body, 7),
3804 MockRead spdy_reads[] = {
3805 CreateMockRead(*conn_resp, 1, ASYNC),
3806 MockRead(ASYNC, ERR_IO_PENDING, 3),
3807 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3808 CreateMockRead(*wrapped_body, 5, ASYNC),
3809 MockRead(ASYNC, 0, 8),
3812 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3813 arraysize(spdy_writes));
3814 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3816 SSLSocketDataProvider ssl(ASYNC, OK);
3817 ssl.SetNextProto(GetParam());
3818 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3819 SSLSocketDataProvider ssl2(ASYNC, OK);
3820 ssl2.SetNextProto(GetParam());
3821 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3823 TestCompletionCallback callback1;
3825 int rv = trans->Start(&request, callback1.callback(), log.bound());
3826 EXPECT_EQ(ERR_IO_PENDING, rv);
3828 // Allow the SpdyProxyClientSocket's write callback to complete.
3829 base::MessageLoop::current()->RunUntilIdle();
3830 // Now allow the read of the response to complete.
3831 spdy_data.CompleteRead();
3832 rv = callback1.WaitForResult();
3833 EXPECT_EQ(OK, rv);
3835 LoadTimingInfo load_timing_info;
3836 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3837 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3839 const HttpResponseInfo* response = trans->GetResponseInfo();
3840 ASSERT_TRUE(response != NULL);
3841 ASSERT_TRUE(response->headers.get() != NULL);
3842 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3844 std::string response_data;
3845 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3846 EXPECT_EQ(kUploadData, response_data);
3849 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3850 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3851 HttpRequestInfo request;
3852 request.method = "GET";
3853 request.url = GURL("https://www.example.org/");
3854 request.load_flags = 0;
3856 // Configure against https proxy server "proxy:70".
3857 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3858 "https://proxy:70"));
3859 BoundTestNetLog log;
3860 session_deps_.net_log = log.bound().net_log();
3861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3863 scoped_ptr<HttpTransaction> trans(
3864 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3866 // CONNECT to www.example.org:443 via SPDY
3867 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3868 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3869 scoped_ptr<SpdyFrame> get(
3870 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3872 MockWrite spdy_writes[] = {
3873 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
3876 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3877 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3878 MockRead spdy_reads[] = {
3879 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
3882 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3883 arraysize(spdy_writes));
3884 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3886 SSLSocketDataProvider ssl(ASYNC, OK);
3887 ssl.SetNextProto(GetParam());
3888 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3889 SSLSocketDataProvider ssl2(ASYNC, OK);
3890 ssl2.SetNextProto(GetParam());
3891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3893 TestCompletionCallback callback1;
3895 int rv = trans->Start(&request, callback1.callback(), log.bound());
3896 EXPECT_EQ(ERR_IO_PENDING, rv);
3898 rv = callback1.WaitForResult();
3899 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3901 // TODO(ttuttle): Anything else to check here?
3904 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3905 // HTTPS Proxy to different servers.
3906 TEST_P(HttpNetworkTransactionTest,
3907 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3908 // Configure against https proxy server "proxy:70".
3909 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3910 "https://proxy:70"));
3911 BoundTestNetLog log;
3912 session_deps_.net_log = log.bound().net_log();
3913 scoped_refptr<HttpNetworkSession> session(
3914 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
3916 HttpRequestInfo request1;
3917 request1.method = "GET";
3918 request1.url = GURL("https://www.example.org/");
3919 request1.load_flags = 0;
3921 HttpRequestInfo request2;
3922 request2.method = "GET";
3923 request2.url = GURL("https://mail.example.org/");
3924 request2.load_flags = 0;
3926 // CONNECT to www.example.org:443 via SPDY.
3927 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3928 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3929 scoped_ptr<SpdyFrame> conn_resp1(
3930 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3932 // Fetch https://www.example.org/ via HTTP.
3933 const char get1[] =
3934 "GET / HTTP/1.1\r\n"
3935 "Host: www.example.org\r\n"
3936 "Connection: keep-alive\r\n\r\n";
3937 scoped_ptr<SpdyFrame> wrapped_get1(
3938 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3939 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3940 "Content-Length: 1\r\n\r\n";
3941 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3942 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3943 scoped_ptr<SpdyFrame> wrapped_body1(
3944 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3945 scoped_ptr<SpdyFrame> window_update(
3946 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3948 // CONNECT to mail.example.org:443 via SPDY.
3949 SpdyHeaderBlock connect2_block;
3950 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3951 if (GetParam() == kProtoHTTP2) {
3952 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
3953 } else {
3954 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
3955 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
3957 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3958 scoped_ptr<SpdyFrame> connect2(
3959 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3961 scoped_ptr<SpdyFrame> conn_resp2(
3962 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3964 // Fetch https://mail.example.org/ via HTTP.
3965 const char get2[] =
3966 "GET / HTTP/1.1\r\n"
3967 "Host: mail.example.org\r\n"
3968 "Connection: keep-alive\r\n\r\n";
3969 scoped_ptr<SpdyFrame> wrapped_get2(
3970 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3971 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3972 "Content-Length: 2\r\n\r\n";
3973 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3974 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3975 scoped_ptr<SpdyFrame> wrapped_body2(
3976 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3978 MockWrite spdy_writes[] = {
3979 CreateMockWrite(*connect1, 0),
3980 CreateMockWrite(*wrapped_get1, 2),
3981 CreateMockWrite(*connect2, 5),
3982 CreateMockWrite(*wrapped_get2, 7),
3985 MockRead spdy_reads[] = {
3986 CreateMockRead(*conn_resp1, 1, ASYNC),
3987 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3988 CreateMockRead(*wrapped_body1, 4, ASYNC),
3989 CreateMockRead(*conn_resp2, 6, ASYNC),
3990 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3991 CreateMockRead(*wrapped_body2, 9, ASYNC),
3992 MockRead(ASYNC, 0, 10),
3995 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
3996 arraysize(spdy_writes));
3997 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3999 SSLSocketDataProvider ssl(ASYNC, OK);
4000 ssl.SetNextProto(GetParam());
4001 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4002 SSLSocketDataProvider ssl2(ASYNC, OK);
4003 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4004 SSLSocketDataProvider ssl3(ASYNC, OK);
4005 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
4007 TestCompletionCallback callback;
4009 scoped_ptr<HttpTransaction> trans(
4010 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4011 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4012 EXPECT_EQ(OK, callback.GetResult(rv));
4014 LoadTimingInfo load_timing_info;
4015 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4016 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4018 const HttpResponseInfo* response = trans->GetResponseInfo();
4019 ASSERT_TRUE(response != NULL);
4020 ASSERT_TRUE(response->headers.get() != NULL);
4021 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4023 std::string response_data;
4024 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4025 rv = trans->Read(buf.get(), 256, callback.callback());
4026 EXPECT_EQ(1, callback.GetResult(rv));
4028 scoped_ptr<HttpTransaction> trans2(
4029 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4030 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4031 EXPECT_EQ(OK, callback.GetResult(rv));
4033 LoadTimingInfo load_timing_info2;
4034 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4035 // Even though the SPDY connection is reused, a new tunnelled connection has
4036 // to be created, so the socket's load timing looks like a fresh connection.
4037 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
4039 // The requests should have different IDs, since they each are using their own
4040 // separate stream.
4041 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4043 rv = trans2->Read(buf.get(), 256, callback.callback());
4044 EXPECT_EQ(2, callback.GetResult(rv));
4047 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4048 // HTTPS Proxy to the same server.
4049 TEST_P(HttpNetworkTransactionTest,
4050 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
4051 // Configure against https proxy server "proxy:70".
4052 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
4053 "https://proxy:70"));
4054 BoundTestNetLog log;
4055 session_deps_.net_log = log.bound().net_log();
4056 scoped_refptr<HttpNetworkSession> session(
4057 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
4059 HttpRequestInfo request1;
4060 request1.method = "GET";
4061 request1.url = GURL("https://www.example.org/");
4062 request1.load_flags = 0;
4064 HttpRequestInfo request2;
4065 request2.method = "GET";
4066 request2.url = GURL("https://www.example.org/2");
4067 request2.load_flags = 0;
4069 // CONNECT to www.example.org:443 via SPDY.
4070 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
4071 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4072 scoped_ptr<SpdyFrame> conn_resp1(
4073 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4075 // Fetch https://www.example.org/ via HTTP.
4076 const char get1[] =
4077 "GET / HTTP/1.1\r\n"
4078 "Host: www.example.org\r\n"
4079 "Connection: keep-alive\r\n\r\n";
4080 scoped_ptr<SpdyFrame> wrapped_get1(
4081 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
4082 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4083 "Content-Length: 1\r\n\r\n";
4084 scoped_ptr<SpdyFrame> wrapped_get_resp1(
4085 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4086 scoped_ptr<SpdyFrame> wrapped_body1(
4087 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
4088 scoped_ptr<SpdyFrame> window_update(
4089 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
4091 // Fetch https://www.example.org/2 via HTTP.
4092 const char get2[] =
4093 "GET /2 HTTP/1.1\r\n"
4094 "Host: www.example.org\r\n"
4095 "Connection: keep-alive\r\n\r\n";
4096 scoped_ptr<SpdyFrame> wrapped_get2(
4097 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
4098 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4099 "Content-Length: 2\r\n\r\n";
4100 scoped_ptr<SpdyFrame> wrapped_get_resp2(
4101 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
4102 scoped_ptr<SpdyFrame> wrapped_body2(
4103 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
4105 MockWrite spdy_writes[] = {
4106 CreateMockWrite(*connect1, 0),
4107 CreateMockWrite(*wrapped_get1, 2),
4108 CreateMockWrite(*wrapped_get2, 5),
4111 MockRead spdy_reads[] = {
4112 CreateMockRead(*conn_resp1, 1, ASYNC),
4113 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4114 CreateMockRead(*wrapped_body1, 4, ASYNC),
4115 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4116 CreateMockRead(*wrapped_body2, 7, ASYNC),
4117 MockRead(ASYNC, 0, 8),
4120 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4121 arraysize(spdy_writes));
4122 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4124 SSLSocketDataProvider ssl(ASYNC, OK);
4125 ssl.SetNextProto(GetParam());
4126 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4127 SSLSocketDataProvider ssl2(ASYNC, OK);
4128 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4130 TestCompletionCallback callback;
4132 scoped_ptr<HttpTransaction> trans(
4133 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4134 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4135 EXPECT_EQ(ERR_IO_PENDING, rv);
4137 rv = callback.WaitForResult();
4138 EXPECT_EQ(OK, rv);
4140 LoadTimingInfo load_timing_info;
4141 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4142 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4144 const HttpResponseInfo* response = trans->GetResponseInfo();
4145 ASSERT_TRUE(response != NULL);
4146 ASSERT_TRUE(response->headers.get() != NULL);
4147 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4149 std::string response_data;
4150 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4151 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
4152 trans.reset();
4154 scoped_ptr<HttpTransaction> trans2(
4155 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4156 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4157 EXPECT_EQ(ERR_IO_PENDING, rv);
4159 rv = callback.WaitForResult();
4160 EXPECT_EQ(OK, rv);
4162 LoadTimingInfo load_timing_info2;
4163 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4164 TestLoadTimingReused(load_timing_info2);
4166 // The requests should have the same ID.
4167 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4169 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
4172 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4173 // Proxy to different servers.
4174 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
4175 // Configure against https proxy server "proxy:70".
4176 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
4177 "https://proxy:70"));
4178 BoundTestNetLog log;
4179 session_deps_.net_log = log.bound().net_log();
4180 scoped_refptr<HttpNetworkSession> session(
4181 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
4183 HttpRequestInfo request1;
4184 request1.method = "GET";
4185 request1.url = GURL("http://www.example.org/");
4186 request1.load_flags = 0;
4188 HttpRequestInfo request2;
4189 request2.method = "GET";
4190 request2.url = GURL("http://mail.example.org/");
4191 request2.load_flags = 0;
4193 // http://www.example.org/
4194 scoped_ptr<SpdyHeaderBlock> headers(
4195 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4196 scoped_ptr<SpdyFrame> get1(
4197 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4198 scoped_ptr<SpdyFrame> get_resp1(
4199 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4200 scoped_ptr<SpdyFrame> body1(
4201 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
4203 // http://mail.example.org/
4204 scoped_ptr<SpdyHeaderBlock> headers2(
4205 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4206 scoped_ptr<SpdyFrame> get2(
4207 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
4208 scoped_ptr<SpdyFrame> get_resp2(
4209 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4210 scoped_ptr<SpdyFrame> body2(
4211 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
4213 MockWrite spdy_writes[] = {
4214 CreateMockWrite(*get1, 0),
4215 CreateMockWrite(*get2, 3),
4218 MockRead spdy_reads[] = {
4219 CreateMockRead(*get_resp1, 1, ASYNC),
4220 CreateMockRead(*body1, 2, ASYNC),
4221 CreateMockRead(*get_resp2, 4, ASYNC),
4222 CreateMockRead(*body2, 5, ASYNC),
4223 MockRead(ASYNC, 0, 6),
4226 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4227 arraysize(spdy_writes));
4228 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4230 SSLSocketDataProvider ssl(ASYNC, OK);
4231 ssl.SetNextProto(GetParam());
4232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4234 TestCompletionCallback callback;
4236 scoped_ptr<HttpTransaction> trans(
4237 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4238 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4239 EXPECT_EQ(OK, callback.GetResult(rv));
4241 LoadTimingInfo load_timing_info;
4242 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4243 TestLoadTimingNotReused(load_timing_info,
4244 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4246 const HttpResponseInfo* response = trans->GetResponseInfo();
4247 ASSERT_TRUE(response != NULL);
4248 ASSERT_TRUE(response->headers.get() != NULL);
4249 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4251 std::string response_data;
4252 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4253 rv = trans->Read(buf.get(), 256, callback.callback());
4254 EXPECT_EQ(1, callback.GetResult(rv));
4255 // Delete the first request, so the second one can reuse the socket.
4256 trans.reset();
4258 scoped_ptr<HttpTransaction> trans2(
4259 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4260 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4261 EXPECT_EQ(OK, callback.GetResult(rv));
4263 LoadTimingInfo load_timing_info2;
4264 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4265 TestLoadTimingReused(load_timing_info2);
4267 // The requests should have the same ID.
4268 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4270 rv = trans2->Read(buf.get(), 256, callback.callback());
4271 EXPECT_EQ(2, callback.GetResult(rv));
4274 // Test the challenge-response-retry sequence through an HTTPS Proxy
4275 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
4276 HttpRequestInfo request;
4277 request.method = "GET";
4278 request.url = GURL("http://www.example.org/");
4279 // when the no authentication data flag is set.
4280 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
4282 // Configure against https proxy server "myproxy:70".
4283 session_deps_.proxy_service.reset(
4284 ProxyService::CreateFixed("https://myproxy:70"));
4285 BoundTestNetLog log;
4286 session_deps_.net_log = log.bound().net_log();
4287 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4289 // Since we have proxy, should use full url
4290 MockWrite data_writes1[] = {
4291 MockWrite(
4292 "GET http://www.example.org/ HTTP/1.1\r\n"
4293 "Host: www.example.org\r\n"
4294 "Proxy-Connection: keep-alive\r\n\r\n"),
4296 // After calling trans->RestartWithAuth(), this is the request we should
4297 // be issuing -- the final header line contains the credentials.
4298 MockWrite(
4299 "GET http://www.example.org/ HTTP/1.1\r\n"
4300 "Host: www.example.org\r\n"
4301 "Proxy-Connection: keep-alive\r\n"
4302 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4305 // The proxy responds to the GET with a 407, using a persistent
4306 // connection.
4307 MockRead data_reads1[] = {
4308 // No credentials.
4309 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4310 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4311 MockRead("Proxy-Connection: keep-alive\r\n"),
4312 MockRead("Content-Length: 0\r\n\r\n"),
4314 MockRead("HTTP/1.1 200 OK\r\n"),
4315 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4316 MockRead("Content-Length: 100\r\n\r\n"),
4317 MockRead(SYNCHRONOUS, OK),
4320 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4321 data_writes1, arraysize(data_writes1));
4322 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4323 SSLSocketDataProvider ssl(ASYNC, OK);
4324 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4326 TestCompletionCallback callback1;
4328 scoped_ptr<HttpTransaction> trans(
4329 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4331 int rv = trans->Start(&request, callback1.callback(), log.bound());
4332 EXPECT_EQ(ERR_IO_PENDING, rv);
4334 rv = callback1.WaitForResult();
4335 EXPECT_EQ(OK, rv);
4337 LoadTimingInfo load_timing_info;
4338 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4339 TestLoadTimingNotReused(load_timing_info,
4340 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4342 const HttpResponseInfo* response = trans->GetResponseInfo();
4343 ASSERT_TRUE(response != NULL);
4344 ASSERT_FALSE(response->headers.get() == NULL);
4345 EXPECT_EQ(407, response->headers->response_code());
4346 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4347 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4349 TestCompletionCallback callback2;
4351 rv = trans->RestartWithAuth(
4352 AuthCredentials(kFoo, kBar), callback2.callback());
4353 EXPECT_EQ(ERR_IO_PENDING, rv);
4355 rv = callback2.WaitForResult();
4356 EXPECT_EQ(OK, rv);
4358 load_timing_info = LoadTimingInfo();
4359 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4360 // Retrying with HTTP AUTH is considered to be reusing a socket.
4361 TestLoadTimingReused(load_timing_info);
4363 response = trans->GetResponseInfo();
4364 ASSERT_TRUE(response != NULL);
4366 EXPECT_TRUE(response->headers->IsKeepAlive());
4367 EXPECT_EQ(200, response->headers->response_code());
4368 EXPECT_EQ(100, response->headers->GetContentLength());
4369 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4371 // The password prompt info should not be set.
4372 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4375 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4376 const MockRead& status, int expected_status) {
4377 HttpRequestInfo request;
4378 request.method = "GET";
4379 request.url = GURL("https://www.example.org/");
4380 request.load_flags = 0;
4382 // Configure against proxy server "myproxy:70".
4383 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4384 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4386 // Since we have proxy, should try to establish tunnel.
4387 MockWrite data_writes[] = {
4388 MockWrite(
4389 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4390 "Host: www.example.org\r\n"
4391 "Proxy-Connection: keep-alive\r\n\r\n"),
4394 MockRead data_reads[] = {
4395 status,
4396 MockRead("Content-Length: 10\r\n\r\n"),
4397 // No response body because the test stops reading here.
4398 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4401 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4402 data_writes, arraysize(data_writes));
4403 session_deps_.socket_factory->AddSocketDataProvider(&data);
4405 TestCompletionCallback callback;
4407 scoped_ptr<HttpTransaction> trans(
4408 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4410 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4411 EXPECT_EQ(ERR_IO_PENDING, rv);
4413 rv = callback.WaitForResult();
4414 EXPECT_EQ(expected_status, rv);
4417 void HttpNetworkTransactionTest::ConnectStatusHelper(
4418 const MockRead& status) {
4419 ConnectStatusHelperWithExpectedStatus(
4420 status, ERR_TUNNEL_CONNECTION_FAILED);
4423 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4424 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4427 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4428 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4431 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4432 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4435 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4436 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4439 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4440 ConnectStatusHelper(
4441 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4444 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4445 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4448 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4449 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4452 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4453 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4456 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4457 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4460 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4461 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4464 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4465 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4468 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4469 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4472 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4473 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4476 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4477 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4480 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4481 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4484 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4485 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4488 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4489 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4492 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4493 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4496 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4497 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4500 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4501 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4504 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4505 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4508 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4509 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4512 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4513 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4516 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4517 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4520 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4521 ConnectStatusHelperWithExpectedStatus(
4522 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4523 ERR_PROXY_AUTH_UNSUPPORTED);
4526 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4527 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4530 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4531 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4534 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4535 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4538 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4539 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4542 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4543 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4546 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4547 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4550 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4551 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4554 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4555 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4558 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4559 ConnectStatusHelper(
4560 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4563 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4564 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4567 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4568 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4571 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4572 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4575 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4576 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4579 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4580 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4583 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4584 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4587 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4588 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4591 // Test the flow when both the proxy server AND origin server require
4592 // authentication. Again, this uses basic auth for both since that is
4593 // the simplest to mock.
4594 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4595 HttpRequestInfo request;
4596 request.method = "GET";
4597 request.url = GURL("http://www.example.org/");
4598 request.load_flags = 0;
4600 // Configure against proxy server "myproxy:70".
4601 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4602 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4604 scoped_ptr<HttpTransaction> trans(
4605 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4607 MockWrite data_writes1[] = {
4608 MockWrite(
4609 "GET http://www.example.org/ HTTP/1.1\r\n"
4610 "Host: www.example.org\r\n"
4611 "Proxy-Connection: keep-alive\r\n\r\n"),
4614 MockRead data_reads1[] = {
4615 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4616 // Give a couple authenticate options (only the middle one is actually
4617 // supported).
4618 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4619 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4620 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4622 // Large content-length -- won't matter, as connection will be reset.
4623 MockRead("Content-Length: 10000\r\n\r\n"),
4624 MockRead(SYNCHRONOUS, ERR_FAILED),
4627 // After calling trans->RestartWithAuth() the first time, this is the
4628 // request we should be issuing -- the final header line contains the
4629 // proxy's credentials.
4630 MockWrite data_writes2[] = {
4631 MockWrite(
4632 "GET http://www.example.org/ HTTP/1.1\r\n"
4633 "Host: www.example.org\r\n"
4634 "Proxy-Connection: keep-alive\r\n"
4635 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4638 // Now the proxy server lets the request pass through to origin server.
4639 // The origin server responds with a 401.
4640 MockRead data_reads2[] = {
4641 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4642 // Note: We are using the same realm-name as the proxy server. This is
4643 // completely valid, as realms are unique across hosts.
4644 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4645 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4646 MockRead("Content-Length: 2000\r\n\r\n"),
4647 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4650 // After calling trans->RestartWithAuth() the second time, we should send
4651 // the credentials for both the proxy and origin server.
4652 MockWrite data_writes3[] = {
4653 MockWrite(
4654 "GET http://www.example.org/ HTTP/1.1\r\n"
4655 "Host: www.example.org\r\n"
4656 "Proxy-Connection: keep-alive\r\n"
4657 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4658 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4661 // Lastly we get the desired content.
4662 MockRead data_reads3[] = {
4663 MockRead("HTTP/1.0 200 OK\r\n"),
4664 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4665 MockRead("Content-Length: 100\r\n\r\n"),
4666 MockRead(SYNCHRONOUS, OK),
4669 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4670 data_writes1, arraysize(data_writes1));
4671 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4672 data_writes2, arraysize(data_writes2));
4673 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4674 data_writes3, arraysize(data_writes3));
4675 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4676 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4677 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4679 TestCompletionCallback callback1;
4681 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4682 EXPECT_EQ(ERR_IO_PENDING, rv);
4684 rv = callback1.WaitForResult();
4685 EXPECT_EQ(OK, rv);
4687 const HttpResponseInfo* response = trans->GetResponseInfo();
4688 ASSERT_TRUE(response != NULL);
4689 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4691 TestCompletionCallback callback2;
4693 rv = trans->RestartWithAuth(
4694 AuthCredentials(kFoo, kBar), callback2.callback());
4695 EXPECT_EQ(ERR_IO_PENDING, rv);
4697 rv = callback2.WaitForResult();
4698 EXPECT_EQ(OK, rv);
4700 response = trans->GetResponseInfo();
4701 ASSERT_TRUE(response != NULL);
4702 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4704 TestCompletionCallback callback3;
4706 rv = trans->RestartWithAuth(
4707 AuthCredentials(kFoo2, kBar2), callback3.callback());
4708 EXPECT_EQ(ERR_IO_PENDING, rv);
4710 rv = callback3.WaitForResult();
4711 EXPECT_EQ(OK, rv);
4713 response = trans->GetResponseInfo();
4714 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4715 EXPECT_EQ(100, response->headers->GetContentLength());
4718 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4719 // can't hook into its internals to cause it to generate predictable NTLM
4720 // authorization headers.
4721 #if defined(NTLM_PORTABLE)
4722 // The NTLM authentication unit tests were generated by capturing the HTTP
4723 // requests and responses using Fiddler 2 and inspecting the generated random
4724 // bytes in the debugger.
4726 // Enter the correct password and authenticate successfully.
4727 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4728 HttpRequestInfo request;
4729 request.method = "GET";
4730 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4732 // Ensure load is not disrupted by flags which suppress behaviour specific
4733 // to other auth schemes.
4734 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4736 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4737 MockGetHostName);
4738 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4740 MockWrite data_writes1[] = {
4741 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4742 "Host: 172.22.68.17\r\n"
4743 "Connection: keep-alive\r\n\r\n"),
4746 MockRead data_reads1[] = {
4747 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4748 // Negotiate and NTLM are often requested together. However, we only want
4749 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4750 // the header that requests Negotiate for this test.
4751 MockRead("WWW-Authenticate: NTLM\r\n"),
4752 MockRead("Connection: close\r\n"),
4753 MockRead("Content-Length: 42\r\n"),
4754 MockRead("Content-Type: text/html\r\n\r\n"),
4755 // Missing content -- won't matter, as connection will be reset.
4756 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4759 MockWrite data_writes2[] = {
4760 // After restarting with a null identity, this is the
4761 // request we should be issuing -- the final header line contains a Type
4762 // 1 message.
4763 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4764 "Host: 172.22.68.17\r\n"
4765 "Connection: keep-alive\r\n"
4766 "Authorization: NTLM "
4767 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4769 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4770 // (the credentials for the origin server). The second request continues
4771 // on the same connection.
4772 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4773 "Host: 172.22.68.17\r\n"
4774 "Connection: keep-alive\r\n"
4775 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4776 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4777 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4778 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4779 "ahlhx5I=\r\n\r\n"),
4782 MockRead data_reads2[] = {
4783 // The origin server responds with a Type 2 message.
4784 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4785 MockRead("WWW-Authenticate: NTLM "
4786 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4787 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4788 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4789 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4790 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4791 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4792 "BtAAAAAAA=\r\n"),
4793 MockRead("Content-Length: 42\r\n"),
4794 MockRead("Content-Type: text/html\r\n\r\n"),
4795 MockRead("You are not authorized to view this page\r\n"),
4797 // Lastly we get the desired content.
4798 MockRead("HTTP/1.1 200 OK\r\n"),
4799 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4800 MockRead("Content-Length: 13\r\n\r\n"),
4801 MockRead("Please Login\r\n"),
4802 MockRead(SYNCHRONOUS, OK),
4805 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4806 data_writes1, arraysize(data_writes1));
4807 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4808 data_writes2, arraysize(data_writes2));
4809 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4810 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4812 TestCompletionCallback callback1;
4814 scoped_ptr<HttpTransaction> trans(
4815 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4817 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4818 EXPECT_EQ(ERR_IO_PENDING, rv);
4820 rv = callback1.WaitForResult();
4821 EXPECT_EQ(OK, rv);
4823 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4825 const HttpResponseInfo* response = trans->GetResponseInfo();
4826 ASSERT_FALSE(response == NULL);
4827 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4829 TestCompletionCallback callback2;
4831 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4832 callback2.callback());
4833 EXPECT_EQ(ERR_IO_PENDING, rv);
4835 rv = callback2.WaitForResult();
4836 EXPECT_EQ(OK, rv);
4838 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4840 response = trans->GetResponseInfo();
4841 ASSERT_TRUE(response != NULL);
4842 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4844 TestCompletionCallback callback3;
4846 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4847 EXPECT_EQ(ERR_IO_PENDING, rv);
4849 rv = callback3.WaitForResult();
4850 EXPECT_EQ(OK, rv);
4852 response = trans->GetResponseInfo();
4853 ASSERT_TRUE(response != NULL);
4854 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4855 EXPECT_EQ(13, response->headers->GetContentLength());
4858 // Enter a wrong password, and then the correct one.
4859 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4860 HttpRequestInfo request;
4861 request.method = "GET";
4862 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4863 request.load_flags = 0;
4865 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4866 MockGetHostName);
4867 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4869 MockWrite data_writes1[] = {
4870 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4871 "Host: 172.22.68.17\r\n"
4872 "Connection: keep-alive\r\n\r\n"),
4875 MockRead data_reads1[] = {
4876 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4877 // Negotiate and NTLM are often requested together. However, we only want
4878 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4879 // the header that requests Negotiate for this test.
4880 MockRead("WWW-Authenticate: NTLM\r\n"),
4881 MockRead("Connection: close\r\n"),
4882 MockRead("Content-Length: 42\r\n"),
4883 MockRead("Content-Type: text/html\r\n\r\n"),
4884 // Missing content -- won't matter, as connection will be reset.
4885 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4888 MockWrite data_writes2[] = {
4889 // After restarting with a null identity, this is the
4890 // request we should be issuing -- the final header line contains a Type
4891 // 1 message.
4892 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4893 "Host: 172.22.68.17\r\n"
4894 "Connection: keep-alive\r\n"
4895 "Authorization: NTLM "
4896 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4898 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4899 // (the credentials for the origin server). The second request continues
4900 // on the same connection.
4901 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4902 "Host: 172.22.68.17\r\n"
4903 "Connection: keep-alive\r\n"
4904 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4905 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4906 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4907 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4908 "4Ww7b7E=\r\n\r\n"),
4911 MockRead data_reads2[] = {
4912 // The origin server responds with a Type 2 message.
4913 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4914 MockRead("WWW-Authenticate: NTLM "
4915 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4916 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4917 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4918 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4919 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4920 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4921 "BtAAAAAAA=\r\n"),
4922 MockRead("Content-Length: 42\r\n"),
4923 MockRead("Content-Type: text/html\r\n\r\n"),
4924 MockRead("You are not authorized to view this page\r\n"),
4926 // Wrong password.
4927 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4928 MockRead("WWW-Authenticate: NTLM\r\n"),
4929 MockRead("Connection: close\r\n"),
4930 MockRead("Content-Length: 42\r\n"),
4931 MockRead("Content-Type: text/html\r\n\r\n"),
4932 // Missing content -- won't matter, as connection will be reset.
4933 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4936 MockWrite data_writes3[] = {
4937 // After restarting with a null identity, this is the
4938 // request we should be issuing -- the final header line contains a Type
4939 // 1 message.
4940 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4941 "Host: 172.22.68.17\r\n"
4942 "Connection: keep-alive\r\n"
4943 "Authorization: NTLM "
4944 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4946 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4947 // (the credentials for the origin server). The second request continues
4948 // on the same connection.
4949 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4950 "Host: 172.22.68.17\r\n"
4951 "Connection: keep-alive\r\n"
4952 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4953 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4954 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4955 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4956 "+4MUm7c=\r\n\r\n"),
4959 MockRead data_reads3[] = {
4960 // The origin server responds with a Type 2 message.
4961 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4962 MockRead("WWW-Authenticate: NTLM "
4963 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4964 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4965 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4966 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4967 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4968 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4969 "BtAAAAAAA=\r\n"),
4970 MockRead("Content-Length: 42\r\n"),
4971 MockRead("Content-Type: text/html\r\n\r\n"),
4972 MockRead("You are not authorized to view this page\r\n"),
4974 // Lastly we get the desired content.
4975 MockRead("HTTP/1.1 200 OK\r\n"),
4976 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4977 MockRead("Content-Length: 13\r\n\r\n"),
4978 MockRead("Please Login\r\n"),
4979 MockRead(SYNCHRONOUS, OK),
4982 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4983 data_writes1, arraysize(data_writes1));
4984 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4985 data_writes2, arraysize(data_writes2));
4986 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4987 data_writes3, arraysize(data_writes3));
4988 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4989 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4990 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4992 TestCompletionCallback callback1;
4994 scoped_ptr<HttpTransaction> trans(
4995 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4997 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4998 EXPECT_EQ(ERR_IO_PENDING, rv);
5000 rv = callback1.WaitForResult();
5001 EXPECT_EQ(OK, rv);
5003 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5005 const HttpResponseInfo* response = trans->GetResponseInfo();
5006 ASSERT_TRUE(response != NULL);
5007 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
5009 TestCompletionCallback callback2;
5011 // Enter the wrong password.
5012 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
5013 callback2.callback());
5014 EXPECT_EQ(ERR_IO_PENDING, rv);
5016 rv = callback2.WaitForResult();
5017 EXPECT_EQ(OK, rv);
5019 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5020 TestCompletionCallback callback3;
5021 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
5022 EXPECT_EQ(ERR_IO_PENDING, rv);
5023 rv = callback3.WaitForResult();
5024 EXPECT_EQ(OK, rv);
5025 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5027 response = trans->GetResponseInfo();
5028 ASSERT_FALSE(response == NULL);
5029 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
5031 TestCompletionCallback callback4;
5033 // Now enter the right password.
5034 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
5035 callback4.callback());
5036 EXPECT_EQ(ERR_IO_PENDING, rv);
5038 rv = callback4.WaitForResult();
5039 EXPECT_EQ(OK, rv);
5041 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5043 TestCompletionCallback callback5;
5045 // One more roundtrip
5046 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
5047 EXPECT_EQ(ERR_IO_PENDING, rv);
5049 rv = callback5.WaitForResult();
5050 EXPECT_EQ(OK, rv);
5052 response = trans->GetResponseInfo();
5053 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5054 EXPECT_EQ(13, response->headers->GetContentLength());
5056 #endif // NTLM_PORTABLE
5058 // Test reading a server response which has only headers, and no body.
5059 // After some maximum number of bytes is consumed, the transaction should
5060 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
5061 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
5062 HttpRequestInfo request;
5063 request.method = "GET";
5064 request.url = GURL("http://www.example.org/");
5065 request.load_flags = 0;
5067 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5068 scoped_ptr<HttpTransaction> trans(
5069 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5071 // Respond with 300 kb of headers (we should fail after 256 kb).
5072 std::string large_headers_string;
5073 FillLargeHeadersString(&large_headers_string, 300 * 1024);
5075 MockRead data_reads[] = {
5076 MockRead("HTTP/1.0 200 OK\r\n"),
5077 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
5078 MockRead("\r\nBODY"),
5079 MockRead(SYNCHRONOUS, OK),
5081 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5082 session_deps_.socket_factory->AddSocketDataProvider(&data);
5084 TestCompletionCallback callback;
5086 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5087 EXPECT_EQ(ERR_IO_PENDING, rv);
5089 rv = callback.WaitForResult();
5090 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
5093 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5094 // establish tunnel.
5095 // http://code.google.com/p/chromium/issues/detail?id=3772
5096 TEST_P(HttpNetworkTransactionTest,
5097 DontRecycleTransportSocketForSSLTunnel) {
5098 HttpRequestInfo request;
5099 request.method = "GET";
5100 request.url = GURL("https://www.example.org/");
5101 request.load_flags = 0;
5103 // Configure against proxy server "myproxy:70".
5104 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5106 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5108 scoped_ptr<HttpTransaction> trans(
5109 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5111 // Since we have proxy, should try to establish tunnel.
5112 MockWrite data_writes1[] = {
5113 MockWrite(
5114 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5115 "Host: www.example.org\r\n"
5116 "Proxy-Connection: keep-alive\r\n\r\n"),
5119 // The proxy responds to the connect with a 404, using a persistent
5120 // connection. Usually a proxy would return 501 (not implemented),
5121 // or 200 (tunnel established).
5122 MockRead data_reads1[] = {
5123 MockRead("HTTP/1.1 404 Not Found\r\n"),
5124 MockRead("Content-Length: 10\r\n\r\n"),
5125 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
5128 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5129 data_writes1, arraysize(data_writes1));
5130 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5132 TestCompletionCallback callback1;
5134 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5135 EXPECT_EQ(ERR_IO_PENDING, rv);
5137 rv = callback1.WaitForResult();
5138 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5140 // Empty the current queue. This is necessary because idle sockets are
5141 // added to the connection pool asynchronously with a PostTask.
5142 base::MessageLoop::current()->RunUntilIdle();
5144 // We now check to make sure the TCPClientSocket was not added back to
5145 // the pool.
5146 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5147 trans.reset();
5148 base::MessageLoop::current()->RunUntilIdle();
5149 // Make sure that the socket didn't get recycled after calling the destructor.
5150 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5153 // Make sure that we recycle a socket after reading all of the response body.
5154 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
5155 HttpRequestInfo request;
5156 request.method = "GET";
5157 request.url = GURL("http://www.example.org/");
5158 request.load_flags = 0;
5160 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5162 scoped_ptr<HttpTransaction> trans(
5163 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5165 MockRead data_reads[] = {
5166 // A part of the response body is received with the response headers.
5167 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5168 // The rest of the response body is received in two parts.
5169 MockRead("lo"),
5170 MockRead(" world"),
5171 MockRead("junk"), // Should not be read!!
5172 MockRead(SYNCHRONOUS, OK),
5175 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5176 session_deps_.socket_factory->AddSocketDataProvider(&data);
5178 TestCompletionCallback callback;
5180 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5181 EXPECT_EQ(ERR_IO_PENDING, rv);
5183 rv = callback.WaitForResult();
5184 EXPECT_EQ(OK, rv);
5186 const HttpResponseInfo* response = trans->GetResponseInfo();
5187 ASSERT_TRUE(response != NULL);
5189 EXPECT_TRUE(response->headers.get() != NULL);
5190 std::string status_line = response->headers->GetStatusLine();
5191 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5193 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5195 std::string response_data;
5196 rv = ReadTransaction(trans.get(), &response_data);
5197 EXPECT_EQ(OK, rv);
5198 EXPECT_EQ("hello world", response_data);
5200 // Empty the current queue. This is necessary because idle sockets are
5201 // added to the connection pool asynchronously with a PostTask.
5202 base::MessageLoop::current()->RunUntilIdle();
5204 // We now check to make sure the socket was added back to the pool.
5205 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5208 // Make sure that we recycle a SSL socket after reading all of the response
5209 // body.
5210 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
5211 HttpRequestInfo request;
5212 request.method = "GET";
5213 request.url = GURL("https://www.example.org/");
5214 request.load_flags = 0;
5216 MockWrite data_writes[] = {
5217 MockWrite(
5218 "GET / HTTP/1.1\r\n"
5219 "Host: www.example.org\r\n"
5220 "Connection: keep-alive\r\n\r\n"),
5223 MockRead data_reads[] = {
5224 MockRead("HTTP/1.1 200 OK\r\n"),
5225 MockRead("Content-Length: 11\r\n\r\n"),
5226 MockRead("hello world"),
5227 MockRead(SYNCHRONOUS, OK),
5230 SSLSocketDataProvider ssl(ASYNC, OK);
5231 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5233 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5234 data_writes, arraysize(data_writes));
5235 session_deps_.socket_factory->AddSocketDataProvider(&data);
5237 TestCompletionCallback callback;
5239 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5240 scoped_ptr<HttpTransaction> trans(
5241 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5243 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5245 EXPECT_EQ(ERR_IO_PENDING, rv);
5246 EXPECT_EQ(OK, callback.WaitForResult());
5248 const HttpResponseInfo* response = trans->GetResponseInfo();
5249 ASSERT_TRUE(response != NULL);
5250 ASSERT_TRUE(response->headers.get() != NULL);
5251 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5253 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5255 std::string response_data;
5256 rv = ReadTransaction(trans.get(), &response_data);
5257 EXPECT_EQ(OK, rv);
5258 EXPECT_EQ("hello world", response_data);
5260 // Empty the current queue. This is necessary because idle sockets are
5261 // added to the connection pool asynchronously with a PostTask.
5262 base::MessageLoop::current()->RunUntilIdle();
5264 // We now check to make sure the socket was added back to the pool.
5265 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5268 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5269 // from the pool and make sure that we recover okay.
5270 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
5271 HttpRequestInfo request;
5272 request.method = "GET";
5273 request.url = GURL("https://www.example.org/");
5274 request.load_flags = 0;
5276 MockWrite data_writes[] = {
5277 MockWrite(
5278 "GET / HTTP/1.1\r\n"
5279 "Host: www.example.org\r\n"
5280 "Connection: keep-alive\r\n\r\n"),
5281 MockWrite(
5282 "GET / HTTP/1.1\r\n"
5283 "Host: www.example.org\r\n"
5284 "Connection: keep-alive\r\n\r\n"),
5287 MockRead data_reads[] = {
5288 MockRead("HTTP/1.1 200 OK\r\n"),
5289 MockRead("Content-Length: 11\r\n\r\n"),
5290 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
5291 MockRead("hello world"),
5292 MockRead(ASYNC, 0, 0) // EOF
5295 SSLSocketDataProvider ssl(ASYNC, OK);
5296 SSLSocketDataProvider ssl2(ASYNC, OK);
5297 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5298 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5300 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5301 data_writes, arraysize(data_writes));
5302 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5303 data_writes, arraysize(data_writes));
5304 session_deps_.socket_factory->AddSocketDataProvider(&data);
5305 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5307 TestCompletionCallback callback;
5309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5310 scoped_ptr<HttpTransaction> trans(
5311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5313 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5315 EXPECT_EQ(ERR_IO_PENDING, rv);
5316 EXPECT_EQ(OK, callback.WaitForResult());
5318 const HttpResponseInfo* response = trans->GetResponseInfo();
5319 ASSERT_TRUE(response != NULL);
5320 ASSERT_TRUE(response->headers.get() != NULL);
5321 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5323 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5325 std::string response_data;
5326 rv = ReadTransaction(trans.get(), &response_data);
5327 EXPECT_EQ(OK, rv);
5328 EXPECT_EQ("hello world", response_data);
5330 // Empty the current queue. This is necessary because idle sockets are
5331 // added to the connection pool asynchronously with a PostTask.
5332 base::MessageLoop::current()->RunUntilIdle();
5334 // We now check to make sure the socket was added back to the pool.
5335 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5337 // Now start the second transaction, which should reuse the previous socket.
5339 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5341 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5343 EXPECT_EQ(ERR_IO_PENDING, rv);
5344 EXPECT_EQ(OK, callback.WaitForResult());
5346 response = trans->GetResponseInfo();
5347 ASSERT_TRUE(response != NULL);
5348 ASSERT_TRUE(response->headers.get() != NULL);
5349 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5351 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5353 rv = ReadTransaction(trans.get(), &response_data);
5354 EXPECT_EQ(OK, rv);
5355 EXPECT_EQ("hello world", response_data);
5357 // Empty the current queue. This is necessary because idle sockets are
5358 // added to the connection pool asynchronously with a PostTask.
5359 base::MessageLoop::current()->RunUntilIdle();
5361 // We now check to make sure the socket was added back to the pool.
5362 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5365 // Make sure that we recycle a socket after a zero-length response.
5366 // http://crbug.com/9880
5367 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
5368 HttpRequestInfo request;
5369 request.method = "GET";
5370 request.url = GURL(
5371 "http://www.example.org/csi?v=3&s=web&action=&"
5372 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5373 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5374 "rt=prt.2642,ol.2649,xjs.2951");
5375 request.load_flags = 0;
5377 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5379 scoped_ptr<HttpTransaction> trans(
5380 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5382 MockRead data_reads[] = {
5383 MockRead("HTTP/1.1 204 No Content\r\n"
5384 "Content-Length: 0\r\n"
5385 "Content-Type: text/html\r\n\r\n"),
5386 MockRead("junk"), // Should not be read!!
5387 MockRead(SYNCHRONOUS, OK),
5390 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5391 session_deps_.socket_factory->AddSocketDataProvider(&data);
5393 TestCompletionCallback callback;
5395 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5396 EXPECT_EQ(ERR_IO_PENDING, rv);
5398 rv = callback.WaitForResult();
5399 EXPECT_EQ(OK, rv);
5401 const HttpResponseInfo* response = trans->GetResponseInfo();
5402 ASSERT_TRUE(response != NULL);
5404 EXPECT_TRUE(response->headers.get() != NULL);
5405 std::string status_line = response->headers->GetStatusLine();
5406 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5408 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5410 std::string response_data;
5411 rv = ReadTransaction(trans.get(), &response_data);
5412 EXPECT_EQ(OK, rv);
5413 EXPECT_EQ("", response_data);
5415 // Empty the current queue. This is necessary because idle sockets are
5416 // added to the connection pool asynchronously with a PostTask.
5417 base::MessageLoop::current()->RunUntilIdle();
5419 // We now check to make sure the socket was added back to the pool.
5420 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5423 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5424 ScopedVector<UploadElementReader> element_readers;
5425 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5426 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
5428 HttpRequestInfo request[2];
5429 // Transaction 1: a GET request that succeeds. The socket is recycled
5430 // after use.
5431 request[0].method = "GET";
5432 request[0].url = GURL("http://www.google.com/");
5433 request[0].load_flags = 0;
5434 // Transaction 2: a POST request. Reuses the socket kept alive from
5435 // transaction 1. The first attempts fails when writing the POST data.
5436 // This causes the transaction to retry with a new socket. The second
5437 // attempt succeeds.
5438 request[1].method = "POST";
5439 request[1].url = GURL("http://www.google.com/login.cgi");
5440 request[1].upload_data_stream = &upload_data_stream;
5441 request[1].load_flags = 0;
5443 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5445 // The first socket is used for transaction 1 and the first attempt of
5446 // transaction 2.
5448 // The response of transaction 1.
5449 MockRead data_reads1[] = {
5450 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5451 MockRead("hello world"),
5452 MockRead(SYNCHRONOUS, OK),
5454 // The mock write results of transaction 1 and the first attempt of
5455 // transaction 2.
5456 MockWrite data_writes1[] = {
5457 MockWrite(SYNCHRONOUS, 64), // GET
5458 MockWrite(SYNCHRONOUS, 93), // POST
5459 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5461 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5462 data_writes1, arraysize(data_writes1));
5464 // The second socket is used for the second attempt of transaction 2.
5466 // The response of transaction 2.
5467 MockRead data_reads2[] = {
5468 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5469 MockRead("welcome"),
5470 MockRead(SYNCHRONOUS, OK),
5472 // The mock write results of the second attempt of transaction 2.
5473 MockWrite data_writes2[] = {
5474 MockWrite(SYNCHRONOUS, 93), // POST
5475 MockWrite(SYNCHRONOUS, 3), // POST data
5477 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5478 data_writes2, arraysize(data_writes2));
5480 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5481 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5483 const char* const kExpectedResponseData[] = {
5484 "hello world", "welcome"
5487 for (int i = 0; i < 2; ++i) {
5488 scoped_ptr<HttpTransaction> trans(
5489 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5491 TestCompletionCallback callback;
5493 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5494 EXPECT_EQ(ERR_IO_PENDING, rv);
5496 rv = callback.WaitForResult();
5497 EXPECT_EQ(OK, rv);
5499 const HttpResponseInfo* response = trans->GetResponseInfo();
5500 ASSERT_TRUE(response != NULL);
5502 EXPECT_TRUE(response->headers.get() != NULL);
5503 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5505 std::string response_data;
5506 rv = ReadTransaction(trans.get(), &response_data);
5507 EXPECT_EQ(OK, rv);
5508 EXPECT_EQ(kExpectedResponseData[i], response_data);
5512 // Test the request-challenge-retry sequence for basic auth when there is
5513 // an identity in the URL. The request should be sent as normal, but when
5514 // it fails the identity from the URL is used to answer the challenge.
5515 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5516 HttpRequestInfo request;
5517 request.method = "GET";
5518 request.url = GURL("http://foo:b@r@www.example.org/");
5519 request.load_flags = LOAD_NORMAL;
5521 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5522 scoped_ptr<HttpTransaction> trans(
5523 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5525 // The password contains an escaped character -- for this test to pass it
5526 // will need to be unescaped by HttpNetworkTransaction.
5527 EXPECT_EQ("b%40r", request.url.password());
5529 MockWrite data_writes1[] = {
5530 MockWrite(
5531 "GET / HTTP/1.1\r\n"
5532 "Host: www.example.org\r\n"
5533 "Connection: keep-alive\r\n\r\n"),
5536 MockRead data_reads1[] = {
5537 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5538 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5539 MockRead("Content-Length: 10\r\n\r\n"),
5540 MockRead(SYNCHRONOUS, ERR_FAILED),
5543 // After the challenge above, the transaction will be restarted using the
5544 // identity from the url (foo, b@r) to answer the challenge.
5545 MockWrite data_writes2[] = {
5546 MockWrite(
5547 "GET / HTTP/1.1\r\n"
5548 "Host: www.example.org\r\n"
5549 "Connection: keep-alive\r\n"
5550 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5553 MockRead data_reads2[] = {
5554 MockRead("HTTP/1.0 200 OK\r\n"),
5555 MockRead("Content-Length: 100\r\n\r\n"),
5556 MockRead(SYNCHRONOUS, OK),
5559 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5560 data_writes1, arraysize(data_writes1));
5561 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5562 data_writes2, arraysize(data_writes2));
5563 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5564 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5566 TestCompletionCallback callback1;
5567 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5568 EXPECT_EQ(ERR_IO_PENDING, rv);
5569 rv = callback1.WaitForResult();
5570 EXPECT_EQ(OK, rv);
5571 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5573 TestCompletionCallback callback2;
5574 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5575 EXPECT_EQ(ERR_IO_PENDING, rv);
5576 rv = callback2.WaitForResult();
5577 EXPECT_EQ(OK, rv);
5578 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5580 const HttpResponseInfo* response = trans->GetResponseInfo();
5581 ASSERT_TRUE(response != NULL);
5583 // There is no challenge info, since the identity in URL worked.
5584 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5586 EXPECT_EQ(100, response->headers->GetContentLength());
5588 // Empty the current queue.
5589 base::MessageLoop::current()->RunUntilIdle();
5592 // Test the request-challenge-retry sequence for basic auth when there is an
5593 // incorrect identity in the URL. The identity from the URL should be used only
5594 // once.
5595 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5596 HttpRequestInfo request;
5597 request.method = "GET";
5598 // Note: the URL has a username:password in it. The password "baz" is
5599 // wrong (should be "bar").
5600 request.url = GURL("http://foo:baz@www.example.org/");
5602 request.load_flags = LOAD_NORMAL;
5604 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5605 scoped_ptr<HttpTransaction> trans(
5606 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5608 MockWrite data_writes1[] = {
5609 MockWrite(
5610 "GET / HTTP/1.1\r\n"
5611 "Host: www.example.org\r\n"
5612 "Connection: keep-alive\r\n\r\n"),
5615 MockRead data_reads1[] = {
5616 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5617 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5618 MockRead("Content-Length: 10\r\n\r\n"),
5619 MockRead(SYNCHRONOUS, ERR_FAILED),
5622 // After the challenge above, the transaction will be restarted using the
5623 // identity from the url (foo, baz) to answer the challenge.
5624 MockWrite data_writes2[] = {
5625 MockWrite(
5626 "GET / HTTP/1.1\r\n"
5627 "Host: www.example.org\r\n"
5628 "Connection: keep-alive\r\n"
5629 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5632 MockRead data_reads2[] = {
5633 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5634 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5635 MockRead("Content-Length: 10\r\n\r\n"),
5636 MockRead(SYNCHRONOUS, ERR_FAILED),
5639 // After the challenge above, the transaction will be restarted using the
5640 // identity supplied by the user (foo, bar) to answer the challenge.
5641 MockWrite data_writes3[] = {
5642 MockWrite(
5643 "GET / HTTP/1.1\r\n"
5644 "Host: www.example.org\r\n"
5645 "Connection: keep-alive\r\n"
5646 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5649 MockRead data_reads3[] = {
5650 MockRead("HTTP/1.0 200 OK\r\n"),
5651 MockRead("Content-Length: 100\r\n\r\n"),
5652 MockRead(SYNCHRONOUS, OK),
5655 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5656 data_writes1, arraysize(data_writes1));
5657 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5658 data_writes2, arraysize(data_writes2));
5659 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5660 data_writes3, arraysize(data_writes3));
5661 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5662 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5663 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5665 TestCompletionCallback callback1;
5667 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5668 EXPECT_EQ(ERR_IO_PENDING, rv);
5670 rv = callback1.WaitForResult();
5671 EXPECT_EQ(OK, rv);
5673 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5674 TestCompletionCallback callback2;
5675 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5676 EXPECT_EQ(ERR_IO_PENDING, rv);
5677 rv = callback2.WaitForResult();
5678 EXPECT_EQ(OK, rv);
5679 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5681 const HttpResponseInfo* response = trans->GetResponseInfo();
5682 ASSERT_TRUE(response != NULL);
5683 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5685 TestCompletionCallback callback3;
5686 rv = trans->RestartWithAuth(
5687 AuthCredentials(kFoo, kBar), callback3.callback());
5688 EXPECT_EQ(ERR_IO_PENDING, rv);
5689 rv = callback3.WaitForResult();
5690 EXPECT_EQ(OK, rv);
5691 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5693 response = trans->GetResponseInfo();
5694 ASSERT_TRUE(response != NULL);
5696 // There is no challenge info, since the identity worked.
5697 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5699 EXPECT_EQ(100, response->headers->GetContentLength());
5701 // Empty the current queue.
5702 base::MessageLoop::current()->RunUntilIdle();
5706 // Test the request-challenge-retry sequence for basic auth when there is a
5707 // correct identity in the URL, but its use is being suppressed. The identity
5708 // from the URL should never be used.
5709 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5710 HttpRequestInfo request;
5711 request.method = "GET";
5712 request.url = GURL("http://foo:bar@www.example.org/");
5713 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5715 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5716 scoped_ptr<HttpTransaction> trans(
5717 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5719 MockWrite data_writes1[] = {
5720 MockWrite(
5721 "GET / HTTP/1.1\r\n"
5722 "Host: www.example.org\r\n"
5723 "Connection: keep-alive\r\n\r\n"),
5726 MockRead data_reads1[] = {
5727 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5728 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5729 MockRead("Content-Length: 10\r\n\r\n"),
5730 MockRead(SYNCHRONOUS, ERR_FAILED),
5733 // After the challenge above, the transaction will be restarted using the
5734 // identity supplied by the user, not the one in the URL, to answer the
5735 // challenge.
5736 MockWrite data_writes3[] = {
5737 MockWrite(
5738 "GET / HTTP/1.1\r\n"
5739 "Host: www.example.org\r\n"
5740 "Connection: keep-alive\r\n"
5741 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5744 MockRead data_reads3[] = {
5745 MockRead("HTTP/1.0 200 OK\r\n"),
5746 MockRead("Content-Length: 100\r\n\r\n"),
5747 MockRead(SYNCHRONOUS, OK),
5750 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5751 data_writes1, arraysize(data_writes1));
5752 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5753 data_writes3, arraysize(data_writes3));
5754 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5755 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5757 TestCompletionCallback callback1;
5758 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5759 EXPECT_EQ(ERR_IO_PENDING, rv);
5760 rv = callback1.WaitForResult();
5761 EXPECT_EQ(OK, rv);
5762 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5764 const HttpResponseInfo* response = trans->GetResponseInfo();
5765 ASSERT_TRUE(response != NULL);
5766 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5768 TestCompletionCallback callback3;
5769 rv = trans->RestartWithAuth(
5770 AuthCredentials(kFoo, kBar), callback3.callback());
5771 EXPECT_EQ(ERR_IO_PENDING, rv);
5772 rv = callback3.WaitForResult();
5773 EXPECT_EQ(OK, rv);
5774 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5776 response = trans->GetResponseInfo();
5777 ASSERT_TRUE(response != NULL);
5779 // There is no challenge info, since the identity worked.
5780 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5781 EXPECT_EQ(100, response->headers->GetContentLength());
5783 // Empty the current queue.
5784 base::MessageLoop::current()->RunUntilIdle();
5787 // Test that previously tried username/passwords for a realm get re-used.
5788 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5791 // Transaction 1: authenticate (foo, bar) on MyRealm1
5793 HttpRequestInfo request;
5794 request.method = "GET";
5795 request.url = GURL("http://www.example.org/x/y/z");
5796 request.load_flags = 0;
5798 scoped_ptr<HttpTransaction> trans(
5799 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5801 MockWrite data_writes1[] = {
5802 MockWrite(
5803 "GET /x/y/z HTTP/1.1\r\n"
5804 "Host: www.example.org\r\n"
5805 "Connection: keep-alive\r\n\r\n"),
5808 MockRead data_reads1[] = {
5809 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5810 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5811 MockRead("Content-Length: 10000\r\n\r\n"),
5812 MockRead(SYNCHRONOUS, ERR_FAILED),
5815 // Resend with authorization (username=foo, password=bar)
5816 MockWrite data_writes2[] = {
5817 MockWrite(
5818 "GET /x/y/z HTTP/1.1\r\n"
5819 "Host: www.example.org\r\n"
5820 "Connection: keep-alive\r\n"
5821 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5824 // Sever accepts the authorization.
5825 MockRead data_reads2[] = {
5826 MockRead("HTTP/1.0 200 OK\r\n"),
5827 MockRead("Content-Length: 100\r\n\r\n"),
5828 MockRead(SYNCHRONOUS, OK),
5831 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5832 data_writes1, arraysize(data_writes1));
5833 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5834 data_writes2, arraysize(data_writes2));
5835 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5836 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5838 TestCompletionCallback callback1;
5840 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5841 EXPECT_EQ(ERR_IO_PENDING, rv);
5843 rv = callback1.WaitForResult();
5844 EXPECT_EQ(OK, rv);
5846 const HttpResponseInfo* response = trans->GetResponseInfo();
5847 ASSERT_TRUE(response != NULL);
5848 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5850 TestCompletionCallback callback2;
5852 rv = trans->RestartWithAuth(
5853 AuthCredentials(kFoo, kBar), callback2.callback());
5854 EXPECT_EQ(ERR_IO_PENDING, rv);
5856 rv = callback2.WaitForResult();
5857 EXPECT_EQ(OK, rv);
5859 response = trans->GetResponseInfo();
5860 ASSERT_TRUE(response != NULL);
5861 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5862 EXPECT_EQ(100, response->headers->GetContentLength());
5865 // ------------------------------------------------------------------------
5867 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5869 HttpRequestInfo request;
5870 request.method = "GET";
5871 // Note that Transaction 1 was at /x/y/z, so this is in the same
5872 // protection space as MyRealm1.
5873 request.url = GURL("http://www.example.org/x/y/a/b");
5874 request.load_flags = 0;
5876 scoped_ptr<HttpTransaction> trans(
5877 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5879 MockWrite data_writes1[] = {
5880 MockWrite(
5881 "GET /x/y/a/b HTTP/1.1\r\n"
5882 "Host: www.example.org\r\n"
5883 "Connection: keep-alive\r\n"
5884 // Send preemptive authorization for MyRealm1
5885 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5888 // The server didn't like the preemptive authorization, and
5889 // challenges us for a different realm (MyRealm2).
5890 MockRead data_reads1[] = {
5891 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5892 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5893 MockRead("Content-Length: 10000\r\n\r\n"),
5894 MockRead(SYNCHRONOUS, ERR_FAILED),
5897 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5898 MockWrite data_writes2[] = {
5899 MockWrite(
5900 "GET /x/y/a/b HTTP/1.1\r\n"
5901 "Host: www.example.org\r\n"
5902 "Connection: keep-alive\r\n"
5903 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5906 // Sever accepts the authorization.
5907 MockRead data_reads2[] = {
5908 MockRead("HTTP/1.0 200 OK\r\n"),
5909 MockRead("Content-Length: 100\r\n\r\n"),
5910 MockRead(SYNCHRONOUS, OK),
5913 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5914 data_writes1, arraysize(data_writes1));
5915 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5916 data_writes2, arraysize(data_writes2));
5917 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5918 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5920 TestCompletionCallback callback1;
5922 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5923 EXPECT_EQ(ERR_IO_PENDING, rv);
5925 rv = callback1.WaitForResult();
5926 EXPECT_EQ(OK, rv);
5928 const HttpResponseInfo* response = trans->GetResponseInfo();
5929 ASSERT_TRUE(response != NULL);
5930 ASSERT_TRUE(response->auth_challenge.get());
5931 EXPECT_FALSE(response->auth_challenge->is_proxy);
5932 EXPECT_EQ("www.example.org:80",
5933 response->auth_challenge->challenger.ToString());
5934 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5935 EXPECT_EQ("basic", response->auth_challenge->scheme);
5937 TestCompletionCallback callback2;
5939 rv = trans->RestartWithAuth(
5940 AuthCredentials(kFoo2, kBar2), callback2.callback());
5941 EXPECT_EQ(ERR_IO_PENDING, rv);
5943 rv = callback2.WaitForResult();
5944 EXPECT_EQ(OK, rv);
5946 response = trans->GetResponseInfo();
5947 ASSERT_TRUE(response != NULL);
5948 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5949 EXPECT_EQ(100, response->headers->GetContentLength());
5952 // ------------------------------------------------------------------------
5954 // Transaction 3: Resend a request in MyRealm's protection space --
5955 // succeed with preemptive authorization.
5957 HttpRequestInfo request;
5958 request.method = "GET";
5959 request.url = GURL("http://www.example.org/x/y/z2");
5960 request.load_flags = 0;
5962 scoped_ptr<HttpTransaction> trans(
5963 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5965 MockWrite data_writes1[] = {
5966 MockWrite(
5967 "GET /x/y/z2 HTTP/1.1\r\n"
5968 "Host: www.example.org\r\n"
5969 "Connection: keep-alive\r\n"
5970 // The authorization for MyRealm1 gets sent preemptively
5971 // (since the url is in the same protection space)
5972 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5975 // Sever accepts the preemptive authorization
5976 MockRead data_reads1[] = {
5977 MockRead("HTTP/1.0 200 OK\r\n"),
5978 MockRead("Content-Length: 100\r\n\r\n"),
5979 MockRead(SYNCHRONOUS, OK),
5982 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5983 data_writes1, arraysize(data_writes1));
5984 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5986 TestCompletionCallback callback1;
5988 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5989 EXPECT_EQ(ERR_IO_PENDING, rv);
5991 rv = callback1.WaitForResult();
5992 EXPECT_EQ(OK, rv);
5994 const HttpResponseInfo* response = trans->GetResponseInfo();
5995 ASSERT_TRUE(response != NULL);
5997 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5998 EXPECT_EQ(100, response->headers->GetContentLength());
6001 // ------------------------------------------------------------------------
6003 // Transaction 4: request another URL in MyRealm (however the
6004 // url is not known to belong to the protection space, so no pre-auth).
6006 HttpRequestInfo request;
6007 request.method = "GET";
6008 request.url = GURL("http://www.example.org/x/1");
6009 request.load_flags = 0;
6011 scoped_ptr<HttpTransaction> trans(
6012 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6014 MockWrite data_writes1[] = {
6015 MockWrite(
6016 "GET /x/1 HTTP/1.1\r\n"
6017 "Host: www.example.org\r\n"
6018 "Connection: keep-alive\r\n\r\n"),
6021 MockRead data_reads1[] = {
6022 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6023 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6024 MockRead("Content-Length: 10000\r\n\r\n"),
6025 MockRead(SYNCHRONOUS, ERR_FAILED),
6028 // Resend with authorization from MyRealm's cache.
6029 MockWrite data_writes2[] = {
6030 MockWrite(
6031 "GET /x/1 HTTP/1.1\r\n"
6032 "Host: www.example.org\r\n"
6033 "Connection: keep-alive\r\n"
6034 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6037 // Sever accepts the authorization.
6038 MockRead data_reads2[] = {
6039 MockRead("HTTP/1.0 200 OK\r\n"),
6040 MockRead("Content-Length: 100\r\n\r\n"),
6041 MockRead(SYNCHRONOUS, OK),
6044 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6045 data_writes1, arraysize(data_writes1));
6046 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6047 data_writes2, arraysize(data_writes2));
6048 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6049 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6051 TestCompletionCallback callback1;
6053 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6054 EXPECT_EQ(ERR_IO_PENDING, rv);
6056 rv = callback1.WaitForResult();
6057 EXPECT_EQ(OK, rv);
6059 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6060 TestCompletionCallback callback2;
6061 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6062 EXPECT_EQ(ERR_IO_PENDING, rv);
6063 rv = callback2.WaitForResult();
6064 EXPECT_EQ(OK, rv);
6065 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6067 const HttpResponseInfo* response = trans->GetResponseInfo();
6068 ASSERT_TRUE(response != NULL);
6069 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6070 EXPECT_EQ(100, response->headers->GetContentLength());
6073 // ------------------------------------------------------------------------
6075 // Transaction 5: request a URL in MyRealm, but the server rejects the
6076 // cached identity. Should invalidate and re-prompt.
6078 HttpRequestInfo request;
6079 request.method = "GET";
6080 request.url = GURL("http://www.example.org/p/q/t");
6081 request.load_flags = 0;
6083 scoped_ptr<HttpTransaction> trans(
6084 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6086 MockWrite data_writes1[] = {
6087 MockWrite(
6088 "GET /p/q/t HTTP/1.1\r\n"
6089 "Host: www.example.org\r\n"
6090 "Connection: keep-alive\r\n\r\n"),
6093 MockRead data_reads1[] = {
6094 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6095 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6096 MockRead("Content-Length: 10000\r\n\r\n"),
6097 MockRead(SYNCHRONOUS, ERR_FAILED),
6100 // Resend with authorization from cache for MyRealm.
6101 MockWrite data_writes2[] = {
6102 MockWrite(
6103 "GET /p/q/t HTTP/1.1\r\n"
6104 "Host: www.example.org\r\n"
6105 "Connection: keep-alive\r\n"
6106 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6109 // Sever rejects the authorization.
6110 MockRead data_reads2[] = {
6111 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6112 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6113 MockRead("Content-Length: 10000\r\n\r\n"),
6114 MockRead(SYNCHRONOUS, ERR_FAILED),
6117 // At this point we should prompt for new credentials for MyRealm.
6118 // Restart with username=foo3, password=foo4.
6119 MockWrite data_writes3[] = {
6120 MockWrite(
6121 "GET /p/q/t HTTP/1.1\r\n"
6122 "Host: www.example.org\r\n"
6123 "Connection: keep-alive\r\n"
6124 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6127 // Sever accepts the authorization.
6128 MockRead data_reads3[] = {
6129 MockRead("HTTP/1.0 200 OK\r\n"),
6130 MockRead("Content-Length: 100\r\n\r\n"),
6131 MockRead(SYNCHRONOUS, OK),
6134 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6135 data_writes1, arraysize(data_writes1));
6136 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6137 data_writes2, arraysize(data_writes2));
6138 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6139 data_writes3, arraysize(data_writes3));
6140 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6141 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6142 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6144 TestCompletionCallback callback1;
6146 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6147 EXPECT_EQ(ERR_IO_PENDING, rv);
6149 rv = callback1.WaitForResult();
6150 EXPECT_EQ(OK, rv);
6152 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6153 TestCompletionCallback callback2;
6154 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6155 EXPECT_EQ(ERR_IO_PENDING, rv);
6156 rv = callback2.WaitForResult();
6157 EXPECT_EQ(OK, rv);
6158 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6160 const HttpResponseInfo* response = trans->GetResponseInfo();
6161 ASSERT_TRUE(response != NULL);
6162 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6164 TestCompletionCallback callback3;
6166 rv = trans->RestartWithAuth(
6167 AuthCredentials(kFoo3, kBar3), callback3.callback());
6168 EXPECT_EQ(ERR_IO_PENDING, rv);
6170 rv = callback3.WaitForResult();
6171 EXPECT_EQ(OK, rv);
6173 response = trans->GetResponseInfo();
6174 ASSERT_TRUE(response != NULL);
6175 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6176 EXPECT_EQ(100, response->headers->GetContentLength());
6180 // Tests that nonce count increments when multiple auth attempts
6181 // are started with the same nonce.
6182 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
6183 HttpAuthHandlerDigest::Factory* digest_factory =
6184 new HttpAuthHandlerDigest::Factory();
6185 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6186 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6187 digest_factory->set_nonce_generator(nonce_generator);
6188 session_deps_.http_auth_handler_factory.reset(digest_factory);
6189 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6191 // Transaction 1: authenticate (foo, bar) on MyRealm1
6193 HttpRequestInfo request;
6194 request.method = "GET";
6195 request.url = GURL("http://www.example.org/x/y/z");
6196 request.load_flags = 0;
6198 scoped_ptr<HttpTransaction> trans(
6199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6201 MockWrite data_writes1[] = {
6202 MockWrite(
6203 "GET /x/y/z HTTP/1.1\r\n"
6204 "Host: www.example.org\r\n"
6205 "Connection: keep-alive\r\n\r\n"),
6208 MockRead data_reads1[] = {
6209 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6210 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6211 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6212 MockRead(SYNCHRONOUS, OK),
6215 // Resend with authorization (username=foo, password=bar)
6216 MockWrite data_writes2[] = {
6217 MockWrite(
6218 "GET /x/y/z HTTP/1.1\r\n"
6219 "Host: www.example.org\r\n"
6220 "Connection: keep-alive\r\n"
6221 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6222 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6223 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6224 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6227 // Sever accepts the authorization.
6228 MockRead data_reads2[] = {
6229 MockRead("HTTP/1.0 200 OK\r\n"),
6230 MockRead(SYNCHRONOUS, OK),
6233 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6234 data_writes1, arraysize(data_writes1));
6235 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6236 data_writes2, arraysize(data_writes2));
6237 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6238 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6240 TestCompletionCallback callback1;
6242 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6243 EXPECT_EQ(ERR_IO_PENDING, rv);
6245 rv = callback1.WaitForResult();
6246 EXPECT_EQ(OK, rv);
6248 const HttpResponseInfo* response = trans->GetResponseInfo();
6249 ASSERT_TRUE(response != NULL);
6250 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
6252 TestCompletionCallback callback2;
6254 rv = trans->RestartWithAuth(
6255 AuthCredentials(kFoo, kBar), callback2.callback());
6256 EXPECT_EQ(ERR_IO_PENDING, rv);
6258 rv = callback2.WaitForResult();
6259 EXPECT_EQ(OK, rv);
6261 response = trans->GetResponseInfo();
6262 ASSERT_TRUE(response != NULL);
6263 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6266 // ------------------------------------------------------------------------
6268 // Transaction 2: Request another resource in digestive's protection space.
6269 // This will preemptively add an Authorization header which should have an
6270 // "nc" value of 2 (as compared to 1 in the first use.
6272 HttpRequestInfo request;
6273 request.method = "GET";
6274 // Note that Transaction 1 was at /x/y/z, so this is in the same
6275 // protection space as digest.
6276 request.url = GURL("http://www.example.org/x/y/a/b");
6277 request.load_flags = 0;
6279 scoped_ptr<HttpTransaction> trans(
6280 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6282 MockWrite data_writes1[] = {
6283 MockWrite(
6284 "GET /x/y/a/b HTTP/1.1\r\n"
6285 "Host: www.example.org\r\n"
6286 "Connection: keep-alive\r\n"
6287 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6288 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6289 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6290 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6293 // Sever accepts the authorization.
6294 MockRead data_reads1[] = {
6295 MockRead("HTTP/1.0 200 OK\r\n"),
6296 MockRead("Content-Length: 100\r\n\r\n"),
6297 MockRead(SYNCHRONOUS, OK),
6300 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6301 data_writes1, arraysize(data_writes1));
6302 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6304 TestCompletionCallback callback1;
6306 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6307 EXPECT_EQ(ERR_IO_PENDING, rv);
6309 rv = callback1.WaitForResult();
6310 EXPECT_EQ(OK, rv);
6312 const HttpResponseInfo* response = trans->GetResponseInfo();
6313 ASSERT_TRUE(response != NULL);
6314 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6318 // Test the ResetStateForRestart() private method.
6319 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
6320 // Create a transaction (the dependencies aren't important).
6321 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6322 scoped_ptr<HttpNetworkTransaction> trans(
6323 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6325 // Setup some state (which we expect ResetStateForRestart() will clear).
6326 trans->read_buf_ = new IOBuffer(15);
6327 trans->read_buf_len_ = 15;
6328 trans->request_headers_.SetHeader("Authorization", "NTLM");
6330 // Setup state in response_
6331 HttpResponseInfo* response = &trans->response_;
6332 response->auth_challenge = new AuthChallengeInfo();
6333 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
6334 response->response_time = base::Time::Now();
6335 response->was_cached = true; // (Wouldn't ever actually be true...)
6337 { // Setup state for response_.vary_data
6338 HttpRequestInfo request;
6339 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6340 std::replace(temp.begin(), temp.end(), '\n', '\0');
6341 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
6342 request.extra_headers.SetHeader("Foo", "1");
6343 request.extra_headers.SetHeader("bar", "23");
6344 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
6347 // Cause the above state to be reset.
6348 trans->ResetStateForRestart();
6350 // Verify that the state that needed to be reset, has been reset.
6351 EXPECT_TRUE(trans->read_buf_.get() == NULL);
6352 EXPECT_EQ(0, trans->read_buf_len_);
6353 EXPECT_TRUE(trans->request_headers_.IsEmpty());
6354 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6355 EXPECT_TRUE(response->headers.get() == NULL);
6356 EXPECT_FALSE(response->was_cached);
6357 EXPECT_EQ(0U, response->ssl_info.cert_status);
6358 EXPECT_FALSE(response->vary_data.is_valid());
6361 // Test HTTPS connections to a site with a bad certificate
6362 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
6363 HttpRequestInfo request;
6364 request.method = "GET";
6365 request.url = GURL("https://www.example.org/");
6366 request.load_flags = 0;
6368 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6369 scoped_ptr<HttpTransaction> trans(
6370 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6372 MockWrite data_writes[] = {
6373 MockWrite(
6374 "GET / HTTP/1.1\r\n"
6375 "Host: www.example.org\r\n"
6376 "Connection: keep-alive\r\n\r\n"),
6379 MockRead data_reads[] = {
6380 MockRead("HTTP/1.0 200 OK\r\n"),
6381 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6382 MockRead("Content-Length: 100\r\n\r\n"),
6383 MockRead(SYNCHRONOUS, OK),
6386 StaticSocketDataProvider ssl_bad_certificate;
6387 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6388 data_writes, arraysize(data_writes));
6389 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6390 SSLSocketDataProvider ssl(ASYNC, OK);
6392 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6393 session_deps_.socket_factory->AddSocketDataProvider(&data);
6394 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6395 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6397 TestCompletionCallback callback;
6399 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6400 EXPECT_EQ(ERR_IO_PENDING, rv);
6402 rv = callback.WaitForResult();
6403 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6405 rv = trans->RestartIgnoringLastError(callback.callback());
6406 EXPECT_EQ(ERR_IO_PENDING, rv);
6408 rv = callback.WaitForResult();
6409 EXPECT_EQ(OK, rv);
6411 const HttpResponseInfo* response = trans->GetResponseInfo();
6413 ASSERT_TRUE(response != NULL);
6414 EXPECT_EQ(100, response->headers->GetContentLength());
6417 // Test HTTPS connections to a site with a bad certificate, going through a
6418 // proxy
6419 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
6420 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6422 HttpRequestInfo request;
6423 request.method = "GET";
6424 request.url = GURL("https://www.example.org/");
6425 request.load_flags = 0;
6427 MockWrite proxy_writes[] = {
6428 MockWrite(
6429 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6430 "Host: www.example.org\r\n"
6431 "Proxy-Connection: keep-alive\r\n\r\n"),
6434 MockRead proxy_reads[] = {
6435 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6436 MockRead(SYNCHRONOUS, OK)
6439 MockWrite data_writes[] = {
6440 MockWrite(
6441 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6442 "Host: www.example.org\r\n"
6443 "Proxy-Connection: keep-alive\r\n\r\n"),
6444 MockWrite(
6445 "GET / HTTP/1.1\r\n"
6446 "Host: www.example.org\r\n"
6447 "Connection: keep-alive\r\n\r\n"),
6450 MockRead data_reads[] = {
6451 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6452 MockRead("HTTP/1.0 200 OK\r\n"),
6453 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6454 MockRead("Content-Length: 100\r\n\r\n"),
6455 MockRead(SYNCHRONOUS, OK),
6458 StaticSocketDataProvider ssl_bad_certificate(
6459 proxy_reads, arraysize(proxy_reads),
6460 proxy_writes, arraysize(proxy_writes));
6461 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6462 data_writes, arraysize(data_writes));
6463 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6464 SSLSocketDataProvider ssl(ASYNC, OK);
6466 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6467 session_deps_.socket_factory->AddSocketDataProvider(&data);
6468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6469 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6471 TestCompletionCallback callback;
6473 for (int i = 0; i < 2; i++) {
6474 session_deps_.socket_factory->ResetNextMockIndexes();
6476 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6477 scoped_ptr<HttpTransaction> trans(
6478 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6480 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6481 EXPECT_EQ(ERR_IO_PENDING, rv);
6483 rv = callback.WaitForResult();
6484 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6486 rv = trans->RestartIgnoringLastError(callback.callback());
6487 EXPECT_EQ(ERR_IO_PENDING, rv);
6489 rv = callback.WaitForResult();
6490 EXPECT_EQ(OK, rv);
6492 const HttpResponseInfo* response = trans->GetResponseInfo();
6494 ASSERT_TRUE(response != NULL);
6495 EXPECT_EQ(100, response->headers->GetContentLength());
6500 // Test HTTPS connections to a site, going through an HTTPS proxy
6501 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6502 session_deps_.proxy_service.reset(
6503 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6504 TestNetLog net_log;
6505 session_deps_.net_log = &net_log;
6507 HttpRequestInfo request;
6508 request.method = "GET";
6509 request.url = GURL("https://www.example.org/");
6510 request.load_flags = 0;
6512 MockWrite data_writes[] = {
6513 MockWrite(
6514 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6515 "Host: www.example.org\r\n"
6516 "Proxy-Connection: keep-alive\r\n\r\n"),
6517 MockWrite(
6518 "GET / HTTP/1.1\r\n"
6519 "Host: www.example.org\r\n"
6520 "Connection: keep-alive\r\n\r\n"),
6523 MockRead data_reads[] = {
6524 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6525 MockRead("HTTP/1.1 200 OK\r\n"),
6526 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6527 MockRead("Content-Length: 100\r\n\r\n"),
6528 MockRead(SYNCHRONOUS, OK),
6531 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6532 data_writes, arraysize(data_writes));
6533 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6534 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6536 session_deps_.socket_factory->AddSocketDataProvider(&data);
6537 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6538 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6540 TestCompletionCallback callback;
6542 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6543 scoped_ptr<HttpTransaction> trans(
6544 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6546 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6547 EXPECT_EQ(ERR_IO_PENDING, rv);
6549 rv = callback.WaitForResult();
6550 EXPECT_EQ(OK, rv);
6551 const HttpResponseInfo* response = trans->GetResponseInfo();
6553 ASSERT_TRUE(response != NULL);
6555 EXPECT_TRUE(response->headers->IsKeepAlive());
6556 EXPECT_EQ(200, response->headers->response_code());
6557 EXPECT_EQ(100, response->headers->GetContentLength());
6558 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6560 LoadTimingInfo load_timing_info;
6561 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6562 TestLoadTimingNotReusedWithPac(load_timing_info,
6563 CONNECT_TIMING_HAS_SSL_TIMES);
6566 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6567 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6568 session_deps_.proxy_service.reset(
6569 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6570 TestNetLog net_log;
6571 session_deps_.net_log = &net_log;
6573 HttpRequestInfo request;
6574 request.method = "GET";
6575 request.url = GURL("https://www.example.org/");
6576 request.load_flags = 0;
6578 MockWrite data_writes[] = {
6579 MockWrite(
6580 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6581 "Host: www.example.org\r\n"
6582 "Proxy-Connection: keep-alive\r\n\r\n"),
6585 MockRead data_reads[] = {
6586 MockRead("HTTP/1.1 302 Redirect\r\n"),
6587 MockRead("Location: http://login.example.com/\r\n"),
6588 MockRead("Content-Length: 0\r\n\r\n"),
6589 MockRead(SYNCHRONOUS, OK),
6592 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6593 data_writes, arraysize(data_writes));
6594 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6596 session_deps_.socket_factory->AddSocketDataProvider(&data);
6597 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6599 TestCompletionCallback callback;
6601 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6602 scoped_ptr<HttpTransaction> trans(
6603 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6605 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6606 EXPECT_EQ(ERR_IO_PENDING, rv);
6608 rv = callback.WaitForResult();
6609 EXPECT_EQ(OK, rv);
6610 const HttpResponseInfo* response = trans->GetResponseInfo();
6612 ASSERT_TRUE(response != NULL);
6614 EXPECT_EQ(302, response->headers->response_code());
6615 std::string url;
6616 EXPECT_TRUE(response->headers->IsRedirect(&url));
6617 EXPECT_EQ("http://login.example.com/", url);
6619 // In the case of redirects from proxies, HttpNetworkTransaction returns
6620 // timing for the proxy connection instead of the connection to the host,
6621 // and no send / receive times.
6622 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6623 LoadTimingInfo load_timing_info;
6624 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6626 EXPECT_FALSE(load_timing_info.socket_reused);
6627 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6629 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6630 EXPECT_LE(load_timing_info.proxy_resolve_start,
6631 load_timing_info.proxy_resolve_end);
6632 EXPECT_LE(load_timing_info.proxy_resolve_end,
6633 load_timing_info.connect_timing.connect_start);
6634 ExpectConnectTimingHasTimes(
6635 load_timing_info.connect_timing,
6636 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6638 EXPECT_TRUE(load_timing_info.send_start.is_null());
6639 EXPECT_TRUE(load_timing_info.send_end.is_null());
6640 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6643 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6644 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6645 session_deps_.proxy_service.reset(
6646 ProxyService::CreateFixed("https://proxy:70"));
6648 HttpRequestInfo request;
6649 request.method = "GET";
6650 request.url = GURL("https://www.example.org/");
6651 request.load_flags = 0;
6653 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6654 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6655 scoped_ptr<SpdyFrame> goaway(
6656 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6657 MockWrite data_writes[] = {
6658 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6659 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
6662 static const char* const kExtraHeaders[] = {
6663 "location",
6664 "http://login.example.com/",
6666 scoped_ptr<SpdyFrame> resp(
6667 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6668 arraysize(kExtraHeaders)/2, 1));
6669 MockRead data_reads[] = {
6670 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
6673 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6674 arraysize(data_writes));
6675 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6676 proxy_ssl.SetNextProto(GetParam());
6678 session_deps_.socket_factory->AddSocketDataProvider(&data);
6679 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6681 TestCompletionCallback callback;
6683 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6684 scoped_ptr<HttpTransaction> trans(
6685 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6687 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6688 EXPECT_EQ(ERR_IO_PENDING, rv);
6690 rv = callback.WaitForResult();
6691 EXPECT_EQ(OK, rv);
6692 const HttpResponseInfo* response = trans->GetResponseInfo();
6694 ASSERT_TRUE(response != NULL);
6696 EXPECT_EQ(302, response->headers->response_code());
6697 std::string url;
6698 EXPECT_TRUE(response->headers->IsRedirect(&url));
6699 EXPECT_EQ("http://login.example.com/", url);
6702 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6703 TEST_P(HttpNetworkTransactionTest,
6704 ErrorResponseToHttpsConnectViaHttpsProxy) {
6705 session_deps_.proxy_service.reset(
6706 ProxyService::CreateFixed("https://proxy:70"));
6708 HttpRequestInfo request;
6709 request.method = "GET";
6710 request.url = GURL("https://www.example.org/");
6711 request.load_flags = 0;
6713 MockWrite data_writes[] = {
6714 MockWrite(
6715 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6716 "Host: www.example.org\r\n"
6717 "Proxy-Connection: keep-alive\r\n\r\n"),
6720 MockRead data_reads[] = {
6721 MockRead("HTTP/1.1 404 Not Found\r\n"),
6722 MockRead("Content-Length: 23\r\n\r\n"),
6723 MockRead("The host does not exist"),
6724 MockRead(SYNCHRONOUS, OK),
6727 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6728 data_writes, arraysize(data_writes));
6729 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6731 session_deps_.socket_factory->AddSocketDataProvider(&data);
6732 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6734 TestCompletionCallback callback;
6736 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6737 scoped_ptr<HttpTransaction> trans(
6738 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6740 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6741 EXPECT_EQ(ERR_IO_PENDING, rv);
6743 rv = callback.WaitForResult();
6744 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6746 // TODO(ttuttle): Anything else to check here?
6749 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6750 TEST_P(HttpNetworkTransactionTest,
6751 ErrorResponseToHttpsConnectViaSpdyProxy) {
6752 session_deps_.proxy_service.reset(
6753 ProxyService::CreateFixed("https://proxy:70"));
6755 HttpRequestInfo request;
6756 request.method = "GET";
6757 request.url = GURL("https://www.example.org/");
6758 request.load_flags = 0;
6760 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6761 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6762 scoped_ptr<SpdyFrame> rst(
6763 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6764 MockWrite data_writes[] = {
6765 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
6768 static const char* const kExtraHeaders[] = {
6769 "location",
6770 "http://login.example.com/",
6772 scoped_ptr<SpdyFrame> resp(
6773 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6774 arraysize(kExtraHeaders)/2, 1));
6775 scoped_ptr<SpdyFrame> body(
6776 spdy_util_.ConstructSpdyBodyFrame(
6777 1, "The host does not exist", 23, true));
6778 MockRead data_reads[] = {
6779 CreateMockRead(*resp.get(), 1),
6780 CreateMockRead(*body.get(), 2),
6781 MockRead(ASYNC, 0, 4), // EOF
6784 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
6785 arraysize(data_writes));
6786 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6787 proxy_ssl.SetNextProto(GetParam());
6789 session_deps_.socket_factory->AddSocketDataProvider(&data);
6790 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6792 TestCompletionCallback callback;
6794 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6795 scoped_ptr<HttpTransaction> trans(
6796 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6798 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6799 EXPECT_EQ(ERR_IO_PENDING, rv);
6801 rv = callback.WaitForResult();
6802 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6804 // TODO(ttuttle): Anything else to check here?
6807 // Test the request-challenge-retry sequence for basic auth, through
6808 // a SPDY proxy over a single SPDY session.
6809 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6810 HttpRequestInfo request;
6811 request.method = "GET";
6812 request.url = GURL("https://www.example.org/");
6813 // when the no authentication data flag is set.
6814 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
6816 // Configure against https proxy server "myproxy:70".
6817 session_deps_.proxy_service.reset(
6818 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6819 BoundTestNetLog log;
6820 session_deps_.net_log = log.bound().net_log();
6821 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6823 // Since we have proxy, should try to establish tunnel.
6824 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
6825 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6826 scoped_ptr<SpdyFrame> rst(
6827 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6829 // After calling trans->RestartWithAuth(), this is the request we should
6830 // be issuing -- the final header line contains the credentials.
6831 const char* const kAuthCredentials[] = {
6832 "proxy-authorization", "Basic Zm9vOmJhcg==",
6834 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6835 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
6836 HostPortPair("www.example.org", 443)));
6837 // fetch https://www.example.org/ via HTTP
6838 const char get[] =
6839 "GET / HTTP/1.1\r\n"
6840 "Host: www.example.org\r\n"
6841 "Connection: keep-alive\r\n\r\n";
6842 scoped_ptr<SpdyFrame> wrapped_get(
6843 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6845 MockWrite spdy_writes[] = {
6846 CreateMockWrite(*req, 0, ASYNC),
6847 CreateMockWrite(*rst, 2, ASYNC),
6848 CreateMockWrite(*connect2, 3),
6849 CreateMockWrite(*wrapped_get, 5),
6852 // The proxy responds to the connect with a 407, using a persistent
6853 // connection.
6854 const char kAuthStatus[] = "407";
6855 const char* const kAuthChallenge[] = {
6856 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6858 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6859 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6861 scoped_ptr<SpdyFrame> conn_resp(
6862 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6863 const char resp[] = "HTTP/1.1 200 OK\r\n"
6864 "Content-Length: 5\r\n\r\n";
6866 scoped_ptr<SpdyFrame> wrapped_get_resp(
6867 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6868 scoped_ptr<SpdyFrame> wrapped_body(
6869 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6870 MockRead spdy_reads[] = {
6871 CreateMockRead(*conn_auth_resp, 1, ASYNC),
6872 CreateMockRead(*conn_resp, 4, ASYNC),
6873 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
6874 CreateMockRead(*wrapped_body, 7, ASYNC),
6875 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
6878 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
6879 arraysize(spdy_writes));
6880 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6881 // Negotiate SPDY to the proxy
6882 SSLSocketDataProvider proxy(ASYNC, OK);
6883 proxy.SetNextProto(GetParam());
6884 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6885 // Vanilla SSL to the server
6886 SSLSocketDataProvider server(ASYNC, OK);
6887 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6889 TestCompletionCallback callback1;
6891 scoped_ptr<HttpTransaction> trans(
6892 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6894 int rv = trans->Start(&request, callback1.callback(), log.bound());
6895 EXPECT_EQ(ERR_IO_PENDING, rv);
6897 rv = callback1.WaitForResult();
6898 EXPECT_EQ(OK, rv);
6899 TestNetLogEntry::List entries;
6900 log.GetEntries(&entries);
6901 size_t pos = ExpectLogContainsSomewhere(
6902 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6903 NetLog::PHASE_NONE);
6904 ExpectLogContainsSomewhere(
6905 entries, pos,
6906 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6907 NetLog::PHASE_NONE);
6909 const HttpResponseInfo* response = trans->GetResponseInfo();
6910 ASSERT_TRUE(response != NULL);
6911 ASSERT_FALSE(response->headers.get() == NULL);
6912 EXPECT_EQ(407, response->headers->response_code());
6913 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6914 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6915 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6917 TestCompletionCallback callback2;
6919 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6920 callback2.callback());
6921 EXPECT_EQ(ERR_IO_PENDING, rv);
6923 rv = callback2.WaitForResult();
6924 EXPECT_EQ(OK, rv);
6926 response = trans->GetResponseInfo();
6927 ASSERT_TRUE(response != NULL);
6929 EXPECT_TRUE(response->headers->IsKeepAlive());
6930 EXPECT_EQ(200, response->headers->response_code());
6931 EXPECT_EQ(5, response->headers->GetContentLength());
6932 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6934 // The password prompt info should not be set.
6935 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6937 LoadTimingInfo load_timing_info;
6938 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6939 TestLoadTimingNotReusedWithPac(load_timing_info,
6940 CONNECT_TIMING_HAS_SSL_TIMES);
6942 trans.reset();
6943 session->CloseAllConnections();
6946 // Test that an explicitly trusted SPDY proxy can push a resource from an
6947 // origin that is different from that of its associated resource.
6948 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6949 HttpRequestInfo request;
6950 HttpRequestInfo push_request;
6952 request.method = "GET";
6953 request.url = GURL("http://www.example.org/");
6954 push_request.method = "GET";
6955 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6957 // Configure against https proxy server "myproxy:70".
6958 session_deps_.proxy_service.reset(
6959 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6960 BoundTestNetLog log;
6961 session_deps_.net_log = log.bound().net_log();
6963 // Enable cross-origin push.
6964 session_deps_.trusted_spdy_proxy = "myproxy:70";
6966 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6968 scoped_ptr<SpdyFrame> stream1_syn(
6969 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6971 MockWrite spdy_writes[] = {
6972 CreateMockWrite(*stream1_syn, 0, ASYNC),
6975 scoped_ptr<SpdyFrame>
6976 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6978 scoped_ptr<SpdyFrame>
6979 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6981 scoped_ptr<SpdyFrame>
6982 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6986 "http://www.another-origin.com/foo.dat"));
6987 const char kPushedData[] = "pushed";
6988 scoped_ptr<SpdyFrame> stream2_body(
6989 spdy_util_.ConstructSpdyBodyFrame(
6990 2, kPushedData, strlen(kPushedData), true));
6992 MockRead spdy_reads[] = {
6993 CreateMockRead(*stream1_reply, 1, ASYNC),
6994 CreateMockRead(*stream2_syn, 2, ASYNC),
6995 CreateMockRead(*stream1_body, 3, ASYNC),
6996 CreateMockRead(*stream2_body, 4, ASYNC),
6997 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
7000 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7001 arraysize(spdy_writes));
7002 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7003 // Negotiate SPDY to the proxy
7004 SSLSocketDataProvider proxy(ASYNC, OK);
7005 proxy.SetNextProto(GetParam());
7006 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7008 scoped_ptr<HttpTransaction> trans(
7009 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7010 TestCompletionCallback callback;
7011 int rv = trans->Start(&request, callback.callback(), log.bound());
7012 EXPECT_EQ(ERR_IO_PENDING, rv);
7014 rv = callback.WaitForResult();
7015 EXPECT_EQ(OK, rv);
7016 const HttpResponseInfo* response = trans->GetResponseInfo();
7018 scoped_ptr<HttpTransaction> push_trans(
7019 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7020 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
7021 EXPECT_EQ(ERR_IO_PENDING, rv);
7023 rv = callback.WaitForResult();
7024 EXPECT_EQ(OK, rv);
7025 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
7027 ASSERT_TRUE(response != NULL);
7028 EXPECT_TRUE(response->headers->IsKeepAlive());
7030 EXPECT_EQ(200, response->headers->response_code());
7031 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7033 std::string response_data;
7034 rv = ReadTransaction(trans.get(), &response_data);
7035 EXPECT_EQ(OK, rv);
7036 EXPECT_EQ("hello!", response_data);
7038 LoadTimingInfo load_timing_info;
7039 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7040 TestLoadTimingNotReusedWithPac(load_timing_info,
7041 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7043 // Verify the pushed stream.
7044 EXPECT_TRUE(push_response->headers.get() != NULL);
7045 EXPECT_EQ(200, push_response->headers->response_code());
7047 rv = ReadTransaction(push_trans.get(), &response_data);
7048 EXPECT_EQ(OK, rv);
7049 EXPECT_EQ("pushed", response_data);
7051 LoadTimingInfo push_load_timing_info;
7052 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
7053 TestLoadTimingReusedWithPac(push_load_timing_info);
7054 // The transactions should share a socket ID, despite being for different
7055 // origins.
7056 EXPECT_EQ(load_timing_info.socket_log_id,
7057 push_load_timing_info.socket_log_id);
7059 trans.reset();
7060 push_trans.reset();
7061 session->CloseAllConnections();
7064 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
7065 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
7066 HttpRequestInfo request;
7068 request.method = "GET";
7069 request.url = GURL("http://www.example.org/");
7071 // Configure against https proxy server "myproxy:70".
7072 session_deps_.proxy_service.reset(
7073 ProxyService::CreateFixed("https://myproxy:70"));
7074 BoundTestNetLog log;
7075 session_deps_.net_log = log.bound().net_log();
7077 // Enable cross-origin push.
7078 session_deps_.trusted_spdy_proxy = "myproxy:70";
7080 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7082 scoped_ptr<SpdyFrame> stream1_syn(
7083 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
7085 scoped_ptr<SpdyFrame> push_rst(
7086 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
7088 MockWrite spdy_writes[] = {
7089 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
7092 scoped_ptr<SpdyFrame>
7093 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
7095 scoped_ptr<SpdyFrame>
7096 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
7098 scoped_ptr<SpdyFrame>
7099 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
7103 "https://www.another-origin.com/foo.dat"));
7105 MockRead spdy_reads[] = {
7106 CreateMockRead(*stream1_reply, 1, ASYNC),
7107 CreateMockRead(*stream2_syn, 2, ASYNC),
7108 CreateMockRead(*stream1_body, 4, ASYNC),
7109 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
7112 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7113 arraysize(spdy_writes));
7114 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7115 // Negotiate SPDY to the proxy
7116 SSLSocketDataProvider proxy(ASYNC, OK);
7117 proxy.SetNextProto(GetParam());
7118 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7120 scoped_ptr<HttpTransaction> trans(
7121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7122 TestCompletionCallback callback;
7123 int rv = trans->Start(&request, callback.callback(), log.bound());
7124 EXPECT_EQ(ERR_IO_PENDING, rv);
7126 rv = callback.WaitForResult();
7127 EXPECT_EQ(OK, rv);
7128 const HttpResponseInfo* response = trans->GetResponseInfo();
7130 ASSERT_TRUE(response != NULL);
7131 EXPECT_TRUE(response->headers->IsKeepAlive());
7133 EXPECT_EQ(200, response->headers->response_code());
7134 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7136 std::string response_data;
7137 rv = ReadTransaction(trans.get(), &response_data);
7138 EXPECT_EQ(OK, rv);
7139 EXPECT_EQ("hello!", response_data);
7141 trans.reset();
7142 session->CloseAllConnections();
7145 // Test HTTPS connections to a site with a bad certificate, going through an
7146 // HTTPS proxy
7147 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
7148 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
7149 "https://proxy:70"));
7151 HttpRequestInfo request;
7152 request.method = "GET";
7153 request.url = GURL("https://www.example.org/");
7154 request.load_flags = 0;
7156 // Attempt to fetch the URL from a server with a bad cert
7157 MockWrite bad_cert_writes[] = {
7158 MockWrite(
7159 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7160 "Host: www.example.org\r\n"
7161 "Proxy-Connection: keep-alive\r\n\r\n"),
7164 MockRead bad_cert_reads[] = {
7165 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7166 MockRead(SYNCHRONOUS, OK)
7169 // Attempt to fetch the URL with a good cert
7170 MockWrite good_data_writes[] = {
7171 MockWrite(
7172 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7173 "Host: www.example.org\r\n"
7174 "Proxy-Connection: keep-alive\r\n\r\n"),
7175 MockWrite(
7176 "GET / HTTP/1.1\r\n"
7177 "Host: www.example.org\r\n"
7178 "Connection: keep-alive\r\n\r\n"),
7181 MockRead good_cert_reads[] = {
7182 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7183 MockRead("HTTP/1.0 200 OK\r\n"),
7184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7185 MockRead("Content-Length: 100\r\n\r\n"),
7186 MockRead(SYNCHRONOUS, OK),
7189 StaticSocketDataProvider ssl_bad_certificate(
7190 bad_cert_reads, arraysize(bad_cert_reads),
7191 bad_cert_writes, arraysize(bad_cert_writes));
7192 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7193 good_data_writes, arraysize(good_data_writes));
7194 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7195 SSLSocketDataProvider ssl(ASYNC, OK);
7197 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7198 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7199 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7200 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7202 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7203 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7204 session_deps_.socket_factory->AddSocketDataProvider(&data);
7205 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7207 TestCompletionCallback callback;
7209 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7210 scoped_ptr<HttpTransaction> trans(
7211 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7213 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7214 EXPECT_EQ(ERR_IO_PENDING, rv);
7216 rv = callback.WaitForResult();
7217 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7219 rv = trans->RestartIgnoringLastError(callback.callback());
7220 EXPECT_EQ(ERR_IO_PENDING, rv);
7222 rv = callback.WaitForResult();
7223 EXPECT_EQ(OK, rv);
7225 const HttpResponseInfo* response = trans->GetResponseInfo();
7227 ASSERT_TRUE(response != NULL);
7228 EXPECT_EQ(100, response->headers->GetContentLength());
7231 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
7232 HttpRequestInfo request;
7233 request.method = "GET";
7234 request.url = GURL("http://www.example.org/");
7235 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7236 "Chromium Ultra Awesome X Edition");
7238 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7239 scoped_ptr<HttpTransaction> trans(
7240 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7242 MockWrite data_writes[] = {
7243 MockWrite(
7244 "GET / HTTP/1.1\r\n"
7245 "Host: www.example.org\r\n"
7246 "Connection: keep-alive\r\n"
7247 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7250 // Lastly, the server responds with the actual content.
7251 MockRead data_reads[] = {
7252 MockRead("HTTP/1.0 200 OK\r\n"),
7253 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7254 MockRead("Content-Length: 100\r\n\r\n"),
7255 MockRead(SYNCHRONOUS, OK),
7258 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7259 data_writes, arraysize(data_writes));
7260 session_deps_.socket_factory->AddSocketDataProvider(&data);
7262 TestCompletionCallback callback;
7264 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7265 EXPECT_EQ(ERR_IO_PENDING, rv);
7267 rv = callback.WaitForResult();
7268 EXPECT_EQ(OK, rv);
7271 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
7272 HttpRequestInfo request;
7273 request.method = "GET";
7274 request.url = GURL("https://www.example.org/");
7275 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7276 "Chromium Ultra Awesome X Edition");
7278 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7279 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7280 scoped_ptr<HttpTransaction> trans(
7281 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7283 MockWrite data_writes[] = {
7284 MockWrite(
7285 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7286 "Host: www.example.org\r\n"
7287 "Proxy-Connection: keep-alive\r\n"
7288 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7290 MockRead data_reads[] = {
7291 // Return an error, so the transaction stops here (this test isn't
7292 // interested in the rest).
7293 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7294 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7295 MockRead("Proxy-Connection: close\r\n\r\n"),
7298 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7299 data_writes, arraysize(data_writes));
7300 session_deps_.socket_factory->AddSocketDataProvider(&data);
7302 TestCompletionCallback callback;
7304 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7305 EXPECT_EQ(ERR_IO_PENDING, rv);
7307 rv = callback.WaitForResult();
7308 EXPECT_EQ(OK, rv);
7311 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
7312 HttpRequestInfo request;
7313 request.method = "GET";
7314 request.url = GURL("http://www.example.org/");
7315 request.load_flags = 0;
7316 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7317 "http://the.previous.site.com/");
7319 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7320 scoped_ptr<HttpTransaction> trans(
7321 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7323 MockWrite data_writes[] = {
7324 MockWrite(
7325 "GET / HTTP/1.1\r\n"
7326 "Host: www.example.org\r\n"
7327 "Connection: keep-alive\r\n"
7328 "Referer: http://the.previous.site.com/\r\n\r\n"),
7331 // Lastly, the server responds with the actual content.
7332 MockRead data_reads[] = {
7333 MockRead("HTTP/1.0 200 OK\r\n"),
7334 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7335 MockRead("Content-Length: 100\r\n\r\n"),
7336 MockRead(SYNCHRONOUS, OK),
7339 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7340 data_writes, arraysize(data_writes));
7341 session_deps_.socket_factory->AddSocketDataProvider(&data);
7343 TestCompletionCallback callback;
7345 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7346 EXPECT_EQ(ERR_IO_PENDING, rv);
7348 rv = callback.WaitForResult();
7349 EXPECT_EQ(OK, rv);
7352 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
7353 HttpRequestInfo request;
7354 request.method = "POST";
7355 request.url = GURL("http://www.example.org/");
7357 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7358 scoped_ptr<HttpTransaction> trans(
7359 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7361 MockWrite data_writes[] = {
7362 MockWrite(
7363 "POST / HTTP/1.1\r\n"
7364 "Host: www.example.org\r\n"
7365 "Connection: keep-alive\r\n"
7366 "Content-Length: 0\r\n\r\n"),
7369 // Lastly, the server responds with the actual content.
7370 MockRead data_reads[] = {
7371 MockRead("HTTP/1.0 200 OK\r\n"),
7372 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7373 MockRead("Content-Length: 100\r\n\r\n"),
7374 MockRead(SYNCHRONOUS, OK),
7377 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7378 data_writes, arraysize(data_writes));
7379 session_deps_.socket_factory->AddSocketDataProvider(&data);
7381 TestCompletionCallback callback;
7383 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7384 EXPECT_EQ(ERR_IO_PENDING, rv);
7386 rv = callback.WaitForResult();
7387 EXPECT_EQ(OK, rv);
7390 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
7391 HttpRequestInfo request;
7392 request.method = "PUT";
7393 request.url = GURL("http://www.example.org/");
7395 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7396 scoped_ptr<HttpTransaction> trans(
7397 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7399 MockWrite data_writes[] = {
7400 MockWrite(
7401 "PUT / HTTP/1.1\r\n"
7402 "Host: www.example.org\r\n"
7403 "Connection: keep-alive\r\n"
7404 "Content-Length: 0\r\n\r\n"),
7407 // Lastly, the server responds with the actual content.
7408 MockRead data_reads[] = {
7409 MockRead("HTTP/1.0 200 OK\r\n"),
7410 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7411 MockRead("Content-Length: 100\r\n\r\n"),
7412 MockRead(SYNCHRONOUS, OK),
7415 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7416 data_writes, arraysize(data_writes));
7417 session_deps_.socket_factory->AddSocketDataProvider(&data);
7419 TestCompletionCallback callback;
7421 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7422 EXPECT_EQ(ERR_IO_PENDING, rv);
7424 rv = callback.WaitForResult();
7425 EXPECT_EQ(OK, rv);
7428 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
7429 HttpRequestInfo request;
7430 request.method = "HEAD";
7431 request.url = GURL("http://www.example.org/");
7433 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7434 scoped_ptr<HttpTransaction> trans(
7435 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7437 MockWrite data_writes[] = {
7438 MockWrite("HEAD / HTTP/1.1\r\n"
7439 "Host: www.example.org\r\n"
7440 "Connection: keep-alive\r\n\r\n"),
7443 // Lastly, the server responds with the actual content.
7444 MockRead data_reads[] = {
7445 MockRead("HTTP/1.0 200 OK\r\n"),
7446 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7447 MockRead("Content-Length: 100\r\n\r\n"),
7448 MockRead(SYNCHRONOUS, OK),
7451 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7452 data_writes, arraysize(data_writes));
7453 session_deps_.socket_factory->AddSocketDataProvider(&data);
7455 TestCompletionCallback callback;
7457 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7458 EXPECT_EQ(ERR_IO_PENDING, rv);
7460 rv = callback.WaitForResult();
7461 EXPECT_EQ(OK, rv);
7464 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7465 HttpRequestInfo request;
7466 request.method = "GET";
7467 request.url = GURL("http://www.example.org/");
7468 request.load_flags = LOAD_BYPASS_CACHE;
7470 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7471 scoped_ptr<HttpTransaction> trans(
7472 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7474 MockWrite data_writes[] = {
7475 MockWrite(
7476 "GET / HTTP/1.1\r\n"
7477 "Host: www.example.org\r\n"
7478 "Connection: keep-alive\r\n"
7479 "Pragma: no-cache\r\n"
7480 "Cache-Control: no-cache\r\n\r\n"),
7483 // Lastly, the server responds with the actual content.
7484 MockRead data_reads[] = {
7485 MockRead("HTTP/1.0 200 OK\r\n"),
7486 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7487 MockRead("Content-Length: 100\r\n\r\n"),
7488 MockRead(SYNCHRONOUS, OK),
7491 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7492 data_writes, arraysize(data_writes));
7493 session_deps_.socket_factory->AddSocketDataProvider(&data);
7495 TestCompletionCallback callback;
7497 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7498 EXPECT_EQ(ERR_IO_PENDING, rv);
7500 rv = callback.WaitForResult();
7501 EXPECT_EQ(OK, rv);
7504 TEST_P(HttpNetworkTransactionTest,
7505 BuildRequest_CacheControlValidateCache) {
7506 HttpRequestInfo request;
7507 request.method = "GET";
7508 request.url = GURL("http://www.example.org/");
7509 request.load_flags = LOAD_VALIDATE_CACHE;
7511 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7512 scoped_ptr<HttpTransaction> trans(
7513 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7515 MockWrite data_writes[] = {
7516 MockWrite(
7517 "GET / HTTP/1.1\r\n"
7518 "Host: www.example.org\r\n"
7519 "Connection: keep-alive\r\n"
7520 "Cache-Control: max-age=0\r\n\r\n"),
7523 // Lastly, the server responds with the actual content.
7524 MockRead data_reads[] = {
7525 MockRead("HTTP/1.0 200 OK\r\n"),
7526 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7527 MockRead("Content-Length: 100\r\n\r\n"),
7528 MockRead(SYNCHRONOUS, OK),
7531 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7532 data_writes, arraysize(data_writes));
7533 session_deps_.socket_factory->AddSocketDataProvider(&data);
7535 TestCompletionCallback callback;
7537 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7538 EXPECT_EQ(ERR_IO_PENDING, rv);
7540 rv = callback.WaitForResult();
7541 EXPECT_EQ(OK, rv);
7544 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7545 HttpRequestInfo request;
7546 request.method = "GET";
7547 request.url = GURL("http://www.example.org/");
7548 request.extra_headers.SetHeader("FooHeader", "Bar");
7550 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7551 scoped_ptr<HttpTransaction> trans(
7552 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7554 MockWrite data_writes[] = {
7555 MockWrite(
7556 "GET / HTTP/1.1\r\n"
7557 "Host: www.example.org\r\n"
7558 "Connection: keep-alive\r\n"
7559 "FooHeader: Bar\r\n\r\n"),
7562 // Lastly, the server responds with the actual content.
7563 MockRead data_reads[] = {
7564 MockRead("HTTP/1.0 200 OK\r\n"),
7565 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7566 MockRead("Content-Length: 100\r\n\r\n"),
7567 MockRead(SYNCHRONOUS, OK),
7570 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7571 data_writes, arraysize(data_writes));
7572 session_deps_.socket_factory->AddSocketDataProvider(&data);
7574 TestCompletionCallback callback;
7576 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7577 EXPECT_EQ(ERR_IO_PENDING, rv);
7579 rv = callback.WaitForResult();
7580 EXPECT_EQ(OK, rv);
7583 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7584 HttpRequestInfo request;
7585 request.method = "GET";
7586 request.url = GURL("http://www.example.org/");
7587 request.extra_headers.SetHeader("referer", "www.foo.com");
7588 request.extra_headers.SetHeader("hEllo", "Kitty");
7589 request.extra_headers.SetHeader("FoO", "bar");
7591 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7592 scoped_ptr<HttpTransaction> trans(
7593 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7595 MockWrite data_writes[] = {
7596 MockWrite(
7597 "GET / HTTP/1.1\r\n"
7598 "Host: www.example.org\r\n"
7599 "Connection: keep-alive\r\n"
7600 "referer: www.foo.com\r\n"
7601 "hEllo: Kitty\r\n"
7602 "FoO: bar\r\n\r\n"),
7605 // Lastly, the server responds with the actual content.
7606 MockRead data_reads[] = {
7607 MockRead("HTTP/1.0 200 OK\r\n"),
7608 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7609 MockRead("Content-Length: 100\r\n\r\n"),
7610 MockRead(SYNCHRONOUS, OK),
7613 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7614 data_writes, arraysize(data_writes));
7615 session_deps_.socket_factory->AddSocketDataProvider(&data);
7617 TestCompletionCallback callback;
7619 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7620 EXPECT_EQ(ERR_IO_PENDING, rv);
7622 rv = callback.WaitForResult();
7623 EXPECT_EQ(OK, rv);
7626 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7627 HttpRequestInfo request;
7628 request.method = "GET";
7629 request.url = GURL("http://www.example.org/");
7630 request.load_flags = 0;
7632 session_deps_.proxy_service.reset(
7633 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7634 TestNetLog net_log;
7635 session_deps_.net_log = &net_log;
7637 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7638 scoped_ptr<HttpTransaction> trans(
7639 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7641 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7642 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7644 MockWrite data_writes[] = {
7645 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7646 MockWrite(
7647 "GET / HTTP/1.1\r\n"
7648 "Host: www.example.org\r\n"
7649 "Connection: keep-alive\r\n\r\n")};
7651 MockRead data_reads[] = {
7652 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7653 MockRead("HTTP/1.0 200 OK\r\n"),
7654 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7655 MockRead("Payload"),
7656 MockRead(SYNCHRONOUS, OK)
7659 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7660 data_writes, arraysize(data_writes));
7661 session_deps_.socket_factory->AddSocketDataProvider(&data);
7663 TestCompletionCallback callback;
7665 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7666 EXPECT_EQ(ERR_IO_PENDING, rv);
7668 rv = callback.WaitForResult();
7669 EXPECT_EQ(OK, rv);
7671 const HttpResponseInfo* response = trans->GetResponseInfo();
7672 ASSERT_TRUE(response != NULL);
7674 LoadTimingInfo load_timing_info;
7675 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7676 TestLoadTimingNotReusedWithPac(load_timing_info,
7677 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7679 std::string response_text;
7680 rv = ReadTransaction(trans.get(), &response_text);
7681 EXPECT_EQ(OK, rv);
7682 EXPECT_EQ("Payload", response_text);
7685 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7686 HttpRequestInfo request;
7687 request.method = "GET";
7688 request.url = GURL("https://www.example.org/");
7689 request.load_flags = 0;
7691 session_deps_.proxy_service.reset(
7692 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7693 TestNetLog net_log;
7694 session_deps_.net_log = &net_log;
7696 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7697 scoped_ptr<HttpTransaction> trans(
7698 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7700 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7701 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7703 MockWrite data_writes[] = {
7704 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7705 arraysize(write_buffer)),
7706 MockWrite(
7707 "GET / HTTP/1.1\r\n"
7708 "Host: www.example.org\r\n"
7709 "Connection: keep-alive\r\n\r\n")};
7711 MockRead data_reads[] = {
7712 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7713 arraysize(read_buffer)),
7714 MockRead("HTTP/1.0 200 OK\r\n"),
7715 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7716 MockRead("Payload"),
7717 MockRead(SYNCHRONOUS, OK)
7720 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7721 data_writes, arraysize(data_writes));
7722 session_deps_.socket_factory->AddSocketDataProvider(&data);
7724 SSLSocketDataProvider ssl(ASYNC, OK);
7725 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7727 TestCompletionCallback callback;
7729 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7730 EXPECT_EQ(ERR_IO_PENDING, rv);
7732 rv = callback.WaitForResult();
7733 EXPECT_EQ(OK, rv);
7735 LoadTimingInfo load_timing_info;
7736 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7737 TestLoadTimingNotReusedWithPac(load_timing_info,
7738 CONNECT_TIMING_HAS_SSL_TIMES);
7740 const HttpResponseInfo* response = trans->GetResponseInfo();
7741 ASSERT_TRUE(response != NULL);
7743 std::string response_text;
7744 rv = ReadTransaction(trans.get(), &response_text);
7745 EXPECT_EQ(OK, rv);
7746 EXPECT_EQ("Payload", response_text);
7749 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7750 HttpRequestInfo request;
7751 request.method = "GET";
7752 request.url = GURL("http://www.example.org/");
7753 request.load_flags = 0;
7755 session_deps_.proxy_service.reset(
7756 ProxyService::CreateFixed("socks4://myproxy:1080"));
7757 TestNetLog net_log;
7758 session_deps_.net_log = &net_log;
7760 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7761 scoped_ptr<HttpTransaction> trans(
7762 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7764 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7765 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7767 MockWrite data_writes[] = {
7768 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7769 MockWrite(
7770 "GET / HTTP/1.1\r\n"
7771 "Host: www.example.org\r\n"
7772 "Connection: keep-alive\r\n\r\n")};
7774 MockRead data_reads[] = {
7775 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7776 MockRead("HTTP/1.0 200 OK\r\n"),
7777 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7778 MockRead("Payload"),
7779 MockRead(SYNCHRONOUS, OK)
7782 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7783 data_writes, arraysize(data_writes));
7784 session_deps_.socket_factory->AddSocketDataProvider(&data);
7786 TestCompletionCallback callback;
7788 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7789 EXPECT_EQ(ERR_IO_PENDING, rv);
7791 rv = callback.WaitForResult();
7792 EXPECT_EQ(OK, rv);
7794 const HttpResponseInfo* response = trans->GetResponseInfo();
7795 ASSERT_TRUE(response != NULL);
7797 LoadTimingInfo load_timing_info;
7798 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7799 TestLoadTimingNotReused(load_timing_info,
7800 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7802 std::string response_text;
7803 rv = ReadTransaction(trans.get(), &response_text);
7804 EXPECT_EQ(OK, rv);
7805 EXPECT_EQ("Payload", response_text);
7808 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7809 HttpRequestInfo request;
7810 request.method = "GET";
7811 request.url = GURL("http://www.example.org/");
7812 request.load_flags = 0;
7814 session_deps_.proxy_service.reset(
7815 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7816 TestNetLog net_log;
7817 session_deps_.net_log = &net_log;
7819 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7820 scoped_ptr<HttpTransaction> trans(
7821 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7823 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7824 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7825 const char kSOCKS5OkRequest[] = {
7826 0x05, // Version
7827 0x01, // Command (CONNECT)
7828 0x00, // Reserved.
7829 0x03, // Address type (DOMAINNAME).
7830 0x0F, // Length of domain (15)
7831 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7832 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7834 const char kSOCKS5OkResponse[] =
7835 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7837 MockWrite data_writes[] = {
7838 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7839 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7840 MockWrite(
7841 "GET / HTTP/1.1\r\n"
7842 "Host: www.example.org\r\n"
7843 "Connection: keep-alive\r\n\r\n")};
7845 MockRead data_reads[] = {
7846 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7847 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7848 MockRead("HTTP/1.0 200 OK\r\n"),
7849 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7850 MockRead("Payload"),
7851 MockRead(SYNCHRONOUS, OK)
7854 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7855 data_writes, arraysize(data_writes));
7856 session_deps_.socket_factory->AddSocketDataProvider(&data);
7858 TestCompletionCallback callback;
7860 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7861 EXPECT_EQ(ERR_IO_PENDING, rv);
7863 rv = callback.WaitForResult();
7864 EXPECT_EQ(OK, rv);
7866 const HttpResponseInfo* response = trans->GetResponseInfo();
7867 ASSERT_TRUE(response != NULL);
7869 LoadTimingInfo load_timing_info;
7870 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7871 TestLoadTimingNotReusedWithPac(load_timing_info,
7872 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7874 std::string response_text;
7875 rv = ReadTransaction(trans.get(), &response_text);
7876 EXPECT_EQ(OK, rv);
7877 EXPECT_EQ("Payload", response_text);
7880 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7881 HttpRequestInfo request;
7882 request.method = "GET";
7883 request.url = GURL("https://www.example.org/");
7884 request.load_flags = 0;
7886 session_deps_.proxy_service.reset(
7887 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7888 TestNetLog net_log;
7889 session_deps_.net_log = &net_log;
7891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7892 scoped_ptr<HttpTransaction> trans(
7893 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7895 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7896 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7897 const unsigned char kSOCKS5OkRequest[] = {
7898 0x05, // Version
7899 0x01, // Command (CONNECT)
7900 0x00, // Reserved.
7901 0x03, // Address type (DOMAINNAME).
7902 0x0F, // Length of domain (15)
7903 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7904 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7907 const char kSOCKS5OkResponse[] =
7908 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7910 MockWrite data_writes[] = {
7911 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7912 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7913 arraysize(kSOCKS5OkRequest)),
7914 MockWrite(
7915 "GET / HTTP/1.1\r\n"
7916 "Host: www.example.org\r\n"
7917 "Connection: keep-alive\r\n\r\n")};
7919 MockRead data_reads[] = {
7920 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7921 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7922 MockRead("HTTP/1.0 200 OK\r\n"),
7923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7924 MockRead("Payload"),
7925 MockRead(SYNCHRONOUS, OK)
7928 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7929 data_writes, arraysize(data_writes));
7930 session_deps_.socket_factory->AddSocketDataProvider(&data);
7932 SSLSocketDataProvider ssl(ASYNC, OK);
7933 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7935 TestCompletionCallback callback;
7937 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7938 EXPECT_EQ(ERR_IO_PENDING, rv);
7940 rv = callback.WaitForResult();
7941 EXPECT_EQ(OK, rv);
7943 const HttpResponseInfo* response = trans->GetResponseInfo();
7944 ASSERT_TRUE(response != NULL);
7946 LoadTimingInfo load_timing_info;
7947 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7948 TestLoadTimingNotReusedWithPac(load_timing_info,
7949 CONNECT_TIMING_HAS_SSL_TIMES);
7951 std::string response_text;
7952 rv = ReadTransaction(trans.get(), &response_text);
7953 EXPECT_EQ(OK, rv);
7954 EXPECT_EQ("Payload", response_text);
7957 namespace {
7959 // Tests that for connection endpoints the group names are correctly set.
7961 struct GroupNameTest {
7962 std::string proxy_server;
7963 std::string url;
7964 std::string expected_group_name;
7965 bool ssl;
7968 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7969 NextProto next_proto,
7970 SpdySessionDependencies* session_deps_) {
7971 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7973 base::WeakPtr<HttpServerProperties> http_server_properties =
7974 session->http_server_properties();
7975 AlternativeService alternative_service(
7976 AlternateProtocolFromNextProto(next_proto), "", 443);
7977 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
7978 http_server_properties->SetAlternativeService(
7979 HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
7980 expiration);
7982 return session;
7985 int GroupNameTransactionHelper(
7986 const std::string& url,
7987 const scoped_refptr<HttpNetworkSession>& session) {
7988 HttpRequestInfo request;
7989 request.method = "GET";
7990 request.url = GURL(url);
7991 request.load_flags = 0;
7993 scoped_ptr<HttpTransaction> trans(
7994 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7996 TestCompletionCallback callback;
7998 // We do not complete this request, the dtor will clean the transaction up.
7999 return trans->Start(&request, callback.callback(), BoundNetLog());
8002 } // namespace
8004 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
8005 const GroupNameTest tests[] = {
8007 "", // unused
8008 "http://www.example.org/direct",
8009 "www.example.org:80",
8010 false,
8013 "", // unused
8014 "http://[2001:1418:13:1::25]/direct",
8015 "[2001:1418:13:1::25]:80",
8016 false,
8019 // SSL Tests
8021 "", // unused
8022 "https://www.example.org/direct_ssl",
8023 "ssl/www.example.org:443",
8024 true,
8027 "", // unused
8028 "https://[2001:1418:13:1::25]/direct",
8029 "ssl/[2001:1418:13:1::25]:443",
8030 true,
8033 "", // unused
8034 "http://host.with.alternate/direct",
8035 "ssl/host.with.alternate:443",
8036 true,
8040 session_deps_.use_alternative_services = true;
8042 for (size_t i = 0; i < arraysize(tests); ++i) {
8043 session_deps_.proxy_service.reset(
8044 ProxyService::CreateFixed(tests[i].proxy_server));
8045 scoped_refptr<HttpNetworkSession> session(
8046 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8048 HttpNetworkSessionPeer peer(session);
8049 CaptureGroupNameTransportSocketPool* transport_conn_pool =
8050 new CaptureGroupNameTransportSocketPool(NULL, NULL);
8051 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8052 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8053 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8054 new MockClientSocketPoolManager);
8055 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8056 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
8057 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8059 EXPECT_EQ(ERR_IO_PENDING,
8060 GroupNameTransactionHelper(tests[i].url, session));
8061 if (tests[i].ssl)
8062 EXPECT_EQ(tests[i].expected_group_name,
8063 ssl_conn_pool->last_group_name_received());
8064 else
8065 EXPECT_EQ(tests[i].expected_group_name,
8066 transport_conn_pool->last_group_name_received());
8070 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
8071 const GroupNameTest tests[] = {
8073 "http_proxy",
8074 "http://www.example.org/http_proxy_normal",
8075 "www.example.org:80",
8076 false,
8079 // SSL Tests
8081 "http_proxy",
8082 "https://www.example.org/http_connect_ssl",
8083 "ssl/www.example.org:443",
8084 true,
8088 "http_proxy",
8089 "http://host.with.alternate/direct",
8090 "ssl/host.with.alternate:443",
8091 true,
8095 "http_proxy",
8096 "ftp://ftp.google.com/http_proxy_normal",
8097 "ftp/ftp.google.com:21",
8098 false,
8102 session_deps_.use_alternative_services = true;
8104 for (size_t i = 0; i < arraysize(tests); ++i) {
8105 session_deps_.proxy_service.reset(
8106 ProxyService::CreateFixed(tests[i].proxy_server));
8107 scoped_refptr<HttpNetworkSession> session(
8108 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8110 HttpNetworkSessionPeer peer(session);
8112 HostPortPair proxy_host("http_proxy", 80);
8113 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
8114 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
8115 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8116 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8118 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8119 new MockClientSocketPoolManager);
8120 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8121 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8122 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8124 EXPECT_EQ(ERR_IO_PENDING,
8125 GroupNameTransactionHelper(tests[i].url, session));
8126 if (tests[i].ssl)
8127 EXPECT_EQ(tests[i].expected_group_name,
8128 ssl_conn_pool->last_group_name_received());
8129 else
8130 EXPECT_EQ(tests[i].expected_group_name,
8131 http_proxy_pool->last_group_name_received());
8135 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
8136 const GroupNameTest tests[] = {
8138 "socks4://socks_proxy:1080",
8139 "http://www.example.org/socks4_direct",
8140 "socks4/www.example.org:80",
8141 false,
8144 "socks5://socks_proxy:1080",
8145 "http://www.example.org/socks5_direct",
8146 "socks5/www.example.org:80",
8147 false,
8150 // SSL Tests
8152 "socks4://socks_proxy:1080",
8153 "https://www.example.org/socks4_ssl",
8154 "socks4/ssl/www.example.org:443",
8155 true,
8158 "socks5://socks_proxy:1080",
8159 "https://www.example.org/socks5_ssl",
8160 "socks5/ssl/www.example.org:443",
8161 true,
8165 "socks4://socks_proxy:1080",
8166 "http://host.with.alternate/direct",
8167 "socks4/ssl/host.with.alternate:443",
8168 true,
8172 session_deps_.use_alternative_services = true;
8174 for (size_t i = 0; i < arraysize(tests); ++i) {
8175 session_deps_.proxy_service.reset(
8176 ProxyService::CreateFixed(tests[i].proxy_server));
8177 scoped_refptr<HttpNetworkSession> session(
8178 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8180 HttpNetworkSessionPeer peer(session);
8182 HostPortPair proxy_host("socks_proxy", 1080);
8183 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
8184 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
8185 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8186 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8188 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8189 new MockClientSocketPoolManager);
8190 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8191 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8192 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8194 scoped_ptr<HttpTransaction> trans(
8195 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8197 EXPECT_EQ(ERR_IO_PENDING,
8198 GroupNameTransactionHelper(tests[i].url, session));
8199 if (tests[i].ssl)
8200 EXPECT_EQ(tests[i].expected_group_name,
8201 ssl_conn_pool->last_group_name_received());
8202 else
8203 EXPECT_EQ(tests[i].expected_group_name,
8204 socks_conn_pool->last_group_name_received());
8208 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
8209 HttpRequestInfo request;
8210 request.method = "GET";
8211 request.url = GURL("http://www.example.org/");
8213 session_deps_.proxy_service.reset(
8214 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8216 // This simulates failure resolving all hostnames; that means we will fail
8217 // connecting to both proxies (myproxy:70 and foobar:80).
8218 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
8220 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8221 scoped_ptr<HttpTransaction> trans(
8222 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8224 TestCompletionCallback callback;
8226 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8227 EXPECT_EQ(ERR_IO_PENDING, rv);
8229 rv = callback.WaitForResult();
8230 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
8233 // Base test to make sure that when the load flags for a request specify to
8234 // bypass the cache, the DNS cache is not used.
8235 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8236 int load_flags) {
8237 // Issue a request, asking to bypass the cache(s).
8238 HttpRequestInfo request;
8239 request.method = "GET";
8240 request.load_flags = load_flags;
8241 request.url = GURL("http://www.example.org/");
8243 // Select a host resolver that does caching.
8244 session_deps_.host_resolver.reset(new MockCachingHostResolver);
8246 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8247 scoped_ptr<HttpTransaction> trans(
8248 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8250 // Warm up the host cache so it has an entry for "www.example.org".
8251 AddressList addrlist;
8252 TestCompletionCallback callback;
8253 int rv = session_deps_.host_resolver->Resolve(
8254 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8255 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8256 EXPECT_EQ(ERR_IO_PENDING, rv);
8257 rv = callback.WaitForResult();
8258 EXPECT_EQ(OK, rv);
8260 // Verify that it was added to host cache, by doing a subsequent async lookup
8261 // and confirming it completes synchronously.
8262 rv = session_deps_.host_resolver->Resolve(
8263 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8264 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8265 ASSERT_EQ(OK, rv);
8267 // Inject a failure the next time that "www.example.org" is resolved. This way
8268 // we can tell if the next lookup hit the cache, or the "network".
8269 // (cache --> success, "network" --> failure).
8270 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
8272 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8273 // first read -- this won't be reached as the host resolution will fail first.
8274 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
8275 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8276 session_deps_.socket_factory->AddSocketDataProvider(&data);
8278 // Run the request.
8279 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8280 ASSERT_EQ(ERR_IO_PENDING, rv);
8281 rv = callback.WaitForResult();
8283 // If we bypassed the cache, we would have gotten a failure while resolving
8284 // "www.example.org".
8285 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8288 // There are multiple load flags that should trigger the host cache bypass.
8289 // Test each in isolation:
8290 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
8291 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8294 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
8295 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8298 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
8299 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8302 // Make sure we can handle an error when writing the request.
8303 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
8304 HttpRequestInfo request;
8305 request.method = "GET";
8306 request.url = GURL("http://www.foo.com/");
8307 request.load_flags = 0;
8309 MockWrite write_failure[] = {
8310 MockWrite(ASYNC, ERR_CONNECTION_RESET),
8312 StaticSocketDataProvider data(NULL, 0,
8313 write_failure, arraysize(write_failure));
8314 session_deps_.socket_factory->AddSocketDataProvider(&data);
8315 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8317 TestCompletionCallback callback;
8319 scoped_ptr<HttpTransaction> trans(
8320 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8322 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8323 EXPECT_EQ(ERR_IO_PENDING, rv);
8325 rv = callback.WaitForResult();
8326 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
8329 // Check that a connection closed after the start of the headers finishes ok.
8330 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
8331 HttpRequestInfo request;
8332 request.method = "GET";
8333 request.url = GURL("http://www.foo.com/");
8334 request.load_flags = 0;
8336 MockRead data_reads[] = {
8337 MockRead("HTTP/1."),
8338 MockRead(SYNCHRONOUS, OK),
8341 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8342 session_deps_.socket_factory->AddSocketDataProvider(&data);
8343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8345 TestCompletionCallback callback;
8347 scoped_ptr<HttpTransaction> trans(
8348 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8350 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8351 EXPECT_EQ(ERR_IO_PENDING, rv);
8353 rv = callback.WaitForResult();
8354 EXPECT_EQ(OK, rv);
8356 const HttpResponseInfo* response = trans->GetResponseInfo();
8357 ASSERT_TRUE(response != NULL);
8359 EXPECT_TRUE(response->headers.get() != NULL);
8360 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8362 std::string response_data;
8363 rv = ReadTransaction(trans.get(), &response_data);
8364 EXPECT_EQ(OK, rv);
8365 EXPECT_EQ("", response_data);
8368 // Make sure that a dropped connection while draining the body for auth
8369 // restart does the right thing.
8370 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
8371 HttpRequestInfo request;
8372 request.method = "GET";
8373 request.url = GURL("http://www.example.org/");
8374 request.load_flags = 0;
8376 MockWrite data_writes1[] = {
8377 MockWrite(
8378 "GET / HTTP/1.1\r\n"
8379 "Host: www.example.org\r\n"
8380 "Connection: keep-alive\r\n\r\n"),
8383 MockRead data_reads1[] = {
8384 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8385 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8386 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8387 MockRead("Content-Length: 14\r\n\r\n"),
8388 MockRead("Unauth"),
8389 MockRead(ASYNC, ERR_CONNECTION_RESET),
8392 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8393 data_writes1, arraysize(data_writes1));
8394 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8396 // After calling trans->RestartWithAuth(), this is the request we should
8397 // be issuing -- the final header line contains the credentials.
8398 MockWrite data_writes2[] = {
8399 MockWrite(
8400 "GET / HTTP/1.1\r\n"
8401 "Host: www.example.org\r\n"
8402 "Connection: keep-alive\r\n"
8403 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8406 // Lastly, the server responds with the actual content.
8407 MockRead data_reads2[] = {
8408 MockRead("HTTP/1.1 200 OK\r\n"),
8409 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8410 MockRead("Content-Length: 100\r\n\r\n"),
8411 MockRead(SYNCHRONOUS, OK),
8414 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8415 data_writes2, arraysize(data_writes2));
8416 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8417 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8419 TestCompletionCallback callback1;
8421 scoped_ptr<HttpTransaction> trans(
8422 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8424 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8425 EXPECT_EQ(ERR_IO_PENDING, rv);
8427 rv = callback1.WaitForResult();
8428 EXPECT_EQ(OK, rv);
8430 const HttpResponseInfo* response = trans->GetResponseInfo();
8431 ASSERT_TRUE(response != NULL);
8432 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8434 TestCompletionCallback callback2;
8436 rv = trans->RestartWithAuth(
8437 AuthCredentials(kFoo, kBar), callback2.callback());
8438 EXPECT_EQ(ERR_IO_PENDING, rv);
8440 rv = callback2.WaitForResult();
8441 EXPECT_EQ(OK, rv);
8443 response = trans->GetResponseInfo();
8444 ASSERT_TRUE(response != NULL);
8445 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8446 EXPECT_EQ(100, response->headers->GetContentLength());
8449 // Test HTTPS connections going through a proxy that sends extra data.
8450 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8451 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8453 HttpRequestInfo request;
8454 request.method = "GET";
8455 request.url = GURL("https://www.example.org/");
8456 request.load_flags = 0;
8458 MockRead proxy_reads[] = {
8459 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8460 MockRead(SYNCHRONOUS, OK)
8463 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8464 SSLSocketDataProvider ssl(ASYNC, OK);
8466 session_deps_.socket_factory->AddSocketDataProvider(&data);
8467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8469 TestCompletionCallback callback;
8471 session_deps_.socket_factory->ResetNextMockIndexes();
8473 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8474 scoped_ptr<HttpTransaction> trans(
8475 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8477 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8478 EXPECT_EQ(ERR_IO_PENDING, rv);
8480 rv = callback.WaitForResult();
8481 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8484 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8485 HttpRequestInfo request;
8486 request.method = "GET";
8487 request.url = GURL("http://www.example.org/");
8488 request.load_flags = 0;
8490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8491 scoped_ptr<HttpTransaction> trans(
8492 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8494 MockRead data_reads[] = {
8495 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8496 MockRead(SYNCHRONOUS, OK),
8499 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8500 session_deps_.socket_factory->AddSocketDataProvider(&data);
8502 TestCompletionCallback callback;
8504 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8505 EXPECT_EQ(ERR_IO_PENDING, rv);
8507 EXPECT_EQ(OK, callback.WaitForResult());
8509 const HttpResponseInfo* response = trans->GetResponseInfo();
8510 ASSERT_TRUE(response != NULL);
8512 EXPECT_TRUE(response->headers.get() != NULL);
8513 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8515 std::string response_data;
8516 rv = ReadTransaction(trans.get(), &response_data);
8517 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8520 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8521 base::FilePath temp_file_path;
8522 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8523 const uint64 kFakeSize = 100000; // file is actually blank
8524 UploadFileElementReader::ScopedOverridingContentLengthForTests
8525 overriding_content_length(kFakeSize);
8527 ScopedVector<UploadElementReader> element_readers;
8528 element_readers.push_back(
8529 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8530 temp_file_path, 0, kuint64max, base::Time()));
8531 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8533 HttpRequestInfo request;
8534 request.method = "POST";
8535 request.url = GURL("http://www.example.org/upload");
8536 request.upload_data_stream = &upload_data_stream;
8537 request.load_flags = 0;
8539 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8540 scoped_ptr<HttpTransaction> trans(
8541 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8543 MockRead data_reads[] = {
8544 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8545 MockRead("hello world"),
8546 MockRead(SYNCHRONOUS, OK),
8548 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8549 session_deps_.socket_factory->AddSocketDataProvider(&data);
8551 TestCompletionCallback callback;
8553 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8554 EXPECT_EQ(ERR_IO_PENDING, rv);
8556 rv = callback.WaitForResult();
8557 EXPECT_EQ(OK, rv);
8559 const HttpResponseInfo* response = trans->GetResponseInfo();
8560 ASSERT_TRUE(response != NULL);
8562 EXPECT_TRUE(response->headers.get() != NULL);
8563 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8565 std::string response_data;
8566 rv = ReadTransaction(trans.get(), &response_data);
8567 EXPECT_EQ(OK, rv);
8568 EXPECT_EQ("hello world", response_data);
8570 base::DeleteFile(temp_file_path, false);
8573 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8574 base::FilePath temp_file;
8575 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8576 std::string temp_file_content("Unreadable file.");
8577 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8578 temp_file_content.length()));
8579 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
8581 ScopedVector<UploadElementReader> element_readers;
8582 element_readers.push_back(
8583 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8584 temp_file, 0, kuint64max, base::Time()));
8585 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8587 HttpRequestInfo request;
8588 request.method = "POST";
8589 request.url = GURL("http://www.example.org/upload");
8590 request.upload_data_stream = &upload_data_stream;
8591 request.load_flags = 0;
8593 // If we try to upload an unreadable file, the transaction should fail.
8594 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8595 scoped_ptr<HttpTransaction> trans(
8596 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8598 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8599 session_deps_.socket_factory->AddSocketDataProvider(&data);
8601 TestCompletionCallback callback;
8603 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8604 EXPECT_EQ(ERR_IO_PENDING, rv);
8606 rv = callback.WaitForResult();
8607 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8609 base::DeleteFile(temp_file, false);
8612 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8613 class FakeUploadElementReader : public UploadElementReader {
8614 public:
8615 FakeUploadElementReader() {}
8616 ~FakeUploadElementReader() override {}
8618 const CompletionCallback& callback() const { return callback_; }
8620 // UploadElementReader overrides:
8621 int Init(const CompletionCallback& callback) override {
8622 callback_ = callback;
8623 return ERR_IO_PENDING;
8625 uint64 GetContentLength() const override { return 0; }
8626 uint64 BytesRemaining() const override { return 0; }
8627 int Read(IOBuffer* buf,
8628 int buf_length,
8629 const CompletionCallback& callback) override {
8630 return ERR_FAILED;
8633 private:
8634 CompletionCallback callback_;
8637 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8638 ScopedVector<UploadElementReader> element_readers;
8639 element_readers.push_back(fake_reader);
8640 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8642 HttpRequestInfo request;
8643 request.method = "POST";
8644 request.url = GURL("http://www.example.org/upload");
8645 request.upload_data_stream = &upload_data_stream;
8646 request.load_flags = 0;
8648 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8649 scoped_ptr<HttpTransaction> trans(
8650 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8652 StaticSocketDataProvider data;
8653 session_deps_.socket_factory->AddSocketDataProvider(&data);
8655 TestCompletionCallback callback;
8656 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8657 EXPECT_EQ(ERR_IO_PENDING, rv);
8658 base::MessageLoop::current()->RunUntilIdle();
8660 // Transaction is pending on request body initialization.
8661 ASSERT_FALSE(fake_reader->callback().is_null());
8663 // Return Init()'s result after the transaction gets destroyed.
8664 trans.reset();
8665 fake_reader->callback().Run(OK); // Should not crash.
8668 // Tests that changes to Auth realms are treated like auth rejections.
8669 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8670 HttpRequestInfo request;
8671 request.method = "GET";
8672 request.url = GURL("http://www.example.org/");
8673 request.load_flags = 0;
8675 // First transaction will request a resource and receive a Basic challenge
8676 // with realm="first_realm".
8677 MockWrite data_writes1[] = {
8678 MockWrite(
8679 "GET / HTTP/1.1\r\n"
8680 "Host: www.example.org\r\n"
8681 "Connection: keep-alive\r\n"
8682 "\r\n"),
8684 MockRead data_reads1[] = {
8685 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8686 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8687 "\r\n"),
8690 // After calling trans->RestartWithAuth(), provide an Authentication header
8691 // for first_realm. The server will reject and provide a challenge with
8692 // second_realm.
8693 MockWrite data_writes2[] = {
8694 MockWrite(
8695 "GET / HTTP/1.1\r\n"
8696 "Host: www.example.org\r\n"
8697 "Connection: keep-alive\r\n"
8698 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8699 "\r\n"),
8701 MockRead data_reads2[] = {
8702 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8703 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8704 "\r\n"),
8707 // This again fails, and goes back to first_realm. Make sure that the
8708 // entry is removed from cache.
8709 MockWrite data_writes3[] = {
8710 MockWrite(
8711 "GET / HTTP/1.1\r\n"
8712 "Host: www.example.org\r\n"
8713 "Connection: keep-alive\r\n"
8714 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8715 "\r\n"),
8717 MockRead data_reads3[] = {
8718 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8719 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8720 "\r\n"),
8723 // Try one last time (with the correct password) and get the resource.
8724 MockWrite data_writes4[] = {
8725 MockWrite(
8726 "GET / HTTP/1.1\r\n"
8727 "Host: www.example.org\r\n"
8728 "Connection: keep-alive\r\n"
8729 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8730 "\r\n"),
8732 MockRead data_reads4[] = {
8733 MockRead("HTTP/1.1 200 OK\r\n"
8734 "Content-Type: text/html; charset=iso-8859-1\r\n"
8735 "Content-Length: 5\r\n"
8736 "\r\n"
8737 "hello"),
8740 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8741 data_writes1, arraysize(data_writes1));
8742 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8743 data_writes2, arraysize(data_writes2));
8744 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8745 data_writes3, arraysize(data_writes3));
8746 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8747 data_writes4, arraysize(data_writes4));
8748 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8749 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8750 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8751 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8753 TestCompletionCallback callback1;
8755 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8756 scoped_ptr<HttpTransaction> trans(
8757 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8759 // Issue the first request with Authorize headers. There should be a
8760 // password prompt for first_realm waiting to be filled in after the
8761 // transaction completes.
8762 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8763 EXPECT_EQ(ERR_IO_PENDING, rv);
8764 rv = callback1.WaitForResult();
8765 EXPECT_EQ(OK, rv);
8766 const HttpResponseInfo* response = trans->GetResponseInfo();
8767 ASSERT_TRUE(response != NULL);
8768 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8769 ASSERT_FALSE(challenge == NULL);
8770 EXPECT_FALSE(challenge->is_proxy);
8771 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8772 EXPECT_EQ("first_realm", challenge->realm);
8773 EXPECT_EQ("basic", challenge->scheme);
8775 // Issue the second request with an incorrect password. There should be a
8776 // password prompt for second_realm waiting to be filled in after the
8777 // transaction completes.
8778 TestCompletionCallback callback2;
8779 rv = trans->RestartWithAuth(
8780 AuthCredentials(kFirst, kBaz), callback2.callback());
8781 EXPECT_EQ(ERR_IO_PENDING, rv);
8782 rv = callback2.WaitForResult();
8783 EXPECT_EQ(OK, rv);
8784 response = trans->GetResponseInfo();
8785 ASSERT_TRUE(response != NULL);
8786 challenge = response->auth_challenge.get();
8787 ASSERT_FALSE(challenge == NULL);
8788 EXPECT_FALSE(challenge->is_proxy);
8789 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8790 EXPECT_EQ("second_realm", challenge->realm);
8791 EXPECT_EQ("basic", challenge->scheme);
8793 // Issue the third request with another incorrect password. There should be
8794 // a password prompt for first_realm waiting to be filled in. If the password
8795 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8796 // first_realm was not correctly removed.
8797 TestCompletionCallback callback3;
8798 rv = trans->RestartWithAuth(
8799 AuthCredentials(kSecond, kFou), callback3.callback());
8800 EXPECT_EQ(ERR_IO_PENDING, rv);
8801 rv = callback3.WaitForResult();
8802 EXPECT_EQ(OK, rv);
8803 response = trans->GetResponseInfo();
8804 ASSERT_TRUE(response != NULL);
8805 challenge = response->auth_challenge.get();
8806 ASSERT_FALSE(challenge == NULL);
8807 EXPECT_FALSE(challenge->is_proxy);
8808 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8809 EXPECT_EQ("first_realm", challenge->realm);
8810 EXPECT_EQ("basic", challenge->scheme);
8812 // Issue the fourth request with the correct password and username.
8813 TestCompletionCallback callback4;
8814 rv = trans->RestartWithAuth(
8815 AuthCredentials(kFirst, kBar), callback4.callback());
8816 EXPECT_EQ(ERR_IO_PENDING, rv);
8817 rv = callback4.WaitForResult();
8818 EXPECT_EQ(OK, rv);
8819 response = trans->GetResponseInfo();
8820 ASSERT_TRUE(response != NULL);
8821 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8824 TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
8825 session_deps_.next_protos = SpdyNextProtos();
8826 session_deps_.use_alternative_services = true;
8828 std::string alternative_service_http_header =
8829 GetAlternativeServiceHttpHeader();
8831 MockRead data_reads[] = {
8832 MockRead("HTTP/1.1 200 OK\r\n"),
8833 MockRead(alternative_service_http_header.c_str()),
8834 MockRead("\r\n"),
8835 MockRead("hello world"),
8836 MockRead(SYNCHRONOUS, OK),
8839 HttpRequestInfo request;
8840 request.method = "GET";
8841 request.url = GURL("http://www.example.org/");
8842 request.load_flags = 0;
8844 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8846 session_deps_.socket_factory->AddSocketDataProvider(&data);
8848 TestCompletionCallback callback;
8850 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8851 scoped_ptr<HttpTransaction> trans(
8852 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8854 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8855 EXPECT_EQ(ERR_IO_PENDING, rv);
8857 HostPortPair http_host_port_pair("www.example.org", 80);
8858 HttpServerProperties& http_server_properties =
8859 *session->http_server_properties();
8860 AlternativeServiceVector alternative_service_vector =
8861 http_server_properties.GetAlternativeServices(http_host_port_pair);
8862 EXPECT_TRUE(alternative_service_vector.empty());
8864 EXPECT_EQ(OK, callback.WaitForResult());
8866 const HttpResponseInfo* response = trans->GetResponseInfo();
8867 ASSERT_TRUE(response != NULL);
8868 ASSERT_TRUE(response->headers.get() != NULL);
8869 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8870 EXPECT_FALSE(response->was_fetched_via_spdy);
8871 EXPECT_FALSE(response->was_npn_negotiated);
8873 std::string response_data;
8874 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8875 EXPECT_EQ("hello world", response_data);
8877 alternative_service_vector =
8878 http_server_properties.GetAlternativeServices(http_host_port_pair);
8879 ASSERT_EQ(1u, alternative_service_vector.size());
8880 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8881 alternative_service_vector[0].protocol);
8882 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
8883 EXPECT_EQ(443, alternative_service_vector[0].port);
8886 // Alternative Service headers must be ignored when |use_alternative_services|
8887 // is false.
8888 TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
8889 session_deps_.next_protos = SpdyNextProtos();
8890 session_deps_.use_alternative_services = false;
8892 std::string alternative_service_http_header =
8893 GetAlternativeServiceHttpHeader();
8895 MockRead data_reads[] = {
8896 MockRead("HTTP/1.1 200 OK\r\n"),
8897 MockRead(alternative_service_http_header.c_str()),
8898 MockRead("\r\n"),
8899 MockRead("hello world"),
8900 MockRead(SYNCHRONOUS, OK),
8903 HttpRequestInfo request;
8904 request.method = "GET";
8905 request.url = GURL("http://www.example.org/");
8906 request.load_flags = 0;
8908 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
8910 session_deps_.socket_factory->AddSocketDataProvider(&data);
8912 TestCompletionCallback callback;
8914 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8915 scoped_ptr<HttpTransaction> trans(
8916 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8918 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8919 EXPECT_EQ(ERR_IO_PENDING, rv);
8921 HostPortPair http_host_port_pair("www.example.org", 80);
8922 HttpServerProperties& http_server_properties =
8923 *session->http_server_properties();
8924 AlternativeServiceVector alternative_service_vector =
8925 http_server_properties.GetAlternativeServices(http_host_port_pair);
8926 EXPECT_TRUE(alternative_service_vector.empty());
8928 EXPECT_EQ(OK, callback.WaitForResult());
8930 const HttpResponseInfo* response = trans->GetResponseInfo();
8931 ASSERT_TRUE(response != nullptr);
8932 ASSERT_TRUE(response->headers.get() != nullptr);
8933 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8934 EXPECT_FALSE(response->was_fetched_via_spdy);
8935 EXPECT_FALSE(response->was_npn_negotiated);
8937 std::string response_data;
8938 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8939 EXPECT_EQ("hello world", response_data);
8941 alternative_service_vector =
8942 http_server_properties.GetAlternativeServices(http_host_port_pair);
8943 EXPECT_TRUE(alternative_service_vector.empty());
8946 TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
8947 session_deps_.next_protos = SpdyNextProtos();
8948 session_deps_.use_alternative_services = true;
8950 MockRead data_reads[] = {
8951 MockRead("HTTP/1.1 200 OK\r\n"),
8952 MockRead("Alt-Svc: "),
8953 MockRead(GetAlternateProtocolFromParam()),
8954 MockRead("=\"www.example.com:443\";p=1.0,"),
8955 MockRead("quic=\":1234\"\r\n\r\n"),
8956 MockRead("hello world"),
8957 MockRead(SYNCHRONOUS, OK),
8960 HttpRequestInfo request;
8961 request.method = "GET";
8962 request.url = GURL("http://www.example.org/");
8963 request.load_flags = 0;
8965 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8967 session_deps_.socket_factory->AddSocketDataProvider(&data);
8969 TestCompletionCallback callback;
8971 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8972 scoped_ptr<HttpTransaction> trans(
8973 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8975 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8976 EXPECT_EQ(ERR_IO_PENDING, rv);
8978 HostPortPair http_host_port_pair("www.example.org", 80);
8979 HttpServerProperties& http_server_properties =
8980 *session->http_server_properties();
8981 AlternativeServiceVector alternative_service_vector =
8982 http_server_properties.GetAlternativeServices(http_host_port_pair);
8983 EXPECT_TRUE(alternative_service_vector.empty());
8985 EXPECT_EQ(OK, callback.WaitForResult());
8987 const HttpResponseInfo* response = trans->GetResponseInfo();
8988 ASSERT_TRUE(response != NULL);
8989 ASSERT_TRUE(response->headers.get() != NULL);
8990 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8991 EXPECT_FALSE(response->was_fetched_via_spdy);
8992 EXPECT_FALSE(response->was_npn_negotiated);
8994 std::string response_data;
8995 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8996 EXPECT_EQ("hello world", response_data);
8998 alternative_service_vector =
8999 http_server_properties.GetAlternativeServices(http_host_port_pair);
9000 ASSERT_EQ(2u, alternative_service_vector.size());
9001 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9002 alternative_service_vector[0].protocol);
9003 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9004 EXPECT_EQ(443, alternative_service_vector[0].port);
9005 EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
9006 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
9007 EXPECT_EQ(1234, alternative_service_vector[1].port);
9010 // Alternate Protocol headers must be honored even if |use_alternative_services|
9011 // is false.
9012 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
9013 session_deps_.next_protos = SpdyNextProtos();
9014 session_deps_.use_alternative_services = false;
9016 std::string alternate_protocol_http_header =
9017 GetAlternateProtocolHttpHeader();
9019 MockRead data_reads[] = {
9020 MockRead("HTTP/1.1 200 OK\r\n"),
9021 MockRead(alternate_protocol_http_header.c_str()),
9022 MockRead("\r\n"),
9023 MockRead("hello world"),
9024 MockRead(SYNCHRONOUS, OK),
9027 HttpRequestInfo request;
9028 request.method = "GET";
9029 request.url = GURL("http://www.example.org/");
9030 request.load_flags = 0;
9032 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9034 session_deps_.socket_factory->AddSocketDataProvider(&data);
9036 TestCompletionCallback callback;
9038 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9039 scoped_ptr<HttpTransaction> trans(
9040 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9042 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9043 EXPECT_EQ(ERR_IO_PENDING, rv);
9045 HostPortPair http_host_port_pair("www.example.org", 80);
9046 HttpServerProperties& http_server_properties =
9047 *session->http_server_properties();
9048 AlternativeServiceVector alternative_service_vector =
9049 http_server_properties.GetAlternativeServices(http_host_port_pair);
9050 EXPECT_TRUE(alternative_service_vector.empty());
9052 EXPECT_EQ(OK, callback.WaitForResult());
9054 const HttpResponseInfo* response = trans->GetResponseInfo();
9055 ASSERT_TRUE(response != NULL);
9056 ASSERT_TRUE(response->headers.get() != NULL);
9057 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9058 EXPECT_FALSE(response->was_fetched_via_spdy);
9059 EXPECT_FALSE(response->was_npn_negotiated);
9061 std::string response_data;
9062 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9063 EXPECT_EQ("hello world", response_data);
9065 alternative_service_vector =
9066 http_server_properties.GetAlternativeServices(http_host_port_pair);
9067 ASSERT_EQ(1u, alternative_service_vector.size());
9068 EXPECT_EQ(443, alternative_service_vector[0].port);
9069 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9070 alternative_service_vector[0].protocol);
9073 TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
9074 session_deps_.next_protos = SpdyNextProtos();
9075 session_deps_.use_alternative_services = true;
9077 MockRead data_reads[] = {
9078 MockRead("HTTP/1.1 200 OK\r\n"),
9079 MockRead("Alternate-Protocol: \r\n\r\n"),
9080 MockRead("hello world"),
9081 MockRead(SYNCHRONOUS, OK),
9084 HttpRequestInfo request;
9085 request.method = "GET";
9086 request.url = GURL("http://www.example.org/");
9087 request.load_flags = 0;
9089 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9091 session_deps_.socket_factory->AddSocketDataProvider(&data);
9093 TestCompletionCallback callback;
9095 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9097 HostPortPair http_host_port_pair("www.example.org", 80);
9098 HttpServerProperties& http_server_properties =
9099 *session->http_server_properties();
9100 AlternativeService alternative_service(QUIC, "", 80);
9101 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9102 http_server_properties.SetAlternativeService(
9103 http_host_port_pair, alternative_service, 1.0, expiration);
9105 AlternativeServiceVector alternative_service_vector =
9106 http_server_properties.GetAlternativeServices(http_host_port_pair);
9107 ASSERT_EQ(1u, alternative_service_vector.size());
9108 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
9110 scoped_ptr<HttpTransaction> trans(
9111 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9113 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9114 EXPECT_EQ(ERR_IO_PENDING, rv);
9116 EXPECT_EQ(OK, callback.WaitForResult());
9118 const HttpResponseInfo* response = trans->GetResponseInfo();
9119 ASSERT_TRUE(response != NULL);
9120 ASSERT_TRUE(response->headers.get() != NULL);
9121 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9122 EXPECT_FALSE(response->was_fetched_via_spdy);
9123 EXPECT_FALSE(response->was_npn_negotiated);
9125 std::string response_data;
9126 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9127 EXPECT_EQ("hello world", response_data);
9129 alternative_service_vector =
9130 http_server_properties.GetAlternativeServices(http_host_port_pair);
9131 EXPECT_TRUE(alternative_service_vector.empty());
9134 TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
9135 session_deps_.next_protos = SpdyNextProtos();
9136 session_deps_.use_alternative_services = true;
9138 std::string alternative_service_http_header =
9139 GetAlternativeServiceHttpHeader();
9140 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
9142 MockRead data_reads[] = {
9143 MockRead("HTTP/1.1 200 OK\r\n"),
9144 MockRead(alternative_service_http_header.c_str()),
9145 MockRead(alternate_protocol_http_header.c_str()),
9146 MockRead("\r\n"),
9147 MockRead("hello world"),
9148 MockRead(SYNCHRONOUS, OK),
9151 HttpRequestInfo request;
9152 request.method = "GET";
9153 request.url = GURL("http://www.example.org/");
9154 request.load_flags = 0;
9156 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9158 session_deps_.socket_factory->AddSocketDataProvider(&data);
9160 TestCompletionCallback callback;
9162 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9163 scoped_ptr<HttpTransaction> trans(
9164 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9166 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9167 EXPECT_EQ(ERR_IO_PENDING, rv);
9169 HostPortPair http_host_port_pair("www.example.org", 80);
9170 HttpServerProperties& http_server_properties =
9171 *session->http_server_properties();
9172 AlternativeServiceVector alternative_service_vector =
9173 http_server_properties.GetAlternativeServices(http_host_port_pair);
9174 EXPECT_TRUE(alternative_service_vector.empty());
9176 EXPECT_EQ(OK, callback.WaitForResult());
9178 const HttpResponseInfo* response = trans->GetResponseInfo();
9179 ASSERT_TRUE(response != NULL);
9180 ASSERT_TRUE(response->headers.get() != NULL);
9181 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9182 EXPECT_FALSE(response->was_fetched_via_spdy);
9183 EXPECT_FALSE(response->was_npn_negotiated);
9185 std::string response_data;
9186 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9187 EXPECT_EQ("hello world", response_data);
9189 alternative_service_vector =
9190 http_server_properties.GetAlternativeServices(http_host_port_pair);
9191 ASSERT_EQ(1u, alternative_service_vector.size());
9192 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9193 alternative_service_vector[0].protocol);
9194 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9195 EXPECT_EQ(443, alternative_service_vector[0].port);
9198 // When |use_alternative_services| is false, do not observe alternative service
9199 // entries that point to a different host.
9200 TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
9201 session_deps_.use_alternative_services = false;
9203 HttpRequestInfo request;
9204 request.method = "GET";
9205 request.url = GURL("http://www.example.org/");
9206 request.load_flags = 0;
9208 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9209 StaticSocketDataProvider first_data;
9210 first_data.set_connect_data(mock_connect);
9211 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9213 MockRead data_reads[] = {
9214 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
9215 MockRead(ASYNC, OK),
9217 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads),
9218 nullptr, 0);
9219 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9221 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9223 base::WeakPtr<HttpServerProperties> http_server_properties =
9224 session->http_server_properties();
9225 AlternativeService alternative_service(
9226 AlternateProtocolFromNextProto(GetParam()), "different.example.org", 80);
9227 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9228 http_server_properties->SetAlternativeService(
9229 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
9231 scoped_ptr<HttpTransaction> trans(
9232 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9233 TestCompletionCallback callback;
9235 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9236 // The connetion to origin was refused, and the alternative service should not
9237 // be used (even though mock data are there), therefore the request should
9238 // fail.
9239 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv));
9242 TEST_P(HttpNetworkTransactionTest,
9243 MarkBrokenAlternateProtocolAndFallback) {
9244 session_deps_.use_alternative_services = true;
9246 HttpRequestInfo request;
9247 request.method = "GET";
9248 request.url = GURL("http://www.example.org/");
9249 request.load_flags = 0;
9251 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9252 StaticSocketDataProvider first_data;
9253 first_data.set_connect_data(mock_connect);
9254 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9256 MockRead data_reads[] = {
9257 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9258 MockRead("hello world"),
9259 MockRead(ASYNC, OK),
9261 StaticSocketDataProvider second_data(
9262 data_reads, arraysize(data_reads), NULL, 0);
9263 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9265 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9267 base::WeakPtr<HttpServerProperties> http_server_properties =
9268 session->http_server_properties();
9269 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
9270 // Port must be < 1024, or the header will be ignored (since initial port was
9271 // port 80 (another restricted port).
9272 const AlternativeService alternative_service(
9273 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9274 666); // Port is ignored by MockConnect anyway.
9275 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9276 http_server_properties->SetAlternativeService(
9277 host_port_pair, alternative_service, 1.0, expiration);
9279 scoped_ptr<HttpTransaction> trans(
9280 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9281 TestCompletionCallback callback;
9283 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9284 EXPECT_EQ(ERR_IO_PENDING, rv);
9285 EXPECT_EQ(OK, callback.WaitForResult());
9287 const HttpResponseInfo* response = trans->GetResponseInfo();
9288 ASSERT_TRUE(response != NULL);
9289 ASSERT_TRUE(response->headers.get() != NULL);
9290 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9292 std::string response_data;
9293 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9294 EXPECT_EQ("hello world", response_data);
9296 const AlternativeServiceVector alternative_service_vector =
9297 http_server_properties->GetAlternativeServices(host_port_pair);
9298 ASSERT_EQ(1u, alternative_service_vector.size());
9299 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
9300 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
9301 alternative_service_vector[0]));
9304 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9305 // to an unrestricted (port >= 1024) when the original traffic was on a
9306 // restricted port (port < 1024). Ensure that we can redirect in all other
9307 // cases.
9308 TEST_P(HttpNetworkTransactionTest,
9309 AlternateProtocolPortRestrictedBlocked) {
9310 session_deps_.use_alternative_services = true;
9312 HttpRequestInfo restricted_port_request;
9313 restricted_port_request.method = "GET";
9314 restricted_port_request.url = GURL("http://www.example.org:1023/");
9315 restricted_port_request.load_flags = 0;
9317 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9318 StaticSocketDataProvider first_data;
9319 first_data.set_connect_data(mock_connect);
9320 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9322 MockRead data_reads[] = {
9323 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9324 MockRead("hello world"),
9325 MockRead(ASYNC, OK),
9327 StaticSocketDataProvider second_data(
9328 data_reads, arraysize(data_reads), NULL, 0);
9329 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9333 base::WeakPtr<HttpServerProperties> http_server_properties =
9334 session->http_server_properties();
9335 const int kUnrestrictedAlternatePort = 1024;
9336 AlternativeService alternative_service(
9337 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9338 kUnrestrictedAlternatePort);
9339 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9340 http_server_properties->SetAlternativeService(
9341 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9342 1.0, expiration);
9344 scoped_ptr<HttpTransaction> trans(
9345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9346 TestCompletionCallback callback;
9348 int rv = trans->Start(
9349 &restricted_port_request,
9350 callback.callback(), BoundNetLog());
9351 EXPECT_EQ(ERR_IO_PENDING, rv);
9352 // Invalid change to unrestricted port should fail.
9353 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
9356 // Ensure that we are allowed to redirect traffic via an alternate protocol to
9357 // an unrestricted (port >= 1024) when the original traffic was on a restricted
9358 // port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
9359 TEST_P(HttpNetworkTransactionTest,
9360 AlternateProtocolPortRestrictedPermitted) {
9361 session_deps_.use_alternative_services = true;
9362 session_deps_.enable_user_alternate_protocol_ports = true;
9364 HttpRequestInfo restricted_port_request;
9365 restricted_port_request.method = "GET";
9366 restricted_port_request.url = GURL("http://www.example.org:1023/");
9367 restricted_port_request.load_flags = 0;
9369 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9370 StaticSocketDataProvider first_data;
9371 first_data.set_connect_data(mock_connect);
9372 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
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 second_data(
9380 data_reads, arraysize(data_reads), NULL, 0);
9381 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9383 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9385 base::WeakPtr<HttpServerProperties> http_server_properties =
9386 session->http_server_properties();
9387 const int kUnrestrictedAlternatePort = 1024;
9388 AlternativeService alternative_service(
9389 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9390 kUnrestrictedAlternatePort);
9391 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9392 http_server_properties->SetAlternativeService(
9393 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9394 1.0, expiration);
9396 scoped_ptr<HttpTransaction> trans(
9397 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9398 TestCompletionCallback callback;
9400 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
9401 &restricted_port_request,
9402 callback.callback(), BoundNetLog()));
9403 // Change to unrestricted port should succeed.
9404 EXPECT_EQ(OK, callback.WaitForResult());
9407 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9408 // to an unrestricted (port >= 1024) when the original traffic was on a
9409 // restricted port (port < 1024). Ensure that we can redirect in all other
9410 // cases.
9411 TEST_P(HttpNetworkTransactionTest,
9412 AlternateProtocolPortRestrictedAllowed) {
9413 session_deps_.use_alternative_services = true;
9415 HttpRequestInfo restricted_port_request;
9416 restricted_port_request.method = "GET";
9417 restricted_port_request.url = GURL("http://www.example.org:1023/");
9418 restricted_port_request.load_flags = 0;
9420 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9421 StaticSocketDataProvider first_data;
9422 first_data.set_connect_data(mock_connect);
9423 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9425 MockRead data_reads[] = {
9426 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9427 MockRead("hello world"),
9428 MockRead(ASYNC, OK),
9430 StaticSocketDataProvider second_data(
9431 data_reads, arraysize(data_reads), NULL, 0);
9432 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9434 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9436 base::WeakPtr<HttpServerProperties> http_server_properties =
9437 session->http_server_properties();
9438 const int kRestrictedAlternatePort = 80;
9439 AlternativeService alternative_service(
9440 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9441 kRestrictedAlternatePort);
9442 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9443 http_server_properties->SetAlternativeService(
9444 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9445 1.0, expiration);
9447 scoped_ptr<HttpTransaction> trans(
9448 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9449 TestCompletionCallback callback;
9451 int rv = trans->Start(
9452 &restricted_port_request,
9453 callback.callback(), BoundNetLog());
9454 EXPECT_EQ(ERR_IO_PENDING, rv);
9455 // Valid change to restricted port should pass.
9456 EXPECT_EQ(OK, callback.WaitForResult());
9459 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9460 // to an unrestricted (port >= 1024) when the original traffic was on a
9461 // restricted port (port < 1024). Ensure that we can redirect in all other
9462 // cases.
9463 TEST_P(HttpNetworkTransactionTest,
9464 AlternateProtocolPortUnrestrictedAllowed1) {
9465 session_deps_.use_alternative_services = true;
9467 HttpRequestInfo unrestricted_port_request;
9468 unrestricted_port_request.method = "GET";
9469 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9470 unrestricted_port_request.load_flags = 0;
9472 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9473 StaticSocketDataProvider first_data;
9474 first_data.set_connect_data(mock_connect);
9475 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9477 MockRead data_reads[] = {
9478 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9479 MockRead("hello world"),
9480 MockRead(ASYNC, OK),
9482 StaticSocketDataProvider second_data(
9483 data_reads, arraysize(data_reads), NULL, 0);
9484 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9486 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9488 base::WeakPtr<HttpServerProperties> http_server_properties =
9489 session->http_server_properties();
9490 const int kRestrictedAlternatePort = 80;
9491 AlternativeService alternative_service(
9492 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9493 kRestrictedAlternatePort);
9494 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9495 http_server_properties->SetAlternativeService(
9496 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9497 1.0, expiration);
9499 scoped_ptr<HttpTransaction> trans(
9500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9501 TestCompletionCallback callback;
9503 int rv = trans->Start(
9504 &unrestricted_port_request, callback.callback(), BoundNetLog());
9505 EXPECT_EQ(ERR_IO_PENDING, rv);
9506 // Valid change to restricted port should pass.
9507 EXPECT_EQ(OK, callback.WaitForResult());
9510 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9511 // to an unrestricted (port >= 1024) when the original traffic was on a
9512 // restricted port (port < 1024). Ensure that we can redirect in all other
9513 // cases.
9514 TEST_P(HttpNetworkTransactionTest,
9515 AlternateProtocolPortUnrestrictedAllowed2) {
9516 session_deps_.use_alternative_services = true;
9518 HttpRequestInfo unrestricted_port_request;
9519 unrestricted_port_request.method = "GET";
9520 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9521 unrestricted_port_request.load_flags = 0;
9523 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9524 StaticSocketDataProvider first_data;
9525 first_data.set_connect_data(mock_connect);
9526 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9528 MockRead data_reads[] = {
9529 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9530 MockRead("hello world"),
9531 MockRead(ASYNC, OK),
9533 StaticSocketDataProvider second_data(
9534 data_reads, arraysize(data_reads), NULL, 0);
9535 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9537 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9539 base::WeakPtr<HttpServerProperties> http_server_properties =
9540 session->http_server_properties();
9541 const int kUnrestrictedAlternatePort = 1025;
9542 AlternativeService alternative_service(
9543 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9544 kUnrestrictedAlternatePort);
9545 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9546 http_server_properties->SetAlternativeService(
9547 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9548 1.0, expiration);
9550 scoped_ptr<HttpTransaction> trans(
9551 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9552 TestCompletionCallback callback;
9554 int rv = trans->Start(
9555 &unrestricted_port_request, callback.callback(), BoundNetLog());
9556 EXPECT_EQ(ERR_IO_PENDING, rv);
9557 // Valid change to an unrestricted port should pass.
9558 EXPECT_EQ(OK, callback.WaitForResult());
9561 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9562 // to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
9563 // once the alternate protocol request fails.
9564 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
9565 session_deps_.use_alternative_services = true;
9567 HttpRequestInfo request;
9568 request.method = "GET";
9569 request.url = GURL("http://www.example.org/");
9570 request.load_flags = 0;
9572 // The alternate protocol request will error out before we attempt to connect,
9573 // so only the standard HTTP request will try to connect.
9574 MockRead data_reads[] = {
9575 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9576 MockRead("hello world"),
9577 MockRead(ASYNC, OK),
9579 StaticSocketDataProvider data(
9580 data_reads, arraysize(data_reads), NULL, 0);
9581 session_deps_.socket_factory->AddSocketDataProvider(&data);
9583 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9585 base::WeakPtr<HttpServerProperties> http_server_properties =
9586 session->http_server_properties();
9587 const int kUnsafePort = 7;
9588 AlternativeService alternative_service(
9589 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9590 kUnsafePort);
9591 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9592 http_server_properties->SetAlternativeService(
9593 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
9595 scoped_ptr<HttpTransaction> trans(
9596 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9597 TestCompletionCallback callback;
9599 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9600 EXPECT_EQ(ERR_IO_PENDING, rv);
9601 // The HTTP request should succeed.
9602 EXPECT_EQ(OK, callback.WaitForResult());
9604 const HttpResponseInfo* response = trans->GetResponseInfo();
9605 ASSERT_TRUE(response != NULL);
9606 ASSERT_TRUE(response->headers.get() != NULL);
9607 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9609 std::string response_data;
9610 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9611 EXPECT_EQ("hello world", response_data);
9614 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
9615 session_deps_.use_alternative_services = true;
9616 session_deps_.next_protos = SpdyNextProtos();
9618 HttpRequestInfo request;
9619 request.method = "GET";
9620 request.url = GURL("http://www.example.org/");
9621 request.load_flags = 0;
9623 std::string alternate_protocol_http_header =
9624 GetAlternateProtocolHttpHeader();
9626 MockRead data_reads[] = {
9627 MockRead("HTTP/1.1 200 OK\r\n"),
9628 MockRead(alternate_protocol_http_header.c_str()),
9629 MockRead("\r\n"),
9630 MockRead("hello world"),
9631 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9632 MockRead(ASYNC, OK)};
9634 StaticSocketDataProvider first_transaction(
9635 data_reads, arraysize(data_reads), NULL, 0);
9636 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9638 SSLSocketDataProvider ssl(ASYNC, OK);
9639 ssl.SetNextProto(GetParam());
9640 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9641 ASSERT_TRUE(ssl.cert.get());
9642 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9644 scoped_ptr<SpdyFrame> req(
9645 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9646 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
9648 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9649 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9650 MockRead spdy_reads[] = {
9651 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
9654 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9655 arraysize(spdy_writes));
9656 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9658 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9659 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9660 NULL, 0, NULL, 0);
9661 hanging_non_alternate_protocol_socket.set_connect_data(
9662 never_finishing_connect);
9663 session_deps_.socket_factory->AddSocketDataProvider(
9664 &hanging_non_alternate_protocol_socket);
9666 TestCompletionCallback callback;
9668 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9669 scoped_ptr<HttpTransaction> trans(
9670 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9672 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9673 EXPECT_EQ(ERR_IO_PENDING, rv);
9674 EXPECT_EQ(OK, callback.WaitForResult());
9676 const HttpResponseInfo* response = trans->GetResponseInfo();
9677 ASSERT_TRUE(response != NULL);
9678 ASSERT_TRUE(response->headers.get() != NULL);
9679 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9681 std::string response_data;
9682 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9683 EXPECT_EQ("hello world", response_data);
9685 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9687 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9688 EXPECT_EQ(ERR_IO_PENDING, rv);
9689 EXPECT_EQ(OK, callback.WaitForResult());
9691 response = trans->GetResponseInfo();
9692 ASSERT_TRUE(response != NULL);
9693 ASSERT_TRUE(response->headers.get() != NULL);
9694 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9695 EXPECT_TRUE(response->was_fetched_via_spdy);
9696 EXPECT_TRUE(response->was_npn_negotiated);
9698 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9699 EXPECT_EQ("hello!", response_data);
9702 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
9703 session_deps_.use_alternative_services = true;
9704 session_deps_.next_protos = SpdyNextProtos();
9706 HttpRequestInfo request;
9707 request.method = "GET";
9708 request.url = GURL("http://www.example.org/");
9709 request.load_flags = 0;
9711 std::string alternate_protocol_http_header =
9712 GetAlternateProtocolHttpHeader();
9714 MockRead data_reads[] = {
9715 MockRead("HTTP/1.1 200 OK\r\n"),
9716 MockRead(alternate_protocol_http_header.c_str()),
9717 MockRead("\r\n"),
9718 MockRead("hello world"),
9719 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9720 MockRead(ASYNC, OK),
9723 StaticSocketDataProvider first_transaction(
9724 data_reads, arraysize(data_reads), NULL, 0);
9725 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9726 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9728 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9729 StaticSocketDataProvider hanging_socket(
9730 NULL, 0, NULL, 0);
9731 hanging_socket.set_connect_data(never_finishing_connect);
9732 // Socket 2 and 3 are the hanging Alternate-Protocol and
9733 // non-Alternate-Protocol jobs from the 2nd transaction.
9734 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9735 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9737 SSLSocketDataProvider ssl(ASYNC, OK);
9738 ssl.SetNextProto(GetParam());
9739 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9740 ASSERT_TRUE(ssl.cert.get());
9741 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9743 scoped_ptr<SpdyFrame> req1(
9744 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9745 scoped_ptr<SpdyFrame> req2(
9746 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9747 MockWrite spdy_writes[] = {
9748 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
9750 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9751 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
9752 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9753 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9754 MockRead spdy_reads[] = {
9755 CreateMockRead(*resp1, 2),
9756 CreateMockRead(*data1, 3),
9757 CreateMockRead(*resp2, 4),
9758 CreateMockRead(*data2, 5),
9759 MockRead(ASYNC, 0, 6),
9762 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
9763 arraysize(spdy_writes));
9764 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9765 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9767 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9768 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9770 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9771 TestCompletionCallback callback1;
9772 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9774 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
9775 EXPECT_EQ(ERR_IO_PENDING, rv);
9776 EXPECT_EQ(OK, callback1.WaitForResult());
9778 const HttpResponseInfo* response = trans1.GetResponseInfo();
9779 ASSERT_TRUE(response != NULL);
9780 ASSERT_TRUE(response->headers.get() != NULL);
9781 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9783 std::string response_data;
9784 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9785 EXPECT_EQ("hello world", response_data);
9787 TestCompletionCallback callback2;
9788 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9789 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
9790 EXPECT_EQ(ERR_IO_PENDING, rv);
9792 TestCompletionCallback callback3;
9793 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
9794 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
9795 EXPECT_EQ(ERR_IO_PENDING, rv);
9797 EXPECT_EQ(OK, callback2.WaitForResult());
9798 EXPECT_EQ(OK, callback3.WaitForResult());
9800 response = trans2.GetResponseInfo();
9801 ASSERT_TRUE(response != NULL);
9802 ASSERT_TRUE(response->headers.get() != NULL);
9803 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9804 EXPECT_TRUE(response->was_fetched_via_spdy);
9805 EXPECT_TRUE(response->was_npn_negotiated);
9806 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9807 EXPECT_EQ("hello!", response_data);
9809 response = trans3.GetResponseInfo();
9810 ASSERT_TRUE(response != NULL);
9811 ASSERT_TRUE(response->headers.get() != NULL);
9812 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9813 EXPECT_TRUE(response->was_fetched_via_spdy);
9814 EXPECT_TRUE(response->was_npn_negotiated);
9815 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9816 EXPECT_EQ("hello!", response_data);
9819 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9820 session_deps_.use_alternative_services = true;
9821 session_deps_.next_protos = SpdyNextProtos();
9823 HttpRequestInfo request;
9824 request.method = "GET";
9825 request.url = GURL("http://www.example.org/");
9826 request.load_flags = 0;
9828 std::string alternate_protocol_http_header =
9829 GetAlternateProtocolHttpHeader();
9831 MockRead data_reads[] = {
9832 MockRead("HTTP/1.1 200 OK\r\n"),
9833 MockRead(alternate_protocol_http_header.c_str()),
9834 MockRead("\r\n"),
9835 MockRead("hello world"),
9836 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9837 MockRead(ASYNC, OK),
9840 StaticSocketDataProvider first_transaction(
9841 data_reads, arraysize(data_reads), NULL, 0);
9842 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9844 SSLSocketDataProvider ssl(ASYNC, OK);
9845 ssl.SetNextProto(GetParam());
9846 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9848 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9849 StaticSocketDataProvider hanging_alternate_protocol_socket(
9850 NULL, 0, NULL, 0);
9851 hanging_alternate_protocol_socket.set_connect_data(
9852 never_finishing_connect);
9853 session_deps_.socket_factory->AddSocketDataProvider(
9854 &hanging_alternate_protocol_socket);
9856 // 2nd request is just a copy of the first one, over HTTP again.
9857 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9859 TestCompletionCallback callback;
9861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9862 scoped_ptr<HttpTransaction> trans(
9863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9865 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9866 EXPECT_EQ(ERR_IO_PENDING, rv);
9867 EXPECT_EQ(OK, callback.WaitForResult());
9869 const HttpResponseInfo* response = trans->GetResponseInfo();
9870 ASSERT_TRUE(response != NULL);
9871 ASSERT_TRUE(response->headers.get() != NULL);
9872 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9874 std::string response_data;
9875 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9876 EXPECT_EQ("hello world", response_data);
9878 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9880 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9881 EXPECT_EQ(ERR_IO_PENDING, rv);
9882 EXPECT_EQ(OK, callback.WaitForResult());
9884 response = trans->GetResponseInfo();
9885 ASSERT_TRUE(response != NULL);
9886 ASSERT_TRUE(response->headers.get() != NULL);
9887 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9888 EXPECT_FALSE(response->was_fetched_via_spdy);
9889 EXPECT_FALSE(response->was_npn_negotiated);
9891 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9892 EXPECT_EQ("hello world", response_data);
9895 class CapturingProxyResolver : public ProxyResolver {
9896 public:
9897 CapturingProxyResolver() {}
9898 ~CapturingProxyResolver() override {}
9900 int GetProxyForURL(const GURL& url,
9901 ProxyInfo* results,
9902 const CompletionCallback& callback,
9903 RequestHandle* request,
9904 const BoundNetLog& net_log) override {
9905 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9906 HostPortPair("myproxy", 80));
9907 results->UseProxyServer(proxy_server);
9908 resolved_.push_back(url);
9909 return OK;
9912 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
9914 LoadState GetLoadState(RequestHandle request) const override {
9915 NOTREACHED();
9916 return LOAD_STATE_IDLE;
9919 const std::vector<GURL>& resolved() const { return resolved_; }
9921 private:
9922 std::vector<GURL> resolved_;
9924 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9927 class CapturingProxyResolverFactory : public ProxyResolverFactory {
9928 public:
9929 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
9930 : ProxyResolverFactory(false), resolver_(resolver) {}
9932 int CreateProxyResolver(
9933 const scoped_refptr<ProxyResolverScriptData>& pac_script,
9934 scoped_ptr<ProxyResolver>* resolver,
9935 const net::CompletionCallback& callback,
9936 scoped_ptr<Request>* request) override {
9937 resolver->reset(new ForwardingProxyResolver(resolver_));
9938 return OK;
9941 private:
9942 ProxyResolver* resolver_;
9945 TEST_P(HttpNetworkTransactionTest,
9946 UseAlternateProtocolForTunneledNpnSpdy) {
9947 session_deps_.use_alternative_services = true;
9948 session_deps_.next_protos = SpdyNextProtos();
9950 ProxyConfig proxy_config;
9951 proxy_config.set_auto_detect(true);
9952 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9954 CapturingProxyResolver capturing_proxy_resolver;
9955 session_deps_.proxy_service.reset(new ProxyService(
9956 new ProxyConfigServiceFixed(proxy_config),
9957 make_scoped_ptr(
9958 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
9959 NULL));
9960 TestNetLog net_log;
9961 session_deps_.net_log = &net_log;
9963 HttpRequestInfo request;
9964 request.method = "GET";
9965 request.url = GURL("http://www.example.org/");
9966 request.load_flags = 0;
9968 std::string alternate_protocol_http_header =
9969 GetAlternateProtocolHttpHeader();
9971 MockRead data_reads[] = {
9972 MockRead("HTTP/1.1 200 OK\r\n"),
9973 MockRead(alternate_protocol_http_header.c_str()),
9974 MockRead("\r\n"),
9975 MockRead("hello world"),
9976 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9977 MockRead(ASYNC, OK),
9980 StaticSocketDataProvider first_transaction(
9981 data_reads, arraysize(data_reads), NULL, 0);
9982 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9984 SSLSocketDataProvider ssl(ASYNC, OK);
9985 ssl.SetNextProto(GetParam());
9986 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9987 ASSERT_TRUE(ssl.cert.get());
9988 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9990 scoped_ptr<SpdyFrame> req(
9991 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9992 MockWrite spdy_writes[] = {
9993 MockWrite(ASYNC, 0,
9994 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9995 "Host: www.example.org\r\n"
9996 "Proxy-Connection: keep-alive\r\n\r\n"),
9997 CreateMockWrite(*req, 2),
10000 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10002 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10003 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10004 MockRead spdy_reads[] = {
10005 MockRead(ASYNC, 1, kCONNECTResponse),
10006 CreateMockRead(*resp.get(), 3),
10007 CreateMockRead(*data.get(), 4),
10008 MockRead(ASYNC, ERR_IO_PENDING, 5),
10011 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10012 arraysize(spdy_writes));
10013 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10015 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10016 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10017 NULL, 0, NULL, 0);
10018 hanging_non_alternate_protocol_socket.set_connect_data(
10019 never_finishing_connect);
10020 session_deps_.socket_factory->AddSocketDataProvider(
10021 &hanging_non_alternate_protocol_socket);
10023 TestCompletionCallback callback;
10025 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10026 scoped_ptr<HttpTransaction> trans(
10027 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10029 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10030 EXPECT_EQ(ERR_IO_PENDING, rv);
10031 EXPECT_EQ(OK, callback.WaitForResult());
10033 const HttpResponseInfo* response = trans->GetResponseInfo();
10034 ASSERT_TRUE(response != NULL);
10035 ASSERT_TRUE(response->headers.get() != NULL);
10036 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10037 EXPECT_FALSE(response->was_fetched_via_spdy);
10038 EXPECT_FALSE(response->was_npn_negotiated);
10040 std::string response_data;
10041 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10042 EXPECT_EQ("hello world", response_data);
10044 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10046 rv = trans->Start(&request, callback.callback(), BoundNetLog());
10047 EXPECT_EQ(ERR_IO_PENDING, rv);
10048 EXPECT_EQ(OK, callback.WaitForResult());
10050 response = trans->GetResponseInfo();
10051 ASSERT_TRUE(response != NULL);
10052 ASSERT_TRUE(response->headers.get() != NULL);
10053 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10054 EXPECT_TRUE(response->was_fetched_via_spdy);
10055 EXPECT_TRUE(response->was_npn_negotiated);
10057 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10058 EXPECT_EQ("hello!", response_data);
10059 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
10060 EXPECT_EQ("http://www.example.org/",
10061 capturing_proxy_resolver.resolved()[0].spec());
10062 EXPECT_EQ("https://www.example.org/",
10063 capturing_proxy_resolver.resolved()[1].spec());
10065 LoadTimingInfo load_timing_info;
10066 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10067 TestLoadTimingNotReusedWithPac(load_timing_info,
10068 CONNECT_TIMING_HAS_SSL_TIMES);
10071 TEST_P(HttpNetworkTransactionTest,
10072 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
10073 session_deps_.use_alternative_services = true;
10074 session_deps_.next_protos = SpdyNextProtos();
10076 HttpRequestInfo request;
10077 request.method = "GET";
10078 request.url = GURL("http://www.example.org/");
10079 request.load_flags = 0;
10081 std::string alternate_protocol_http_header =
10082 GetAlternateProtocolHttpHeader();
10084 MockRead data_reads[] = {
10085 MockRead("HTTP/1.1 200 OK\r\n"),
10086 MockRead(alternate_protocol_http_header.c_str()),
10087 MockRead("\r\n"),
10088 MockRead("hello world"),
10089 MockRead(ASYNC, OK),
10092 StaticSocketDataProvider first_transaction(
10093 data_reads, arraysize(data_reads), NULL, 0);
10094 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
10096 SSLSocketDataProvider ssl(ASYNC, OK);
10097 ssl.SetNextProto(GetParam());
10098 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10099 ASSERT_TRUE(ssl.cert.get());
10100 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10102 scoped_ptr<SpdyFrame> req(
10103 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10104 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
10106 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10107 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10108 MockRead spdy_reads[] = {
10109 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
10112 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10113 arraysize(spdy_writes));
10114 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10116 TestCompletionCallback callback;
10118 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10120 scoped_ptr<HttpTransaction> trans(
10121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10123 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10124 EXPECT_EQ(ERR_IO_PENDING, rv);
10125 EXPECT_EQ(OK, callback.WaitForResult());
10127 const HttpResponseInfo* response = trans->GetResponseInfo();
10128 ASSERT_TRUE(response != NULL);
10129 ASSERT_TRUE(response->headers.get() != NULL);
10130 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10132 std::string response_data;
10133 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10134 EXPECT_EQ("hello world", response_data);
10136 // Set up an initial SpdySession in the pool to reuse.
10137 HostPortPair host_port_pair("www.example.org", 443);
10138 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10139 PRIVACY_MODE_DISABLED);
10140 base::WeakPtr<SpdySession> spdy_session =
10141 CreateSecureSpdySession(session, key, BoundNetLog());
10143 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10145 rv = trans->Start(&request, callback.callback(), BoundNetLog());
10146 EXPECT_EQ(ERR_IO_PENDING, rv);
10147 EXPECT_EQ(OK, callback.WaitForResult());
10149 response = trans->GetResponseInfo();
10150 ASSERT_TRUE(response != NULL);
10151 ASSERT_TRUE(response->headers.get() != NULL);
10152 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10153 EXPECT_TRUE(response->was_fetched_via_spdy);
10154 EXPECT_TRUE(response->was_npn_negotiated);
10156 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10157 EXPECT_EQ("hello!", response_data);
10160 // GenerateAuthToken is a mighty big test.
10161 // It tests all permutation of GenerateAuthToken behavior:
10162 // - Synchronous and Asynchronous completion.
10163 // - OK or error on completion.
10164 // - Direct connection, non-authenticating proxy, and authenticating proxy.
10165 // - HTTP or HTTPS backend (to include proxy tunneling).
10166 // - Non-authenticating and authenticating backend.
10168 // In all, there are 44 reasonable permuations (for example, if there are
10169 // problems generating an auth token for an authenticating proxy, we don't
10170 // need to test all permutations of the backend server).
10172 // The test proceeds by going over each of the configuration cases, and
10173 // potentially running up to three rounds in each of the tests. The TestConfig
10174 // specifies both the configuration for the test as well as the expectations
10175 // for the results.
10176 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
10177 static const char kServer[] = "http://www.example.com";
10178 static const char kSecureServer[] = "https://www.example.com";
10179 static const char kProxy[] = "myproxy:70";
10180 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
10182 enum AuthTiming {
10183 AUTH_NONE,
10184 AUTH_SYNC,
10185 AUTH_ASYNC,
10188 const MockWrite kGet(
10189 "GET / HTTP/1.1\r\n"
10190 "Host: www.example.com\r\n"
10191 "Connection: keep-alive\r\n\r\n");
10192 const MockWrite kGetProxy(
10193 "GET http://www.example.com/ HTTP/1.1\r\n"
10194 "Host: www.example.com\r\n"
10195 "Proxy-Connection: keep-alive\r\n\r\n");
10196 const MockWrite kGetAuth(
10197 "GET / HTTP/1.1\r\n"
10198 "Host: www.example.com\r\n"
10199 "Connection: keep-alive\r\n"
10200 "Authorization: auth_token\r\n\r\n");
10201 const MockWrite kGetProxyAuth(
10202 "GET http://www.example.com/ HTTP/1.1\r\n"
10203 "Host: www.example.com\r\n"
10204 "Proxy-Connection: keep-alive\r\n"
10205 "Proxy-Authorization: auth_token\r\n\r\n");
10206 const MockWrite kGetAuthThroughProxy(
10207 "GET http://www.example.com/ HTTP/1.1\r\n"
10208 "Host: www.example.com\r\n"
10209 "Proxy-Connection: keep-alive\r\n"
10210 "Authorization: auth_token\r\n\r\n");
10211 const MockWrite kGetAuthWithProxyAuth(
10212 "GET http://www.example.com/ HTTP/1.1\r\n"
10213 "Host: www.example.com\r\n"
10214 "Proxy-Connection: keep-alive\r\n"
10215 "Proxy-Authorization: auth_token\r\n"
10216 "Authorization: auth_token\r\n\r\n");
10217 const MockWrite kConnect(
10218 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10219 "Host: www.example.com\r\n"
10220 "Proxy-Connection: keep-alive\r\n\r\n");
10221 const MockWrite kConnectProxyAuth(
10222 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10223 "Host: www.example.com\r\n"
10224 "Proxy-Connection: keep-alive\r\n"
10225 "Proxy-Authorization: auth_token\r\n\r\n");
10227 const MockRead kSuccess(
10228 "HTTP/1.1 200 OK\r\n"
10229 "Content-Type: text/html; charset=iso-8859-1\r\n"
10230 "Content-Length: 3\r\n\r\n"
10231 "Yes");
10232 const MockRead kFailure(
10233 "Should not be called.");
10234 const MockRead kServerChallenge(
10235 "HTTP/1.1 401 Unauthorized\r\n"
10236 "WWW-Authenticate: Mock realm=server\r\n"
10237 "Content-Type: text/html; charset=iso-8859-1\r\n"
10238 "Content-Length: 14\r\n\r\n"
10239 "Unauthorized\r\n");
10240 const MockRead kProxyChallenge(
10241 "HTTP/1.1 407 Unauthorized\r\n"
10242 "Proxy-Authenticate: Mock realm=proxy\r\n"
10243 "Proxy-Connection: close\r\n"
10244 "Content-Type: text/html; charset=iso-8859-1\r\n"
10245 "Content-Length: 14\r\n\r\n"
10246 "Unauthorized\r\n");
10247 const MockRead kProxyConnected(
10248 "HTTP/1.1 200 Connection Established\r\n\r\n");
10250 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10251 // no constructors, but the C++ compiler on Windows warns about
10252 // unspecified data in compound literals. So, moved to using constructors,
10253 // and TestRound's created with the default constructor should not be used.
10254 struct TestRound {
10255 TestRound()
10256 : expected_rv(ERR_UNEXPECTED),
10257 extra_write(NULL),
10258 extra_read(NULL) {
10260 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10261 int expected_rv_arg)
10262 : write(write_arg),
10263 read(read_arg),
10264 expected_rv(expected_rv_arg),
10265 extra_write(NULL),
10266 extra_read(NULL) {
10268 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10269 int expected_rv_arg, const MockWrite* extra_write_arg,
10270 const MockRead* extra_read_arg)
10271 : write(write_arg),
10272 read(read_arg),
10273 expected_rv(expected_rv_arg),
10274 extra_write(extra_write_arg),
10275 extra_read(extra_read_arg) {
10277 MockWrite write;
10278 MockRead read;
10279 int expected_rv;
10280 const MockWrite* extra_write;
10281 const MockRead* extra_read;
10284 static const int kNoSSL = 500;
10286 struct TestConfig {
10287 const char* const proxy_url;
10288 AuthTiming proxy_auth_timing;
10289 int proxy_auth_rv;
10290 const char* const server_url;
10291 AuthTiming server_auth_timing;
10292 int server_auth_rv;
10293 int num_auth_rounds;
10294 int first_ssl_round;
10295 TestRound rounds[3];
10296 } test_configs[] = {
10297 // Non-authenticating HTTP server with a direct connection.
10298 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10299 { TestRound(kGet, kSuccess, OK)}},
10300 // Authenticating HTTP server with a direct connection.
10301 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10302 { TestRound(kGet, kServerChallenge, OK),
10303 TestRound(kGetAuth, kSuccess, OK)}},
10304 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10305 { TestRound(kGet, kServerChallenge, OK),
10306 TestRound(kGetAuth, kFailure, kAuthErr)}},
10307 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10308 { TestRound(kGet, kServerChallenge, OK),
10309 TestRound(kGetAuth, kSuccess, OK)}},
10310 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10311 { TestRound(kGet, kServerChallenge, OK),
10312 TestRound(kGetAuth, kFailure, kAuthErr)}},
10313 // Non-authenticating HTTP server through a non-authenticating proxy.
10314 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10315 { TestRound(kGetProxy, kSuccess, OK)}},
10316 // Authenticating HTTP server through a non-authenticating proxy.
10317 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10318 { TestRound(kGetProxy, kServerChallenge, OK),
10319 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10320 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10321 { TestRound(kGetProxy, kServerChallenge, OK),
10322 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10323 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10324 { TestRound(kGetProxy, kServerChallenge, OK),
10325 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10326 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10327 { TestRound(kGetProxy, kServerChallenge, OK),
10328 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10329 // Non-authenticating HTTP server through an authenticating proxy.
10330 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10331 { TestRound(kGetProxy, kProxyChallenge, OK),
10332 TestRound(kGetProxyAuth, kSuccess, OK)}},
10333 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10334 { TestRound(kGetProxy, kProxyChallenge, OK),
10335 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10336 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10337 { TestRound(kGetProxy, kProxyChallenge, OK),
10338 TestRound(kGetProxyAuth, kSuccess, OK)}},
10339 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10340 { TestRound(kGetProxy, kProxyChallenge, OK),
10341 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10342 // Authenticating HTTP server through an authenticating proxy.
10343 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10344 { TestRound(kGetProxy, kProxyChallenge, OK),
10345 TestRound(kGetProxyAuth, kServerChallenge, OK),
10346 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10347 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10348 { TestRound(kGetProxy, kProxyChallenge, OK),
10349 TestRound(kGetProxyAuth, kServerChallenge, OK),
10350 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10351 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10352 { TestRound(kGetProxy, kProxyChallenge, OK),
10353 TestRound(kGetProxyAuth, kServerChallenge, OK),
10354 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10355 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10356 { TestRound(kGetProxy, kProxyChallenge, OK),
10357 TestRound(kGetProxyAuth, kServerChallenge, OK),
10358 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10359 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10360 { TestRound(kGetProxy, kProxyChallenge, OK),
10361 TestRound(kGetProxyAuth, kServerChallenge, OK),
10362 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10363 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10364 { TestRound(kGetProxy, kProxyChallenge, OK),
10365 TestRound(kGetProxyAuth, kServerChallenge, OK),
10366 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10367 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10368 { TestRound(kGetProxy, kProxyChallenge, OK),
10369 TestRound(kGetProxyAuth, kServerChallenge, OK),
10370 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10371 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10372 { TestRound(kGetProxy, kProxyChallenge, OK),
10373 TestRound(kGetProxyAuth, kServerChallenge, OK),
10374 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10375 // Non-authenticating HTTPS server with a direct connection.
10376 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10377 { TestRound(kGet, kSuccess, OK)}},
10378 // Authenticating HTTPS server with a direct connection.
10379 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10380 { TestRound(kGet, kServerChallenge, OK),
10381 TestRound(kGetAuth, kSuccess, OK)}},
10382 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10383 { TestRound(kGet, kServerChallenge, OK),
10384 TestRound(kGetAuth, kFailure, kAuthErr)}},
10385 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10386 { TestRound(kGet, kServerChallenge, OK),
10387 TestRound(kGetAuth, kSuccess, OK)}},
10388 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10389 { TestRound(kGet, kServerChallenge, OK),
10390 TestRound(kGetAuth, kFailure, kAuthErr)}},
10391 // Non-authenticating HTTPS server with a non-authenticating proxy.
10392 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10393 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
10394 // Authenticating HTTPS server through a non-authenticating proxy.
10395 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10396 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10397 TestRound(kGetAuth, kSuccess, OK)}},
10398 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10399 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10400 TestRound(kGetAuth, kFailure, kAuthErr)}},
10401 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10402 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10403 TestRound(kGetAuth, kSuccess, OK)}},
10404 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10405 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10406 TestRound(kGetAuth, kFailure, kAuthErr)}},
10407 // Non-Authenticating HTTPS server through an authenticating proxy.
10408 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10409 { TestRound(kConnect, kProxyChallenge, OK),
10410 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10411 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10412 { TestRound(kConnect, kProxyChallenge, OK),
10413 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10414 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10415 { TestRound(kConnect, kProxyChallenge, OK),
10416 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10417 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10418 { TestRound(kConnect, kProxyChallenge, OK),
10419 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10420 // Authenticating HTTPS server through an authenticating proxy.
10421 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10422 { TestRound(kConnect, kProxyChallenge, OK),
10423 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10424 &kGet, &kServerChallenge),
10425 TestRound(kGetAuth, kSuccess, OK)}},
10426 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10427 { TestRound(kConnect, kProxyChallenge, OK),
10428 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10429 &kGet, &kServerChallenge),
10430 TestRound(kGetAuth, kFailure, kAuthErr)}},
10431 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10432 { TestRound(kConnect, kProxyChallenge, OK),
10433 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10434 &kGet, &kServerChallenge),
10435 TestRound(kGetAuth, kSuccess, OK)}},
10436 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10437 { TestRound(kConnect, kProxyChallenge, OK),
10438 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10439 &kGet, &kServerChallenge),
10440 TestRound(kGetAuth, kFailure, kAuthErr)}},
10441 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10442 { TestRound(kConnect, kProxyChallenge, OK),
10443 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10444 &kGet, &kServerChallenge),
10445 TestRound(kGetAuth, kSuccess, OK)}},
10446 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10447 { TestRound(kConnect, kProxyChallenge, OK),
10448 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10449 &kGet, &kServerChallenge),
10450 TestRound(kGetAuth, kFailure, kAuthErr)}},
10451 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10452 { TestRound(kConnect, kProxyChallenge, OK),
10453 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10454 &kGet, &kServerChallenge),
10455 TestRound(kGetAuth, kSuccess, OK)}},
10456 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10457 { TestRound(kConnect, kProxyChallenge, OK),
10458 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10459 &kGet, &kServerChallenge),
10460 TestRound(kGetAuth, kFailure, kAuthErr)}},
10463 for (size_t i = 0; i < arraysize(test_configs); ++i) {
10464 HttpAuthHandlerMock::Factory* auth_factory(
10465 new HttpAuthHandlerMock::Factory());
10466 session_deps_.http_auth_handler_factory.reset(auth_factory);
10467 const TestConfig& test_config = test_configs[i];
10469 // Set up authentication handlers as necessary.
10470 if (test_config.proxy_auth_timing != AUTH_NONE) {
10471 for (int n = 0; n < 2; n++) {
10472 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10473 std::string auth_challenge = "Mock realm=proxy";
10474 GURL origin(test_config.proxy_url);
10475 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10476 auth_challenge.end());
10477 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
10478 origin, BoundNetLog());
10479 auth_handler->SetGenerateExpectation(
10480 test_config.proxy_auth_timing == AUTH_ASYNC,
10481 test_config.proxy_auth_rv);
10482 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10485 if (test_config.server_auth_timing != AUTH_NONE) {
10486 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10487 std::string auth_challenge = "Mock realm=server";
10488 GURL origin(test_config.server_url);
10489 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10490 auth_challenge.end());
10491 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10492 origin, BoundNetLog());
10493 auth_handler->SetGenerateExpectation(
10494 test_config.server_auth_timing == AUTH_ASYNC,
10495 test_config.server_auth_rv);
10496 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10498 if (test_config.proxy_url) {
10499 session_deps_.proxy_service.reset(
10500 ProxyService::CreateFixed(test_config.proxy_url));
10501 } else {
10502 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10505 HttpRequestInfo request;
10506 request.method = "GET";
10507 request.url = GURL(test_config.server_url);
10508 request.load_flags = 0;
10510 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10511 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10513 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
10515 std::vector<std::vector<MockRead>> mock_reads(1);
10516 std::vector<std::vector<MockWrite>> mock_writes(1);
10517 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10518 const TestRound& read_write_round = test_config.rounds[round];
10520 // Set up expected reads and writes.
10521 mock_reads.back().push_back(read_write_round.read);
10522 mock_writes.back().push_back(read_write_round.write);
10524 // kProxyChallenge uses Proxy-Connection: close which means that the
10525 // socket is closed and a new one will be created for the next request.
10526 if (read_write_round.read.data == kProxyChallenge.data) {
10527 mock_reads.push_back(std::vector<MockRead>());
10528 mock_writes.push_back(std::vector<MockWrite>());
10531 if (read_write_round.extra_read) {
10532 mock_reads.back().push_back(*read_write_round.extra_read);
10534 if (read_write_round.extra_write) {
10535 mock_writes.back().push_back(*read_write_round.extra_write);
10538 // Add an SSL sequence if necessary.
10539 if (round >= test_config.first_ssl_round)
10540 session_deps_.socket_factory->AddSSLSocketDataProvider(
10541 &ssl_socket_data_provider);
10544 ScopedVector<StaticSocketDataProvider> data_providers;
10545 for (size_t i = 0; i < mock_reads.size(); ++i) {
10546 data_providers.push_back(new StaticSocketDataProvider(
10547 vector_as_array(&mock_reads[i]), mock_reads[i].size(),
10548 vector_as_array(&mock_writes[i]), mock_writes[i].size()));
10549 session_deps_.socket_factory->AddSocketDataProvider(
10550 data_providers.back());
10553 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10554 const TestRound& read_write_round = test_config.rounds[round];
10555 // Start or restart the transaction.
10556 TestCompletionCallback callback;
10557 int rv;
10558 if (round == 0) {
10559 rv = trans.Start(&request, callback.callback(), BoundNetLog());
10560 } else {
10561 rv = trans.RestartWithAuth(
10562 AuthCredentials(kFoo, kBar), callback.callback());
10564 if (rv == ERR_IO_PENDING)
10565 rv = callback.WaitForResult();
10567 // Compare results with expected data.
10568 EXPECT_EQ(read_write_round.expected_rv, rv);
10569 const HttpResponseInfo* response = trans.GetResponseInfo();
10570 if (read_write_round.expected_rv != OK) {
10571 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
10572 continue;
10574 if (round + 1 < test_config.num_auth_rounds) {
10575 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10576 } else {
10577 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10583 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
10584 // Do multi-round authentication and make sure it works correctly.
10585 HttpAuthHandlerMock::Factory* auth_factory(
10586 new HttpAuthHandlerMock::Factory());
10587 session_deps_.http_auth_handler_factory.reset(auth_factory);
10588 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10589 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
10590 session_deps_.host_resolver->set_synchronous_mode(true);
10592 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10593 auth_handler->set_connection_based(true);
10594 std::string auth_challenge = "Mock realm=server";
10595 GURL origin("http://www.example.com");
10596 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10597 auth_challenge.end());
10598 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10599 origin, BoundNetLog());
10600 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10602 int rv = OK;
10603 const HttpResponseInfo* response = NULL;
10604 HttpRequestInfo request;
10605 request.method = "GET";
10606 request.url = origin;
10607 request.load_flags = 0;
10609 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10611 // Use a TCP Socket Pool with only one connection per group. This is used
10612 // to validate that the TCP socket is not released to the pool between
10613 // each round of multi-round authentication.
10614 HttpNetworkSessionPeer session_peer(session);
10615 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
10616 50, // Max sockets for pool
10617 1, // Max sockets per group
10618 session_deps_.host_resolver.get(),
10619 session_deps_.socket_factory.get(),
10620 session_deps_.net_log);
10621 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
10622 new MockClientSocketPoolManager);
10623 mock_pool_manager->SetTransportSocketPool(transport_pool);
10624 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
10626 scoped_ptr<HttpTransaction> trans(
10627 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10628 TestCompletionCallback callback;
10630 const MockWrite kGet(
10631 "GET / HTTP/1.1\r\n"
10632 "Host: www.example.com\r\n"
10633 "Connection: keep-alive\r\n\r\n");
10634 const MockWrite kGetAuth(
10635 "GET / HTTP/1.1\r\n"
10636 "Host: www.example.com\r\n"
10637 "Connection: keep-alive\r\n"
10638 "Authorization: auth_token\r\n\r\n");
10640 const MockRead kServerChallenge(
10641 "HTTP/1.1 401 Unauthorized\r\n"
10642 "WWW-Authenticate: Mock realm=server\r\n"
10643 "Content-Type: text/html; charset=iso-8859-1\r\n"
10644 "Content-Length: 14\r\n\r\n"
10645 "Unauthorized\r\n");
10646 const MockRead kSuccess(
10647 "HTTP/1.1 200 OK\r\n"
10648 "Content-Type: text/html; charset=iso-8859-1\r\n"
10649 "Content-Length: 3\r\n\r\n"
10650 "Yes");
10652 MockWrite writes[] = {
10653 // First round
10654 kGet,
10655 // Second round
10656 kGetAuth,
10657 // Third round
10658 kGetAuth,
10659 // Fourth round
10660 kGetAuth,
10661 // Competing request
10662 kGet,
10664 MockRead reads[] = {
10665 // First round
10666 kServerChallenge,
10667 // Second round
10668 kServerChallenge,
10669 // Third round
10670 kServerChallenge,
10671 // Fourth round
10672 kSuccess,
10673 // Competing response
10674 kSuccess,
10676 StaticSocketDataProvider data_provider(reads, arraysize(reads),
10677 writes, arraysize(writes));
10678 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10680 const char kSocketGroup[] = "www.example.com:80";
10682 // First round of authentication.
10683 auth_handler->SetGenerateExpectation(false, OK);
10684 rv = trans->Start(&request, callback.callback(), BoundNetLog());
10685 if (rv == ERR_IO_PENDING)
10686 rv = callback.WaitForResult();
10687 EXPECT_EQ(OK, rv);
10688 response = trans->GetResponseInfo();
10689 ASSERT_TRUE(response != NULL);
10690 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10691 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10693 // In between rounds, another request comes in for the same domain.
10694 // It should not be able to grab the TCP socket that trans has already
10695 // claimed.
10696 scoped_ptr<HttpTransaction> trans_compete(
10697 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10698 TestCompletionCallback callback_compete;
10699 rv = trans_compete->Start(
10700 &request, callback_compete.callback(), BoundNetLog());
10701 EXPECT_EQ(ERR_IO_PENDING, rv);
10702 // callback_compete.WaitForResult at this point would stall forever,
10703 // since the HttpNetworkTransaction does not release the request back to
10704 // the pool until after authentication completes.
10706 // Second round of authentication.
10707 auth_handler->SetGenerateExpectation(false, OK);
10708 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
10709 if (rv == ERR_IO_PENDING)
10710 rv = callback.WaitForResult();
10711 EXPECT_EQ(OK, rv);
10712 response = trans->GetResponseInfo();
10713 ASSERT_TRUE(response != NULL);
10714 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10715 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10717 // Third round of authentication.
10718 auth_handler->SetGenerateExpectation(false, OK);
10719 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10720 if (rv == ERR_IO_PENDING)
10721 rv = callback.WaitForResult();
10722 EXPECT_EQ(OK, rv);
10723 response = trans->GetResponseInfo();
10724 ASSERT_TRUE(response != NULL);
10725 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10726 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10728 // Fourth round of authentication, which completes successfully.
10729 auth_handler->SetGenerateExpectation(false, OK);
10730 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10731 if (rv == ERR_IO_PENDING)
10732 rv = callback.WaitForResult();
10733 EXPECT_EQ(OK, rv);
10734 response = trans->GetResponseInfo();
10735 ASSERT_TRUE(response != NULL);
10736 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10737 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10739 // Read the body since the fourth round was successful. This will also
10740 // release the socket back to the pool.
10741 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
10742 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10743 if (rv == ERR_IO_PENDING)
10744 rv = callback.WaitForResult();
10745 EXPECT_EQ(3, rv);
10746 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10747 EXPECT_EQ(0, rv);
10748 // There are still 0 idle sockets, since the trans_compete transaction
10749 // will be handed it immediately after trans releases it to the group.
10750 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10752 // The competing request can now finish. Wait for the headers and then
10753 // read the body.
10754 rv = callback_compete.WaitForResult();
10755 EXPECT_EQ(OK, rv);
10756 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10757 if (rv == ERR_IO_PENDING)
10758 rv = callback.WaitForResult();
10759 EXPECT_EQ(3, rv);
10760 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10761 EXPECT_EQ(0, rv);
10763 // Finally, the socket is released to the group.
10764 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10767 // This tests the case that a request is issued via http instead of spdy after
10768 // npn is negotiated.
10769 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
10770 session_deps_.use_alternative_services = true;
10771 NextProtoVector next_protos;
10772 next_protos.push_back(kProtoHTTP11);
10773 session_deps_.next_protos = next_protos;
10775 HttpRequestInfo request;
10776 request.method = "GET";
10777 request.url = GURL("https://www.example.org/");
10778 request.load_flags = 0;
10780 MockWrite data_writes[] = {
10781 MockWrite(
10782 "GET / HTTP/1.1\r\n"
10783 "Host: www.example.org\r\n"
10784 "Connection: keep-alive\r\n\r\n"),
10787 std::string alternate_protocol_http_header =
10788 GetAlternateProtocolHttpHeader();
10790 MockRead data_reads[] = {
10791 MockRead("HTTP/1.1 200 OK\r\n"),
10792 MockRead(alternate_protocol_http_header.c_str()),
10793 MockRead("\r\n"),
10794 MockRead("hello world"),
10795 MockRead(SYNCHRONOUS, OK),
10798 SSLSocketDataProvider ssl(ASYNC, OK);
10799 ssl.SetNextProto(kProtoHTTP11);
10801 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10803 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
10804 data_writes, arraysize(data_writes));
10805 session_deps_.socket_factory->AddSocketDataProvider(&data);
10807 TestCompletionCallback callback;
10809 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10810 scoped_ptr<HttpTransaction> trans(
10811 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10813 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10815 EXPECT_EQ(ERR_IO_PENDING, rv);
10816 EXPECT_EQ(OK, callback.WaitForResult());
10818 const HttpResponseInfo* response = trans->GetResponseInfo();
10819 ASSERT_TRUE(response != NULL);
10820 ASSERT_TRUE(response->headers.get() != NULL);
10821 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10823 std::string response_data;
10824 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10825 EXPECT_EQ("hello world", response_data);
10827 EXPECT_FALSE(response->was_fetched_via_spdy);
10828 EXPECT_TRUE(response->was_npn_negotiated);
10831 // Simulate the SSL handshake completing with an NPN negotiation followed by an
10832 // immediate server closing of the socket.
10833 // Regression test for https://crbug.com/46369.
10834 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
10835 session_deps_.use_alternative_services = true;
10836 session_deps_.next_protos = SpdyNextProtos();
10838 HttpRequestInfo request;
10839 request.method = "GET";
10840 request.url = GURL("https://www.example.org/");
10841 request.load_flags = 0;
10843 SSLSocketDataProvider ssl(ASYNC, OK);
10844 ssl.SetNextProto(GetParam());
10845 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10847 scoped_ptr<SpdyFrame> req(
10848 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10849 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
10851 MockRead spdy_reads[] = {
10852 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10855 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10856 arraysize(spdy_writes));
10857 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10859 TestCompletionCallback callback;
10861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10862 scoped_ptr<HttpTransaction> trans(
10863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10865 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10866 EXPECT_EQ(ERR_IO_PENDING, rv);
10867 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10870 // A subclass of HttpAuthHandlerMock that records the request URL when
10871 // it gets it. This is needed since the auth handler may get destroyed
10872 // before we get a chance to query it.
10873 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10874 public:
10875 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10877 ~UrlRecordingHttpAuthHandlerMock() override {}
10879 protected:
10880 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10881 const HttpRequestInfo* request,
10882 const CompletionCallback& callback,
10883 std::string* auth_token) override {
10884 *url_ = request->url;
10885 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10886 credentials, request, callback, auth_token);
10889 private:
10890 GURL* url_;
10893 // This test ensures that the URL passed into the proxy is upgraded to https
10894 // when doing an Alternate Protocol upgrade.
10895 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10896 session_deps_.use_alternative_services = true;
10897 session_deps_.next_protos = SpdyNextProtos();
10899 session_deps_.proxy_service.reset(
10900 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10901 TestNetLog net_log;
10902 session_deps_.net_log = &net_log;
10903 GURL request_url;
10905 HttpAuthHandlerMock::Factory* auth_factory =
10906 new HttpAuthHandlerMock::Factory();
10907 UrlRecordingHttpAuthHandlerMock* auth_handler =
10908 new UrlRecordingHttpAuthHandlerMock(&request_url);
10909 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10910 auth_factory->set_do_init_from_challenge(true);
10911 session_deps_.http_auth_handler_factory.reset(auth_factory);
10914 HttpRequestInfo request;
10915 request.method = "GET";
10916 request.url = GURL("http://www.example.org");
10917 request.load_flags = 0;
10919 // First round goes unauthenticated through the proxy.
10920 MockWrite data_writes_1[] = {
10921 MockWrite(
10922 "GET http://www.example.org/ HTTP/1.1\r\n"
10923 "Host: www.example.org\r\n"
10924 "Proxy-Connection: keep-alive\r\n"
10925 "\r\n"),
10927 MockRead data_reads_1[] = {
10928 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10929 MockRead("HTTP/1.1 200 OK\r\n"),
10930 MockRead("Alternate-Protocol: 443:"),
10931 MockRead(GetAlternateProtocolFromParam()),
10932 MockRead("\r\n"),
10933 MockRead("Proxy-Connection: close\r\n"),
10934 MockRead("\r\n"),
10936 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10937 data_writes_1, arraysize(data_writes_1));
10939 // Second round tries to tunnel to www.example.org due to the
10940 // Alternate-Protocol announcement in the first round. It fails due
10941 // to a proxy authentication challenge.
10942 // After the failure, a tunnel is established to www.example.org using
10943 // Proxy-Authorization headers. There is then a SPDY request round.
10945 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10946 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10947 // does a Disconnect and Connect on the same socket, rather than trying
10948 // to obtain a new one.
10950 // NOTE: Originally, the proxy response to the second CONNECT request
10951 // simply returned another 407 so the unit test could skip the SSL connection
10952 // establishment and SPDY framing issues. Alas, the
10953 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10954 // complicated to set up expectations for than the SPDY session.
10956 scoped_ptr<SpdyFrame> req(
10957 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10958 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10959 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10961 MockWrite data_writes_2[] = {
10962 // First connection attempt without Proxy-Authorization.
10963 MockWrite(ASYNC, 0,
10964 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10965 "Host: www.example.org\r\n"
10966 "Proxy-Connection: keep-alive\r\n"
10967 "\r\n"),
10969 // Second connection attempt with Proxy-Authorization.
10970 MockWrite(ASYNC, 2,
10971 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10972 "Host: www.example.org\r\n"
10973 "Proxy-Connection: keep-alive\r\n"
10974 "Proxy-Authorization: auth_token\r\n"
10975 "\r\n"),
10977 // SPDY request
10978 CreateMockWrite(*req, 4),
10980 MockRead data_reads_2[] = {
10981 // First connection attempt fails
10982 MockRead(ASYNC, 1,
10983 "HTTP/1.1 407 Unauthorized\r\n"
10984 "Proxy-Authenticate: Mock\r\n"
10985 "Content-Length: 0\r\n"
10986 "Proxy-Connection: keep-alive\r\n"
10987 "\r\n"),
10989 // Second connection attempt passes
10990 MockRead(ASYNC, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
10992 // SPDY response
10993 CreateMockRead(*resp.get(), 5), CreateMockRead(*data.get(), 6),
10994 MockRead(ASYNC, 0, 0, 7),
10996 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
10997 data_writes_2, arraysize(data_writes_2));
10999 SSLSocketDataProvider ssl(ASYNC, OK);
11000 ssl.SetNextProto(GetParam());
11001 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11002 ASSERT_TRUE(ssl.cert.get());
11004 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
11005 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
11006 NULL, 0, NULL, 0);
11007 hanging_non_alternate_protocol_socket.set_connect_data(
11008 never_finishing_connect);
11010 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
11011 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
11012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11013 session_deps_.socket_factory->AddSocketDataProvider(
11014 &hanging_non_alternate_protocol_socket);
11015 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11017 // First round should work and provide the Alternate-Protocol state.
11018 TestCompletionCallback callback_1;
11019 scoped_ptr<HttpTransaction> trans_1(
11020 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11021 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
11022 EXPECT_EQ(ERR_IO_PENDING, rv);
11023 EXPECT_EQ(OK, callback_1.WaitForResult());
11025 // Second round should attempt a tunnel connect and get an auth challenge.
11026 TestCompletionCallback callback_2;
11027 scoped_ptr<HttpTransaction> trans_2(
11028 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11029 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
11030 EXPECT_EQ(ERR_IO_PENDING, rv);
11031 EXPECT_EQ(OK, callback_2.WaitForResult());
11032 const HttpResponseInfo* response = trans_2->GetResponseInfo();
11033 ASSERT_TRUE(response != NULL);
11034 ASSERT_FALSE(response->auth_challenge.get() == NULL);
11036 // Restart with auth. Tunnel should work and response received.
11037 TestCompletionCallback callback_3;
11038 rv = trans_2->RestartWithAuth(
11039 AuthCredentials(kFoo, kBar), callback_3.callback());
11040 EXPECT_EQ(ERR_IO_PENDING, rv);
11041 EXPECT_EQ(OK, callback_3.WaitForResult());
11043 // After all that work, these two lines (or actually, just the scheme) are
11044 // what this test is all about. Make sure it happens correctly.
11045 EXPECT_EQ("https", request_url.scheme());
11046 EXPECT_EQ("www.example.org", request_url.host());
11048 LoadTimingInfo load_timing_info;
11049 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
11050 TestLoadTimingNotReusedWithPac(load_timing_info,
11051 CONNECT_TIMING_HAS_SSL_TIMES);
11054 // Test that if we cancel the transaction as the connection is completing, that
11055 // everything tears down correctly.
11056 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
11057 // Setup everything about the connection to complete synchronously, so that
11058 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
11059 // for is the callback from the HttpStreamRequest.
11060 // Then cancel the transaction.
11061 // Verify that we don't crash.
11062 MockConnect mock_connect(SYNCHRONOUS, OK);
11063 MockRead data_reads[] = {
11064 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
11065 MockRead(SYNCHRONOUS, "hello world"),
11066 MockRead(SYNCHRONOUS, OK),
11069 HttpRequestInfo request;
11070 request.method = "GET";
11071 request.url = GURL("http://www.example.org/");
11072 request.load_flags = 0;
11074 session_deps_.host_resolver->set_synchronous_mode(true);
11075 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11076 scoped_ptr<HttpTransaction> trans(
11077 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11079 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
11080 data.set_connect_data(mock_connect);
11081 session_deps_.socket_factory->AddSocketDataProvider(&data);
11083 TestCompletionCallback callback;
11085 BoundTestNetLog log;
11086 int rv = trans->Start(&request, callback.callback(), log.bound());
11087 EXPECT_EQ(ERR_IO_PENDING, rv);
11088 trans.reset(); // Cancel the transaction here.
11090 base::MessageLoop::current()->RunUntilIdle();
11093 // Test that if a transaction is cancelled after receiving the headers, the
11094 // stream is drained properly and added back to the socket pool. The main
11095 // purpose of this test is to make sure that an HttpStreamParser can be read
11096 // from after the HttpNetworkTransaction and the objects it owns have been
11097 // deleted.
11098 // See http://crbug.com/368418
11099 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
11100 MockRead data_reads[] = {
11101 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
11102 MockRead(ASYNC, "Content-Length: 2\r\n"),
11103 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
11104 MockRead(ASYNC, "1"),
11105 // 2 async reads are necessary to trigger a ReadResponseBody call after the
11106 // HttpNetworkTransaction has been deleted.
11107 MockRead(ASYNC, "2"),
11108 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
11110 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
11111 session_deps_.socket_factory->AddSocketDataProvider(&data);
11113 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11116 HttpRequestInfo request;
11117 request.method = "GET";
11118 request.url = GURL("http://www.example.org/");
11119 request.load_flags = 0;
11121 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11122 TestCompletionCallback callback;
11124 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
11125 EXPECT_EQ(ERR_IO_PENDING, rv);
11126 callback.WaitForResult();
11128 const HttpResponseInfo* response = trans.GetResponseInfo();
11129 ASSERT_TRUE(response != NULL);
11130 EXPECT_TRUE(response->headers.get() != NULL);
11131 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11133 // The transaction and HttpRequestInfo are deleted.
11136 // Let the HttpResponseBodyDrainer drain the socket.
11137 base::MessageLoop::current()->RunUntilIdle();
11139 // Socket should now be idle, waiting to be reused.
11140 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
11143 // Test a basic GET request through a proxy.
11144 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
11145 session_deps_.proxy_service.reset(
11146 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11147 BoundTestNetLog log;
11148 session_deps_.net_log = log.bound().net_log();
11149 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11151 HttpRequestInfo request;
11152 request.method = "GET";
11153 request.url = GURL("http://www.example.org/");
11155 MockWrite data_writes1[] = {
11156 MockWrite(
11157 "GET http://www.example.org/ HTTP/1.1\r\n"
11158 "Host: www.example.org\r\n"
11159 "Proxy-Connection: keep-alive\r\n\r\n"),
11162 MockRead data_reads1[] = {
11163 MockRead("HTTP/1.1 200 OK\r\n"),
11164 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11165 MockRead("Content-Length: 100\r\n\r\n"),
11166 MockRead(SYNCHRONOUS, OK),
11169 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11170 data_writes1, arraysize(data_writes1));
11171 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11173 TestCompletionCallback callback1;
11175 scoped_ptr<HttpTransaction> trans(
11176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11177 BeforeProxyHeadersSentHandler proxy_headers_handler;
11178 trans->SetBeforeProxyHeadersSentCallback(
11179 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
11180 base::Unretained(&proxy_headers_handler)));
11182 int rv = trans->Start(&request, callback1.callback(), log.bound());
11183 EXPECT_EQ(ERR_IO_PENDING, rv);
11185 rv = callback1.WaitForResult();
11186 EXPECT_EQ(OK, rv);
11188 const HttpResponseInfo* response = trans->GetResponseInfo();
11189 ASSERT_TRUE(response != NULL);
11191 EXPECT_TRUE(response->headers->IsKeepAlive());
11192 EXPECT_EQ(200, response->headers->response_code());
11193 EXPECT_EQ(100, response->headers->GetContentLength());
11194 EXPECT_TRUE(response->was_fetched_via_proxy);
11195 EXPECT_TRUE(
11196 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
11197 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
11198 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
11199 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11201 LoadTimingInfo load_timing_info;
11202 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11203 TestLoadTimingNotReusedWithPac(load_timing_info,
11204 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11207 // Test a basic HTTPS GET request through a proxy.
11208 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
11209 session_deps_.proxy_service.reset(
11210 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11211 BoundTestNetLog log;
11212 session_deps_.net_log = log.bound().net_log();
11213 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11215 HttpRequestInfo request;
11216 request.method = "GET";
11217 request.url = GURL("https://www.example.org/");
11219 // Since we have proxy, should try to establish tunnel.
11220 MockWrite data_writes1[] = {
11221 MockWrite(
11222 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11223 "Host: www.example.org\r\n"
11224 "Proxy-Connection: keep-alive\r\n\r\n"),
11226 MockWrite(
11227 "GET / HTTP/1.1\r\n"
11228 "Host: www.example.org\r\n"
11229 "Connection: keep-alive\r\n\r\n"),
11232 MockRead data_reads1[] = {
11233 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11235 MockRead("HTTP/1.1 200 OK\r\n"),
11236 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11237 MockRead("Content-Length: 100\r\n\r\n"),
11238 MockRead(SYNCHRONOUS, OK),
11241 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11242 data_writes1, arraysize(data_writes1));
11243 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11244 SSLSocketDataProvider ssl(ASYNC, OK);
11245 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11247 TestCompletionCallback callback1;
11249 scoped_ptr<HttpTransaction> trans(
11250 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11252 int rv = trans->Start(&request, callback1.callback(), log.bound());
11253 EXPECT_EQ(ERR_IO_PENDING, rv);
11255 rv = callback1.WaitForResult();
11256 EXPECT_EQ(OK, rv);
11257 TestNetLogEntry::List entries;
11258 log.GetEntries(&entries);
11259 size_t pos = ExpectLogContainsSomewhere(
11260 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11261 NetLog::PHASE_NONE);
11262 ExpectLogContainsSomewhere(
11263 entries, pos,
11264 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11265 NetLog::PHASE_NONE);
11267 const HttpResponseInfo* response = trans->GetResponseInfo();
11268 ASSERT_TRUE(response != NULL);
11270 EXPECT_TRUE(response->headers->IsKeepAlive());
11271 EXPECT_EQ(200, response->headers->response_code());
11272 EXPECT_EQ(100, response->headers->GetContentLength());
11273 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11274 EXPECT_TRUE(response->was_fetched_via_proxy);
11275 EXPECT_TRUE(
11276 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
11278 LoadTimingInfo load_timing_info;
11279 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11280 TestLoadTimingNotReusedWithPac(load_timing_info,
11281 CONNECT_TIMING_HAS_SSL_TIMES);
11284 // Test a basic HTTPS GET request through a proxy, but the server hangs up
11285 // while establishing the tunnel.
11286 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
11287 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
11288 BoundTestNetLog log;
11289 session_deps_.net_log = log.bound().net_log();
11290 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11292 HttpRequestInfo request;
11293 request.method = "GET";
11294 request.url = GURL("https://www.example.org/");
11296 // Since we have proxy, should try to establish tunnel.
11297 MockWrite data_writes1[] = {
11298 MockWrite(
11299 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11300 "Host: www.example.org\r\n"
11301 "Proxy-Connection: keep-alive\r\n\r\n"),
11303 MockWrite(
11304 "GET / HTTP/1.1\r\n"
11305 "Host: www.example.org\r\n"
11306 "Connection: keep-alive\r\n\r\n"),
11309 MockRead data_reads1[] = {
11310 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
11311 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11312 MockRead(ASYNC, 0, 0), // EOF
11315 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11316 data_writes1, arraysize(data_writes1));
11317 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11318 SSLSocketDataProvider ssl(ASYNC, OK);
11319 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11321 TestCompletionCallback callback1;
11323 scoped_ptr<HttpTransaction> trans(
11324 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11326 int rv = trans->Start(&request, callback1.callback(), log.bound());
11327 EXPECT_EQ(ERR_IO_PENDING, rv);
11329 rv = callback1.WaitForResult();
11330 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
11331 TestNetLogEntry::List entries;
11332 log.GetEntries(&entries);
11333 size_t pos = ExpectLogContainsSomewhere(
11334 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11335 NetLog::PHASE_NONE);
11336 ExpectLogContainsSomewhere(
11337 entries, pos,
11338 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11339 NetLog::PHASE_NONE);
11342 // Test for crbug.com/55424.
11343 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
11344 scoped_ptr<SpdyFrame> req(
11345 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11346 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
11348 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11349 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
11350 MockRead spdy_reads[] = {
11351 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
11354 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11355 arraysize(spdy_writes));
11356 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11358 SSLSocketDataProvider ssl(ASYNC, OK);
11359 ssl.SetNextProto(GetParam());
11360 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11362 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11364 // Set up an initial SpdySession in the pool to reuse.
11365 HostPortPair host_port_pair("www.example.org", 443);
11366 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
11367 PRIVACY_MODE_DISABLED);
11368 base::WeakPtr<SpdySession> spdy_session =
11369 CreateInsecureSpdySession(session, key, BoundNetLog());
11371 HttpRequestInfo request;
11372 request.method = "GET";
11373 request.url = GURL("https://www.example.org/");
11374 request.load_flags = 0;
11376 // This is the important line that marks this as a preconnect.
11377 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
11379 scoped_ptr<HttpTransaction> trans(
11380 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11382 TestCompletionCallback callback;
11383 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11384 EXPECT_EQ(ERR_IO_PENDING, rv);
11385 EXPECT_EQ(OK, callback.WaitForResult());
11388 // Given a net error, cause that error to be returned from the first Write()
11389 // call and verify that the HttpTransaction fails with that error.
11390 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11391 int error, IoMode mode) {
11392 HttpRequestInfo request_info;
11393 request_info.url = GURL("https://www.example.com/");
11394 request_info.method = "GET";
11395 request_info.load_flags = LOAD_NORMAL;
11397 SSLSocketDataProvider ssl_data(mode, OK);
11398 MockWrite data_writes[] = {
11399 MockWrite(mode, error),
11401 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
11402 session_deps_.socket_factory->AddSocketDataProvider(&data);
11403 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
11405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11406 scoped_ptr<HttpTransaction> trans(
11407 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11409 TestCompletionCallback callback;
11410 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11411 if (rv == ERR_IO_PENDING)
11412 rv = callback.WaitForResult();
11413 ASSERT_EQ(error, rv);
11416 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
11417 // Just check a grab bag of cert errors.
11418 static const int kErrors[] = {
11419 ERR_CERT_COMMON_NAME_INVALID,
11420 ERR_CERT_AUTHORITY_INVALID,
11421 ERR_CERT_DATE_INVALID,
11423 for (size_t i = 0; i < arraysize(kErrors); i++) {
11424 CheckErrorIsPassedBack(kErrors[i], ASYNC);
11425 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
11429 // Ensure that a client certificate is removed from the SSL client auth
11430 // cache when:
11431 // 1) No proxy is involved.
11432 // 2) TLS False Start is disabled.
11433 // 3) The initial TLS handshake requests a client certificate.
11434 // 4) The client supplies an invalid/unacceptable certificate.
11435 TEST_P(HttpNetworkTransactionTest,
11436 ClientAuthCertCache_Direct_NoFalseStart) {
11437 HttpRequestInfo request_info;
11438 request_info.url = GURL("https://www.example.com/");
11439 request_info.method = "GET";
11440 request_info.load_flags = LOAD_NORMAL;
11442 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11443 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11445 // [ssl_]data1 contains the data for the first SSL handshake. When a
11446 // CertificateRequest is received for the first time, the handshake will
11447 // be aborted to allow the caller to provide a certificate.
11448 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11449 ssl_data1.cert_request_info = cert_request.get();
11450 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11451 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11452 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11454 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11455 // False Start is not being used, the result of the SSL handshake will be
11456 // returned as part of the SSLClientSocket::Connect() call. This test
11457 // matches the result of a server sending a handshake_failure alert,
11458 // rather than a Finished message, because it requires a client
11459 // certificate and none was supplied.
11460 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11461 ssl_data2.cert_request_info = cert_request.get();
11462 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11463 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11464 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11466 // [ssl_]data3 contains the data for the third SSL handshake. When a
11467 // connection to a server fails during an SSL handshake,
11468 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11469 // connection was attempted with TLSv1.2. This is transparent to the caller
11470 // of the HttpNetworkTransaction. Because this test failure is due to
11471 // requiring a client certificate, this fallback handshake should also
11472 // fail.
11473 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11474 ssl_data3.cert_request_info = cert_request.get();
11475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11476 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11477 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11479 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11480 // connection to a server fails during an SSL handshake,
11481 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11482 // connection was attempted with TLSv1.1. This is transparent to the caller
11483 // of the HttpNetworkTransaction. Because this test failure is due to
11484 // requiring a client certificate, this fallback handshake should also
11485 // fail.
11486 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11487 ssl_data4.cert_request_info = cert_request.get();
11488 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11489 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
11490 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11492 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11493 scoped_ptr<HttpTransaction> trans(
11494 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11496 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11497 TestCompletionCallback callback;
11498 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11499 ASSERT_EQ(ERR_IO_PENDING, rv);
11501 // Complete the SSL handshake, which should abort due to requiring a
11502 // client certificate.
11503 rv = callback.WaitForResult();
11504 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11506 // Indicate that no certificate should be supplied. From the perspective
11507 // of SSLClientCertCache, NULL is just as meaningful as a real
11508 // certificate, so this is the same as supply a
11509 // legitimate-but-unacceptable certificate.
11510 rv = trans->RestartWithCertificate(NULL, callback.callback());
11511 ASSERT_EQ(ERR_IO_PENDING, rv);
11513 // Ensure the certificate was added to the client auth cache before
11514 // allowing the connection to continue restarting.
11515 scoped_refptr<X509Certificate> client_cert;
11516 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11517 HostPortPair("www.example.com", 443), &client_cert));
11518 ASSERT_EQ(NULL, client_cert.get());
11520 // Restart the handshake. This will consume ssl_data2, which fails, and
11521 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11522 // The result code is checked against what ssl_data4 should return.
11523 rv = callback.WaitForResult();
11524 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11526 // Ensure that the client certificate is removed from the cache on a
11527 // handshake failure.
11528 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11529 HostPortPair("www.example.com", 443), &client_cert));
11532 // Ensure that a client certificate is removed from the SSL client auth
11533 // cache when:
11534 // 1) No proxy is involved.
11535 // 2) TLS False Start is enabled.
11536 // 3) The initial TLS handshake requests a client certificate.
11537 // 4) The client supplies an invalid/unacceptable certificate.
11538 TEST_P(HttpNetworkTransactionTest,
11539 ClientAuthCertCache_Direct_FalseStart) {
11540 HttpRequestInfo request_info;
11541 request_info.url = GURL("https://www.example.com/");
11542 request_info.method = "GET";
11543 request_info.load_flags = LOAD_NORMAL;
11545 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11546 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11548 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11549 // return successfully after reading up to the peer's Certificate message.
11550 // This is to allow the caller to call SSLClientSocket::Write(), which can
11551 // enqueue application data to be sent in the same packet as the
11552 // ChangeCipherSpec and Finished messages.
11553 // The actual handshake will be finished when SSLClientSocket::Read() is
11554 // called, which expects to process the peer's ChangeCipherSpec and
11555 // Finished messages. If there was an error negotiating with the peer,
11556 // such as due to the peer requiring a client certificate when none was
11557 // supplied, the alert sent by the peer won't be processed until Read() is
11558 // called.
11560 // Like the non-False Start case, when a client certificate is requested by
11561 // the peer, the handshake is aborted during the Connect() call.
11562 // [ssl_]data1 represents the initial SSL handshake with the peer.
11563 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11564 ssl_data1.cert_request_info = cert_request.get();
11565 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11566 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11567 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11569 // When a client certificate is supplied, Connect() will not be aborted
11570 // when the peer requests the certificate. Instead, the handshake will
11571 // artificially succeed, allowing the caller to write the HTTP request to
11572 // the socket. The handshake messages are not processed until Read() is
11573 // called, which then detects that the handshake was aborted, due to the
11574 // peer sending a handshake_failure because it requires a client
11575 // certificate.
11576 SSLSocketDataProvider ssl_data2(ASYNC, OK);
11577 ssl_data2.cert_request_info = cert_request.get();
11578 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11579 MockRead data2_reads[] = {
11580 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
11582 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
11583 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11585 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11586 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11587 // TLSv1. It has the same behaviour as [ssl_]data2.
11588 SSLSocketDataProvider ssl_data3(ASYNC, OK);
11589 ssl_data3.cert_request_info = cert_request.get();
11590 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11591 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
11592 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11594 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11595 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11596 SSLSocketDataProvider ssl_data4(ASYNC, OK);
11597 ssl_data4.cert_request_info = cert_request.get();
11598 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11599 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
11600 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11602 // Need one more if TLSv1.2 is enabled.
11603 SSLSocketDataProvider ssl_data5(ASYNC, OK);
11604 ssl_data5.cert_request_info = cert_request.get();
11605 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11606 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
11607 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11609 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11610 scoped_ptr<HttpTransaction> trans(
11611 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11613 // Begin the initial SSL handshake.
11614 TestCompletionCallback callback;
11615 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11616 ASSERT_EQ(ERR_IO_PENDING, rv);
11618 // Complete the SSL handshake, which should abort due to requiring a
11619 // client certificate.
11620 rv = callback.WaitForResult();
11621 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11623 // Indicate that no certificate should be supplied. From the perspective
11624 // of SSLClientCertCache, NULL is just as meaningful as a real
11625 // certificate, so this is the same as supply a
11626 // legitimate-but-unacceptable certificate.
11627 rv = trans->RestartWithCertificate(NULL, callback.callback());
11628 ASSERT_EQ(ERR_IO_PENDING, rv);
11630 // Ensure the certificate was added to the client auth cache before
11631 // allowing the connection to continue restarting.
11632 scoped_refptr<X509Certificate> client_cert;
11633 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11634 HostPortPair("www.example.com", 443), &client_cert));
11635 ASSERT_EQ(NULL, client_cert.get());
11637 // Restart the handshake. This will consume ssl_data2, which fails, and
11638 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11639 // The result code is checked against what ssl_data4 should return.
11640 rv = callback.WaitForResult();
11641 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11643 // Ensure that the client certificate is removed from the cache on a
11644 // handshake failure.
11645 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11646 HostPortPair("www.example.com", 443), &client_cert));
11649 // Ensure that a client certificate is removed from the SSL client auth
11650 // cache when:
11651 // 1) An HTTPS proxy is involved.
11652 // 3) The HTTPS proxy requests a client certificate.
11653 // 4) The client supplies an invalid/unacceptable certificate for the
11654 // proxy.
11655 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11656 // then for connecting to an HTTP endpoint.
11657 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
11658 session_deps_.proxy_service.reset(
11659 ProxyService::CreateFixed("https://proxy:70"));
11660 BoundTestNetLog log;
11661 session_deps_.net_log = log.bound().net_log();
11663 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11664 cert_request->host_and_port = HostPortPair("proxy", 70);
11666 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11667 // [ssl_]data[1-3]. Rather than represending the endpoint
11668 // (www.example.com:443), they represent failures with the HTTPS proxy
11669 // (proxy:70).
11670 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11671 ssl_data1.cert_request_info = cert_request.get();
11672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11673 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11674 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11676 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11677 ssl_data2.cert_request_info = cert_request.get();
11678 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11679 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11680 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11682 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11683 #if 0
11684 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11685 ssl_data3.cert_request_info = cert_request.get();
11686 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11687 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11688 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11689 #endif
11691 HttpRequestInfo requests[2];
11692 requests[0].url = GURL("https://www.example.com/");
11693 requests[0].method = "GET";
11694 requests[0].load_flags = LOAD_NORMAL;
11696 requests[1].url = GURL("http://www.example.com/");
11697 requests[1].method = "GET";
11698 requests[1].load_flags = LOAD_NORMAL;
11700 for (size_t i = 0; i < arraysize(requests); ++i) {
11701 session_deps_.socket_factory->ResetNextMockIndexes();
11702 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11703 scoped_ptr<HttpNetworkTransaction> trans(
11704 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11706 // Begin the SSL handshake with the proxy.
11707 TestCompletionCallback callback;
11708 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
11709 ASSERT_EQ(ERR_IO_PENDING, rv);
11711 // Complete the SSL handshake, which should abort due to requiring a
11712 // client certificate.
11713 rv = callback.WaitForResult();
11714 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11716 // Indicate that no certificate should be supplied. From the perspective
11717 // of SSLClientCertCache, NULL is just as meaningful as a real
11718 // certificate, so this is the same as supply a
11719 // legitimate-but-unacceptable certificate.
11720 rv = trans->RestartWithCertificate(NULL, callback.callback());
11721 ASSERT_EQ(ERR_IO_PENDING, rv);
11723 // Ensure the certificate was added to the client auth cache before
11724 // allowing the connection to continue restarting.
11725 scoped_refptr<X509Certificate> client_cert;
11726 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11727 HostPortPair("proxy", 70), &client_cert));
11728 ASSERT_EQ(NULL, client_cert.get());
11729 // Ensure the certificate was NOT cached for the endpoint. This only
11730 // applies to HTTPS requests, but is fine to check for HTTP requests.
11731 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11732 HostPortPair("www.example.com", 443), &client_cert));
11734 // Restart the handshake. This will consume ssl_data2, which fails, and
11735 // then consume ssl_data3, which should also fail. The result code is
11736 // checked against what ssl_data3 should return.
11737 rv = callback.WaitForResult();
11738 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
11740 // Now that the new handshake has failed, ensure that the client
11741 // certificate was removed from the client auth cache.
11742 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11743 HostPortPair("proxy", 70), &client_cert));
11744 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11745 HostPortPair("www.example.com", 443), &client_cert));
11749 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
11750 session_deps_.use_alternative_services = true;
11751 session_deps_.next_protos = SpdyNextProtos();
11753 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11754 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11755 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11756 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11757 pool_peer.DisableDomainAuthenticationVerification();
11759 SSLSocketDataProvider ssl(ASYNC, OK);
11760 ssl.SetNextProto(GetParam());
11761 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11763 scoped_ptr<SpdyFrame> host1_req(
11764 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11765 scoped_ptr<SpdyFrame> host2_req(
11766 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11767 MockWrite spdy_writes[] = {
11768 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11770 scoped_ptr<SpdyFrame> host1_resp(
11771 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11772 scoped_ptr<SpdyFrame> host1_resp_body(
11773 spdy_util_.ConstructSpdyBodyFrame(1, true));
11774 scoped_ptr<SpdyFrame> host2_resp(
11775 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11776 scoped_ptr<SpdyFrame> host2_resp_body(
11777 spdy_util_.ConstructSpdyBodyFrame(3, true));
11778 MockRead spdy_reads[] = {
11779 CreateMockRead(*host1_resp, 1),
11780 CreateMockRead(*host1_resp_body, 2),
11781 CreateMockRead(*host2_resp, 4),
11782 CreateMockRead(*host2_resp_body, 5),
11783 MockRead(ASYNC, 0, 6),
11786 IPAddressNumber ip;
11787 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11788 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11789 MockConnect connect(ASYNC, OK, peer_addr);
11790 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11791 spdy_writes, arraysize(spdy_writes));
11792 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11794 TestCompletionCallback callback;
11795 HttpRequestInfo request1;
11796 request1.method = "GET";
11797 request1.url = GURL("https://www.example.org/");
11798 request1.load_flags = 0;
11799 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11801 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11802 EXPECT_EQ(ERR_IO_PENDING, rv);
11803 EXPECT_EQ(OK, callback.WaitForResult());
11805 const HttpResponseInfo* response = trans1.GetResponseInfo();
11806 ASSERT_TRUE(response != NULL);
11807 ASSERT_TRUE(response->headers.get() != NULL);
11808 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11810 std::string response_data;
11811 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11812 EXPECT_EQ("hello!", response_data);
11814 // Preload www.gmail.com into HostCache.
11815 HostPortPair host_port("www.gmail.com", 443);
11816 HostResolver::RequestInfo resolve_info(host_port);
11817 AddressList ignored;
11818 rv = session_deps_.host_resolver->Resolve(resolve_info,
11819 DEFAULT_PRIORITY,
11820 &ignored,
11821 callback.callback(),
11822 NULL,
11823 BoundNetLog());
11824 EXPECT_EQ(ERR_IO_PENDING, rv);
11825 rv = callback.WaitForResult();
11826 EXPECT_EQ(OK, rv);
11828 HttpRequestInfo request2;
11829 request2.method = "GET";
11830 request2.url = GURL("https://www.gmail.com/");
11831 request2.load_flags = 0;
11832 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11834 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11835 EXPECT_EQ(ERR_IO_PENDING, rv);
11836 EXPECT_EQ(OK, callback.WaitForResult());
11838 response = trans2.GetResponseInfo();
11839 ASSERT_TRUE(response != NULL);
11840 ASSERT_TRUE(response->headers.get() != NULL);
11841 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11842 EXPECT_TRUE(response->was_fetched_via_spdy);
11843 EXPECT_TRUE(response->was_npn_negotiated);
11844 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11845 EXPECT_EQ("hello!", response_data);
11848 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11849 session_deps_.use_alternative_services = true;
11850 session_deps_.next_protos = SpdyNextProtos();
11852 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11853 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11854 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11855 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11856 pool_peer.DisableDomainAuthenticationVerification();
11858 SSLSocketDataProvider ssl(ASYNC, OK);
11859 ssl.SetNextProto(GetParam());
11860 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11862 scoped_ptr<SpdyFrame> host1_req(
11863 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11864 scoped_ptr<SpdyFrame> host2_req(
11865 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11866 MockWrite spdy_writes[] = {
11867 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11869 scoped_ptr<SpdyFrame> host1_resp(
11870 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11871 scoped_ptr<SpdyFrame> host1_resp_body(
11872 spdy_util_.ConstructSpdyBodyFrame(1, true));
11873 scoped_ptr<SpdyFrame> host2_resp(
11874 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11875 scoped_ptr<SpdyFrame> host2_resp_body(
11876 spdy_util_.ConstructSpdyBodyFrame(3, true));
11877 MockRead spdy_reads[] = {
11878 CreateMockRead(*host1_resp, 1),
11879 CreateMockRead(*host1_resp_body, 2),
11880 CreateMockRead(*host2_resp, 4),
11881 CreateMockRead(*host2_resp_body, 5),
11882 MockRead(ASYNC, 0, 6),
11885 IPAddressNumber ip;
11886 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11887 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11888 MockConnect connect(ASYNC, OK, peer_addr);
11889 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
11890 spdy_writes, arraysize(spdy_writes));
11891 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11893 TestCompletionCallback callback;
11894 HttpRequestInfo request1;
11895 request1.method = "GET";
11896 request1.url = GURL("https://www.example.org/");
11897 request1.load_flags = 0;
11898 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11900 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11901 EXPECT_EQ(ERR_IO_PENDING, rv);
11902 EXPECT_EQ(OK, callback.WaitForResult());
11904 const HttpResponseInfo* response = trans1.GetResponseInfo();
11905 ASSERT_TRUE(response != NULL);
11906 ASSERT_TRUE(response->headers.get() != NULL);
11907 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11909 std::string response_data;
11910 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11911 EXPECT_EQ("hello!", response_data);
11913 HttpRequestInfo request2;
11914 request2.method = "GET";
11915 request2.url = GURL("https://www.gmail.com/");
11916 request2.load_flags = 0;
11917 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11919 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11920 EXPECT_EQ(ERR_IO_PENDING, rv);
11921 EXPECT_EQ(OK, callback.WaitForResult());
11923 response = trans2.GetResponseInfo();
11924 ASSERT_TRUE(response != NULL);
11925 ASSERT_TRUE(response->headers.get() != NULL);
11926 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11927 EXPECT_TRUE(response->was_fetched_via_spdy);
11928 EXPECT_TRUE(response->was_npn_negotiated);
11929 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11930 EXPECT_EQ("hello!", response_data);
11933 class OneTimeCachingHostResolver : public HostResolver {
11934 public:
11935 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11936 : host_port_(host_port) {}
11937 ~OneTimeCachingHostResolver() override {}
11939 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11941 // HostResolver methods:
11942 int Resolve(const RequestInfo& info,
11943 RequestPriority priority,
11944 AddressList* addresses,
11945 const CompletionCallback& callback,
11946 RequestHandle* out_req,
11947 const BoundNetLog& net_log) override {
11948 return host_resolver_.Resolve(
11949 info, priority, addresses, callback, out_req, net_log);
11952 int ResolveFromCache(const RequestInfo& info,
11953 AddressList* addresses,
11954 const BoundNetLog& net_log) override {
11955 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11956 if (rv == OK && info.host_port_pair().Equals(host_port_))
11957 host_resolver_.GetHostCache()->clear();
11958 return rv;
11961 void CancelRequest(RequestHandle req) override {
11962 host_resolver_.CancelRequest(req);
11965 MockCachingHostResolver* GetMockHostResolver() {
11966 return &host_resolver_;
11969 private:
11970 MockCachingHostResolver host_resolver_;
11971 const HostPortPair host_port_;
11974 TEST_P(HttpNetworkTransactionTest,
11975 UseIPConnectionPoolingWithHostCacheExpiration) {
11976 session_deps_.use_alternative_services = true;
11977 session_deps_.next_protos = SpdyNextProtos();
11979 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11980 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11981 HttpNetworkSession::Params params =
11982 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11983 params.host_resolver = &host_resolver;
11984 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11985 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11986 pool_peer.DisableDomainAuthenticationVerification();
11988 SSLSocketDataProvider ssl(ASYNC, OK);
11989 ssl.SetNextProto(GetParam());
11990 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11992 scoped_ptr<SpdyFrame> host1_req(
11993 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11994 scoped_ptr<SpdyFrame> host2_req(
11995 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11996 MockWrite spdy_writes[] = {
11997 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
11999 scoped_ptr<SpdyFrame> host1_resp(
12000 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12001 scoped_ptr<SpdyFrame> host1_resp_body(
12002 spdy_util_.ConstructSpdyBodyFrame(1, true));
12003 scoped_ptr<SpdyFrame> host2_resp(
12004 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12005 scoped_ptr<SpdyFrame> host2_resp_body(
12006 spdy_util_.ConstructSpdyBodyFrame(3, true));
12007 MockRead spdy_reads[] = {
12008 CreateMockRead(*host1_resp, 1),
12009 CreateMockRead(*host1_resp_body, 2),
12010 CreateMockRead(*host2_resp, 4),
12011 CreateMockRead(*host2_resp_body, 5),
12012 MockRead(ASYNC, 0, 6),
12015 IPAddressNumber ip;
12016 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12017 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12018 MockConnect connect(ASYNC, OK, peer_addr);
12019 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12020 spdy_writes, arraysize(spdy_writes));
12021 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
12023 TestCompletionCallback callback;
12024 HttpRequestInfo request1;
12025 request1.method = "GET";
12026 request1.url = GURL("https://www.example.org/");
12027 request1.load_flags = 0;
12028 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
12030 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
12031 EXPECT_EQ(ERR_IO_PENDING, rv);
12032 EXPECT_EQ(OK, callback.WaitForResult());
12034 const HttpResponseInfo* response = trans1.GetResponseInfo();
12035 ASSERT_TRUE(response != NULL);
12036 ASSERT_TRUE(response->headers.get() != NULL);
12037 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12039 std::string response_data;
12040 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12041 EXPECT_EQ("hello!", response_data);
12043 // Preload cache entries into HostCache.
12044 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
12045 AddressList ignored;
12046 rv = host_resolver.Resolve(resolve_info,
12047 DEFAULT_PRIORITY,
12048 &ignored,
12049 callback.callback(),
12050 NULL,
12051 BoundNetLog());
12052 EXPECT_EQ(ERR_IO_PENDING, rv);
12053 rv = callback.WaitForResult();
12054 EXPECT_EQ(OK, rv);
12056 HttpRequestInfo request2;
12057 request2.method = "GET";
12058 request2.url = GURL("https://www.gmail.com/");
12059 request2.load_flags = 0;
12060 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
12062 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
12063 EXPECT_EQ(ERR_IO_PENDING, rv);
12064 EXPECT_EQ(OK, callback.WaitForResult());
12066 response = trans2.GetResponseInfo();
12067 ASSERT_TRUE(response != NULL);
12068 ASSERT_TRUE(response->headers.get() != NULL);
12069 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12070 EXPECT_TRUE(response->was_fetched_via_spdy);
12071 EXPECT_TRUE(response->was_npn_negotiated);
12072 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12073 EXPECT_EQ("hello!", response_data);
12076 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
12077 const std::string https_url = "https://www.example.org:8080/";
12078 const std::string http_url = "http://www.example.org:8080/";
12080 // SPDY GET for HTTPS URL
12081 scoped_ptr<SpdyFrame> req1(
12082 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
12084 MockWrite writes1[] = {
12085 CreateMockWrite(*req1, 0),
12088 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12089 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12090 MockRead reads1[] = {
12091 CreateMockRead(*resp1, 1),
12092 CreateMockRead(*body1, 2),
12093 MockRead(ASYNC, ERR_IO_PENDING, 3)
12096 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
12097 arraysize(writes1));
12098 MockConnect connect_data1(ASYNC, OK);
12099 data1.set_connect_data(connect_data1);
12101 // HTTP GET for the HTTP URL
12102 MockWrite writes2[] = {
12103 MockWrite(ASYNC, 0,
12104 "GET / HTTP/1.1\r\n"
12105 "Host: www.example.org:8080\r\n"
12106 "Connection: keep-alive\r\n\r\n"),
12109 MockRead reads2[] = {
12110 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
12111 MockRead(ASYNC, 2, "hello"),
12112 MockRead(ASYNC, OK, 3),
12115 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
12116 arraysize(writes2));
12118 SSLSocketDataProvider ssl(ASYNC, OK);
12119 ssl.SetNextProto(GetParam());
12120 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12121 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12122 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12124 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12126 // Start the first transaction to set up the SpdySession
12127 HttpRequestInfo request1;
12128 request1.method = "GET";
12129 request1.url = GURL(https_url);
12130 request1.load_flags = 0;
12131 HttpNetworkTransaction trans1(LOWEST, session.get());
12132 TestCompletionCallback callback1;
12133 EXPECT_EQ(ERR_IO_PENDING,
12134 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12135 base::MessageLoop::current()->RunUntilIdle();
12137 EXPECT_EQ(OK, callback1.WaitForResult());
12138 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12140 // Now, start the HTTP request
12141 HttpRequestInfo request2;
12142 request2.method = "GET";
12143 request2.url = GURL(http_url);
12144 request2.load_flags = 0;
12145 HttpNetworkTransaction trans2(MEDIUM, session.get());
12146 TestCompletionCallback callback2;
12147 EXPECT_EQ(ERR_IO_PENDING,
12148 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12149 base::MessageLoop::current()->RunUntilIdle();
12151 EXPECT_EQ(OK, callback2.WaitForResult());
12152 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12155 class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
12156 public:
12157 void Run(bool pooling, bool valid) {
12158 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
12159 443);
12160 HostPortPair alternative("www.example.org", 443);
12162 base::FilePath certs_dir = GetTestCertsDirectory();
12163 scoped_refptr<X509Certificate> cert(
12164 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
12165 ASSERT_TRUE(cert.get());
12166 bool common_name_fallback_used;
12167 EXPECT_EQ(valid,
12168 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
12169 EXPECT_TRUE(
12170 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
12171 SSLSocketDataProvider ssl(ASYNC, OK);
12172 ssl.SetNextProto(GetParam());
12173 ssl.cert = cert;
12174 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12176 // If pooling, then start a request to alternative first to create a
12177 // SpdySession.
12178 std::string url0 = "https://www.example.org:443";
12179 // Second request to origin, which has an alternative service, and could
12180 // open a connection to the alternative host or pool to the existing one.
12181 std::string url1("https://");
12182 url1.append(origin.host());
12183 url1.append(":443");
12185 scoped_ptr<SpdyFrame> req0;
12186 scoped_ptr<SpdyFrame> req1;
12187 scoped_ptr<SpdyFrame> resp0;
12188 scoped_ptr<SpdyFrame> body0;
12189 scoped_ptr<SpdyFrame> resp1;
12190 scoped_ptr<SpdyFrame> body1;
12191 std::vector<MockWrite> writes;
12192 std::vector<MockRead> reads;
12194 if (pooling) {
12195 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
12196 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
12198 writes.push_back(CreateMockWrite(*req0, 0));
12199 writes.push_back(CreateMockWrite(*req1, 3));
12201 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12202 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12203 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12204 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
12206 reads.push_back(CreateMockRead(*resp0, 1));
12207 reads.push_back(CreateMockRead(*body0, 2));
12208 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
12209 reads.push_back(CreateMockRead(*resp1, 5));
12210 reads.push_back(CreateMockRead(*body1, 6));
12211 reads.push_back(MockRead(ASYNC, OK, 7));
12212 } else {
12213 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
12215 writes.push_back(CreateMockWrite(*req1, 0));
12217 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12218 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12220 reads.push_back(CreateMockRead(*resp1, 1));
12221 reads.push_back(CreateMockRead(*body1, 2));
12222 reads.push_back(MockRead(ASYNC, OK, 3));
12225 SequencedSocketData data(vector_as_array(&reads), reads.size(),
12226 vector_as_array(&writes), writes.size());
12227 session_deps_.socket_factory->AddSocketDataProvider(&data);
12229 // Connection to the origin fails.
12230 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12231 StaticSocketDataProvider data_refused;
12232 data_refused.set_connect_data(mock_connect);
12233 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12235 session_deps_.use_alternative_services = true;
12236 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12237 base::WeakPtr<HttpServerProperties> http_server_properties =
12238 session->http_server_properties();
12239 AlternativeService alternative_service(
12240 AlternateProtocolFromNextProto(GetParam()), alternative);
12241 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12242 http_server_properties->SetAlternativeService(origin, alternative_service,
12243 1.0, expiration);
12245 // First request to alternative.
12246 if (pooling) {
12247 scoped_ptr<HttpTransaction> trans0(
12248 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12249 HttpRequestInfo request0;
12250 request0.method = "GET";
12251 request0.url = GURL(url0);
12252 request0.load_flags = 0;
12253 TestCompletionCallback callback0;
12255 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
12256 EXPECT_EQ(ERR_IO_PENDING, rv);
12257 rv = callback0.WaitForResult();
12258 EXPECT_EQ(OK, rv);
12261 // Second request to origin.
12262 scoped_ptr<HttpTransaction> trans1(
12263 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12264 HttpRequestInfo request1;
12265 request1.method = "GET";
12266 request1.url = GURL(url1);
12267 request1.load_flags = 0;
12268 TestCompletionCallback callback1;
12270 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12271 EXPECT_EQ(ERR_IO_PENDING, rv);
12272 base::MessageLoop::current()->RunUntilIdle();
12273 if (data.IsReadPaused()) {
12274 data.CompleteRead();
12276 rv = callback1.WaitForResult();
12277 if (valid) {
12278 EXPECT_EQ(OK, rv);
12279 } else {
12280 if (pooling) {
12281 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12282 } else {
12283 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
12289 INSTANTIATE_TEST_CASE_P(NextProto,
12290 AltSvcCertificateVerificationTest,
12291 testing::Values(kProtoSPDY31,
12292 kProtoHTTP2));
12294 // The alternative service host must exhibit a certificate that is valid for the
12295 // origin host. Test that this is enforced when pooling to an existing
12296 // connection.
12297 TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
12298 Run(true, true);
12301 TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
12302 Run(true, false);
12305 // The alternative service host must exhibit a certificate that is valid for the
12306 // origin host. Test that this is enforced when opening a new connection.
12307 TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
12308 Run(false, true);
12311 TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
12312 Run(false, false);
12315 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12316 // with the alternative server. That connection should not be used.
12317 TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
12318 HostPortPair origin("origin.example.org", 443);
12319 HostPortPair alternative("alternative.example.org", 443);
12321 // Negotiate HTTP/1.1 with alternative.example.org.
12322 SSLSocketDataProvider ssl(ASYNC, OK);
12323 ssl.SetNextProto(kProtoHTTP11);
12324 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12326 // No data should be read from the alternative, because HTTP/1.1 is
12327 // negotiated.
12328 StaticSocketDataProvider data;
12329 session_deps_.socket_factory->AddSocketDataProvider(&data);
12331 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12332 // negotiated. In order to test this, a failed connection to the origin is
12333 // mocked. This way the request relies on the alternate Job.
12334 StaticSocketDataProvider data_refused;
12335 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12336 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12338 // Set up alternative service for origin.
12339 session_deps_.use_alternative_services = true;
12340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12341 base::WeakPtr<HttpServerProperties> http_server_properties =
12342 session->http_server_properties();
12343 AlternativeService alternative_service(
12344 AlternateProtocolFromNextProto(GetParam()), alternative);
12345 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12346 http_server_properties->SetAlternativeService(origin, alternative_service,
12347 1.0, expiration);
12349 scoped_ptr<HttpTransaction> trans(
12350 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12351 HttpRequestInfo request;
12352 request.method = "GET";
12353 request.url = GURL("https://origin.example.org:443");
12354 request.load_flags = 0;
12355 TestCompletionCallback callback;
12357 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12358 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12359 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12360 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
12363 // A request to a server with an alternative service fires two Jobs: one to the
12364 // origin, and an alternate one to the alternative server. If the former
12365 // succeeds, the request should succeed, even if the latter fails because
12366 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12367 TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
12368 HostPortPair origin("origin.example.org", 443);
12369 HostPortPair alternative("alternative.example.org", 443);
12371 // Negotiate HTTP/1.1 with alternative.
12372 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
12373 alternative_ssl.SetNextProto(kProtoHTTP11);
12374 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
12376 // No data should be read from the alternative, because HTTP/1.1 is
12377 // negotiated.
12378 StaticSocketDataProvider data;
12379 session_deps_.socket_factory->AddSocketDataProvider(&data);
12381 // Negotiate HTTP/1.1 with origin.
12382 SSLSocketDataProvider origin_ssl(ASYNC, OK);
12383 origin_ssl.SetNextProto(kProtoHTTP11);
12384 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
12386 MockWrite http_writes[] = {
12387 MockWrite(
12388 "GET / HTTP/1.1\r\n"
12389 "Host: origin.example.org\r\n"
12390 "Connection: keep-alive\r\n\r\n"),
12391 MockWrite(
12392 "GET /second HTTP/1.1\r\n"
12393 "Host: origin.example.org\r\n"
12394 "Connection: keep-alive\r\n\r\n"),
12397 MockRead http_reads[] = {
12398 MockRead("HTTP/1.1 200 OK\r\n"),
12399 MockRead("Content-Type: text/html\r\n"),
12400 MockRead("Content-Length: 6\r\n\r\n"),
12401 MockRead("foobar"),
12402 MockRead("HTTP/1.1 200 OK\r\n"),
12403 MockRead("Content-Type: text/html\r\n"),
12404 MockRead("Content-Length: 7\r\n\r\n"),
12405 MockRead("another"),
12407 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12408 http_writes, arraysize(http_writes));
12409 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12411 // Set up alternative service for origin.
12412 session_deps_.use_alternative_services = true;
12413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12414 base::WeakPtr<HttpServerProperties> http_server_properties =
12415 session->http_server_properties();
12416 AlternativeService alternative_service(
12417 AlternateProtocolFromNextProto(GetParam()), alternative);
12418 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12419 http_server_properties->SetAlternativeService(origin, alternative_service,
12420 1.0, expiration);
12422 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
12423 HttpRequestInfo request1;
12424 request1.method = "GET";
12425 request1.url = GURL("https://origin.example.org:443");
12426 request1.load_flags = 0;
12427 TestCompletionCallback callback1;
12429 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
12430 rv = callback1.GetResult(rv);
12431 EXPECT_EQ(OK, rv);
12433 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
12434 ASSERT_TRUE(response1 != nullptr);
12435 ASSERT_TRUE(response1->headers.get() != nullptr);
12436 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12438 std::string response_data1;
12439 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
12440 EXPECT_EQ("foobar", response_data1);
12442 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12443 // for alternative service.
12444 EXPECT_TRUE(
12445 http_server_properties->IsAlternativeServiceBroken(alternative_service));
12447 // Since |alternative_service| is broken, a second transaction to origin
12448 // should not start an alternate Job. It should pool to existing connection
12449 // to origin.
12450 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
12451 HttpRequestInfo request2;
12452 request2.method = "GET";
12453 request2.url = GURL("https://origin.example.org:443/second");
12454 request2.load_flags = 0;
12455 TestCompletionCallback callback2;
12457 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
12458 rv = callback2.GetResult(rv);
12459 EXPECT_EQ(OK, rv);
12461 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
12462 ASSERT_TRUE(response2 != nullptr);
12463 ASSERT_TRUE(response2->headers.get() != nullptr);
12464 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
12466 std::string response_data2;
12467 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
12468 EXPECT_EQ("another", response_data2);
12471 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12472 // HTTP/1.1 socket open to the alternative server. That socket should not be
12473 // used.
12474 TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
12475 HostPortPair origin("origin.example.org", 443);
12476 HostPortPair alternative("alternative.example.org", 443);
12477 std::string origin_url = "https://origin.example.org:443";
12478 std::string alternative_url = "https://alternative.example.org:443";
12480 // Negotiate HTTP/1.1 with alternative.example.org.
12481 SSLSocketDataProvider ssl(ASYNC, OK);
12482 ssl.SetNextProto(kProtoHTTP11);
12483 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12485 // HTTP/1.1 data for |request1| and |request2|.
12486 MockWrite http_writes[] = {
12487 MockWrite(
12488 "GET / HTTP/1.1\r\n"
12489 "Host: alternative.example.org\r\n"
12490 "Connection: keep-alive\r\n\r\n"),
12491 MockWrite(
12492 "GET / HTTP/1.1\r\n"
12493 "Host: alternative.example.org\r\n"
12494 "Connection: keep-alive\r\n\r\n"),
12497 MockRead http_reads[] = {
12498 MockRead(
12499 "HTTP/1.1 200 OK\r\n"
12500 "Content-Type: text/html; charset=iso-8859-1\r\n"
12501 "Content-Length: 40\r\n\r\n"
12502 "first HTTP/1.1 response from alternative"),
12503 MockRead(
12504 "HTTP/1.1 200 OK\r\n"
12505 "Content-Type: text/html; charset=iso-8859-1\r\n"
12506 "Content-Length: 41\r\n\r\n"
12507 "second HTTP/1.1 response from alternative"),
12509 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12510 http_writes, arraysize(http_writes));
12511 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12513 // This test documents that an alternate Job should not pool to an already
12514 // existing HTTP/1.1 connection. In order to test this, a failed connection
12515 // to the origin is mocked. This way |request2| relies on the alternate Job.
12516 StaticSocketDataProvider data_refused;
12517 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12518 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12520 // Set up alternative service for origin.
12521 session_deps_.use_alternative_services = true;
12522 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12523 base::WeakPtr<HttpServerProperties> http_server_properties =
12524 session->http_server_properties();
12525 AlternativeService alternative_service(
12526 AlternateProtocolFromNextProto(GetParam()), alternative);
12527 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12528 http_server_properties->SetAlternativeService(origin, alternative_service,
12529 1.0, expiration);
12531 // First transaction to alternative to open an HTTP/1.1 socket.
12532 scoped_ptr<HttpTransaction> trans1(
12533 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12534 HttpRequestInfo request1;
12535 request1.method = "GET";
12536 request1.url = GURL(alternative_url);
12537 request1.load_flags = 0;
12538 TestCompletionCallback callback1;
12540 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12541 EXPECT_EQ(OK, callback1.GetResult(rv));
12542 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12543 ASSERT_TRUE(response1);
12544 ASSERT_TRUE(response1->headers.get());
12545 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
12546 EXPECT_TRUE(response1->was_npn_negotiated);
12547 EXPECT_FALSE(response1->was_fetched_via_spdy);
12548 std::string response_data1;
12549 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
12550 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
12552 // Request for origin.example.org, which has an alternative service. This
12553 // will start two Jobs: the alternative looks for connections to pool to,
12554 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12555 // open other connections to alternative server. The Job to origin fails, so
12556 // this request fails.
12557 scoped_ptr<HttpTransaction> trans2(
12558 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12559 HttpRequestInfo request2;
12560 request2.method = "GET";
12561 request2.url = GURL(origin_url);
12562 request2.load_flags = 0;
12563 TestCompletionCallback callback2;
12565 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
12566 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
12568 // Another transaction to alternative. This is to test that the HTTP/1.1
12569 // socket is still open and in the pool.
12570 scoped_ptr<HttpTransaction> trans3(
12571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12572 HttpRequestInfo request3;
12573 request3.method = "GET";
12574 request3.url = GURL(alternative_url);
12575 request3.load_flags = 0;
12576 TestCompletionCallback callback3;
12578 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
12579 EXPECT_EQ(OK, callback3.GetResult(rv));
12580 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
12581 ASSERT_TRUE(response3);
12582 ASSERT_TRUE(response3->headers.get());
12583 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
12584 EXPECT_TRUE(response3->was_npn_negotiated);
12585 EXPECT_FALSE(response3->was_fetched_via_spdy);
12586 std::string response_data3;
12587 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
12588 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
12591 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
12592 const std::string https_url = "https://www.example.org:8080/";
12593 const std::string http_url = "http://www.example.org:8080/";
12595 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12596 const HostPortPair host_port_pair("www.example.org", 8080);
12597 scoped_ptr<SpdyFrame> connect(
12598 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
12599 scoped_ptr<SpdyFrame> req1(
12600 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
12601 scoped_ptr<SpdyFrame> wrapped_req1(
12602 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
12604 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12605 SpdyHeaderBlock req2_block;
12606 req2_block[spdy_util_.GetMethodKey()] = "GET";
12607 req2_block[spdy_util_.GetPathKey()] = "/";
12608 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
12609 req2_block[spdy_util_.GetSchemeKey()] = "http";
12610 spdy_util_.MaybeAddVersionHeader(&req2_block);
12611 scoped_ptr<SpdyFrame> req2(
12612 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
12614 MockWrite writes1[] = {
12615 CreateMockWrite(*connect, 0),
12616 CreateMockWrite(*wrapped_req1, 2),
12617 CreateMockWrite(*req2, 5),
12620 scoped_ptr<SpdyFrame> conn_resp(
12621 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12622 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12623 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12624 scoped_ptr<SpdyFrame> wrapped_resp1(
12625 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
12626 scoped_ptr<SpdyFrame> wrapped_body1(
12627 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
12628 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12629 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
12630 MockRead reads1[] = {
12631 CreateMockRead(*conn_resp, 1),
12632 CreateMockRead(*wrapped_resp1, 3),
12633 CreateMockRead(*wrapped_body1, 4),
12634 CreateMockRead(*resp2, 6),
12635 CreateMockRead(*body2, 7),
12636 MockRead(ASYNC, ERR_IO_PENDING, 8)
12639 DeterministicSocketData data1(reads1, arraysize(reads1),
12640 writes1, arraysize(writes1));
12641 MockConnect connect_data1(ASYNC, OK);
12642 data1.set_connect_data(connect_data1);
12644 session_deps_.proxy_service.reset(
12645 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12646 TestNetLog log;
12647 session_deps_.net_log = &log;
12648 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12649 ssl1.SetNextProto(GetParam());
12650 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12651 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12652 ssl2.SetNextProto(GetParam());
12653 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12654 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
12656 scoped_refptr<HttpNetworkSession> session(
12657 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12659 // Start the first transaction to set up the SpdySession
12660 HttpRequestInfo request1;
12661 request1.method = "GET";
12662 request1.url = GURL(https_url);
12663 request1.load_flags = 0;
12664 HttpNetworkTransaction trans1(LOWEST, session.get());
12665 TestCompletionCallback callback1;
12666 EXPECT_EQ(ERR_IO_PENDING,
12667 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12668 base::MessageLoop::current()->RunUntilIdle();
12669 data1.RunFor(4);
12671 EXPECT_EQ(OK, callback1.WaitForResult());
12672 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12674 LoadTimingInfo load_timing_info1;
12675 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
12676 TestLoadTimingNotReusedWithPac(load_timing_info1,
12677 CONNECT_TIMING_HAS_SSL_TIMES);
12679 // Now, start the HTTP request
12680 HttpRequestInfo request2;
12681 request2.method = "GET";
12682 request2.url = GURL(http_url);
12683 request2.load_flags = 0;
12684 HttpNetworkTransaction trans2(MEDIUM, session.get());
12685 TestCompletionCallback callback2;
12686 EXPECT_EQ(ERR_IO_PENDING,
12687 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12688 base::MessageLoop::current()->RunUntilIdle();
12689 data1.RunFor(3);
12691 EXPECT_EQ(OK, callback2.WaitForResult());
12692 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12694 LoadTimingInfo load_timing_info2;
12695 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
12696 // The established SPDY sessions is considered reused by the HTTP request.
12697 TestLoadTimingReusedWithPac(load_timing_info2);
12698 // HTTP requests over a SPDY session should have a different connection
12699 // socket_log_id than requests over a tunnel.
12700 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
12703 // Test that in the case where we have a SPDY session to a SPDY proxy
12704 // that we do not pool other origins that resolve to the same IP when
12705 // the certificate does not match the new origin.
12706 // http://crbug.com/134690
12707 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
12708 const std::string url1 = "http://www.example.org/";
12709 const std::string url2 = "https://news.example.org/";
12710 const std::string ip_addr = "1.2.3.4";
12712 // SPDY GET for HTTP URL (through SPDY proxy)
12713 scoped_ptr<SpdyHeaderBlock> headers(
12714 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12715 scoped_ptr<SpdyFrame> req1(
12716 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
12718 MockWrite writes1[] = {
12719 CreateMockWrite(*req1, 0),
12722 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12723 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
12724 MockRead reads1[] = {
12725 CreateMockRead(*resp1, 1),
12726 CreateMockRead(*body1, 2),
12727 MockRead(ASYNC, OK, 3) // EOF
12730 scoped_ptr<DeterministicSocketData> data1(
12731 new DeterministicSocketData(reads1, arraysize(reads1),
12732 writes1, arraysize(writes1)));
12733 IPAddressNumber ip;
12734 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
12735 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12736 MockConnect connect_data1(ASYNC, OK, peer_addr);
12737 data1->set_connect_data(connect_data1);
12739 // SPDY GET for HTTPS URL (direct)
12740 scoped_ptr<SpdyFrame> req2(
12741 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
12743 MockWrite writes2[] = {
12744 CreateMockWrite(*req2, 0),
12747 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12748 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12749 MockRead reads2[] = {
12750 CreateMockRead(*resp2, 1),
12751 CreateMockRead(*body2, 2),
12752 MockRead(ASYNC, OK, 3) // EOF
12755 scoped_ptr<DeterministicSocketData> data2(
12756 new DeterministicSocketData(reads2, arraysize(reads2),
12757 writes2, arraysize(writes2)));
12758 MockConnect connect_data2(ASYNC, OK);
12759 data2->set_connect_data(connect_data2);
12761 // Set up a proxy config that sends HTTP requests to a proxy, and
12762 // all others direct.
12763 ProxyConfig proxy_config;
12764 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
12765 session_deps_.proxy_service.reset(new ProxyService(
12766 new ProxyConfigServiceFixed(proxy_config), nullptr, NULL));
12768 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12769 ssl1.SetNextProto(GetParam());
12770 // Load a valid cert. Note, that this does not need to
12771 // be valid for proxy because the MockSSLClientSocket does
12772 // not actually verify it. But SpdySession will use this
12773 // to see if it is valid for the new origin
12774 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12775 ASSERT_TRUE(ssl1.cert.get());
12776 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12777 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12778 data1.get());
12780 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12781 ssl2.SetNextProto(GetParam());
12782 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12783 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12784 data2.get());
12786 session_deps_.host_resolver.reset(new MockCachingHostResolver());
12787 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
12788 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
12790 scoped_refptr<HttpNetworkSession> session(
12791 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12793 // Start the first transaction to set up the SpdySession
12794 HttpRequestInfo request1;
12795 request1.method = "GET";
12796 request1.url = GURL(url1);
12797 request1.load_flags = 0;
12798 HttpNetworkTransaction trans1(LOWEST, session.get());
12799 TestCompletionCallback callback1;
12800 ASSERT_EQ(ERR_IO_PENDING,
12801 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12802 data1->RunFor(3);
12804 ASSERT_TRUE(callback1.have_result());
12805 EXPECT_EQ(OK, callback1.WaitForResult());
12806 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12808 // Now, start the HTTP request
12809 HttpRequestInfo request2;
12810 request2.method = "GET";
12811 request2.url = GURL(url2);
12812 request2.load_flags = 0;
12813 HttpNetworkTransaction trans2(MEDIUM, session.get());
12814 TestCompletionCallback callback2;
12815 EXPECT_EQ(ERR_IO_PENDING,
12816 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12817 base::MessageLoop::current()->RunUntilIdle();
12818 data2->RunFor(3);
12820 ASSERT_TRUE(callback2.have_result());
12821 EXPECT_EQ(OK, callback2.WaitForResult());
12822 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12825 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12826 // error) in SPDY session, removes the socket from pool and closes the SPDY
12827 // session. Verify that new url's from the same HttpNetworkSession (and a new
12828 // SpdySession) do work. http://crbug.com/224701
12829 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
12830 const std::string https_url = "https://www.example.org/";
12832 MockRead reads1[] = {
12833 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
12836 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
12838 scoped_ptr<SpdyFrame> req2(
12839 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
12840 MockWrite writes2[] = {
12841 CreateMockWrite(*req2, 0),
12844 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12845 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12846 MockRead reads2[] = {
12847 CreateMockRead(*resp2, 1),
12848 CreateMockRead(*body2, 2),
12849 MockRead(ASYNC, OK, 3) // EOF
12852 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
12853 arraysize(writes2));
12855 SSLSocketDataProvider ssl1(ASYNC, OK);
12856 ssl1.SetNextProto(GetParam());
12857 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12858 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12860 SSLSocketDataProvider ssl2(ASYNC, OK);
12861 ssl2.SetNextProto(GetParam());
12862 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12863 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12865 scoped_refptr<HttpNetworkSession> session(
12866 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
12868 // Start the first transaction to set up the SpdySession and verify that
12869 // connection was closed.
12870 HttpRequestInfo request1;
12871 request1.method = "GET";
12872 request1.url = GURL(https_url);
12873 request1.load_flags = 0;
12874 HttpNetworkTransaction trans1(MEDIUM, session.get());
12875 TestCompletionCallback callback1;
12876 EXPECT_EQ(ERR_IO_PENDING,
12877 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12878 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
12880 // Now, start the second request and make sure it succeeds.
12881 HttpRequestInfo request2;
12882 request2.method = "GET";
12883 request2.url = GURL(https_url);
12884 request2.load_flags = 0;
12885 HttpNetworkTransaction trans2(MEDIUM, session.get());
12886 TestCompletionCallback callback2;
12887 EXPECT_EQ(ERR_IO_PENDING,
12888 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12890 ASSERT_EQ(OK, callback2.WaitForResult());
12891 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12894 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
12895 session_deps_.next_protos = SpdyNextProtos();
12896 ClientSocketPoolManager::set_max_sockets_per_group(
12897 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12898 ClientSocketPoolManager::set_max_sockets_per_pool(
12899 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12901 // Use two different hosts with different IPs so they don't get pooled.
12902 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
12903 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
12904 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12906 SSLSocketDataProvider ssl1(ASYNC, OK);
12907 ssl1.SetNextProto(GetParam());
12908 SSLSocketDataProvider ssl2(ASYNC, OK);
12909 ssl2.SetNextProto(GetParam());
12910 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12911 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12913 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
12914 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
12915 MockWrite spdy1_writes[] = {
12916 CreateMockWrite(*host1_req, 0),
12918 scoped_ptr<SpdyFrame> host1_resp(
12919 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12920 scoped_ptr<SpdyFrame> host1_resp_body(
12921 spdy_util_.ConstructSpdyBodyFrame(1, true));
12922 MockRead spdy1_reads[] = {
12923 CreateMockRead(*host1_resp, 1),
12924 CreateMockRead(*host1_resp_body, 2),
12925 MockRead(ASYNC, ERR_IO_PENDING, 3),
12928 scoped_ptr<SequencedSocketData> spdy1_data(
12929 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
12930 arraysize(spdy1_writes)));
12931 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
12933 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
12934 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
12935 MockWrite spdy2_writes[] = {
12936 CreateMockWrite(*host2_req, 0),
12938 scoped_ptr<SpdyFrame> host2_resp(
12939 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12940 scoped_ptr<SpdyFrame> host2_resp_body(
12941 spdy_util_.ConstructSpdyBodyFrame(1, true));
12942 MockRead spdy2_reads[] = {
12943 CreateMockRead(*host2_resp, 1),
12944 CreateMockRead(*host2_resp_body, 2),
12945 MockRead(ASYNC, ERR_IO_PENDING, 3),
12948 scoped_ptr<SequencedSocketData> spdy2_data(
12949 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
12950 arraysize(spdy2_writes)));
12951 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
12953 MockWrite http_write[] = {
12954 MockWrite("GET / HTTP/1.1\r\n"
12955 "Host: www.a.com\r\n"
12956 "Connection: keep-alive\r\n\r\n"),
12959 MockRead http_read[] = {
12960 MockRead("HTTP/1.1 200 OK\r\n"),
12961 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12962 MockRead("Content-Length: 6\r\n\r\n"),
12963 MockRead("hello!"),
12965 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
12966 http_write, arraysize(http_write));
12967 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12969 HostPortPair host_port_pair_a("www.a.com", 443);
12970 SpdySessionKey spdy_session_key_a(
12971 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12972 EXPECT_FALSE(
12973 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12975 TestCompletionCallback callback;
12976 HttpRequestInfo request1;
12977 request1.method = "GET";
12978 request1.url = GURL("https://www.a.com/");
12979 request1.load_flags = 0;
12980 scoped_ptr<HttpNetworkTransaction> trans(
12981 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12983 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
12984 EXPECT_EQ(ERR_IO_PENDING, rv);
12985 EXPECT_EQ(OK, callback.WaitForResult());
12987 const HttpResponseInfo* response = trans->GetResponseInfo();
12988 ASSERT_TRUE(response != NULL);
12989 ASSERT_TRUE(response->headers.get() != NULL);
12990 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12991 EXPECT_TRUE(response->was_fetched_via_spdy);
12992 EXPECT_TRUE(response->was_npn_negotiated);
12994 std::string response_data;
12995 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12996 EXPECT_EQ("hello!", response_data);
12997 trans.reset();
12998 EXPECT_TRUE(
12999 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
13001 HostPortPair host_port_pair_b("www.b.com", 443);
13002 SpdySessionKey spdy_session_key_b(
13003 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
13004 EXPECT_FALSE(
13005 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
13006 HttpRequestInfo request2;
13007 request2.method = "GET";
13008 request2.url = GURL("https://www.b.com/");
13009 request2.load_flags = 0;
13010 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13012 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
13013 EXPECT_EQ(ERR_IO_PENDING, rv);
13014 EXPECT_EQ(OK, callback.WaitForResult());
13016 response = trans->GetResponseInfo();
13017 ASSERT_TRUE(response != NULL);
13018 ASSERT_TRUE(response->headers.get() != NULL);
13019 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13020 EXPECT_TRUE(response->was_fetched_via_spdy);
13021 EXPECT_TRUE(response->was_npn_negotiated);
13022 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
13023 EXPECT_EQ("hello!", response_data);
13024 EXPECT_FALSE(
13025 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
13026 EXPECT_TRUE(
13027 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
13029 HostPortPair host_port_pair_a1("www.a.com", 80);
13030 SpdySessionKey spdy_session_key_a1(
13031 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
13032 EXPECT_FALSE(
13033 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
13034 HttpRequestInfo request3;
13035 request3.method = "GET";
13036 request3.url = GURL("http://www.a.com/");
13037 request3.load_flags = 0;
13038 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13040 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
13041 EXPECT_EQ(ERR_IO_PENDING, rv);
13042 EXPECT_EQ(OK, callback.WaitForResult());
13044 response = trans->GetResponseInfo();
13045 ASSERT_TRUE(response != NULL);
13046 ASSERT_TRUE(response->headers.get() != NULL);
13047 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13048 EXPECT_FALSE(response->was_fetched_via_spdy);
13049 EXPECT_FALSE(response->was_npn_negotiated);
13050 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
13051 EXPECT_EQ("hello!", response_data);
13052 EXPECT_FALSE(
13053 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
13054 EXPECT_FALSE(
13055 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
13058 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
13059 HttpRequestInfo request;
13060 request.method = "GET";
13061 request.url = GURL("http://www.example.org/");
13062 request.load_flags = 0;
13064 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13065 scoped_ptr<HttpTransaction> trans(
13066 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13068 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
13069 StaticSocketDataProvider data;
13070 data.set_connect_data(mock_connect);
13071 session_deps_.socket_factory->AddSocketDataProvider(&data);
13073 TestCompletionCallback callback;
13075 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13076 EXPECT_EQ(ERR_IO_PENDING, rv);
13078 rv = callback.WaitForResult();
13079 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
13081 // We don't care whether this succeeds or fails, but it shouldn't crash.
13082 HttpRequestHeaders request_headers;
13083 trans->GetFullRequestHeaders(&request_headers);
13085 ConnectionAttempts attempts;
13086 trans->GetConnectionAttempts(&attempts);
13087 ASSERT_EQ(1u, attempts.size());
13088 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
13091 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
13092 HttpRequestInfo request;
13093 request.method = "GET";
13094 request.url = GURL("http://www.example.org/");
13095 request.load_flags = 0;
13097 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13098 scoped_ptr<HttpTransaction> trans(
13099 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13101 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13102 StaticSocketDataProvider data;
13103 data.set_connect_data(mock_connect);
13104 session_deps_.socket_factory->AddSocketDataProvider(&data);
13106 TestCompletionCallback callback;
13108 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13109 EXPECT_EQ(ERR_IO_PENDING, rv);
13111 rv = callback.WaitForResult();
13112 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
13114 // We don't care whether this succeeds or fails, but it shouldn't crash.
13115 HttpRequestHeaders request_headers;
13116 trans->GetFullRequestHeaders(&request_headers);
13118 ConnectionAttempts attempts;
13119 trans->GetConnectionAttempts(&attempts);
13120 ASSERT_EQ(1u, attempts.size());
13121 EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
13124 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
13125 HttpRequestInfo request;
13126 request.method = "GET";
13127 request.url = GURL("http://www.example.org/");
13128 request.load_flags = 0;
13130 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13131 scoped_ptr<HttpTransaction> trans(
13132 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13134 MockWrite data_writes[] = {
13135 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13137 MockRead data_reads[] = {
13138 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
13141 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13142 data_writes, arraysize(data_writes));
13143 session_deps_.socket_factory->AddSocketDataProvider(&data);
13145 TestCompletionCallback callback;
13147 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13148 EXPECT_EQ(ERR_IO_PENDING, rv);
13150 rv = callback.WaitForResult();
13151 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13153 HttpRequestHeaders request_headers;
13154 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13155 EXPECT_TRUE(request_headers.HasHeader("Host"));
13158 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
13159 HttpRequestInfo request;
13160 request.method = "GET";
13161 request.url = GURL("http://www.example.org/");
13162 request.load_flags = 0;
13164 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13165 scoped_ptr<HttpTransaction> trans(
13166 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13168 MockWrite data_writes[] = {
13169 MockWrite(ASYNC, ERR_CONNECTION_RESET),
13171 MockRead data_reads[] = {
13172 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
13175 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13176 data_writes, arraysize(data_writes));
13177 session_deps_.socket_factory->AddSocketDataProvider(&data);
13179 TestCompletionCallback callback;
13181 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13182 EXPECT_EQ(ERR_IO_PENDING, rv);
13184 rv = callback.WaitForResult();
13185 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13187 HttpRequestHeaders request_headers;
13188 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13189 EXPECT_TRUE(request_headers.HasHeader("Host"));
13192 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
13193 HttpRequestInfo request;
13194 request.method = "GET";
13195 request.url = GURL("http://www.example.org/");
13196 request.load_flags = 0;
13198 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13199 scoped_ptr<HttpTransaction> trans(
13200 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13202 MockWrite data_writes[] = {
13203 MockWrite(
13204 "GET / HTTP/1.1\r\n"
13205 "Host: www.example.org\r\n"
13206 "Connection: keep-alive\r\n\r\n"),
13208 MockRead data_reads[] = {
13209 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
13212 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13213 data_writes, arraysize(data_writes));
13214 session_deps_.socket_factory->AddSocketDataProvider(&data);
13216 TestCompletionCallback callback;
13218 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13219 EXPECT_EQ(ERR_IO_PENDING, rv);
13221 rv = callback.WaitForResult();
13222 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13224 HttpRequestHeaders request_headers;
13225 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13226 EXPECT_TRUE(request_headers.HasHeader("Host"));
13229 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
13230 HttpRequestInfo request;
13231 request.method = "GET";
13232 request.url = GURL("http://www.example.org/");
13233 request.load_flags = 0;
13235 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13236 scoped_ptr<HttpTransaction> trans(
13237 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13239 MockWrite data_writes[] = {
13240 MockWrite(
13241 "GET / HTTP/1.1\r\n"
13242 "Host: www.example.org\r\n"
13243 "Connection: keep-alive\r\n\r\n"),
13245 MockRead data_reads[] = {
13246 MockRead(ASYNC, ERR_CONNECTION_RESET),
13249 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13250 data_writes, arraysize(data_writes));
13251 session_deps_.socket_factory->AddSocketDataProvider(&data);
13253 TestCompletionCallback callback;
13255 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13256 EXPECT_EQ(ERR_IO_PENDING, rv);
13258 rv = callback.WaitForResult();
13259 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13261 HttpRequestHeaders request_headers;
13262 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13263 EXPECT_TRUE(request_headers.HasHeader("Host"));
13266 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
13267 HttpRequestInfo request;
13268 request.method = "GET";
13269 request.url = GURL("http://www.example.org/");
13270 request.load_flags = 0;
13271 request.extra_headers.SetHeader("X-Foo", "bar");
13273 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13274 scoped_ptr<HttpTransaction> trans(
13275 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13277 MockWrite data_writes[] = {
13278 MockWrite(
13279 "GET / HTTP/1.1\r\n"
13280 "Host: www.example.org\r\n"
13281 "Connection: keep-alive\r\n"
13282 "X-Foo: bar\r\n\r\n"),
13284 MockRead data_reads[] = {
13285 MockRead("HTTP/1.1 200 OK\r\n"
13286 "Content-Length: 5\r\n\r\n"
13287 "hello"),
13288 MockRead(ASYNC, ERR_UNEXPECTED),
13291 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13292 data_writes, arraysize(data_writes));
13293 session_deps_.socket_factory->AddSocketDataProvider(&data);
13295 TestCompletionCallback callback;
13297 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13298 EXPECT_EQ(ERR_IO_PENDING, rv);
13300 rv = callback.WaitForResult();
13301 EXPECT_EQ(OK, rv);
13303 HttpRequestHeaders request_headers;
13304 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13305 std::string foo;
13306 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
13307 EXPECT_EQ("bar", foo);
13310 namespace {
13312 // Fake HttpStream that simply records calls to SetPriority().
13313 class FakeStream : public HttpStream,
13314 public base::SupportsWeakPtr<FakeStream> {
13315 public:
13316 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
13317 ~FakeStream() override {}
13319 RequestPriority priority() const { return priority_; }
13321 int InitializeStream(const HttpRequestInfo* request_info,
13322 RequestPriority priority,
13323 const BoundNetLog& net_log,
13324 const CompletionCallback& callback) override {
13325 return ERR_IO_PENDING;
13328 int SendRequest(const HttpRequestHeaders& request_headers,
13329 HttpResponseInfo* response,
13330 const CompletionCallback& callback) override {
13331 ADD_FAILURE();
13332 return ERR_UNEXPECTED;
13335 int ReadResponseHeaders(const CompletionCallback& callback) override {
13336 ADD_FAILURE();
13337 return ERR_UNEXPECTED;
13340 int ReadResponseBody(IOBuffer* buf,
13341 int buf_len,
13342 const CompletionCallback& callback) override {
13343 ADD_FAILURE();
13344 return ERR_UNEXPECTED;
13347 void Close(bool not_reusable) override {}
13349 bool IsResponseBodyComplete() const override {
13350 ADD_FAILURE();
13351 return false;
13354 bool IsConnectionReused() const override {
13355 ADD_FAILURE();
13356 return false;
13359 void SetConnectionReused() override { ADD_FAILURE(); }
13361 bool CanReuseConnection() const override { return false; }
13363 int64 GetTotalReceivedBytes() const override {
13364 ADD_FAILURE();
13365 return 0;
13368 int64_t GetTotalSentBytes() const override {
13369 ADD_FAILURE();
13370 return 0;
13373 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13374 ADD_FAILURE();
13375 return false;
13378 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
13380 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13381 ADD_FAILURE();
13384 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
13386 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13388 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
13390 HttpStream* RenewStreamForAuth() override { return NULL; }
13392 private:
13393 RequestPriority priority_;
13395 DISALLOW_COPY_AND_ASSIGN(FakeStream);
13398 // Fake HttpStreamRequest that simply records calls to SetPriority()
13399 // and vends FakeStreams with its current priority.
13400 class FakeStreamRequest : public HttpStreamRequest,
13401 public base::SupportsWeakPtr<FakeStreamRequest> {
13402 public:
13403 FakeStreamRequest(RequestPriority priority,
13404 HttpStreamRequest::Delegate* delegate)
13405 : priority_(priority),
13406 delegate_(delegate),
13407 websocket_stream_create_helper_(NULL) {}
13409 FakeStreamRequest(RequestPriority priority,
13410 HttpStreamRequest::Delegate* delegate,
13411 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
13412 : priority_(priority),
13413 delegate_(delegate),
13414 websocket_stream_create_helper_(create_helper) {}
13416 ~FakeStreamRequest() override {}
13418 RequestPriority priority() const { return priority_; }
13420 const WebSocketHandshakeStreamBase::CreateHelper*
13421 websocket_stream_create_helper() const {
13422 return websocket_stream_create_helper_;
13425 // Create a new FakeStream and pass it to the request's
13426 // delegate. Returns a weak pointer to the FakeStream.
13427 base::WeakPtr<FakeStream> FinishStreamRequest() {
13428 FakeStream* fake_stream = new FakeStream(priority_);
13429 // Do this before calling OnStreamReady() as OnStreamReady() may
13430 // immediately delete |fake_stream|.
13431 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
13432 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
13433 return weak_stream;
13436 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
13437 ADD_FAILURE();
13438 return ERR_UNEXPECTED;
13441 LoadState GetLoadState() const override {
13442 ADD_FAILURE();
13443 return LoadState();
13446 void SetPriority(RequestPriority priority) override { priority_ = priority; }
13448 bool was_npn_negotiated() const override { return false; }
13450 NextProto protocol_negotiated() const override { return kProtoUnknown; }
13452 bool using_spdy() const override { return false; }
13454 const ConnectionAttempts& connection_attempts() const override {
13455 static ConnectionAttempts no_attempts;
13456 return no_attempts;
13459 private:
13460 RequestPriority priority_;
13461 HttpStreamRequest::Delegate* const delegate_;
13462 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
13464 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
13467 // Fake HttpStreamFactory that vends FakeStreamRequests.
13468 class FakeStreamFactory : public HttpStreamFactory {
13469 public:
13470 FakeStreamFactory() {}
13471 ~FakeStreamFactory() override {}
13473 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13474 // RequestStream() (which may be NULL if it was destroyed already).
13475 base::WeakPtr<FakeStreamRequest> last_stream_request() {
13476 return last_stream_request_;
13479 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
13480 RequestPriority priority,
13481 const SSLConfig& server_ssl_config,
13482 const SSLConfig& proxy_ssl_config,
13483 HttpStreamRequest::Delegate* delegate,
13484 const BoundNetLog& net_log) override {
13485 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
13486 last_stream_request_ = fake_request->AsWeakPtr();
13487 return fake_request;
13490 HttpStreamRequest* RequestWebSocketHandshakeStream(
13491 const HttpRequestInfo& info,
13492 RequestPriority priority,
13493 const SSLConfig& server_ssl_config,
13494 const SSLConfig& proxy_ssl_config,
13495 HttpStreamRequest::Delegate* delegate,
13496 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
13497 const BoundNetLog& net_log) override {
13498 FakeStreamRequest* fake_request =
13499 new FakeStreamRequest(priority, delegate, create_helper);
13500 last_stream_request_ = fake_request->AsWeakPtr();
13501 return fake_request;
13504 void PreconnectStreams(int num_streams,
13505 const HttpRequestInfo& info,
13506 const SSLConfig& server_ssl_config,
13507 const SSLConfig& proxy_ssl_config) override {
13508 ADD_FAILURE();
13511 const HostMappingRules* GetHostMappingRules() const override {
13512 ADD_FAILURE();
13513 return NULL;
13516 private:
13517 base::WeakPtr<FakeStreamRequest> last_stream_request_;
13519 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
13522 // TODO(ricea): Maybe unify this with the one in
13523 // url_request_http_job_unittest.cc ?
13524 class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
13525 public:
13526 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
13527 bool using_proxy)
13528 : state_(connection.release(), using_proxy) {}
13530 // Fake implementation of HttpStreamBase methods.
13531 // This ends up being quite "real" because this object has to really send data
13532 // on the mock socket. It might be easier to use the real implementation, but
13533 // the fact that the WebSocket code is not compiled on iOS makes that
13534 // difficult.
13535 int InitializeStream(const HttpRequestInfo* request_info,
13536 RequestPriority priority,
13537 const BoundNetLog& net_log,
13538 const CompletionCallback& callback) override {
13539 state_.Initialize(request_info, priority, net_log, callback);
13540 return OK;
13543 int SendRequest(const HttpRequestHeaders& request_headers,
13544 HttpResponseInfo* response,
13545 const CompletionCallback& callback) override {
13546 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
13547 response, callback);
13550 int ReadResponseHeaders(const CompletionCallback& callback) override {
13551 return parser()->ReadResponseHeaders(callback);
13554 int ReadResponseBody(IOBuffer* buf,
13555 int buf_len,
13556 const CompletionCallback& callback) override {
13557 NOTREACHED();
13558 return ERR_IO_PENDING;
13561 void Close(bool not_reusable) override {
13562 if (parser())
13563 parser()->Close(true);
13566 bool IsResponseBodyComplete() const override {
13567 NOTREACHED();
13568 return false;
13571 bool IsConnectionReused() const override {
13572 NOTREACHED();
13573 return false;
13575 void SetConnectionReused() override { NOTREACHED(); }
13577 bool CanReuseConnection() const override { return false; }
13579 int64 GetTotalReceivedBytes() const override {
13580 NOTREACHED();
13581 return 0;
13584 int64_t GetTotalSentBytes() const override {
13585 NOTREACHED();
13586 return 0;
13589 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
13590 NOTREACHED();
13591 return false;
13594 void GetSSLInfo(SSLInfo* ssl_info) override {}
13596 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
13597 NOTREACHED();
13600 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
13602 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
13604 UploadProgress GetUploadProgress() const override {
13605 NOTREACHED();
13606 return UploadProgress();
13609 HttpStream* RenewStreamForAuth() override {
13610 NOTREACHED();
13611 return nullptr;
13614 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13615 scoped_ptr<WebSocketStream> Upgrade() override {
13616 NOTREACHED();
13617 return scoped_ptr<WebSocketStream>();
13620 private:
13621 HttpStreamParser* parser() const { return state_.parser(); }
13622 HttpBasicState state_;
13624 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
13627 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13628 // worth doing.
13629 class FakeWebSocketStreamCreateHelper :
13630 public WebSocketHandshakeStreamBase::CreateHelper {
13631 public:
13632 WebSocketHandshakeStreamBase* CreateBasicStream(
13633 scoped_ptr<ClientSocketHandle> connection,
13634 bool using_proxy) override {
13635 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
13636 using_proxy);
13639 WebSocketHandshakeStreamBase* CreateSpdyStream(
13640 const base::WeakPtr<SpdySession>& session,
13641 bool use_relative_url) override {
13642 NOTREACHED();
13643 return NULL;
13646 ~FakeWebSocketStreamCreateHelper() override {}
13648 virtual scoped_ptr<WebSocketStream> Upgrade() {
13649 NOTREACHED();
13650 return scoped_ptr<WebSocketStream>();
13654 } // namespace
13656 // Make sure that HttpNetworkTransaction passes on its priority to its
13657 // stream request on start.
13658 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
13659 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13660 HttpNetworkSessionPeer peer(session);
13661 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13662 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13664 HttpNetworkTransaction trans(LOW, session.get());
13666 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
13668 HttpRequestInfo request;
13669 TestCompletionCallback callback;
13670 EXPECT_EQ(ERR_IO_PENDING,
13671 trans.Start(&request, callback.callback(), BoundNetLog()));
13673 base::WeakPtr<FakeStreamRequest> fake_request =
13674 fake_factory->last_stream_request();
13675 ASSERT_TRUE(fake_request != NULL);
13676 EXPECT_EQ(LOW, fake_request->priority());
13679 // Make sure that HttpNetworkTransaction passes on its priority
13680 // updates to its stream request.
13681 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
13682 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13683 HttpNetworkSessionPeer peer(session);
13684 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13685 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13687 HttpNetworkTransaction trans(LOW, session.get());
13689 HttpRequestInfo request;
13690 TestCompletionCallback callback;
13691 EXPECT_EQ(ERR_IO_PENDING,
13692 trans.Start(&request, callback.callback(), BoundNetLog()));
13694 base::WeakPtr<FakeStreamRequest> fake_request =
13695 fake_factory->last_stream_request();
13696 ASSERT_TRUE(fake_request != NULL);
13697 EXPECT_EQ(LOW, fake_request->priority());
13699 trans.SetPriority(LOWEST);
13700 ASSERT_TRUE(fake_request != NULL);
13701 EXPECT_EQ(LOWEST, fake_request->priority());
13704 // Make sure that HttpNetworkTransaction passes on its priority
13705 // updates to its stream.
13706 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
13707 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13708 HttpNetworkSessionPeer peer(session);
13709 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13710 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13712 HttpNetworkTransaction trans(LOW, session.get());
13714 HttpRequestInfo request;
13715 TestCompletionCallback callback;
13716 EXPECT_EQ(ERR_IO_PENDING,
13717 trans.Start(&request, callback.callback(), BoundNetLog()));
13719 base::WeakPtr<FakeStreamRequest> fake_request =
13720 fake_factory->last_stream_request();
13721 ASSERT_TRUE(fake_request != NULL);
13722 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
13723 ASSERT_TRUE(fake_stream != NULL);
13724 EXPECT_EQ(LOW, fake_stream->priority());
13726 trans.SetPriority(LOWEST);
13727 EXPECT_EQ(LOWEST, fake_stream->priority());
13730 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
13731 // The same logic needs to be tested for both ws: and wss: schemes, but this
13732 // test is already parameterised on NextProto, so it uses a loop to verify
13733 // that the different schemes work.
13734 std::string test_cases[] = {"ws://www.example.org/",
13735 "wss://www.example.org/"};
13736 for (size_t i = 0; i < arraysize(test_cases); ++i) {
13737 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13738 HttpNetworkSessionPeer peer(session);
13739 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13740 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13741 peer.SetHttpStreamFactoryForWebSocket(
13742 scoped_ptr<HttpStreamFactory>(fake_factory));
13744 HttpNetworkTransaction trans(LOW, session.get());
13745 trans.SetWebSocketHandshakeStreamCreateHelper(
13746 &websocket_stream_create_helper);
13748 HttpRequestInfo request;
13749 TestCompletionCallback callback;
13750 request.method = "GET";
13751 request.url = GURL(test_cases[i]);
13753 EXPECT_EQ(ERR_IO_PENDING,
13754 trans.Start(&request, callback.callback(), BoundNetLog()));
13756 base::WeakPtr<FakeStreamRequest> fake_request =
13757 fake_factory->last_stream_request();
13758 ASSERT_TRUE(fake_request != NULL);
13759 EXPECT_EQ(&websocket_stream_create_helper,
13760 fake_request->websocket_stream_create_helper());
13764 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13765 // if the transport socket pool is stalled on the global socket limit.
13766 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
13767 ClientSocketPoolManager::set_max_sockets_per_group(
13768 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13769 ClientSocketPoolManager::set_max_sockets_per_pool(
13770 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13772 // Set up SSL request.
13774 HttpRequestInfo ssl_request;
13775 ssl_request.method = "GET";
13776 ssl_request.url = GURL("https://www.example.org/");
13778 MockWrite ssl_writes[] = {
13779 MockWrite(
13780 "GET / HTTP/1.1\r\n"
13781 "Host: www.example.org\r\n"
13782 "Connection: keep-alive\r\n\r\n"),
13784 MockRead ssl_reads[] = {
13785 MockRead("HTTP/1.1 200 OK\r\n"),
13786 MockRead("Content-Length: 11\r\n\r\n"),
13787 MockRead("hello world"),
13788 MockRead(SYNCHRONOUS, OK),
13790 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
13791 ssl_writes, arraysize(ssl_writes));
13792 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13794 SSLSocketDataProvider ssl(ASYNC, OK);
13795 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13797 // Set up HTTP request.
13799 HttpRequestInfo http_request;
13800 http_request.method = "GET";
13801 http_request.url = GURL("http://www.example.org/");
13803 MockWrite http_writes[] = {
13804 MockWrite(
13805 "GET / HTTP/1.1\r\n"
13806 "Host: www.example.org\r\n"
13807 "Connection: keep-alive\r\n\r\n"),
13809 MockRead http_reads[] = {
13810 MockRead("HTTP/1.1 200 OK\r\n"),
13811 MockRead("Content-Length: 7\r\n\r\n"),
13812 MockRead("falafel"),
13813 MockRead(SYNCHRONOUS, OK),
13815 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13816 http_writes, arraysize(http_writes));
13817 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13819 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13821 // Start the SSL request.
13822 TestCompletionCallback ssl_callback;
13823 scoped_ptr<HttpTransaction> ssl_trans(
13824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13825 ASSERT_EQ(ERR_IO_PENDING,
13826 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
13827 BoundNetLog()));
13829 // Start the HTTP request. Pool should stall.
13830 TestCompletionCallback http_callback;
13831 scoped_ptr<HttpTransaction> http_trans(
13832 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13833 ASSERT_EQ(ERR_IO_PENDING,
13834 http_trans->Start(&http_request, http_callback.callback(),
13835 BoundNetLog()));
13836 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13838 // Wait for response from SSL request.
13839 ASSERT_EQ(OK, ssl_callback.WaitForResult());
13840 std::string response_data;
13841 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
13842 EXPECT_EQ("hello world", response_data);
13844 // The SSL socket should automatically be closed, so the HTTP request can
13845 // start.
13846 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13847 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
13849 // The HTTP request can now complete.
13850 ASSERT_EQ(OK, http_callback.WaitForResult());
13851 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13852 EXPECT_EQ("falafel", response_data);
13854 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13857 // Tests that when a SSL connection is established but there's no corresponding
13858 // request that needs it, the new socket is closed if the transport socket pool
13859 // is stalled on the global socket limit.
13860 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
13861 ClientSocketPoolManager::set_max_sockets_per_group(
13862 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13863 ClientSocketPoolManager::set_max_sockets_per_pool(
13864 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13866 // Set up an ssl request.
13868 HttpRequestInfo ssl_request;
13869 ssl_request.method = "GET";
13870 ssl_request.url = GURL("https://www.foopy.com/");
13872 // No data will be sent on the SSL socket.
13873 StaticSocketDataProvider ssl_data;
13874 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13876 SSLSocketDataProvider ssl(ASYNC, OK);
13877 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13879 // Set up HTTP request.
13881 HttpRequestInfo http_request;
13882 http_request.method = "GET";
13883 http_request.url = GURL("http://www.example.org/");
13885 MockWrite http_writes[] = {
13886 MockWrite(
13887 "GET / HTTP/1.1\r\n"
13888 "Host: www.example.org\r\n"
13889 "Connection: keep-alive\r\n\r\n"),
13891 MockRead http_reads[] = {
13892 MockRead("HTTP/1.1 200 OK\r\n"),
13893 MockRead("Content-Length: 7\r\n\r\n"),
13894 MockRead("falafel"),
13895 MockRead(SYNCHRONOUS, OK),
13897 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13898 http_writes, arraysize(http_writes));
13899 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13901 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13903 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13904 // cancelled when a normal transaction is cancelled.
13905 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
13906 SSLConfig ssl_config;
13907 session->ssl_config_service()->GetSSLConfig(&ssl_config);
13908 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
13909 ssl_config);
13910 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13912 // Start the HTTP request. Pool should stall.
13913 TestCompletionCallback http_callback;
13914 scoped_ptr<HttpTransaction> http_trans(
13915 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13916 ASSERT_EQ(ERR_IO_PENDING,
13917 http_trans->Start(&http_request, http_callback.callback(),
13918 BoundNetLog()));
13919 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13921 // The SSL connection will automatically be closed once the connection is
13922 // established, to let the HTTP request start.
13923 ASSERT_EQ(OK, http_callback.WaitForResult());
13924 std::string response_data;
13925 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13926 EXPECT_EQ("falafel", response_data);
13928 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13931 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
13932 ScopedVector<UploadElementReader> element_readers;
13933 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13934 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13936 HttpRequestInfo request;
13937 request.method = "POST";
13938 request.url = GURL("http://www.foo.com/");
13939 request.upload_data_stream = &upload_data_stream;
13940 request.load_flags = 0;
13942 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13943 scoped_ptr<HttpTransaction> trans(
13944 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13945 // Send headers successfully, but get an error while sending the body.
13946 MockWrite data_writes[] = {
13947 MockWrite("POST / HTTP/1.1\r\n"
13948 "Host: www.foo.com\r\n"
13949 "Connection: keep-alive\r\n"
13950 "Content-Length: 3\r\n\r\n"),
13951 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13954 MockRead data_reads[] = {
13955 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13956 MockRead("hello world"),
13957 MockRead(SYNCHRONOUS, OK),
13959 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13960 arraysize(data_writes));
13961 session_deps_.socket_factory->AddSocketDataProvider(&data);
13963 TestCompletionCallback callback;
13965 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13966 EXPECT_EQ(ERR_IO_PENDING, rv);
13968 rv = callback.WaitForResult();
13969 EXPECT_EQ(OK, rv);
13971 const HttpResponseInfo* response = trans->GetResponseInfo();
13972 ASSERT_TRUE(response != NULL);
13974 EXPECT_TRUE(response->headers.get() != NULL);
13975 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13977 std::string response_data;
13978 rv = ReadTransaction(trans.get(), &response_data);
13979 EXPECT_EQ(OK, rv);
13980 EXPECT_EQ("hello world", response_data);
13983 // This test makes sure the retry logic doesn't trigger when reading an error
13984 // response from a server that rejected a POST with a CONNECTION_RESET.
13985 TEST_P(HttpNetworkTransactionTest,
13986 PostReadsErrorResponseAfterResetOnReusedSocket) {
13987 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13988 MockWrite data_writes[] = {
13989 MockWrite("GET / HTTP/1.1\r\n"
13990 "Host: www.foo.com\r\n"
13991 "Connection: keep-alive\r\n\r\n"),
13992 MockWrite("POST / HTTP/1.1\r\n"
13993 "Host: www.foo.com\r\n"
13994 "Connection: keep-alive\r\n"
13995 "Content-Length: 3\r\n\r\n"),
13996 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13999 MockRead data_reads[] = {
14000 MockRead("HTTP/1.1 200 Peachy\r\n"
14001 "Content-Length: 14\r\n\r\n"),
14002 MockRead("first response"),
14003 MockRead("HTTP/1.1 400 Not OK\r\n"
14004 "Content-Length: 15\r\n\r\n"),
14005 MockRead("second response"),
14006 MockRead(SYNCHRONOUS, OK),
14008 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14009 arraysize(data_writes));
14010 session_deps_.socket_factory->AddSocketDataProvider(&data);
14012 TestCompletionCallback callback;
14013 HttpRequestInfo request1;
14014 request1.method = "GET";
14015 request1.url = GURL("http://www.foo.com/");
14016 request1.load_flags = 0;
14018 scoped_ptr<HttpTransaction> trans1(
14019 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14020 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
14021 EXPECT_EQ(ERR_IO_PENDING, rv);
14023 rv = callback.WaitForResult();
14024 EXPECT_EQ(OK, rv);
14026 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
14027 ASSERT_TRUE(response1 != NULL);
14029 EXPECT_TRUE(response1->headers.get() != NULL);
14030 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
14032 std::string response_data1;
14033 rv = ReadTransaction(trans1.get(), &response_data1);
14034 EXPECT_EQ(OK, rv);
14035 EXPECT_EQ("first response", response_data1);
14036 // Delete the transaction to release the socket back into the socket pool.
14037 trans1.reset();
14039 ScopedVector<UploadElementReader> element_readers;
14040 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14041 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14043 HttpRequestInfo request2;
14044 request2.method = "POST";
14045 request2.url = GURL("http://www.foo.com/");
14046 request2.upload_data_stream = &upload_data_stream;
14047 request2.load_flags = 0;
14049 scoped_ptr<HttpTransaction> trans2(
14050 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14051 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
14052 EXPECT_EQ(ERR_IO_PENDING, rv);
14054 rv = callback.WaitForResult();
14055 EXPECT_EQ(OK, rv);
14057 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
14058 ASSERT_TRUE(response2 != NULL);
14060 EXPECT_TRUE(response2->headers.get() != NULL);
14061 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
14063 std::string response_data2;
14064 rv = ReadTransaction(trans2.get(), &response_data2);
14065 EXPECT_EQ(OK, rv);
14066 EXPECT_EQ("second response", response_data2);
14069 TEST_P(HttpNetworkTransactionTest,
14070 PostReadsErrorResponseAfterResetPartialBodySent) {
14071 ScopedVector<UploadElementReader> element_readers;
14072 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14073 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14075 HttpRequestInfo request;
14076 request.method = "POST";
14077 request.url = GURL("http://www.foo.com/");
14078 request.upload_data_stream = &upload_data_stream;
14079 request.load_flags = 0;
14081 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14082 scoped_ptr<HttpTransaction> trans(
14083 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14084 // Send headers successfully, but get an error while sending the body.
14085 MockWrite data_writes[] = {
14086 MockWrite("POST / HTTP/1.1\r\n"
14087 "Host: www.foo.com\r\n"
14088 "Connection: keep-alive\r\n"
14089 "Content-Length: 3\r\n\r\n"
14090 "fo"),
14091 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14094 MockRead data_reads[] = {
14095 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14096 MockRead("hello world"),
14097 MockRead(SYNCHRONOUS, OK),
14099 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14100 arraysize(data_writes));
14101 session_deps_.socket_factory->AddSocketDataProvider(&data);
14103 TestCompletionCallback callback;
14105 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14106 EXPECT_EQ(ERR_IO_PENDING, rv);
14108 rv = callback.WaitForResult();
14109 EXPECT_EQ(OK, rv);
14111 const HttpResponseInfo* response = trans->GetResponseInfo();
14112 ASSERT_TRUE(response != NULL);
14114 EXPECT_TRUE(response->headers.get() != NULL);
14115 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14117 std::string response_data;
14118 rv = ReadTransaction(trans.get(), &response_data);
14119 EXPECT_EQ(OK, rv);
14120 EXPECT_EQ("hello world", response_data);
14123 // This tests the more common case than the previous test, where headers and
14124 // body are not merged into a single request.
14125 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
14126 ScopedVector<UploadElementReader> element_readers;
14127 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14128 ChunkedUploadDataStream upload_data_stream(0);
14130 HttpRequestInfo request;
14131 request.method = "POST";
14132 request.url = GURL("http://www.foo.com/");
14133 request.upload_data_stream = &upload_data_stream;
14134 request.load_flags = 0;
14136 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14137 scoped_ptr<HttpTransaction> trans(
14138 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14139 // Send headers successfully, but get an error while sending the body.
14140 MockWrite data_writes[] = {
14141 MockWrite("POST / HTTP/1.1\r\n"
14142 "Host: www.foo.com\r\n"
14143 "Connection: keep-alive\r\n"
14144 "Transfer-Encoding: chunked\r\n\r\n"),
14145 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14148 MockRead data_reads[] = {
14149 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14150 MockRead("hello world"),
14151 MockRead(SYNCHRONOUS, OK),
14153 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14154 arraysize(data_writes));
14155 session_deps_.socket_factory->AddSocketDataProvider(&data);
14157 TestCompletionCallback callback;
14159 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14160 EXPECT_EQ(ERR_IO_PENDING, rv);
14161 // Make sure the headers are sent before adding a chunk. This ensures that
14162 // they can't be merged with the body in a single send. Not currently
14163 // necessary since a chunked body is never merged with headers, but this makes
14164 // the test more future proof.
14165 base::RunLoop().RunUntilIdle();
14167 upload_data_stream.AppendData("last chunk", 10, true);
14169 rv = callback.WaitForResult();
14170 EXPECT_EQ(OK, rv);
14172 const HttpResponseInfo* response = trans->GetResponseInfo();
14173 ASSERT_TRUE(response != NULL);
14175 EXPECT_TRUE(response->headers.get() != NULL);
14176 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14178 std::string response_data;
14179 rv = ReadTransaction(trans.get(), &response_data);
14180 EXPECT_EQ(OK, rv);
14181 EXPECT_EQ("hello world", response_data);
14184 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
14185 ScopedVector<UploadElementReader> element_readers;
14186 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14187 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14189 HttpRequestInfo request;
14190 request.method = "POST";
14191 request.url = GURL("http://www.foo.com/");
14192 request.upload_data_stream = &upload_data_stream;
14193 request.load_flags = 0;
14195 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14196 scoped_ptr<HttpTransaction> trans(
14197 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14199 MockWrite data_writes[] = {
14200 MockWrite("POST / HTTP/1.1\r\n"
14201 "Host: www.foo.com\r\n"
14202 "Connection: keep-alive\r\n"
14203 "Content-Length: 3\r\n\r\n"),
14204 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14207 MockRead data_reads[] = {
14208 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14209 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14210 MockRead("hello world"),
14211 MockRead(SYNCHRONOUS, OK),
14213 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14214 arraysize(data_writes));
14215 session_deps_.socket_factory->AddSocketDataProvider(&data);
14217 TestCompletionCallback callback;
14219 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14220 EXPECT_EQ(ERR_IO_PENDING, rv);
14222 rv = callback.WaitForResult();
14223 EXPECT_EQ(OK, rv);
14225 const HttpResponseInfo* response = trans->GetResponseInfo();
14226 ASSERT_TRUE(response != NULL);
14228 EXPECT_TRUE(response->headers.get() != NULL);
14229 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14231 std::string response_data;
14232 rv = ReadTransaction(trans.get(), &response_data);
14233 EXPECT_EQ(OK, rv);
14234 EXPECT_EQ("hello world", response_data);
14237 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
14238 ScopedVector<UploadElementReader> element_readers;
14239 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14240 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14242 HttpRequestInfo request;
14243 request.method = "POST";
14244 request.url = GURL("http://www.foo.com/");
14245 request.upload_data_stream = &upload_data_stream;
14246 request.load_flags = 0;
14248 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14249 scoped_ptr<HttpTransaction> trans(
14250 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14251 // Send headers successfully, but get an error while sending the body.
14252 MockWrite data_writes[] = {
14253 MockWrite("POST / HTTP/1.1\r\n"
14254 "Host: www.foo.com\r\n"
14255 "Connection: keep-alive\r\n"
14256 "Content-Length: 3\r\n\r\n"),
14257 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14260 MockRead data_reads[] = {
14261 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14262 MockRead("hello world"),
14263 MockRead(SYNCHRONOUS, OK),
14265 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14266 arraysize(data_writes));
14267 session_deps_.socket_factory->AddSocketDataProvider(&data);
14269 TestCompletionCallback callback;
14271 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14272 EXPECT_EQ(ERR_IO_PENDING, rv);
14274 rv = callback.WaitForResult();
14275 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14278 TEST_P(HttpNetworkTransactionTest,
14279 PostIgnoresNonErrorResponseAfterResetAnd100) {
14280 ScopedVector<UploadElementReader> element_readers;
14281 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14282 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14284 HttpRequestInfo request;
14285 request.method = "POST";
14286 request.url = GURL("http://www.foo.com/");
14287 request.upload_data_stream = &upload_data_stream;
14288 request.load_flags = 0;
14290 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14291 scoped_ptr<HttpTransaction> trans(
14292 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14293 // Send headers successfully, but get an error while sending the body.
14294 MockWrite data_writes[] = {
14295 MockWrite("POST / HTTP/1.1\r\n"
14296 "Host: www.foo.com\r\n"
14297 "Connection: keep-alive\r\n"
14298 "Content-Length: 3\r\n\r\n"),
14299 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14302 MockRead data_reads[] = {
14303 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14304 MockRead("HTTP/1.0 302 Redirect\r\n"),
14305 MockRead("Location: http://somewhere-else.com/\r\n"),
14306 MockRead("Content-Length: 0\r\n\r\n"),
14307 MockRead(SYNCHRONOUS, OK),
14309 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14310 arraysize(data_writes));
14311 session_deps_.socket_factory->AddSocketDataProvider(&data);
14313 TestCompletionCallback callback;
14315 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14316 EXPECT_EQ(ERR_IO_PENDING, rv);
14318 rv = callback.WaitForResult();
14319 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14322 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
14323 ScopedVector<UploadElementReader> element_readers;
14324 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14325 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14327 HttpRequestInfo request;
14328 request.method = "POST";
14329 request.url = GURL("http://www.foo.com/");
14330 request.upload_data_stream = &upload_data_stream;
14331 request.load_flags = 0;
14333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14334 scoped_ptr<HttpTransaction> trans(
14335 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14336 // Send headers successfully, but get an error while sending the body.
14337 MockWrite data_writes[] = {
14338 MockWrite("POST / HTTP/1.1\r\n"
14339 "Host: www.foo.com\r\n"
14340 "Connection: keep-alive\r\n"
14341 "Content-Length: 3\r\n\r\n"),
14342 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14345 MockRead data_reads[] = {
14346 MockRead("HTTP 0.9 rocks!"),
14347 MockRead(SYNCHRONOUS, OK),
14349 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14350 arraysize(data_writes));
14351 session_deps_.socket_factory->AddSocketDataProvider(&data);
14353 TestCompletionCallback callback;
14355 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14356 EXPECT_EQ(ERR_IO_PENDING, rv);
14358 rv = callback.WaitForResult();
14359 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14362 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
14363 ScopedVector<UploadElementReader> element_readers;
14364 element_readers.push_back(new UploadBytesElementReader("foo", 3));
14365 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
14367 HttpRequestInfo request;
14368 request.method = "POST";
14369 request.url = GURL("http://www.foo.com/");
14370 request.upload_data_stream = &upload_data_stream;
14371 request.load_flags = 0;
14373 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14374 scoped_ptr<HttpTransaction> trans(
14375 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14376 // Send headers successfully, but get an error while sending the body.
14377 MockWrite data_writes[] = {
14378 MockWrite("POST / HTTP/1.1\r\n"
14379 "Host: www.foo.com\r\n"
14380 "Connection: keep-alive\r\n"
14381 "Content-Length: 3\r\n\r\n"),
14382 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14385 MockRead data_reads[] = {
14386 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14387 MockRead(SYNCHRONOUS, OK),
14389 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14390 arraysize(data_writes));
14391 session_deps_.socket_factory->AddSocketDataProvider(&data);
14393 TestCompletionCallback callback;
14395 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14396 EXPECT_EQ(ERR_IO_PENDING, rv);
14398 rv = callback.WaitForResult();
14399 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14402 // Verify that proxy headers are not sent to the destination server when
14403 // establishing a tunnel for a secure WebSocket connection.
14404 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
14405 HttpRequestInfo request;
14406 request.method = "GET";
14407 request.url = GURL("wss://www.example.org/");
14408 AddWebSocketHeaders(&request.extra_headers);
14410 // Configure against proxy server "myproxy:70".
14411 session_deps_.proxy_service.reset(
14412 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14414 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14416 // Since a proxy is configured, try to establish a tunnel.
14417 MockWrite data_writes[] = {
14418 MockWrite(
14419 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14420 "Host: www.example.org\r\n"
14421 "Proxy-Connection: keep-alive\r\n\r\n"),
14423 // After calling trans->RestartWithAuth(), this is the request we should
14424 // be issuing -- the final header line contains the credentials.
14425 MockWrite(
14426 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14427 "Host: www.example.org\r\n"
14428 "Proxy-Connection: keep-alive\r\n"
14429 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14431 MockWrite(
14432 "GET / HTTP/1.1\r\n"
14433 "Host: www.example.org\r\n"
14434 "Connection: Upgrade\r\n"
14435 "Upgrade: websocket\r\n"
14436 "Origin: http://www.example.org\r\n"
14437 "Sec-WebSocket-Version: 13\r\n"
14438 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14441 // The proxy responds to the connect with a 407, using a persistent
14442 // connection.
14443 MockRead data_reads[] = {
14444 // No credentials.
14445 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14446 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14447 MockRead("Content-Length: 0\r\n"),
14448 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
14450 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14452 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14453 MockRead("Upgrade: websocket\r\n"),
14454 MockRead("Connection: Upgrade\r\n"),
14455 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14458 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14459 arraysize(data_writes));
14460 session_deps_.socket_factory->AddSocketDataProvider(&data);
14461 SSLSocketDataProvider ssl(ASYNC, OK);
14462 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14464 scoped_ptr<HttpTransaction> trans(
14465 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14466 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14467 trans->SetWebSocketHandshakeStreamCreateHelper(
14468 &websocket_stream_create_helper);
14471 TestCompletionCallback callback;
14473 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14474 EXPECT_EQ(ERR_IO_PENDING, rv);
14476 rv = callback.WaitForResult();
14477 EXPECT_EQ(OK, rv);
14480 const HttpResponseInfo* response = trans->GetResponseInfo();
14481 ASSERT_TRUE(response);
14482 ASSERT_TRUE(response->headers.get());
14483 EXPECT_EQ(407, response->headers->response_code());
14486 TestCompletionCallback callback;
14488 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
14489 callback.callback());
14490 EXPECT_EQ(ERR_IO_PENDING, rv);
14492 rv = callback.WaitForResult();
14493 EXPECT_EQ(OK, rv);
14496 response = trans->GetResponseInfo();
14497 ASSERT_TRUE(response);
14498 ASSERT_TRUE(response->headers.get());
14500 EXPECT_EQ(101, response->headers->response_code());
14502 trans.reset();
14503 session->CloseAllConnections();
14506 // Verify that proxy headers are not sent to the destination server when
14507 // establishing a tunnel for an insecure WebSocket connection.
14508 // This requires the authentication info to be injected into the auth cache
14509 // due to crbug.com/395064
14510 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14511 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
14512 HttpRequestInfo request;
14513 request.method = "GET";
14514 request.url = GURL("ws://www.example.org/");
14515 AddWebSocketHeaders(&request.extra_headers);
14517 // Configure against proxy server "myproxy:70".
14518 session_deps_.proxy_service.reset(
14519 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14521 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14523 MockWrite data_writes[] = {
14524 // Try to establish a tunnel for the WebSocket connection, with
14525 // credentials. Because WebSockets have a separate set of socket pools,
14526 // they cannot and will not use the same TCP/IP connection as the
14527 // preflight HTTP request.
14528 MockWrite(
14529 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14530 "Host: www.example.org:80\r\n"
14531 "Proxy-Connection: keep-alive\r\n"
14532 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14534 MockWrite(
14535 "GET / HTTP/1.1\r\n"
14536 "Host: www.example.org\r\n"
14537 "Connection: Upgrade\r\n"
14538 "Upgrade: websocket\r\n"
14539 "Origin: http://www.example.org\r\n"
14540 "Sec-WebSocket-Version: 13\r\n"
14541 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14544 MockRead data_reads[] = {
14545 // HTTP CONNECT with credentials.
14546 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14548 // WebSocket connection established inside tunnel.
14549 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14550 MockRead("Upgrade: websocket\r\n"),
14551 MockRead("Connection: Upgrade\r\n"),
14552 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14555 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14556 arraysize(data_writes));
14557 session_deps_.socket_factory->AddSocketDataProvider(&data);
14559 session->http_auth_cache()->Add(
14560 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
14561 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
14563 scoped_ptr<HttpTransaction> trans(
14564 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14565 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
14566 trans->SetWebSocketHandshakeStreamCreateHelper(
14567 &websocket_stream_create_helper);
14569 TestCompletionCallback callback;
14571 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14572 EXPECT_EQ(ERR_IO_PENDING, rv);
14574 rv = callback.WaitForResult();
14575 EXPECT_EQ(OK, rv);
14577 const HttpResponseInfo* response = trans->GetResponseInfo();
14578 ASSERT_TRUE(response);
14579 ASSERT_TRUE(response->headers.get());
14581 EXPECT_EQ(101, response->headers->response_code());
14583 trans.reset();
14584 session->CloseAllConnections();
14587 } // namespace net