Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blobe3d3a59641b7fef5a0a133d07fb718af7b4ddba7
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
8 #include <stdarg.h>
9 #include <string>
10 #include <vector>
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/json/json_writer.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/test/test_file_util.h"
23 #include "net/base/auth.h"
24 #include "net/base/capturing_net_log.h"
25 #include "net/base/completion_callback.h"
26 #include "net/base/load_timing_info.h"
27 #include "net/base/load_timing_info_test_util.h"
28 #include "net/base/net_log.h"
29 #include "net/base/net_log_unittest.h"
30 #include "net/base/request_priority.h"
31 #include "net/base/test_completion_callback.h"
32 #include "net/base/test_data_directory.h"
33 #include "net/base/upload_bytes_element_reader.h"
34 #include "net/base/upload_data_stream.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_stream.h"
44 #include "net/http/http_network_session.h"
45 #include "net/http/http_network_session_peer.h"
46 #include "net/http/http_server_properties_impl.h"
47 #include "net/http/http_stream.h"
48 #include "net/http/http_stream_factory.h"
49 #include "net/http/http_transaction_unittest.h"
50 #include "net/proxy/proxy_config_service_fixed.h"
51 #include "net/proxy/proxy_info.h"
52 #include "net/proxy/proxy_resolver.h"
53 #include "net/proxy/proxy_service.h"
54 #include "net/socket/client_socket_factory.h"
55 #include "net/socket/client_socket_pool_manager.h"
56 #include "net/socket/mock_client_socket_pool_manager.h"
57 #include "net/socket/next_proto.h"
58 #include "net/socket/socket_test_util.h"
59 #include "net/socket/ssl_client_socket.h"
60 #include "net/spdy/spdy_framer.h"
61 #include "net/spdy/spdy_session.h"
62 #include "net/spdy/spdy_session_pool.h"
63 #include "net/spdy/spdy_test_util_common.h"
64 #include "net/ssl/ssl_cert_request_info.h"
65 #include "net/ssl/ssl_config_service.h"
66 #include "net/ssl/ssl_config_service_defaults.h"
67 #include "net/ssl/ssl_info.h"
68 #include "net/test/cert_test_util.h"
69 #include "net/websockets/websocket_handshake_stream_base.h"
70 #include "testing/gtest/include/gtest/gtest.h"
71 #include "testing/platform_test.h"
72 #include "url/gurl.h"
74 using base::ASCIIToUTF16;
76 //-----------------------------------------------------------------------------
78 namespace {
80 const base::string16 kBar(ASCIIToUTF16("bar"));
81 const base::string16 kBar2(ASCIIToUTF16("bar2"));
82 const base::string16 kBar3(ASCIIToUTF16("bar3"));
83 const base::string16 kBaz(ASCIIToUTF16("baz"));
84 const base::string16 kFirst(ASCIIToUTF16("first"));
85 const base::string16 kFoo(ASCIIToUTF16("foo"));
86 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
87 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
88 const base::string16 kFou(ASCIIToUTF16("fou"));
89 const base::string16 kSecond(ASCIIToUTF16("second"));
90 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
91 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
93 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
94 return session->GetTransportSocketPool(
95 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
98 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
99 return session->GetSSLSocketPool(
100 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
103 bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) {
104 return session->GetTransportSocketPool(
105 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled();
108 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
109 // a JSONified list of headers as a single string. Uses single quotes instead
110 // of double quotes for easier comparison. Returns false on failure.
111 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
112 if (!params)
113 return false;
114 base::ListValue* header_list;
115 if (!params->GetList("headers", &header_list))
116 return false;
117 std::string double_quote_headers;
118 base::JSONWriter::Write(header_list, &double_quote_headers);
119 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
120 return true;
123 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
124 // used.
125 void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
126 EXPECT_TRUE(load_timing_info.socket_reused);
127 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
129 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
130 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
132 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
133 EXPECT_FALSE(load_timing_info.send_start.is_null());
135 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
137 // Set at a higher level.
138 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
139 EXPECT_TRUE(load_timing_info.request_start.is_null());
140 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
143 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
144 // used.
145 void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
146 int connect_timing_flags) {
147 EXPECT_FALSE(load_timing_info.socket_reused);
148 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
150 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
151 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
153 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
154 connect_timing_flags);
155 EXPECT_LE(load_timing_info.connect_timing.connect_end,
156 load_timing_info.send_start);
158 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
160 // Set at a higher level.
161 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
162 EXPECT_TRUE(load_timing_info.request_start.is_null());
163 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
166 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
167 // used.
168 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
169 EXPECT_TRUE(load_timing_info.socket_reused);
170 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
172 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
174 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
175 EXPECT_LE(load_timing_info.proxy_resolve_start,
176 load_timing_info.proxy_resolve_end);
177 EXPECT_LE(load_timing_info.proxy_resolve_end,
178 load_timing_info.send_start);
179 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
181 // Set at a higher level.
182 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
183 EXPECT_TRUE(load_timing_info.request_start.is_null());
184 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
187 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
188 // used.
189 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
190 int connect_timing_flags) {
191 EXPECT_FALSE(load_timing_info.socket_reused);
192 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
194 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
195 EXPECT_LE(load_timing_info.proxy_resolve_start,
196 load_timing_info.proxy_resolve_end);
197 EXPECT_LE(load_timing_info.proxy_resolve_end,
198 load_timing_info.connect_timing.connect_start);
199 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
200 connect_timing_flags);
201 EXPECT_LE(load_timing_info.connect_timing.connect_end,
202 load_timing_info.send_start);
204 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
206 // Set at a higher level.
207 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
208 EXPECT_TRUE(load_timing_info.request_start.is_null());
209 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
212 } // namespace
214 namespace net {
216 namespace {
218 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
219 return SpdySessionDependencies::SpdyCreateSession(session_deps);
222 } // namespace
224 class HttpNetworkTransactionTest
225 : public PlatformTest,
226 public ::testing::WithParamInterface<NextProto> {
227 public:
228 virtual ~HttpNetworkTransactionTest() {
229 // Important to restore the per-pool limit first, since the pool limit must
230 // always be greater than group limit, and the tests reduce both limits.
231 ClientSocketPoolManager::set_max_sockets_per_pool(
232 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
233 ClientSocketPoolManager::set_max_sockets_per_group(
234 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
237 protected:
238 HttpNetworkTransactionTest()
239 : spdy_util_(GetParam()),
240 session_deps_(GetParam()),
241 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
242 HttpNetworkSession::NORMAL_SOCKET_POOL)),
243 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
244 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
247 struct SimpleGetHelperResult {
248 int rv;
249 std::string status_line;
250 std::string response_data;
251 int64 totalReceivedBytes;
252 LoadTimingInfo load_timing_info;
255 virtual void SetUp() {
256 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
257 base::MessageLoop::current()->RunUntilIdle();
260 virtual void TearDown() {
261 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
262 base::MessageLoop::current()->RunUntilIdle();
263 // Empty the current queue.
264 base::MessageLoop::current()->RunUntilIdle();
265 PlatformTest::TearDown();
266 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
267 base::MessageLoop::current()->RunUntilIdle();
268 HttpStreamFactory::set_use_alternate_protocols(false);
269 HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
272 // This is the expected return from a current server advertising SPDY.
273 std::string GetAlternateProtocolHttpHeader() {
274 return
275 std::string("Alternate-Protocol: 443:") +
276 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
277 "\r\n\r\n";
280 // Either |write_failure| specifies a write failure or |read_failure|
281 // specifies a read failure when using a reused socket. In either case, the
282 // failure should cause the network transaction to resend the request, and the
283 // other argument should be NULL.
284 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
285 const MockRead* read_failure);
287 // Either |write_failure| specifies a write failure or |read_failure|
288 // specifies a read failure when using a reused socket. In either case, the
289 // failure should cause the network transaction to resend the request, and the
290 // other argument should be NULL.
291 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
292 const MockRead* read_failure,
293 bool use_spdy);
295 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
296 size_t data_count) {
297 SimpleGetHelperResult out;
299 HttpRequestInfo request;
300 request.method = "GET";
301 request.url = GURL("http://www.google.com/");
302 request.load_flags = 0;
304 CapturingBoundNetLog log;
305 session_deps_.net_log = log.bound().net_log();
306 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
307 scoped_ptr<HttpTransaction> trans(
308 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
310 for (size_t i = 0; i < data_count; ++i) {
311 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
314 TestCompletionCallback callback;
316 EXPECT_TRUE(log.bound().IsLogging());
317 int rv = trans->Start(&request, callback.callback(), log.bound());
318 EXPECT_EQ(ERR_IO_PENDING, rv);
320 out.rv = callback.WaitForResult();
322 // Even in the failure cases that use this function, connections are always
323 // successfully established before the error.
324 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
325 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
327 if (out.rv != OK)
328 return out;
330 const HttpResponseInfo* response = trans->GetResponseInfo();
331 // Can't use ASSERT_* inside helper functions like this, so
332 // return an error.
333 if (response == NULL || response->headers.get() == NULL) {
334 out.rv = ERR_UNEXPECTED;
335 return out;
337 out.status_line = response->headers->GetStatusLine();
339 EXPECT_EQ("127.0.0.1", response->socket_address.host());
340 EXPECT_EQ(80, response->socket_address.port());
342 rv = ReadTransaction(trans.get(), &out.response_data);
343 EXPECT_EQ(OK, rv);
345 net::CapturingNetLog::CapturedEntryList entries;
346 log.GetEntries(&entries);
347 size_t pos = ExpectLogContainsSomewhere(
348 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
349 NetLog::PHASE_NONE);
350 ExpectLogContainsSomewhere(
351 entries, pos,
352 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
353 NetLog::PHASE_NONE);
355 std::string line;
356 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
357 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
359 HttpRequestHeaders request_headers;
360 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
361 std::string value;
362 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
363 EXPECT_EQ("www.google.com", value);
364 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
365 EXPECT_EQ("keep-alive", value);
367 std::string response_headers;
368 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
369 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
370 response_headers);
372 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
373 return out;
376 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
377 size_t reads_count) {
378 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
379 StaticSocketDataProvider* data[] = { &reads };
380 return SimpleGetHelperForData(data, 1);
383 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
384 int64 size = 0;
385 for (size_t i = 0; i < reads_count; ++i)
386 size += data_reads[i].data_len;
387 return size;
390 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
391 int expected_status);
393 void ConnectStatusHelper(const MockRead& status);
395 void BypassHostCacheOnRefreshHelper(int load_flags);
397 void CheckErrorIsPassedBack(int error, IoMode mode);
399 SpdyTestUtil spdy_util_;
400 SpdySessionDependencies session_deps_;
402 // Original socket limits. Some tests set these. Safest to always restore
403 // them once each test has been run.
404 int old_max_group_sockets_;
405 int old_max_pool_sockets_;
408 INSTANTIATE_TEST_CASE_P(
409 NextProto,
410 HttpNetworkTransactionTest,
411 testing::Values(kProtoDeprecatedSPDY2,
412 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
414 namespace {
416 class BeforeNetworkStartHandler {
417 public:
418 explicit BeforeNetworkStartHandler(bool defer)
419 : defer_on_before_network_start_(defer),
420 observed_before_network_start_(false) {}
422 void OnBeforeNetworkStart(bool* defer) {
423 *defer = defer_on_before_network_start_;
424 observed_before_network_start_ = true;
427 bool observed_before_network_start() const {
428 return observed_before_network_start_;
431 private:
432 const bool defer_on_before_network_start_;
433 bool observed_before_network_start_;
435 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
438 // Fill |str| with a long header list that consumes >= |size| bytes.
439 void FillLargeHeadersString(std::string* str, int size) {
440 const char* row =
441 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
442 const int sizeof_row = strlen(row);
443 const int num_rows = static_cast<int>(
444 ceil(static_cast<float>(size) / sizeof_row));
445 const int sizeof_data = num_rows * sizeof_row;
446 DCHECK(sizeof_data >= size);
447 str->reserve(sizeof_data);
449 for (int i = 0; i < num_rows; ++i)
450 str->append(row, sizeof_row);
453 // Alternative functions that eliminate randomness and dependency on the local
454 // host name so that the generated NTLM messages are reproducible.
455 void MockGenerateRandom1(uint8* output, size_t n) {
456 static const uint8 bytes[] = {
457 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
459 static size_t current_byte = 0;
460 for (size_t i = 0; i < n; ++i) {
461 output[i] = bytes[current_byte++];
462 current_byte %= arraysize(bytes);
466 void MockGenerateRandom2(uint8* output, size_t n) {
467 static const uint8 bytes[] = {
468 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
469 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
471 static size_t current_byte = 0;
472 for (size_t i = 0; i < n; ++i) {
473 output[i] = bytes[current_byte++];
474 current_byte %= arraysize(bytes);
478 std::string MockGetHostName() {
479 return "WTC-WIN7";
482 template<typename ParentPool>
483 class CaptureGroupNameSocketPool : public ParentPool {
484 public:
485 CaptureGroupNameSocketPool(HostResolver* host_resolver,
486 CertVerifier* cert_verifier);
488 const std::string last_group_name_received() const {
489 return last_group_name_;
492 virtual int RequestSocket(const std::string& group_name,
493 const void* socket_params,
494 RequestPriority priority,
495 ClientSocketHandle* handle,
496 const CompletionCallback& callback,
497 const BoundNetLog& net_log) {
498 last_group_name_ = group_name;
499 return ERR_IO_PENDING;
501 virtual void CancelRequest(const std::string& group_name,
502 ClientSocketHandle* handle) {}
503 virtual void ReleaseSocket(const std::string& group_name,
504 scoped_ptr<StreamSocket> socket,
505 int id) {}
506 virtual void CloseIdleSockets() {}
507 virtual int IdleSocketCount() const {
508 return 0;
510 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
511 return 0;
513 virtual LoadState GetLoadState(const std::string& group_name,
514 const ClientSocketHandle* handle) const {
515 return LOAD_STATE_IDLE;
517 virtual base::TimeDelta ConnectionTimeout() const {
518 return base::TimeDelta();
521 private:
522 std::string last_group_name_;
525 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
526 CaptureGroupNameTransportSocketPool;
527 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
528 CaptureGroupNameHttpProxySocketPool;
529 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
530 CaptureGroupNameSOCKSSocketPool;
531 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
532 CaptureGroupNameSSLSocketPool;
534 template<typename ParentPool>
535 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
536 HostResolver* host_resolver,
537 CertVerifier* /* cert_verifier */)
538 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
540 template<>
541 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
542 HostResolver* host_resolver,
543 CertVerifier* /* cert_verifier */)
544 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
546 template <>
547 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
548 HostResolver* host_resolver,
549 CertVerifier* cert_verifier)
550 : SSLClientSocketPool(0,
552 NULL,
553 host_resolver,
554 cert_verifier,
555 NULL,
556 NULL,
557 NULL,
558 std::string(),
559 NULL,
560 NULL,
561 NULL,
562 NULL,
563 NULL,
564 NULL) {}
566 //-----------------------------------------------------------------------------
568 // Helper functions for validating that AuthChallengeInfo's are correctly
569 // configured for common cases.
570 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
571 if (!auth_challenge)
572 return false;
573 EXPECT_FALSE(auth_challenge->is_proxy);
574 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
575 EXPECT_EQ("MyRealm1", auth_challenge->realm);
576 EXPECT_EQ("basic", auth_challenge->scheme);
577 return true;
580 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
581 if (!auth_challenge)
582 return false;
583 EXPECT_TRUE(auth_challenge->is_proxy);
584 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
585 EXPECT_EQ("MyRealm1", auth_challenge->realm);
586 EXPECT_EQ("basic", auth_challenge->scheme);
587 return true;
590 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
591 if (!auth_challenge)
592 return false;
593 EXPECT_FALSE(auth_challenge->is_proxy);
594 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
595 EXPECT_EQ("digestive", auth_challenge->realm);
596 EXPECT_EQ("digest", auth_challenge->scheme);
597 return true;
600 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
601 if (!auth_challenge)
602 return false;
603 EXPECT_FALSE(auth_challenge->is_proxy);
604 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
605 EXPECT_EQ(std::string(), auth_challenge->realm);
606 EXPECT_EQ("ntlm", auth_challenge->scheme);
607 return true;
610 } // namespace
612 TEST_P(HttpNetworkTransactionTest, Basic) {
613 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
614 scoped_ptr<HttpTransaction> trans(
615 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
618 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
619 MockRead data_reads[] = {
620 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
621 MockRead("hello world"),
622 MockRead(SYNCHRONOUS, OK),
624 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
625 arraysize(data_reads));
626 EXPECT_EQ(OK, out.rv);
627 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
628 EXPECT_EQ("hello world", out.response_data);
629 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
630 EXPECT_EQ(reads_size, out.totalReceivedBytes);
633 // Response with no status line.
634 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
635 MockRead data_reads[] = {
636 MockRead("hello world"),
637 MockRead(SYNCHRONOUS, OK),
639 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
640 arraysize(data_reads));
641 EXPECT_EQ(OK, out.rv);
642 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
643 EXPECT_EQ("hello world", out.response_data);
644 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
645 EXPECT_EQ(reads_size, out.totalReceivedBytes);
648 // Allow up to 4 bytes of junk to precede status line.
649 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
650 MockRead data_reads[] = {
651 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
652 MockRead(SYNCHRONOUS, OK),
654 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
655 arraysize(data_reads));
656 EXPECT_EQ(OK, out.rv);
657 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
658 EXPECT_EQ("DATA", out.response_data);
659 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
660 EXPECT_EQ(reads_size, out.totalReceivedBytes);
663 // Allow up to 4 bytes of junk to precede status line.
664 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
665 MockRead data_reads[] = {
666 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
667 MockRead(SYNCHRONOUS, OK),
669 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
670 arraysize(data_reads));
671 EXPECT_EQ(OK, out.rv);
672 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
673 EXPECT_EQ("DATA", out.response_data);
674 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
675 EXPECT_EQ(reads_size, out.totalReceivedBytes);
678 // Beyond 4 bytes of slop and it should fail to find a status line.
679 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
680 MockRead data_reads[] = {
681 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
682 MockRead(SYNCHRONOUS, OK),
684 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
685 arraysize(data_reads));
686 EXPECT_EQ(OK, out.rv);
687 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
688 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
689 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
690 EXPECT_EQ(reads_size, out.totalReceivedBytes);
693 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
694 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
695 MockRead data_reads[] = {
696 MockRead("\n"),
697 MockRead("\n"),
698 MockRead("Q"),
699 MockRead("J"),
700 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
701 MockRead(SYNCHRONOUS, OK),
703 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
704 arraysize(data_reads));
705 EXPECT_EQ(OK, out.rv);
706 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
707 EXPECT_EQ("DATA", out.response_data);
708 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
709 EXPECT_EQ(reads_size, out.totalReceivedBytes);
712 // Close the connection before enough bytes to have a status line.
713 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
714 MockRead data_reads[] = {
715 MockRead("HTT"),
716 MockRead(SYNCHRONOUS, OK),
718 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
719 arraysize(data_reads));
720 EXPECT_EQ(OK, out.rv);
721 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
722 EXPECT_EQ("HTT", out.response_data);
723 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
724 EXPECT_EQ(reads_size, out.totalReceivedBytes);
727 // Simulate a 204 response, lacking a Content-Length header, sent over a
728 // persistent connection. The response should still terminate since a 204
729 // cannot have a response body.
730 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
731 char junk[] = "junk";
732 MockRead data_reads[] = {
733 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
734 MockRead(junk), // Should not be read!!
735 MockRead(SYNCHRONOUS, OK),
737 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
738 arraysize(data_reads));
739 EXPECT_EQ(OK, out.rv);
740 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
741 EXPECT_EQ("", out.response_data);
742 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
743 int64 response_size = reads_size - strlen(junk);
744 EXPECT_EQ(response_size, out.totalReceivedBytes);
747 // A simple request using chunked encoding with some extra data after.
748 // (Like might be seen in a pipelined response.)
749 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
750 std::string final_chunk = "0\r\n\r\n";
751 std::string extra_data = "HTTP/1.1 200 OK\r\n";
752 std::string last_read = final_chunk + extra_data;
753 MockRead data_reads[] = {
754 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
755 MockRead("5\r\nHello\r\n"),
756 MockRead("1\r\n"),
757 MockRead(" \r\n"),
758 MockRead("5\r\nworld\r\n"),
759 MockRead(last_read.data()),
760 MockRead(SYNCHRONOUS, OK),
762 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
763 arraysize(data_reads));
764 EXPECT_EQ(OK, out.rv);
765 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
766 EXPECT_EQ("Hello world", out.response_data);
767 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
768 int64 response_size = reads_size - extra_data.size();
769 EXPECT_EQ(response_size, out.totalReceivedBytes);
772 // Next tests deal with http://crbug.com/56344.
774 TEST_P(HttpNetworkTransactionTest,
775 MultipleContentLengthHeadersNoTransferEncoding) {
776 MockRead data_reads[] = {
777 MockRead("HTTP/1.1 200 OK\r\n"),
778 MockRead("Content-Length: 10\r\n"),
779 MockRead("Content-Length: 5\r\n\r\n"),
781 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
782 arraysize(data_reads));
783 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
786 TEST_P(HttpNetworkTransactionTest,
787 DuplicateContentLengthHeadersNoTransferEncoding) {
788 MockRead data_reads[] = {
789 MockRead("HTTP/1.1 200 OK\r\n"),
790 MockRead("Content-Length: 5\r\n"),
791 MockRead("Content-Length: 5\r\n\r\n"),
792 MockRead("Hello"),
794 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
795 arraysize(data_reads));
796 EXPECT_EQ(OK, out.rv);
797 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
798 EXPECT_EQ("Hello", out.response_data);
801 TEST_P(HttpNetworkTransactionTest,
802 ComplexContentLengthHeadersNoTransferEncoding) {
803 // More than 2 dupes.
805 MockRead data_reads[] = {
806 MockRead("HTTP/1.1 200 OK\r\n"),
807 MockRead("Content-Length: 5\r\n"),
808 MockRead("Content-Length: 5\r\n"),
809 MockRead("Content-Length: 5\r\n\r\n"),
810 MockRead("Hello"),
812 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
813 arraysize(data_reads));
814 EXPECT_EQ(OK, out.rv);
815 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
816 EXPECT_EQ("Hello", out.response_data);
818 // HTTP/1.0
820 MockRead data_reads[] = {
821 MockRead("HTTP/1.0 200 OK\r\n"),
822 MockRead("Content-Length: 5\r\n"),
823 MockRead("Content-Length: 5\r\n"),
824 MockRead("Content-Length: 5\r\n\r\n"),
825 MockRead("Hello"),
827 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
828 arraysize(data_reads));
829 EXPECT_EQ(OK, out.rv);
830 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
831 EXPECT_EQ("Hello", out.response_data);
833 // 2 dupes and one mismatched.
835 MockRead data_reads[] = {
836 MockRead("HTTP/1.1 200 OK\r\n"),
837 MockRead("Content-Length: 10\r\n"),
838 MockRead("Content-Length: 10\r\n"),
839 MockRead("Content-Length: 5\r\n\r\n"),
841 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
842 arraysize(data_reads));
843 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
847 TEST_P(HttpNetworkTransactionTest,
848 MultipleContentLengthHeadersTransferEncoding) {
849 MockRead data_reads[] = {
850 MockRead("HTTP/1.1 200 OK\r\n"),
851 MockRead("Content-Length: 666\r\n"),
852 MockRead("Content-Length: 1337\r\n"),
853 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
854 MockRead("5\r\nHello\r\n"),
855 MockRead("1\r\n"),
856 MockRead(" \r\n"),
857 MockRead("5\r\nworld\r\n"),
858 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
859 MockRead(SYNCHRONOUS, OK),
861 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
862 arraysize(data_reads));
863 EXPECT_EQ(OK, out.rv);
864 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
865 EXPECT_EQ("Hello world", out.response_data);
868 // Next tests deal with http://crbug.com/98895.
870 // Checks that a single Content-Disposition header results in no error.
871 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
872 MockRead data_reads[] = {
873 MockRead("HTTP/1.1 200 OK\r\n"),
874 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
875 MockRead("Content-Length: 5\r\n\r\n"),
876 MockRead("Hello"),
878 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
879 arraysize(data_reads));
880 EXPECT_EQ(OK, out.rv);
881 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
882 EXPECT_EQ("Hello", out.response_data);
885 // Checks that two identical Content-Disposition headers result in no error.
886 TEST_P(HttpNetworkTransactionTest,
887 TwoIdenticalContentDispositionHeaders) {
888 MockRead data_reads[] = {
889 MockRead("HTTP/1.1 200 OK\r\n"),
890 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
891 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
892 MockRead("Content-Length: 5\r\n\r\n"),
893 MockRead("Hello"),
895 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
896 arraysize(data_reads));
897 EXPECT_EQ(OK, out.rv);
898 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
899 EXPECT_EQ("Hello", out.response_data);
902 // Checks that two distinct Content-Disposition headers result in an error.
903 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
904 MockRead data_reads[] = {
905 MockRead("HTTP/1.1 200 OK\r\n"),
906 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
907 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
908 MockRead("Content-Length: 5\r\n\r\n"),
909 MockRead("Hello"),
911 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
912 arraysize(data_reads));
913 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
916 // Checks that two identical Location headers result in no error.
917 // Also tests Location header behavior.
918 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
919 MockRead data_reads[] = {
920 MockRead("HTTP/1.1 302 Redirect\r\n"),
921 MockRead("Location: http://good.com/\r\n"),
922 MockRead("Location: http://good.com/\r\n"),
923 MockRead("Content-Length: 0\r\n\r\n"),
924 MockRead(SYNCHRONOUS, OK),
927 HttpRequestInfo request;
928 request.method = "GET";
929 request.url = GURL("http://redirect.com/");
930 request.load_flags = 0;
932 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
933 scoped_ptr<HttpTransaction> trans(
934 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
936 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
937 session_deps_.socket_factory->AddSocketDataProvider(&data);
939 TestCompletionCallback callback;
941 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
942 EXPECT_EQ(ERR_IO_PENDING, rv);
944 EXPECT_EQ(OK, callback.WaitForResult());
946 const HttpResponseInfo* response = trans->GetResponseInfo();
947 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
948 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
949 std::string url;
950 EXPECT_TRUE(response->headers->IsRedirect(&url));
951 EXPECT_EQ("http://good.com/", url);
954 // Checks that two distinct Location headers result in an error.
955 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
956 MockRead data_reads[] = {
957 MockRead("HTTP/1.1 302 Redirect\r\n"),
958 MockRead("Location: http://good.com/\r\n"),
959 MockRead("Location: http://evil.com/\r\n"),
960 MockRead("Content-Length: 0\r\n\r\n"),
961 MockRead(SYNCHRONOUS, OK),
963 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
964 arraysize(data_reads));
965 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
968 // Do a request using the HEAD method. Verify that we don't try to read the
969 // message body (since HEAD has none).
970 TEST_P(HttpNetworkTransactionTest, Head) {
971 HttpRequestInfo request;
972 request.method = "HEAD";
973 request.url = GURL("http://www.google.com/");
974 request.load_flags = 0;
976 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
977 scoped_ptr<HttpTransaction> trans(
978 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
980 MockWrite data_writes1[] = {
981 MockWrite("HEAD / HTTP/1.1\r\n"
982 "Host: www.google.com\r\n"
983 "Connection: keep-alive\r\n"
984 "Content-Length: 0\r\n\r\n"),
986 MockRead data_reads1[] = {
987 MockRead("HTTP/1.1 404 Not Found\r\n"),
988 MockRead("Server: Blah\r\n"),
989 MockRead("Content-Length: 1234\r\n\r\n"),
991 // No response body because the test stops reading here.
992 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
995 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
996 data_writes1, arraysize(data_writes1));
997 session_deps_.socket_factory->AddSocketDataProvider(&data1);
999 TestCompletionCallback callback1;
1001 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1002 EXPECT_EQ(ERR_IO_PENDING, rv);
1004 rv = callback1.WaitForResult();
1005 EXPECT_EQ(OK, rv);
1007 const HttpResponseInfo* response = trans->GetResponseInfo();
1008 ASSERT_TRUE(response != NULL);
1010 // Check that the headers got parsed.
1011 EXPECT_TRUE(response->headers.get() != NULL);
1012 EXPECT_EQ(1234, response->headers->GetContentLength());
1013 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1015 std::string server_header;
1016 void* iter = NULL;
1017 bool has_server_header = response->headers->EnumerateHeader(
1018 &iter, "Server", &server_header);
1019 EXPECT_TRUE(has_server_header);
1020 EXPECT_EQ("Blah", server_header);
1022 // Reading should give EOF right away, since there is no message body
1023 // (despite non-zero content-length).
1024 std::string response_data;
1025 rv = ReadTransaction(trans.get(), &response_data);
1026 EXPECT_EQ(OK, rv);
1027 EXPECT_EQ("", response_data);
1030 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1031 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1033 MockRead data_reads[] = {
1034 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1035 MockRead("hello"),
1036 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1037 MockRead("world"),
1038 MockRead(SYNCHRONOUS, OK),
1040 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1041 session_deps_.socket_factory->AddSocketDataProvider(&data);
1043 const char* const kExpectedResponseData[] = {
1044 "hello", "world"
1047 for (int i = 0; i < 2; ++i) {
1048 HttpRequestInfo request;
1049 request.method = "GET";
1050 request.url = GURL("http://www.google.com/");
1051 request.load_flags = 0;
1053 scoped_ptr<HttpTransaction> trans(
1054 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1056 TestCompletionCallback callback;
1058 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1059 EXPECT_EQ(ERR_IO_PENDING, rv);
1061 rv = callback.WaitForResult();
1062 EXPECT_EQ(OK, rv);
1064 const HttpResponseInfo* response = trans->GetResponseInfo();
1065 ASSERT_TRUE(response != NULL);
1067 EXPECT_TRUE(response->headers.get() != NULL);
1068 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1070 std::string response_data;
1071 rv = ReadTransaction(trans.get(), &response_data);
1072 EXPECT_EQ(OK, rv);
1073 EXPECT_EQ(kExpectedResponseData[i], response_data);
1077 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1078 ScopedVector<UploadElementReader> element_readers;
1079 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1080 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1082 HttpRequestInfo request;
1083 request.method = "POST";
1084 request.url = GURL("http://www.foo.com/");
1085 request.upload_data_stream = &upload_data_stream;
1086 request.load_flags = 0;
1088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1089 scoped_ptr<HttpTransaction> trans(
1090 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1092 MockRead data_reads[] = {
1093 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1094 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1095 MockRead("hello world"),
1096 MockRead(SYNCHRONOUS, OK),
1098 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1099 session_deps_.socket_factory->AddSocketDataProvider(&data);
1101 TestCompletionCallback callback;
1103 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1104 EXPECT_EQ(ERR_IO_PENDING, rv);
1106 rv = callback.WaitForResult();
1107 EXPECT_EQ(OK, rv);
1109 const HttpResponseInfo* response = trans->GetResponseInfo();
1110 ASSERT_TRUE(response != NULL);
1112 EXPECT_TRUE(response->headers.get() != NULL);
1113 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1115 std::string response_data;
1116 rv = ReadTransaction(trans.get(), &response_data);
1117 EXPECT_EQ(OK, rv);
1118 EXPECT_EQ("hello world", response_data);
1121 // This test is almost the same as Ignores100 above, but the response contains
1122 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1123 // HTTP/1.1 and the two status headers are read in one read.
1124 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1125 HttpRequestInfo request;
1126 request.method = "GET";
1127 request.url = GURL("http://www.foo.com/");
1128 request.load_flags = 0;
1130 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1131 scoped_ptr<HttpTransaction> trans(
1132 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1134 MockRead data_reads[] = {
1135 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1136 "HTTP/1.1 200 OK\r\n\r\n"),
1137 MockRead("hello world"),
1138 MockRead(SYNCHRONOUS, OK),
1140 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1141 session_deps_.socket_factory->AddSocketDataProvider(&data);
1143 TestCompletionCallback callback;
1145 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1146 EXPECT_EQ(ERR_IO_PENDING, rv);
1148 rv = callback.WaitForResult();
1149 EXPECT_EQ(OK, rv);
1151 const HttpResponseInfo* response = trans->GetResponseInfo();
1152 ASSERT_TRUE(response != NULL);
1154 EXPECT_TRUE(response->headers.get() != NULL);
1155 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1157 std::string response_data;
1158 rv = ReadTransaction(trans.get(), &response_data);
1159 EXPECT_EQ(OK, rv);
1160 EXPECT_EQ("hello world", response_data);
1163 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1164 HttpRequestInfo request;
1165 request.method = "POST";
1166 request.url = GURL("http://www.foo.com/");
1167 request.load_flags = 0;
1169 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1170 scoped_ptr<HttpTransaction> trans(
1171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1173 MockRead data_reads[] = {
1174 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1175 MockRead(ASYNC, 0),
1177 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1178 session_deps_.socket_factory->AddSocketDataProvider(&data);
1180 TestCompletionCallback callback;
1182 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1183 EXPECT_EQ(ERR_IO_PENDING, rv);
1185 rv = callback.WaitForResult();
1186 EXPECT_EQ(OK, rv);
1188 std::string response_data;
1189 rv = ReadTransaction(trans.get(), &response_data);
1190 EXPECT_EQ(OK, rv);
1191 EXPECT_EQ("", response_data);
1194 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1195 HttpRequestInfo request;
1196 request.method = "POST";
1197 request.url = GURL("http://www.foo.com/");
1198 request.load_flags = 0;
1200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1201 scoped_ptr<HttpTransaction> trans(
1202 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1205 MockRead data_reads[] = {
1206 MockRead(ASYNC, 0),
1208 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1209 session_deps_.socket_factory->AddSocketDataProvider(&data);
1211 TestCompletionCallback callback;
1213 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1214 EXPECT_EQ(ERR_IO_PENDING, rv);
1216 rv = callback.WaitForResult();
1217 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1220 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1221 const MockWrite* write_failure,
1222 const MockRead* read_failure) {
1223 HttpRequestInfo request;
1224 request.method = "GET";
1225 request.url = GURL("http://www.foo.com/");
1226 request.load_flags = 0;
1228 CapturingNetLog net_log;
1229 session_deps_.net_log = &net_log;
1230 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1232 // Written data for successfully sending both requests.
1233 MockWrite data1_writes[] = {
1234 MockWrite("GET / HTTP/1.1\r\n"
1235 "Host: www.foo.com\r\n"
1236 "Connection: keep-alive\r\n\r\n"),
1237 MockWrite("GET / HTTP/1.1\r\n"
1238 "Host: www.foo.com\r\n"
1239 "Connection: keep-alive\r\n\r\n")
1242 // Read results for the first request.
1243 MockRead data1_reads[] = {
1244 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1245 MockRead("hello"),
1246 MockRead(ASYNC, OK),
1249 if (write_failure) {
1250 ASSERT_FALSE(read_failure);
1251 data1_writes[1] = *write_failure;
1252 } else {
1253 ASSERT_TRUE(read_failure);
1254 data1_reads[2] = *read_failure;
1257 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1258 data1_writes, arraysize(data1_writes));
1259 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1261 MockRead data2_reads[] = {
1262 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1263 MockRead("world"),
1264 MockRead(ASYNC, OK),
1266 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1267 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1269 const char* kExpectedResponseData[] = {
1270 "hello", "world"
1273 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1274 for (int i = 0; i < 2; ++i) {
1275 TestCompletionCallback callback;
1277 scoped_ptr<HttpTransaction> trans(
1278 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1280 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1281 EXPECT_EQ(ERR_IO_PENDING, rv);
1283 rv = callback.WaitForResult();
1284 EXPECT_EQ(OK, rv);
1286 LoadTimingInfo load_timing_info;
1287 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1288 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1289 if (i == 0) {
1290 first_socket_log_id = load_timing_info.socket_log_id;
1291 } else {
1292 // The second request should be using a new socket.
1293 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1296 const HttpResponseInfo* response = trans->GetResponseInfo();
1297 ASSERT_TRUE(response != NULL);
1299 EXPECT_TRUE(response->headers.get() != NULL);
1300 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1302 std::string response_data;
1303 rv = ReadTransaction(trans.get(), &response_data);
1304 EXPECT_EQ(OK, rv);
1305 EXPECT_EQ(kExpectedResponseData[i], response_data);
1309 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1310 const MockWrite* write_failure,
1311 const MockRead* read_failure,
1312 bool use_spdy) {
1313 HttpRequestInfo request;
1314 request.method = "GET";
1315 request.url = GURL("https://www.foo.com/");
1316 request.load_flags = 0;
1318 CapturingNetLog net_log;
1319 session_deps_.net_log = &net_log;
1320 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1322 SSLSocketDataProvider ssl1(ASYNC, OK);
1323 SSLSocketDataProvider ssl2(ASYNC, OK);
1324 if (use_spdy) {
1325 ssl1.SetNextProto(GetParam());
1326 ssl2.SetNextProto(GetParam());
1328 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1329 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1331 // SPDY versions of the request and response.
1332 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1333 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1334 scoped_ptr<SpdyFrame> spdy_response(
1335 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1336 scoped_ptr<SpdyFrame> spdy_data(
1337 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1339 // HTTP/1.1 versions of the request and response.
1340 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1341 "Host: www.foo.com\r\n"
1342 "Connection: keep-alive\r\n\r\n";
1343 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1344 const char kHttpData[] = "hello";
1346 std::vector<MockRead> data1_reads;
1347 std::vector<MockWrite> data1_writes;
1348 if (write_failure) {
1349 ASSERT_FALSE(read_failure);
1350 data1_writes.push_back(*write_failure);
1351 data1_reads.push_back(MockRead(ASYNC, OK));
1352 } else {
1353 ASSERT_TRUE(read_failure);
1354 if (use_spdy) {
1355 data1_writes.push_back(CreateMockWrite(*spdy_request));
1356 } else {
1357 data1_writes.push_back(MockWrite(kHttpRequest));
1359 data1_reads.push_back(*read_failure);
1362 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1363 &data1_writes[0], data1_writes.size());
1364 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1366 std::vector<MockRead> data2_reads;
1367 std::vector<MockWrite> data2_writes;
1369 if (use_spdy) {
1370 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1372 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1373 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1374 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1375 } else {
1376 data2_writes.push_back(
1377 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1379 data2_reads.push_back(
1380 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1381 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1382 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1384 OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
1385 &data2_writes[0], data2_writes.size());
1386 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1388 // Preconnect a socket.
1389 net::SSLConfig ssl_config;
1390 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1391 if (session->http_stream_factory()->has_next_protos())
1392 ssl_config.next_protos = session->http_stream_factory()->next_protos();
1393 session->http_stream_factory()->PreconnectStreams(
1394 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1395 // Wait for the preconnect to complete.
1396 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1397 base::RunLoop().RunUntilIdle();
1398 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1400 // Make the request.
1401 TestCompletionCallback callback;
1403 scoped_ptr<HttpTransaction> trans(
1404 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1406 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1407 EXPECT_EQ(ERR_IO_PENDING, rv);
1409 rv = callback.WaitForResult();
1410 EXPECT_EQ(OK, rv);
1412 LoadTimingInfo load_timing_info;
1413 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1414 TestLoadTimingNotReused(
1415 load_timing_info,
1416 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1418 const HttpResponseInfo* response = trans->GetResponseInfo();
1419 ASSERT_TRUE(response != NULL);
1421 EXPECT_TRUE(response->headers.get() != NULL);
1422 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1424 std::string response_data;
1425 rv = ReadTransaction(trans.get(), &response_data);
1426 EXPECT_EQ(OK, rv);
1427 EXPECT_EQ(kHttpData, response_data);
1430 TEST_P(HttpNetworkTransactionTest,
1431 KeepAliveConnectionNotConnectedOnWrite) {
1432 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1433 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1436 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1437 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1438 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1441 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1442 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1443 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1446 TEST_P(HttpNetworkTransactionTest,
1447 PreconnectErrorNotConnectedOnWrite) {
1448 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1449 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1452 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1453 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1454 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1457 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1458 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1459 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1462 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1463 MockRead read_failure(ASYNC, OK); // EOF
1464 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1467 TEST_P(HttpNetworkTransactionTest,
1468 SpdyPreconnectErrorNotConnectedOnWrite) {
1469 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1470 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1473 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1474 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1475 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1478 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1479 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1480 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1483 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1484 MockRead read_failure(ASYNC, OK); // EOF
1485 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1488 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1489 HttpRequestInfo request;
1490 request.method = "GET";
1491 request.url = GURL("http://www.google.com/");
1492 request.load_flags = 0;
1494 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1495 scoped_ptr<HttpTransaction> trans(
1496 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1498 MockRead data_reads[] = {
1499 MockRead(ASYNC, ERR_CONNECTION_RESET),
1500 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1501 MockRead("hello world"),
1502 MockRead(SYNCHRONOUS, OK),
1504 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1505 session_deps_.socket_factory->AddSocketDataProvider(&data);
1507 TestCompletionCallback callback;
1509 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1510 EXPECT_EQ(ERR_IO_PENDING, rv);
1512 rv = callback.WaitForResult();
1513 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1515 const HttpResponseInfo* response = trans->GetResponseInfo();
1516 EXPECT_TRUE(response == NULL);
1519 // What do various browsers do when the server closes a non-keepalive
1520 // connection without sending any response header or body?
1522 // IE7: error page
1523 // Safari 3.1.2 (Windows): error page
1524 // Firefox 3.0.1: blank page
1525 // Opera 9.52: after five attempts, blank page
1526 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1527 // Us: error page (EMPTY_RESPONSE)
1528 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1529 MockRead data_reads[] = {
1530 MockRead(SYNCHRONOUS, OK), // EOF
1531 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1532 MockRead("hello world"),
1533 MockRead(SYNCHRONOUS, OK),
1535 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1536 arraysize(data_reads));
1537 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1540 // Test that network access can be deferred and resumed.
1541 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1542 HttpRequestInfo request;
1543 request.method = "GET";
1544 request.url = GURL("http://www.google.com/");
1545 request.load_flags = 0;
1547 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1548 scoped_ptr<HttpTransaction> trans(
1549 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1551 // Defer on OnBeforeNetworkStart.
1552 BeforeNetworkStartHandler net_start_handler(true); // defer
1553 trans->SetBeforeNetworkStartCallback(
1554 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1555 base::Unretained(&net_start_handler)));
1557 MockRead data_reads[] = {
1558 MockRead("HTTP/1.0 200 OK\r\n"),
1559 MockRead("Content-Length: 5\r\n\r\n"),
1560 MockRead("hello"),
1561 MockRead(SYNCHRONOUS, 0),
1563 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1564 session_deps_.socket_factory->AddSocketDataProvider(&data);
1566 TestCompletionCallback callback;
1568 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1569 EXPECT_EQ(ERR_IO_PENDING, rv);
1570 base::MessageLoop::current()->RunUntilIdle();
1572 // Should have deferred for network start.
1573 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1574 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1575 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1577 trans->ResumeNetworkStart();
1578 rv = callback.WaitForResult();
1579 EXPECT_EQ(OK, rv);
1580 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1582 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1583 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1584 if (rv == ERR_IO_PENDING)
1585 rv = callback.WaitForResult();
1586 EXPECT_EQ(5, rv);
1587 trans.reset();
1590 // Test that network use can be deferred and canceled.
1591 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1592 HttpRequestInfo request;
1593 request.method = "GET";
1594 request.url = GURL("http://www.google.com/");
1595 request.load_flags = 0;
1597 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1598 scoped_ptr<HttpTransaction> trans(
1599 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1601 // Defer on OnBeforeNetworkStart.
1602 BeforeNetworkStartHandler net_start_handler(true); // defer
1603 trans->SetBeforeNetworkStartCallback(
1604 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1605 base::Unretained(&net_start_handler)));
1607 TestCompletionCallback callback;
1609 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1610 EXPECT_EQ(ERR_IO_PENDING, rv);
1611 base::MessageLoop::current()->RunUntilIdle();
1613 // Should have deferred for network start.
1614 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1615 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1616 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1619 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1620 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1621 // destructor in such situations.
1622 // See http://crbug.com/154712 and http://crbug.com/156609.
1623 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1624 HttpRequestInfo request;
1625 request.method = "GET";
1626 request.url = GURL("http://www.google.com/");
1627 request.load_flags = 0;
1629 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1630 scoped_ptr<HttpTransaction> trans(
1631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1633 MockRead data_reads[] = {
1634 MockRead("HTTP/1.0 200 OK\r\n"),
1635 MockRead("Connection: keep-alive\r\n"),
1636 MockRead("Content-Length: 100\r\n\r\n"),
1637 MockRead("hello"),
1638 MockRead(SYNCHRONOUS, 0),
1640 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1641 session_deps_.socket_factory->AddSocketDataProvider(&data);
1643 TestCompletionCallback callback;
1645 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1646 EXPECT_EQ(ERR_IO_PENDING, rv);
1648 rv = callback.WaitForResult();
1649 EXPECT_EQ(OK, rv);
1651 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1652 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1653 if (rv == ERR_IO_PENDING)
1654 rv = callback.WaitForResult();
1655 EXPECT_EQ(5, rv);
1656 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1657 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1659 trans.reset();
1660 base::MessageLoop::current()->RunUntilIdle();
1661 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1664 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1665 HttpRequestInfo request;
1666 request.method = "GET";
1667 request.url = GURL("http://www.google.com/");
1668 request.load_flags = 0;
1670 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1671 scoped_ptr<HttpTransaction> trans(
1672 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1674 MockRead data_reads[] = {
1675 MockRead("HTTP/1.0 200 OK\r\n"),
1676 MockRead("Connection: keep-alive\r\n"),
1677 MockRead("Content-Length: 100\r\n\r\n"),
1678 MockRead(SYNCHRONOUS, 0),
1680 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1681 session_deps_.socket_factory->AddSocketDataProvider(&data);
1683 TestCompletionCallback callback;
1685 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1686 EXPECT_EQ(ERR_IO_PENDING, rv);
1688 rv = callback.WaitForResult();
1689 EXPECT_EQ(OK, rv);
1691 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1692 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1693 if (rv == ERR_IO_PENDING)
1694 rv = callback.WaitForResult();
1695 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1697 trans.reset();
1698 base::MessageLoop::current()->RunUntilIdle();
1699 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1702 // Test that we correctly reuse a keep-alive connection after not explicitly
1703 // reading the body.
1704 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1705 HttpRequestInfo request;
1706 request.method = "GET";
1707 request.url = GURL("http://www.foo.com/");
1708 request.load_flags = 0;
1710 CapturingNetLog net_log;
1711 session_deps_.net_log = &net_log;
1712 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1714 // Note that because all these reads happen in the same
1715 // StaticSocketDataProvider, it shows that the same socket is being reused for
1716 // all transactions.
1717 MockRead data1_reads[] = {
1718 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1719 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1720 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1721 MockRead("HTTP/1.1 302 Found\r\n"
1722 "Content-Length: 0\r\n\r\n"),
1723 MockRead("HTTP/1.1 302 Found\r\n"
1724 "Content-Length: 5\r\n\r\n"
1725 "hello"),
1726 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1727 "Content-Length: 0\r\n\r\n"),
1728 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1729 "Content-Length: 5\r\n\r\n"
1730 "hello"),
1731 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1732 MockRead("hello"),
1734 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1735 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1737 MockRead data2_reads[] = {
1738 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1740 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1741 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1743 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1744 std::string response_lines[kNumUnreadBodies];
1746 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1747 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1748 TestCompletionCallback callback;
1750 scoped_ptr<HttpTransaction> trans(
1751 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1753 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1754 EXPECT_EQ(ERR_IO_PENDING, rv);
1756 rv = callback.WaitForResult();
1757 EXPECT_EQ(OK, rv);
1759 LoadTimingInfo load_timing_info;
1760 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1761 if (i == 0) {
1762 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1763 first_socket_log_id = load_timing_info.socket_log_id;
1764 } else {
1765 TestLoadTimingReused(load_timing_info);
1766 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1769 const HttpResponseInfo* response = trans->GetResponseInfo();
1770 ASSERT_TRUE(response != NULL);
1772 ASSERT_TRUE(response->headers.get() != NULL);
1773 response_lines[i] = response->headers->GetStatusLine();
1775 // We intentionally don't read the response bodies.
1778 const char* const kStatusLines[] = {
1779 "HTTP/1.1 204 No Content",
1780 "HTTP/1.1 205 Reset Content",
1781 "HTTP/1.1 304 Not Modified",
1782 "HTTP/1.1 302 Found",
1783 "HTTP/1.1 302 Found",
1784 "HTTP/1.1 301 Moved Permanently",
1785 "HTTP/1.1 301 Moved Permanently",
1788 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1789 forgot_to_update_kStatusLines);
1791 for (int i = 0; i < kNumUnreadBodies; ++i)
1792 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1794 TestCompletionCallback callback;
1795 scoped_ptr<HttpTransaction> trans(
1796 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1797 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1798 EXPECT_EQ(ERR_IO_PENDING, rv);
1799 rv = callback.WaitForResult();
1800 EXPECT_EQ(OK, rv);
1801 const HttpResponseInfo* response = trans->GetResponseInfo();
1802 ASSERT_TRUE(response != NULL);
1803 ASSERT_TRUE(response->headers.get() != NULL);
1804 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1805 std::string response_data;
1806 rv = ReadTransaction(trans.get(), &response_data);
1807 EXPECT_EQ(OK, rv);
1808 EXPECT_EQ("hello", response_data);
1811 // Test the request-challenge-retry sequence for basic auth.
1812 // (basic auth is the easiest to mock, because it has no randomness).
1813 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1814 HttpRequestInfo request;
1815 request.method = "GET";
1816 request.url = GURL("http://www.google.com/");
1817 request.load_flags = 0;
1819 CapturingNetLog log;
1820 session_deps_.net_log = &log;
1821 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1822 scoped_ptr<HttpTransaction> trans(
1823 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1825 MockWrite data_writes1[] = {
1826 MockWrite("GET / HTTP/1.1\r\n"
1827 "Host: www.google.com\r\n"
1828 "Connection: keep-alive\r\n\r\n"),
1831 MockRead data_reads1[] = {
1832 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1833 // Give a couple authenticate options (only the middle one is actually
1834 // supported).
1835 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1836 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1837 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1838 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1839 // Large content-length -- won't matter, as connection will be reset.
1840 MockRead("Content-Length: 10000\r\n\r\n"),
1841 MockRead(SYNCHRONOUS, ERR_FAILED),
1844 // After calling trans->RestartWithAuth(), this is the request we should
1845 // be issuing -- the final header line contains the credentials.
1846 MockWrite data_writes2[] = {
1847 MockWrite("GET / HTTP/1.1\r\n"
1848 "Host: www.google.com\r\n"
1849 "Connection: keep-alive\r\n"
1850 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1853 // Lastly, the server responds with the actual content.
1854 MockRead data_reads2[] = {
1855 MockRead("HTTP/1.0 200 OK\r\n"),
1856 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1857 MockRead("Content-Length: 100\r\n\r\n"),
1858 MockRead(SYNCHRONOUS, OK),
1861 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1862 data_writes1, arraysize(data_writes1));
1863 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1864 data_writes2, arraysize(data_writes2));
1865 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1866 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1868 TestCompletionCallback callback1;
1870 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1871 EXPECT_EQ(ERR_IO_PENDING, rv);
1873 rv = callback1.WaitForResult();
1874 EXPECT_EQ(OK, rv);
1876 LoadTimingInfo load_timing_info1;
1877 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1878 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1880 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1881 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1883 const HttpResponseInfo* response = trans->GetResponseInfo();
1884 ASSERT_TRUE(response != NULL);
1885 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1887 TestCompletionCallback callback2;
1889 rv = trans->RestartWithAuth(
1890 AuthCredentials(kFoo, kBar), callback2.callback());
1891 EXPECT_EQ(ERR_IO_PENDING, rv);
1893 rv = callback2.WaitForResult();
1894 EXPECT_EQ(OK, rv);
1896 LoadTimingInfo load_timing_info2;
1897 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1898 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1899 // The load timing after restart should have a new socket ID, and times after
1900 // those of the first load timing.
1901 EXPECT_LE(load_timing_info1.receive_headers_end,
1902 load_timing_info2.connect_timing.connect_start);
1903 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1905 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1906 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1908 response = trans->GetResponseInfo();
1909 ASSERT_TRUE(response != NULL);
1910 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1911 EXPECT_EQ(100, response->headers->GetContentLength());
1914 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1915 HttpRequestInfo request;
1916 request.method = "GET";
1917 request.url = GURL("http://www.google.com/");
1918 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1920 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1921 scoped_ptr<HttpTransaction> trans(
1922 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1924 MockWrite data_writes[] = {
1925 MockWrite("GET / HTTP/1.1\r\n"
1926 "Host: www.google.com\r\n"
1927 "Connection: keep-alive\r\n\r\n"),
1930 MockRead data_reads[] = {
1931 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1932 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1933 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1934 // Large content-length -- won't matter, as connection will be reset.
1935 MockRead("Content-Length: 10000\r\n\r\n"),
1936 MockRead(SYNCHRONOUS, ERR_FAILED),
1939 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1940 data_writes, arraysize(data_writes));
1941 session_deps_.socket_factory->AddSocketDataProvider(&data);
1942 TestCompletionCallback callback;
1944 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1945 EXPECT_EQ(ERR_IO_PENDING, rv);
1947 rv = callback.WaitForResult();
1948 EXPECT_EQ(0, rv);
1950 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
1951 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
1953 const HttpResponseInfo* response = trans->GetResponseInfo();
1954 ASSERT_TRUE(response != NULL);
1955 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1958 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1959 // connection.
1960 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1961 HttpRequestInfo request;
1962 request.method = "GET";
1963 request.url = GURL("http://www.google.com/");
1964 request.load_flags = 0;
1966 CapturingNetLog log;
1967 session_deps_.net_log = &log;
1968 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1970 MockWrite data_writes1[] = {
1971 MockWrite("GET / HTTP/1.1\r\n"
1972 "Host: www.google.com\r\n"
1973 "Connection: keep-alive\r\n\r\n"),
1975 // After calling trans->RestartWithAuth(), this is the request we should
1976 // be issuing -- the final header line contains the credentials.
1977 MockWrite("GET / HTTP/1.1\r\n"
1978 "Host: www.google.com\r\n"
1979 "Connection: keep-alive\r\n"
1980 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1983 MockRead data_reads1[] = {
1984 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1985 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1986 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1987 MockRead("Content-Length: 14\r\n\r\n"),
1988 MockRead("Unauthorized\r\n"),
1990 // Lastly, the server responds with the actual content.
1991 MockRead("HTTP/1.1 200 OK\r\n"),
1992 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1993 MockRead("Content-Length: 5\r\n\r\n"),
1994 MockRead("Hello"),
1997 // If there is a regression where we disconnect a Keep-Alive
1998 // connection during an auth roundtrip, we'll end up reading this.
1999 MockRead data_reads2[] = {
2000 MockRead(SYNCHRONOUS, ERR_FAILED),
2003 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2004 data_writes1, arraysize(data_writes1));
2005 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2006 NULL, 0);
2007 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2008 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2010 TestCompletionCallback callback1;
2012 scoped_ptr<HttpTransaction> trans(
2013 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2014 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2015 EXPECT_EQ(ERR_IO_PENDING, rv);
2017 rv = callback1.WaitForResult();
2018 EXPECT_EQ(OK, rv);
2020 LoadTimingInfo load_timing_info1;
2021 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2022 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2024 const HttpResponseInfo* response = trans->GetResponseInfo();
2025 ASSERT_TRUE(response != NULL);
2026 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2028 TestCompletionCallback callback2;
2030 rv = trans->RestartWithAuth(
2031 AuthCredentials(kFoo, kBar), callback2.callback());
2032 EXPECT_EQ(ERR_IO_PENDING, rv);
2034 rv = callback2.WaitForResult();
2035 EXPECT_EQ(OK, rv);
2037 LoadTimingInfo load_timing_info2;
2038 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2039 TestLoadTimingReused(load_timing_info2);
2040 // The load timing after restart should have the same socket ID, and times
2041 // those of the first load timing.
2042 EXPECT_LE(load_timing_info1.receive_headers_end,
2043 load_timing_info2.send_start);
2044 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2046 response = trans->GetResponseInfo();
2047 ASSERT_TRUE(response != NULL);
2048 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2049 EXPECT_EQ(5, response->headers->GetContentLength());
2051 std::string response_data;
2052 rv = ReadTransaction(trans.get(), &response_data);
2053 EXPECT_EQ(OK, rv);
2054 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2055 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2058 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2059 // connection and with no response body to drain.
2060 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2061 HttpRequestInfo request;
2062 request.method = "GET";
2063 request.url = GURL("http://www.google.com/");
2064 request.load_flags = 0;
2066 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2068 MockWrite data_writes1[] = {
2069 MockWrite("GET / HTTP/1.1\r\n"
2070 "Host: www.google.com\r\n"
2071 "Connection: keep-alive\r\n\r\n"),
2073 // After calling trans->RestartWithAuth(), this is the request we should
2074 // be issuing -- the final header line contains the credentials.
2075 MockWrite("GET / HTTP/1.1\r\n"
2076 "Host: www.google.com\r\n"
2077 "Connection: keep-alive\r\n"
2078 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2081 MockRead data_reads1[] = {
2082 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2083 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2084 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2086 // Lastly, the server responds with the actual content.
2087 MockRead("HTTP/1.1 200 OK\r\n"),
2088 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2089 MockRead("Content-Length: 5\r\n\r\n"),
2090 MockRead("hello"),
2093 // An incorrect reconnect would cause this to be read.
2094 MockRead data_reads2[] = {
2095 MockRead(SYNCHRONOUS, ERR_FAILED),
2098 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2099 data_writes1, arraysize(data_writes1));
2100 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2101 NULL, 0);
2102 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2103 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2105 TestCompletionCallback callback1;
2107 scoped_ptr<HttpTransaction> trans(
2108 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2109 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2110 EXPECT_EQ(ERR_IO_PENDING, rv);
2112 rv = callback1.WaitForResult();
2113 EXPECT_EQ(OK, rv);
2115 const HttpResponseInfo* response = trans->GetResponseInfo();
2116 ASSERT_TRUE(response != NULL);
2117 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2119 TestCompletionCallback callback2;
2121 rv = trans->RestartWithAuth(
2122 AuthCredentials(kFoo, kBar), callback2.callback());
2123 EXPECT_EQ(ERR_IO_PENDING, rv);
2125 rv = callback2.WaitForResult();
2126 EXPECT_EQ(OK, rv);
2128 response = trans->GetResponseInfo();
2129 ASSERT_TRUE(response != NULL);
2130 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2131 EXPECT_EQ(5, response->headers->GetContentLength());
2134 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2135 // connection and with a large response body to drain.
2136 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2137 HttpRequestInfo request;
2138 request.method = "GET";
2139 request.url = GURL("http://www.google.com/");
2140 request.load_flags = 0;
2142 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2144 MockWrite data_writes1[] = {
2145 MockWrite("GET / HTTP/1.1\r\n"
2146 "Host: www.google.com\r\n"
2147 "Connection: keep-alive\r\n\r\n"),
2149 // After calling trans->RestartWithAuth(), this is the request we should
2150 // be issuing -- the final header line contains the credentials.
2151 MockWrite("GET / HTTP/1.1\r\n"
2152 "Host: www.google.com\r\n"
2153 "Connection: keep-alive\r\n"
2154 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2157 // Respond with 5 kb of response body.
2158 std::string large_body_string("Unauthorized");
2159 large_body_string.append(5 * 1024, ' ');
2160 large_body_string.append("\r\n");
2162 MockRead data_reads1[] = {
2163 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2164 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2165 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2166 // 5134 = 12 + 5 * 1024 + 2
2167 MockRead("Content-Length: 5134\r\n\r\n"),
2168 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2170 // Lastly, the server responds with the actual content.
2171 MockRead("HTTP/1.1 200 OK\r\n"),
2172 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2173 MockRead("Content-Length: 5\r\n\r\n"),
2174 MockRead("hello"),
2177 // An incorrect reconnect would cause this to be read.
2178 MockRead data_reads2[] = {
2179 MockRead(SYNCHRONOUS, ERR_FAILED),
2182 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2183 data_writes1, arraysize(data_writes1));
2184 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2185 NULL, 0);
2186 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2187 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2189 TestCompletionCallback callback1;
2191 scoped_ptr<HttpTransaction> trans(
2192 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2193 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2194 EXPECT_EQ(ERR_IO_PENDING, rv);
2196 rv = callback1.WaitForResult();
2197 EXPECT_EQ(OK, rv);
2199 const HttpResponseInfo* response = trans->GetResponseInfo();
2200 ASSERT_TRUE(response != NULL);
2201 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2203 TestCompletionCallback callback2;
2205 rv = trans->RestartWithAuth(
2206 AuthCredentials(kFoo, kBar), callback2.callback());
2207 EXPECT_EQ(ERR_IO_PENDING, rv);
2209 rv = callback2.WaitForResult();
2210 EXPECT_EQ(OK, rv);
2212 response = trans->GetResponseInfo();
2213 ASSERT_TRUE(response != NULL);
2214 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2215 EXPECT_EQ(5, response->headers->GetContentLength());
2218 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2219 // connection, but the server gets impatient and closes the connection.
2220 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2221 HttpRequestInfo request;
2222 request.method = "GET";
2223 request.url = GURL("http://www.google.com/");
2224 request.load_flags = 0;
2226 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2228 MockWrite data_writes1[] = {
2229 MockWrite("GET / HTTP/1.1\r\n"
2230 "Host: www.google.com\r\n"
2231 "Connection: keep-alive\r\n\r\n"),
2232 // This simulates the seemingly successful write to a closed connection
2233 // if the bug is not fixed.
2234 MockWrite("GET / HTTP/1.1\r\n"
2235 "Host: www.google.com\r\n"
2236 "Connection: keep-alive\r\n"
2237 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2240 MockRead data_reads1[] = {
2241 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2242 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2244 MockRead("Content-Length: 14\r\n\r\n"),
2245 // Tell MockTCPClientSocket to simulate the server closing the connection.
2246 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2247 MockRead("Unauthorized\r\n"),
2248 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2251 // After calling trans->RestartWithAuth(), this is the request we should
2252 // be issuing -- the final header line contains the credentials.
2253 MockWrite data_writes2[] = {
2254 MockWrite("GET / HTTP/1.1\r\n"
2255 "Host: www.google.com\r\n"
2256 "Connection: keep-alive\r\n"
2257 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2260 // Lastly, the server responds with the actual content.
2261 MockRead data_reads2[] = {
2262 MockRead("HTTP/1.1 200 OK\r\n"),
2263 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2264 MockRead("Content-Length: 5\r\n\r\n"),
2265 MockRead("hello"),
2268 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2269 data_writes1, arraysize(data_writes1));
2270 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2271 data_writes2, arraysize(data_writes2));
2272 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2273 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2275 TestCompletionCallback callback1;
2277 scoped_ptr<HttpTransaction> trans(
2278 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2279 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2280 EXPECT_EQ(ERR_IO_PENDING, rv);
2282 rv = callback1.WaitForResult();
2283 EXPECT_EQ(OK, rv);
2285 const HttpResponseInfo* response = trans->GetResponseInfo();
2286 ASSERT_TRUE(response != NULL);
2287 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2289 TestCompletionCallback callback2;
2291 rv = trans->RestartWithAuth(
2292 AuthCredentials(kFoo, kBar), callback2.callback());
2293 EXPECT_EQ(ERR_IO_PENDING, rv);
2295 rv = callback2.WaitForResult();
2296 EXPECT_EQ(OK, rv);
2298 response = trans->GetResponseInfo();
2299 ASSERT_TRUE(response != NULL);
2300 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2301 EXPECT_EQ(5, response->headers->GetContentLength());
2304 // Test the request-challenge-retry sequence for basic auth, over a connection
2305 // that requires a restart when setting up an SSL tunnel.
2306 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
2307 HttpRequestInfo request;
2308 request.method = "GET";
2309 request.url = GURL("https://www.google.com/");
2310 // when the no authentication data flag is set.
2311 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2313 // Configure against proxy server "myproxy:70".
2314 session_deps_.proxy_service.reset(
2315 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2316 CapturingBoundNetLog log;
2317 session_deps_.net_log = log.bound().net_log();
2318 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2320 // Since we have proxy, should try to establish tunnel.
2321 MockWrite data_writes1[] = {
2322 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2323 "Host: www.google.com\r\n"
2324 "Proxy-Connection: keep-alive\r\n\r\n"),
2326 // After calling trans->RestartWithAuth(), this is the request we should
2327 // be issuing -- the final header line contains the credentials.
2328 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2329 "Host: www.google.com\r\n"
2330 "Proxy-Connection: keep-alive\r\n"
2331 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2333 MockWrite("GET / HTTP/1.1\r\n"
2334 "Host: www.google.com\r\n"
2335 "Connection: keep-alive\r\n\r\n"),
2338 // The proxy responds to the connect with a 407, using a persistent
2339 // connection.
2340 MockRead data_reads1[] = {
2341 // No credentials.
2342 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2343 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2344 MockRead("Proxy-Connection: close\r\n\r\n"),
2346 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2348 MockRead("HTTP/1.1 200 OK\r\n"),
2349 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2350 MockRead("Content-Length: 5\r\n\r\n"),
2351 MockRead(SYNCHRONOUS, "hello"),
2354 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2355 data_writes1, arraysize(data_writes1));
2356 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2357 SSLSocketDataProvider ssl(ASYNC, OK);
2358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2360 TestCompletionCallback callback1;
2362 scoped_ptr<HttpTransaction> trans(
2363 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2365 int rv = trans->Start(&request, callback1.callback(), log.bound());
2366 EXPECT_EQ(ERR_IO_PENDING, rv);
2368 rv = callback1.WaitForResult();
2369 EXPECT_EQ(OK, rv);
2370 net::CapturingNetLog::CapturedEntryList entries;
2371 log.GetEntries(&entries);
2372 size_t pos = ExpectLogContainsSomewhere(
2373 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2374 NetLog::PHASE_NONE);
2375 ExpectLogContainsSomewhere(
2376 entries, pos,
2377 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2378 NetLog::PHASE_NONE);
2380 const HttpResponseInfo* response = trans->GetResponseInfo();
2381 ASSERT_TRUE(response != NULL);
2382 ASSERT_FALSE(response->headers.get() == NULL);
2383 EXPECT_EQ(407, response->headers->response_code());
2384 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2385 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2387 LoadTimingInfo load_timing_info;
2388 // CONNECT requests and responses are handled at the connect job level, so
2389 // the transaction does not yet have a connection.
2390 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2392 TestCompletionCallback callback2;
2394 rv = trans->RestartWithAuth(
2395 AuthCredentials(kFoo, kBar), callback2.callback());
2396 EXPECT_EQ(ERR_IO_PENDING, rv);
2398 rv = callback2.WaitForResult();
2399 EXPECT_EQ(OK, rv);
2401 response = trans->GetResponseInfo();
2402 ASSERT_TRUE(response != NULL);
2404 EXPECT_TRUE(response->headers->IsKeepAlive());
2405 EXPECT_EQ(200, response->headers->response_code());
2406 EXPECT_EQ(5, response->headers->GetContentLength());
2407 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2409 // The password prompt info should not be set.
2410 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2412 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2413 TestLoadTimingNotReusedWithPac(load_timing_info,
2414 CONNECT_TIMING_HAS_SSL_TIMES);
2416 trans.reset();
2417 session->CloseAllConnections();
2420 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2421 // proxy connection, when setting up an SSL tunnel.
2422 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2423 HttpRequestInfo request;
2424 request.method = "GET";
2425 request.url = GURL("https://www.google.com/");
2426 // Ensure that proxy authentication is attempted even
2427 // when the no authentication data flag is set.
2428 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2430 // Configure against proxy server "myproxy:70".
2431 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2432 CapturingBoundNetLog log;
2433 session_deps_.net_log = log.bound().net_log();
2434 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2436 scoped_ptr<HttpTransaction> trans(
2437 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2439 // Since we have proxy, should try to establish tunnel.
2440 MockWrite data_writes1[] = {
2441 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2442 "Host: www.google.com\r\n"
2443 "Proxy-Connection: keep-alive\r\n\r\n"),
2445 // After calling trans->RestartWithAuth(), this is the request we should
2446 // be issuing -- the final header line contains the credentials.
2447 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2448 "Host: www.google.com\r\n"
2449 "Proxy-Connection: keep-alive\r\n"
2450 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2453 // The proxy responds to the connect with a 407, using a persistent
2454 // connection.
2455 MockRead data_reads1[] = {
2456 // No credentials.
2457 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2458 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2459 MockRead("Content-Length: 10\r\n\r\n"),
2460 MockRead("0123456789"),
2462 // Wrong credentials (wrong password).
2463 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2464 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2465 MockRead("Content-Length: 10\r\n\r\n"),
2466 // No response body because the test stops reading here.
2467 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2470 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2471 data_writes1, arraysize(data_writes1));
2472 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2474 TestCompletionCallback callback1;
2476 int rv = trans->Start(&request, callback1.callback(), log.bound());
2477 EXPECT_EQ(ERR_IO_PENDING, rv);
2479 rv = callback1.WaitForResult();
2480 EXPECT_EQ(OK, rv);
2481 net::CapturingNetLog::CapturedEntryList entries;
2482 log.GetEntries(&entries);
2483 size_t pos = ExpectLogContainsSomewhere(
2484 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2485 NetLog::PHASE_NONE);
2486 ExpectLogContainsSomewhere(
2487 entries, pos,
2488 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2489 NetLog::PHASE_NONE);
2491 const HttpResponseInfo* response = trans->GetResponseInfo();
2492 ASSERT_TRUE(response != NULL);
2493 ASSERT_FALSE(response->headers.get() == NULL);
2494 EXPECT_TRUE(response->headers->IsKeepAlive());
2495 EXPECT_EQ(407, response->headers->response_code());
2496 EXPECT_EQ(10, response->headers->GetContentLength());
2497 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2498 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2500 TestCompletionCallback callback2;
2502 // Wrong password (should be "bar").
2503 rv = trans->RestartWithAuth(
2504 AuthCredentials(kFoo, kBaz), callback2.callback());
2505 EXPECT_EQ(ERR_IO_PENDING, rv);
2507 rv = callback2.WaitForResult();
2508 EXPECT_EQ(OK, rv);
2510 response = trans->GetResponseInfo();
2511 ASSERT_TRUE(response != NULL);
2512 ASSERT_FALSE(response->headers.get() == NULL);
2513 EXPECT_TRUE(response->headers->IsKeepAlive());
2514 EXPECT_EQ(407, response->headers->response_code());
2515 EXPECT_EQ(10, response->headers->GetContentLength());
2516 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2517 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2519 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2520 // out of scope.
2521 session->CloseAllConnections();
2524 // Test that we don't read the response body when we fail to establish a tunnel,
2525 // even if the user cancels the proxy's auth attempt.
2526 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2527 HttpRequestInfo request;
2528 request.method = "GET";
2529 request.url = GURL("https://www.google.com/");
2530 request.load_flags = 0;
2532 // Configure against proxy server "myproxy:70".
2533 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2535 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2537 scoped_ptr<HttpTransaction> trans(
2538 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2540 // Since we have proxy, should try to establish tunnel.
2541 MockWrite data_writes[] = {
2542 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2543 "Host: www.google.com\r\n"
2544 "Proxy-Connection: keep-alive\r\n\r\n"),
2547 // The proxy responds to the connect with a 407.
2548 MockRead data_reads[] = {
2549 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2550 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2551 MockRead("Content-Length: 10\r\n\r\n"),
2552 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2555 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2556 data_writes, arraysize(data_writes));
2557 session_deps_.socket_factory->AddSocketDataProvider(&data);
2559 TestCompletionCallback callback;
2561 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2562 EXPECT_EQ(ERR_IO_PENDING, rv);
2564 rv = callback.WaitForResult();
2565 EXPECT_EQ(OK, rv);
2567 const HttpResponseInfo* response = trans->GetResponseInfo();
2568 ASSERT_TRUE(response != NULL);
2570 EXPECT_TRUE(response->headers->IsKeepAlive());
2571 EXPECT_EQ(407, response->headers->response_code());
2572 EXPECT_EQ(10, response->headers->GetContentLength());
2573 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2575 std::string response_data;
2576 rv = ReadTransaction(trans.get(), &response_data);
2577 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2579 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2580 session->CloseAllConnections();
2583 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2584 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2585 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2586 HttpRequestInfo request;
2587 request.method = "GET";
2588 request.url = GURL("http://www.google.com/");
2589 request.load_flags = 0;
2591 // We are using a DIRECT connection (i.e. no proxy) for this session.
2592 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2593 scoped_ptr<HttpTransaction> trans(
2594 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
2596 MockWrite data_writes1[] = {
2597 MockWrite("GET / HTTP/1.1\r\n"
2598 "Host: www.google.com\r\n"
2599 "Connection: keep-alive\r\n\r\n"),
2602 MockRead data_reads1[] = {
2603 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2604 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2605 // Large content-length -- won't matter, as connection will be reset.
2606 MockRead("Content-Length: 10000\r\n\r\n"),
2607 MockRead(SYNCHRONOUS, ERR_FAILED),
2610 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2611 data_writes1, arraysize(data_writes1));
2612 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2614 TestCompletionCallback callback;
2616 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2617 EXPECT_EQ(ERR_IO_PENDING, rv);
2619 rv = callback.WaitForResult();
2620 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2623 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2624 // through a non-authenticating proxy. The request should fail with
2625 // ERR_UNEXPECTED_PROXY_AUTH.
2626 // Note that it is impossible to detect if an HTTP server returns a 407 through
2627 // a non-authenticating proxy - there is nothing to indicate whether the
2628 // response came from the proxy or the server, so it is treated as if the proxy
2629 // issued the challenge.
2630 TEST_P(HttpNetworkTransactionTest,
2631 HttpsServerRequestsProxyAuthThroughProxy) {
2632 HttpRequestInfo request;
2633 request.method = "GET";
2634 request.url = GURL("https://www.google.com/");
2636 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2637 CapturingBoundNetLog log;
2638 session_deps_.net_log = log.bound().net_log();
2639 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2641 // Since we have proxy, should try to establish tunnel.
2642 MockWrite data_writes1[] = {
2643 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2644 "Host: www.google.com\r\n"
2645 "Proxy-Connection: keep-alive\r\n\r\n"),
2647 MockWrite("GET / HTTP/1.1\r\n"
2648 "Host: www.google.com\r\n"
2649 "Connection: keep-alive\r\n\r\n"),
2652 MockRead data_reads1[] = {
2653 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2655 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2656 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2657 MockRead("\r\n"),
2658 MockRead(SYNCHRONOUS, OK),
2661 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2662 data_writes1, arraysize(data_writes1));
2663 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2664 SSLSocketDataProvider ssl(ASYNC, OK);
2665 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2667 TestCompletionCallback callback1;
2669 scoped_ptr<HttpTransaction> trans(
2670 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2672 int rv = trans->Start(&request, callback1.callback(), log.bound());
2673 EXPECT_EQ(ERR_IO_PENDING, rv);
2675 rv = callback1.WaitForResult();
2676 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2677 net::CapturingNetLog::CapturedEntryList entries;
2678 log.GetEntries(&entries);
2679 size_t pos = ExpectLogContainsSomewhere(
2680 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2681 NetLog::PHASE_NONE);
2682 ExpectLogContainsSomewhere(
2683 entries, pos,
2684 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2685 NetLog::PHASE_NONE);
2688 // Test the load timing for HTTPS requests with an HTTP proxy.
2689 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2690 HttpRequestInfo request1;
2691 request1.method = "GET";
2692 request1.url = GURL("https://www.google.com/1");
2694 HttpRequestInfo request2;
2695 request2.method = "GET";
2696 request2.url = GURL("https://www.google.com/2");
2698 // Configure against proxy server "myproxy:70".
2699 session_deps_.proxy_service.reset(
2700 ProxyService::CreateFixed("PROXY myproxy:70"));
2701 CapturingBoundNetLog log;
2702 session_deps_.net_log = log.bound().net_log();
2703 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2705 // Since we have proxy, should try to establish tunnel.
2706 MockWrite data_writes1[] = {
2707 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2708 "Host: www.google.com\r\n"
2709 "Proxy-Connection: keep-alive\r\n\r\n"),
2711 MockWrite("GET /1 HTTP/1.1\r\n"
2712 "Host: www.google.com\r\n"
2713 "Connection: keep-alive\r\n\r\n"),
2715 MockWrite("GET /2 HTTP/1.1\r\n"
2716 "Host: www.google.com\r\n"
2717 "Connection: keep-alive\r\n\r\n"),
2720 // The proxy responds to the connect with a 407, using a persistent
2721 // connection.
2722 MockRead data_reads1[] = {
2723 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2725 MockRead("HTTP/1.1 200 OK\r\n"),
2726 MockRead("Content-Length: 1\r\n\r\n"),
2727 MockRead(SYNCHRONOUS, "1"),
2729 MockRead("HTTP/1.1 200 OK\r\n"),
2730 MockRead("Content-Length: 2\r\n\r\n"),
2731 MockRead(SYNCHRONOUS, "22"),
2734 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2735 data_writes1, arraysize(data_writes1));
2736 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2737 SSLSocketDataProvider ssl(ASYNC, OK);
2738 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2740 TestCompletionCallback callback1;
2741 scoped_ptr<HttpTransaction> trans1(
2742 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2744 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2745 EXPECT_EQ(ERR_IO_PENDING, rv);
2747 rv = callback1.WaitForResult();
2748 EXPECT_EQ(OK, rv);
2750 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2751 ASSERT_TRUE(response1 != NULL);
2752 ASSERT_TRUE(response1->headers.get() != NULL);
2753 EXPECT_EQ(1, response1->headers->GetContentLength());
2755 LoadTimingInfo load_timing_info1;
2756 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2757 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2759 trans1.reset();
2761 TestCompletionCallback callback2;
2762 scoped_ptr<HttpTransaction> trans2(
2763 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2765 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2766 EXPECT_EQ(ERR_IO_PENDING, rv);
2768 rv = callback2.WaitForResult();
2769 EXPECT_EQ(OK, rv);
2771 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2772 ASSERT_TRUE(response2 != NULL);
2773 ASSERT_TRUE(response2->headers.get() != NULL);
2774 EXPECT_EQ(2, response2->headers->GetContentLength());
2776 LoadTimingInfo load_timing_info2;
2777 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2778 TestLoadTimingReused(load_timing_info2);
2780 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2782 trans2.reset();
2783 session->CloseAllConnections();
2786 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2787 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2788 HttpRequestInfo request1;
2789 request1.method = "GET";
2790 request1.url = GURL("https://www.google.com/1");
2792 HttpRequestInfo request2;
2793 request2.method = "GET";
2794 request2.url = GURL("https://www.google.com/2");
2796 // Configure against proxy server "myproxy:70".
2797 session_deps_.proxy_service.reset(
2798 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2799 CapturingBoundNetLog log;
2800 session_deps_.net_log = log.bound().net_log();
2801 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2803 // Since we have proxy, should try to establish tunnel.
2804 MockWrite data_writes1[] = {
2805 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2806 "Host: www.google.com\r\n"
2807 "Proxy-Connection: keep-alive\r\n\r\n"),
2809 MockWrite("GET /1 HTTP/1.1\r\n"
2810 "Host: www.google.com\r\n"
2811 "Connection: keep-alive\r\n\r\n"),
2813 MockWrite("GET /2 HTTP/1.1\r\n"
2814 "Host: www.google.com\r\n"
2815 "Connection: keep-alive\r\n\r\n"),
2818 // The proxy responds to the connect with a 407, using a persistent
2819 // connection.
2820 MockRead data_reads1[] = {
2821 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2823 MockRead("HTTP/1.1 200 OK\r\n"),
2824 MockRead("Content-Length: 1\r\n\r\n"),
2825 MockRead(SYNCHRONOUS, "1"),
2827 MockRead("HTTP/1.1 200 OK\r\n"),
2828 MockRead("Content-Length: 2\r\n\r\n"),
2829 MockRead(SYNCHRONOUS, "22"),
2832 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2833 data_writes1, arraysize(data_writes1));
2834 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2835 SSLSocketDataProvider ssl(ASYNC, OK);
2836 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2838 TestCompletionCallback callback1;
2839 scoped_ptr<HttpTransaction> trans1(
2840 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2842 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2843 EXPECT_EQ(ERR_IO_PENDING, rv);
2845 rv = callback1.WaitForResult();
2846 EXPECT_EQ(OK, rv);
2848 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2849 ASSERT_TRUE(response1 != NULL);
2850 ASSERT_TRUE(response1->headers.get() != NULL);
2851 EXPECT_EQ(1, response1->headers->GetContentLength());
2853 LoadTimingInfo load_timing_info1;
2854 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2855 TestLoadTimingNotReusedWithPac(load_timing_info1,
2856 CONNECT_TIMING_HAS_SSL_TIMES);
2858 trans1.reset();
2860 TestCompletionCallback callback2;
2861 scoped_ptr<HttpTransaction> trans2(
2862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2864 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2865 EXPECT_EQ(ERR_IO_PENDING, rv);
2867 rv = callback2.WaitForResult();
2868 EXPECT_EQ(OK, rv);
2870 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2871 ASSERT_TRUE(response2 != NULL);
2872 ASSERT_TRUE(response2->headers.get() != NULL);
2873 EXPECT_EQ(2, response2->headers->GetContentLength());
2875 LoadTimingInfo load_timing_info2;
2876 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2877 TestLoadTimingReusedWithPac(load_timing_info2);
2879 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2881 trans2.reset();
2882 session->CloseAllConnections();
2885 // Test a simple get through an HTTPS Proxy.
2886 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2887 HttpRequestInfo request;
2888 request.method = "GET";
2889 request.url = GURL("http://www.google.com/");
2891 // Configure against https proxy server "proxy:70".
2892 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2893 "https://proxy:70"));
2894 CapturingBoundNetLog log;
2895 session_deps_.net_log = log.bound().net_log();
2896 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2898 // Since we have proxy, should use full url
2899 MockWrite data_writes1[] = {
2900 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2901 "Host: www.google.com\r\n"
2902 "Proxy-Connection: keep-alive\r\n\r\n"),
2905 MockRead data_reads1[] = {
2906 MockRead("HTTP/1.1 200 OK\r\n"),
2907 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2908 MockRead("Content-Length: 100\r\n\r\n"),
2909 MockRead(SYNCHRONOUS, OK),
2912 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2913 data_writes1, arraysize(data_writes1));
2914 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2915 SSLSocketDataProvider ssl(ASYNC, OK);
2916 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2918 TestCompletionCallback callback1;
2920 scoped_ptr<HttpTransaction> trans(
2921 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2923 int rv = trans->Start(&request, callback1.callback(), log.bound());
2924 EXPECT_EQ(ERR_IO_PENDING, rv);
2926 rv = callback1.WaitForResult();
2927 EXPECT_EQ(OK, rv);
2929 LoadTimingInfo load_timing_info;
2930 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2931 TestLoadTimingNotReused(load_timing_info,
2932 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2934 const HttpResponseInfo* response = trans->GetResponseInfo();
2935 ASSERT_TRUE(response != NULL);
2937 EXPECT_TRUE(response->headers->IsKeepAlive());
2938 EXPECT_EQ(200, response->headers->response_code());
2939 EXPECT_EQ(100, response->headers->GetContentLength());
2940 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2942 // The password prompt info should not be set.
2943 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2946 // Test a SPDY get through an HTTPS Proxy.
2947 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2948 HttpRequestInfo request;
2949 request.method = "GET";
2950 request.url = GURL("http://www.google.com/");
2951 request.load_flags = 0;
2953 // Configure against https proxy server "proxy:70".
2954 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2955 "https://proxy:70"));
2956 CapturingBoundNetLog log;
2957 session_deps_.net_log = log.bound().net_log();
2958 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2960 // fetch http://www.google.com/ via SPDY
2961 scoped_ptr<SpdyFrame> req(
2962 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2963 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2965 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2966 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2967 MockRead spdy_reads[] = {
2968 CreateMockRead(*resp),
2969 CreateMockRead(*data),
2970 MockRead(ASYNC, 0, 0),
2973 DelayedSocketData spdy_data(
2974 1, // wait for one write to finish before reading.
2975 spdy_reads, arraysize(spdy_reads),
2976 spdy_writes, arraysize(spdy_writes));
2977 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2979 SSLSocketDataProvider ssl(ASYNC, OK);
2980 ssl.SetNextProto(GetParam());
2981 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2983 TestCompletionCallback callback1;
2985 scoped_ptr<HttpTransaction> trans(
2986 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2988 int rv = trans->Start(&request, callback1.callback(), log.bound());
2989 EXPECT_EQ(ERR_IO_PENDING, rv);
2991 rv = callback1.WaitForResult();
2992 EXPECT_EQ(OK, rv);
2994 LoadTimingInfo load_timing_info;
2995 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2996 TestLoadTimingNotReused(load_timing_info,
2997 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2999 const HttpResponseInfo* response = trans->GetResponseInfo();
3000 ASSERT_TRUE(response != NULL);
3001 ASSERT_TRUE(response->headers.get() != NULL);
3002 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3004 std::string response_data;
3005 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3006 EXPECT_EQ(kUploadData, response_data);
3009 // Test a SPDY get through an HTTPS Proxy.
3010 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3011 HttpRequestInfo request;
3012 request.method = "GET";
3013 request.url = GURL("http://www.google.com/");
3014 request.load_flags = 0;
3016 // Configure against https proxy server "myproxy:70".
3017 session_deps_.proxy_service.reset(
3018 ProxyService::CreateFixed("https://myproxy:70"));
3019 CapturingBoundNetLog log;
3020 session_deps_.net_log = log.bound().net_log();
3021 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3023 // The first request will be a bare GET, the second request will be a
3024 // GET with a Proxy-Authorization header.
3025 scoped_ptr<SpdyFrame> req_get(
3026 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3027 const char* const kExtraAuthorizationHeaders[] = {
3028 "proxy-authorization", "Basic Zm9vOmJhcg=="
3030 scoped_ptr<SpdyFrame> req_get_authorization(
3031 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3032 arraysize(kExtraAuthorizationHeaders) / 2,
3033 false,
3035 LOWEST,
3036 false));
3037 MockWrite spdy_writes[] = {
3038 CreateMockWrite(*req_get, 1),
3039 CreateMockWrite(*req_get_authorization, 4),
3042 // The first response is a 407 proxy authentication challenge, and the second
3043 // response will be a 200 response since the second request includes a valid
3044 // Authorization header.
3045 const char* const kExtraAuthenticationHeaders[] = {
3046 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3048 scoped_ptr<SpdyFrame> resp_authentication(
3049 spdy_util_.ConstructSpdySynReplyError(
3050 "407 Proxy Authentication Required",
3051 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3052 1));
3053 scoped_ptr<SpdyFrame> body_authentication(
3054 spdy_util_.ConstructSpdyBodyFrame(1, true));
3055 scoped_ptr<SpdyFrame> resp_data(
3056 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3057 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3058 MockRead spdy_reads[] = {
3059 CreateMockRead(*resp_authentication, 2),
3060 CreateMockRead(*body_authentication, 3),
3061 CreateMockRead(*resp_data, 5),
3062 CreateMockRead(*body_data, 6),
3063 MockRead(ASYNC, 0, 7),
3066 OrderedSocketData data(
3067 spdy_reads, arraysize(spdy_reads),
3068 spdy_writes, arraysize(spdy_writes));
3069 session_deps_.socket_factory->AddSocketDataProvider(&data);
3071 SSLSocketDataProvider ssl(ASYNC, OK);
3072 ssl.SetNextProto(GetParam());
3073 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3075 TestCompletionCallback callback1;
3077 scoped_ptr<HttpTransaction> trans(
3078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3080 int rv = trans->Start(&request, callback1.callback(), log.bound());
3081 EXPECT_EQ(ERR_IO_PENDING, rv);
3083 rv = callback1.WaitForResult();
3084 EXPECT_EQ(OK, rv);
3086 const HttpResponseInfo* const response = trans->GetResponseInfo();
3088 ASSERT_TRUE(response != NULL);
3089 ASSERT_TRUE(response->headers.get() != NULL);
3090 EXPECT_EQ(407, response->headers->response_code());
3091 EXPECT_TRUE(response->was_fetched_via_spdy);
3092 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3094 TestCompletionCallback callback2;
3096 rv = trans->RestartWithAuth(
3097 AuthCredentials(kFoo, kBar), callback2.callback());
3098 EXPECT_EQ(ERR_IO_PENDING, rv);
3100 rv = callback2.WaitForResult();
3101 EXPECT_EQ(OK, rv);
3103 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3105 ASSERT_TRUE(response_restart != NULL);
3106 ASSERT_TRUE(response_restart->headers.get() != NULL);
3107 EXPECT_EQ(200, response_restart->headers->response_code());
3108 // The password prompt info should not be set.
3109 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3112 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3113 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3114 HttpRequestInfo request;
3115 request.method = "GET";
3116 request.url = GURL("https://www.google.com/");
3117 request.load_flags = 0;
3119 // Configure against https proxy server "proxy:70".
3120 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3121 "https://proxy:70"));
3122 CapturingBoundNetLog log;
3123 session_deps_.net_log = log.bound().net_log();
3124 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3126 scoped_ptr<HttpTransaction> trans(
3127 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3129 // CONNECT to www.google.com:443 via SPDY
3130 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3131 LOWEST));
3132 // fetch https://www.google.com/ via HTTP
3134 const char get[] = "GET / HTTP/1.1\r\n"
3135 "Host: www.google.com\r\n"
3136 "Connection: keep-alive\r\n\r\n";
3137 scoped_ptr<SpdyFrame> wrapped_get(
3138 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3139 scoped_ptr<SpdyFrame> conn_resp(
3140 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3141 const char resp[] = "HTTP/1.1 200 OK\r\n"
3142 "Content-Length: 10\r\n\r\n";
3143 scoped_ptr<SpdyFrame> wrapped_get_resp(
3144 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3145 scoped_ptr<SpdyFrame> wrapped_body(
3146 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3147 scoped_ptr<SpdyFrame> window_update(
3148 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3150 MockWrite spdy_writes[] = {
3151 CreateMockWrite(*connect, 1),
3152 CreateMockWrite(*wrapped_get, 3),
3153 CreateMockWrite(*window_update, 5),
3156 MockRead spdy_reads[] = {
3157 CreateMockRead(*conn_resp, 2, ASYNC),
3158 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3159 CreateMockRead(*wrapped_body, 6, ASYNC),
3160 CreateMockRead(*wrapped_body, 7, ASYNC),
3161 MockRead(ASYNC, 0, 8),
3164 OrderedSocketData spdy_data(
3165 spdy_reads, arraysize(spdy_reads),
3166 spdy_writes, arraysize(spdy_writes));
3167 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3169 SSLSocketDataProvider ssl(ASYNC, OK);
3170 ssl.SetNextProto(GetParam());
3171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3172 SSLSocketDataProvider ssl2(ASYNC, OK);
3173 ssl2.was_npn_negotiated = false;
3174 ssl2.protocol_negotiated = kProtoUnknown;
3175 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3177 TestCompletionCallback callback1;
3179 int rv = trans->Start(&request, callback1.callback(), log.bound());
3180 EXPECT_EQ(ERR_IO_PENDING, rv);
3182 rv = callback1.WaitForResult();
3183 EXPECT_EQ(OK, rv);
3185 LoadTimingInfo load_timing_info;
3186 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3187 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3189 const HttpResponseInfo* response = trans->GetResponseInfo();
3190 ASSERT_TRUE(response != NULL);
3191 ASSERT_TRUE(response->headers.get() != NULL);
3192 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3194 std::string response_data;
3195 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3196 EXPECT_EQ("1234567890", response_data);
3199 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3200 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3201 HttpRequestInfo request;
3202 request.method = "GET";
3203 request.url = GURL("https://www.google.com/");
3204 request.load_flags = 0;
3206 // Configure against https proxy server "proxy:70".
3207 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3208 "https://proxy:70"));
3209 CapturingBoundNetLog log;
3210 session_deps_.net_log = log.bound().net_log();
3211 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3213 scoped_ptr<HttpTransaction> trans(
3214 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3216 // CONNECT to www.google.com:443 via SPDY
3217 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3218 LOWEST));
3219 // fetch https://www.google.com/ via SPDY
3220 const char* const kMyUrl = "https://www.google.com/";
3221 scoped_ptr<SpdyFrame> get(
3222 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3223 scoped_ptr<SpdyFrame> wrapped_get(
3224 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3225 scoped_ptr<SpdyFrame> conn_resp(
3226 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3227 scoped_ptr<SpdyFrame> get_resp(
3228 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3229 scoped_ptr<SpdyFrame> wrapped_get_resp(
3230 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3231 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3232 scoped_ptr<SpdyFrame> wrapped_body(
3233 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3234 scoped_ptr<SpdyFrame> window_update_get_resp(
3235 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3236 scoped_ptr<SpdyFrame> window_update_body(
3237 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3239 MockWrite spdy_writes[] = {
3240 CreateMockWrite(*connect, 1),
3241 CreateMockWrite(*wrapped_get, 3),
3242 CreateMockWrite(*window_update_get_resp, 5),
3243 CreateMockWrite(*window_update_body, 7),
3246 MockRead spdy_reads[] = {
3247 CreateMockRead(*conn_resp, 2, ASYNC),
3248 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3249 CreateMockRead(*wrapped_body, 6, ASYNC),
3250 MockRead(ASYNC, 0, 8),
3253 OrderedSocketData spdy_data(
3254 spdy_reads, arraysize(spdy_reads),
3255 spdy_writes, arraysize(spdy_writes));
3256 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3258 SSLSocketDataProvider ssl(ASYNC, OK);
3259 ssl.SetNextProto(GetParam());
3260 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3261 SSLSocketDataProvider ssl2(ASYNC, OK);
3262 ssl2.SetNextProto(GetParam());
3263 ssl2.protocol_negotiated = GetParam();
3264 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3266 TestCompletionCallback callback1;
3268 int rv = trans->Start(&request, callback1.callback(), log.bound());
3269 EXPECT_EQ(ERR_IO_PENDING, rv);
3271 rv = callback1.WaitForResult();
3272 EXPECT_EQ(OK, rv);
3274 LoadTimingInfo load_timing_info;
3275 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3276 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3278 const HttpResponseInfo* response = trans->GetResponseInfo();
3279 ASSERT_TRUE(response != NULL);
3280 ASSERT_TRUE(response->headers.get() != NULL);
3281 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3283 std::string response_data;
3284 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3285 EXPECT_EQ(kUploadData, response_data);
3288 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3289 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3290 HttpRequestInfo request;
3291 request.method = "GET";
3292 request.url = GURL("https://www.google.com/");
3293 request.load_flags = 0;
3295 // Configure against https proxy server "proxy:70".
3296 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3297 "https://proxy:70"));
3298 CapturingBoundNetLog log;
3299 session_deps_.net_log = log.bound().net_log();
3300 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3302 scoped_ptr<HttpTransaction> trans(
3303 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3305 // CONNECT to www.google.com:443 via SPDY
3306 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3307 LOWEST));
3308 scoped_ptr<SpdyFrame> get(
3309 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3311 MockWrite spdy_writes[] = {
3312 CreateMockWrite(*connect, 1),
3313 CreateMockWrite(*get, 3),
3316 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3317 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3318 MockRead spdy_reads[] = {
3319 CreateMockRead(*resp, 2, ASYNC),
3320 MockRead(ASYNC, 0, 4),
3323 OrderedSocketData spdy_data(
3324 spdy_reads, arraysize(spdy_reads),
3325 spdy_writes, arraysize(spdy_writes));
3326 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3328 SSLSocketDataProvider ssl(ASYNC, OK);
3329 ssl.SetNextProto(GetParam());
3330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3331 SSLSocketDataProvider ssl2(ASYNC, OK);
3332 ssl2.SetNextProto(GetParam());
3333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3335 TestCompletionCallback callback1;
3337 int rv = trans->Start(&request, callback1.callback(), log.bound());
3338 EXPECT_EQ(ERR_IO_PENDING, rv);
3340 rv = callback1.WaitForResult();
3341 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3343 // TODO(ttuttle): Anything else to check here?
3346 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3347 // HTTPS Proxy to different servers.
3348 TEST_P(HttpNetworkTransactionTest,
3349 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3350 // Configure against https proxy server "proxy:70".
3351 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3352 "https://proxy:70"));
3353 CapturingBoundNetLog log;
3354 session_deps_.net_log = log.bound().net_log();
3355 scoped_refptr<HttpNetworkSession> session(
3356 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3358 HttpRequestInfo request1;
3359 request1.method = "GET";
3360 request1.url = GURL("https://www.google.com/");
3361 request1.load_flags = 0;
3363 HttpRequestInfo request2;
3364 request2.method = "GET";
3365 request2.url = GURL("https://news.google.com/");
3366 request2.load_flags = 0;
3368 // CONNECT to www.google.com:443 via SPDY.
3369 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3370 LOWEST));
3371 scoped_ptr<SpdyFrame> conn_resp1(
3372 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3374 // Fetch https://www.google.com/ via HTTP.
3375 const char get1[] = "GET / HTTP/1.1\r\n"
3376 "Host: www.google.com\r\n"
3377 "Connection: keep-alive\r\n\r\n";
3378 scoped_ptr<SpdyFrame> wrapped_get1(
3379 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3380 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3381 "Content-Length: 1\r\n\r\n";
3382 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3383 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3384 scoped_ptr<SpdyFrame> wrapped_body1(
3385 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3386 scoped_ptr<SpdyFrame> window_update(
3387 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3389 // CONNECT to news.google.com:443 via SPDY.
3390 SpdySynStreamIR connect2_ir(3);
3391 spdy_util_.SetPriority(LOWEST, &connect2_ir);
3392 connect2_ir.SetHeader(spdy_util_.GetMethodKey(), "CONNECT");
3393 connect2_ir.SetHeader(spdy_util_.GetPathKey(), "news.google.com:443");
3394 connect2_ir.SetHeader(spdy_util_.GetHostKey(), "news.google.com");
3395 spdy_util_.MaybeAddVersionHeader(&connect2_ir);
3396 scoped_ptr<SpdyFrame> connect2(
3397 spdy_util_.CreateFramer(false)->SerializeFrame(connect2_ir));
3399 scoped_ptr<SpdyFrame> conn_resp2(
3400 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3402 // Fetch https://news.google.com/ via HTTP.
3403 const char get2[] = "GET / HTTP/1.1\r\n"
3404 "Host: news.google.com\r\n"
3405 "Connection: keep-alive\r\n\r\n";
3406 scoped_ptr<SpdyFrame> wrapped_get2(
3407 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3408 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3409 "Content-Length: 2\r\n\r\n";
3410 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3411 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3412 scoped_ptr<SpdyFrame> wrapped_body2(
3413 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3415 MockWrite spdy_writes[] = {
3416 CreateMockWrite(*connect1, 0),
3417 CreateMockWrite(*wrapped_get1, 2),
3418 CreateMockWrite(*connect2, 5),
3419 CreateMockWrite(*wrapped_get2, 7),
3422 MockRead spdy_reads[] = {
3423 CreateMockRead(*conn_resp1, 1, ASYNC),
3424 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3425 CreateMockRead(*wrapped_body1, 4, ASYNC),
3426 CreateMockRead(*conn_resp2, 6, ASYNC),
3427 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3428 CreateMockRead(*wrapped_body2, 9, ASYNC),
3429 MockRead(ASYNC, 0, 10),
3432 DeterministicSocketData spdy_data(
3433 spdy_reads, arraysize(spdy_reads),
3434 spdy_writes, arraysize(spdy_writes));
3435 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3437 SSLSocketDataProvider ssl(ASYNC, OK);
3438 ssl.SetNextProto(GetParam());
3439 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3440 SSLSocketDataProvider ssl2(ASYNC, OK);
3441 ssl2.was_npn_negotiated = false;
3442 ssl2.protocol_negotiated = kProtoUnknown;
3443 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3444 SSLSocketDataProvider ssl3(ASYNC, OK);
3445 ssl3.was_npn_negotiated = false;
3446 ssl3.protocol_negotiated = kProtoUnknown;
3447 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3449 TestCompletionCallback callback;
3451 scoped_ptr<HttpTransaction> trans(
3452 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3453 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3454 EXPECT_EQ(ERR_IO_PENDING, rv);
3455 // The first connect and request, each of their responses, and the body.
3456 spdy_data.RunFor(5);
3458 rv = callback.WaitForResult();
3459 EXPECT_EQ(OK, rv);
3461 LoadTimingInfo load_timing_info;
3462 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3463 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3465 const HttpResponseInfo* response = trans->GetResponseInfo();
3466 ASSERT_TRUE(response != NULL);
3467 ASSERT_TRUE(response->headers.get() != NULL);
3468 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3470 std::string response_data;
3471 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3472 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3474 scoped_ptr<HttpTransaction> trans2(
3475 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3476 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3477 EXPECT_EQ(ERR_IO_PENDING, rv);
3479 // The second connect and request, each of their responses, and the body.
3480 spdy_data.RunFor(5);
3481 rv = callback.WaitForResult();
3482 EXPECT_EQ(OK, rv);
3484 LoadTimingInfo load_timing_info2;
3485 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3486 // Even though the SPDY connection is reused, a new tunnelled connection has
3487 // to be created, so the socket's load timing looks like a fresh connection.
3488 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3490 // The requests should have different IDs, since they each are using their own
3491 // separate stream.
3492 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3494 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3497 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3498 // HTTPS Proxy to the same server.
3499 TEST_P(HttpNetworkTransactionTest,
3500 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3501 // Configure against https proxy server "proxy:70".
3502 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3503 "https://proxy:70"));
3504 CapturingBoundNetLog log;
3505 session_deps_.net_log = log.bound().net_log();
3506 scoped_refptr<HttpNetworkSession> session(
3507 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3509 HttpRequestInfo request1;
3510 request1.method = "GET";
3511 request1.url = GURL("https://www.google.com/");
3512 request1.load_flags = 0;
3514 HttpRequestInfo request2;
3515 request2.method = "GET";
3516 request2.url = GURL("https://www.google.com/2");
3517 request2.load_flags = 0;
3519 // CONNECT to www.google.com:443 via SPDY.
3520 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3521 LOWEST));
3522 scoped_ptr<SpdyFrame> conn_resp1(
3523 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3525 // Fetch https://www.google.com/ via HTTP.
3526 const char get1[] = "GET / HTTP/1.1\r\n"
3527 "Host: www.google.com\r\n"
3528 "Connection: keep-alive\r\n\r\n";
3529 scoped_ptr<SpdyFrame> wrapped_get1(
3530 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3531 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3532 "Content-Length: 1\r\n\r\n";
3533 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3534 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3535 scoped_ptr<SpdyFrame> wrapped_body1(
3536 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3537 scoped_ptr<SpdyFrame> window_update(
3538 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3540 // Fetch https://www.google.com/2 via HTTP.
3541 const char get2[] = "GET /2 HTTP/1.1\r\n"
3542 "Host: www.google.com\r\n"
3543 "Connection: keep-alive\r\n\r\n";
3544 scoped_ptr<SpdyFrame> wrapped_get2(
3545 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3546 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3547 "Content-Length: 2\r\n\r\n";
3548 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3549 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3550 scoped_ptr<SpdyFrame> wrapped_body2(
3551 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3553 MockWrite spdy_writes[] = {
3554 CreateMockWrite(*connect1, 0),
3555 CreateMockWrite(*wrapped_get1, 2),
3556 CreateMockWrite(*wrapped_get2, 5),
3559 MockRead spdy_reads[] = {
3560 CreateMockRead(*conn_resp1, 1, ASYNC),
3561 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3562 CreateMockRead(*wrapped_body1, 4, ASYNC),
3563 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3564 CreateMockRead(*wrapped_body2, 7, ASYNC),
3565 MockRead(ASYNC, 0, 8),
3568 DeterministicSocketData spdy_data(
3569 spdy_reads, arraysize(spdy_reads),
3570 spdy_writes, arraysize(spdy_writes));
3571 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3573 SSLSocketDataProvider ssl(ASYNC, OK);
3574 ssl.SetNextProto(GetParam());
3575 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3576 SSLSocketDataProvider ssl2(ASYNC, OK);
3577 ssl2.was_npn_negotiated = false;
3578 ssl2.protocol_negotiated = kProtoUnknown;
3579 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3581 TestCompletionCallback callback;
3583 scoped_ptr<HttpTransaction> trans(
3584 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3585 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3586 EXPECT_EQ(ERR_IO_PENDING, rv);
3587 // The first connect and request, each of their responses, and the body.
3588 spdy_data.RunFor(5);
3590 rv = callback.WaitForResult();
3591 EXPECT_EQ(OK, rv);
3593 LoadTimingInfo load_timing_info;
3594 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3595 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3597 const HttpResponseInfo* response = trans->GetResponseInfo();
3598 ASSERT_TRUE(response != NULL);
3599 ASSERT_TRUE(response->headers.get() != NULL);
3600 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3602 std::string response_data;
3603 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3604 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3605 trans.reset();
3607 scoped_ptr<HttpTransaction> trans2(
3608 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3609 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3610 EXPECT_EQ(ERR_IO_PENDING, rv);
3612 // The second request, response, and body. There should not be a second
3613 // connect.
3614 spdy_data.RunFor(3);
3615 rv = callback.WaitForResult();
3616 EXPECT_EQ(OK, rv);
3618 LoadTimingInfo load_timing_info2;
3619 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3620 TestLoadTimingReused(load_timing_info2);
3622 // The requests should have the same ID.
3623 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3625 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3628 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3629 // Proxy to different servers.
3630 TEST_P(HttpNetworkTransactionTest,
3631 HttpsProxySpdyLoadTimingTwoHttpRequests) {
3632 // Configure against https proxy server "proxy:70".
3633 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3634 "https://proxy:70"));
3635 CapturingBoundNetLog log;
3636 session_deps_.net_log = log.bound().net_log();
3637 scoped_refptr<HttpNetworkSession> session(
3638 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3640 HttpRequestInfo request1;
3641 request1.method = "GET";
3642 request1.url = GURL("http://www.google.com/");
3643 request1.load_flags = 0;
3645 HttpRequestInfo request2;
3646 request2.method = "GET";
3647 request2.url = GURL("http://news.google.com/");
3648 request2.load_flags = 0;
3650 // http://www.google.com/
3651 scoped_ptr<SpdyHeaderBlock> headers(
3652 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3653 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
3654 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3655 scoped_ptr<SpdyFrame> get_resp1(
3656 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3657 scoped_ptr<SpdyFrame> body1(
3658 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3660 // http://news.google.com/
3661 scoped_ptr<SpdyHeaderBlock> headers2(
3662 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3663 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
3664 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3665 scoped_ptr<SpdyFrame> get_resp2(
3666 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3667 scoped_ptr<SpdyFrame> body2(
3668 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3670 MockWrite spdy_writes[] = {
3671 CreateMockWrite(*get1, 0),
3672 CreateMockWrite(*get2, 3),
3675 MockRead spdy_reads[] = {
3676 CreateMockRead(*get_resp1, 1, ASYNC),
3677 CreateMockRead(*body1, 2, ASYNC),
3678 CreateMockRead(*get_resp2, 4, ASYNC),
3679 CreateMockRead(*body2, 5, ASYNC),
3680 MockRead(ASYNC, 0, 6),
3683 DeterministicSocketData spdy_data(
3684 spdy_reads, arraysize(spdy_reads),
3685 spdy_writes, arraysize(spdy_writes));
3686 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3688 SSLSocketDataProvider ssl(ASYNC, OK);
3689 ssl.SetNextProto(GetParam());
3690 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3692 TestCompletionCallback callback;
3694 scoped_ptr<HttpTransaction> trans(
3695 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3696 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3697 EXPECT_EQ(ERR_IO_PENDING, rv);
3698 spdy_data.RunFor(2);
3700 rv = callback.WaitForResult();
3701 EXPECT_EQ(OK, rv);
3703 LoadTimingInfo load_timing_info;
3704 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3705 TestLoadTimingNotReused(load_timing_info,
3706 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3708 const HttpResponseInfo* response = trans->GetResponseInfo();
3709 ASSERT_TRUE(response != NULL);
3710 ASSERT_TRUE(response->headers.get() != NULL);
3711 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3713 std::string response_data;
3714 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3715 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3716 spdy_data.RunFor(1);
3717 EXPECT_EQ(1, callback.WaitForResult());
3718 // Delete the first request, so the second one can reuse the socket.
3719 trans.reset();
3721 scoped_ptr<HttpTransaction> trans2(
3722 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3723 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3724 EXPECT_EQ(ERR_IO_PENDING, rv);
3726 spdy_data.RunFor(2);
3727 rv = callback.WaitForResult();
3728 EXPECT_EQ(OK, rv);
3730 LoadTimingInfo load_timing_info2;
3731 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3732 TestLoadTimingReused(load_timing_info2);
3734 // The requests should have the same ID.
3735 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3737 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3738 spdy_data.RunFor(1);
3739 EXPECT_EQ(2, callback.WaitForResult());
3742 // Test the challenge-response-retry sequence through an HTTPS Proxy
3743 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3744 HttpRequestInfo request;
3745 request.method = "GET";
3746 request.url = GURL("http://www.google.com/");
3747 // when the no authentication data flag is set.
3748 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3750 // Configure against https proxy server "myproxy:70".
3751 session_deps_.proxy_service.reset(
3752 ProxyService::CreateFixed("https://myproxy:70"));
3753 CapturingBoundNetLog log;
3754 session_deps_.net_log = log.bound().net_log();
3755 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3757 // Since we have proxy, should use full url
3758 MockWrite data_writes1[] = {
3759 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3760 "Host: www.google.com\r\n"
3761 "Proxy-Connection: keep-alive\r\n\r\n"),
3763 // After calling trans->RestartWithAuth(), this is the request we should
3764 // be issuing -- the final header line contains the credentials.
3765 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3766 "Host: www.google.com\r\n"
3767 "Proxy-Connection: keep-alive\r\n"
3768 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3771 // The proxy responds to the GET with a 407, using a persistent
3772 // connection.
3773 MockRead data_reads1[] = {
3774 // No credentials.
3775 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3776 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3777 MockRead("Proxy-Connection: keep-alive\r\n"),
3778 MockRead("Content-Length: 0\r\n\r\n"),
3780 MockRead("HTTP/1.1 200 OK\r\n"),
3781 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3782 MockRead("Content-Length: 100\r\n\r\n"),
3783 MockRead(SYNCHRONOUS, OK),
3786 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3787 data_writes1, arraysize(data_writes1));
3788 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3789 SSLSocketDataProvider ssl(ASYNC, OK);
3790 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3792 TestCompletionCallback callback1;
3794 scoped_ptr<HttpTransaction> trans(
3795 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3797 int rv = trans->Start(&request, callback1.callback(), log.bound());
3798 EXPECT_EQ(ERR_IO_PENDING, rv);
3800 rv = callback1.WaitForResult();
3801 EXPECT_EQ(OK, rv);
3803 LoadTimingInfo load_timing_info;
3804 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3805 TestLoadTimingNotReused(load_timing_info,
3806 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3808 const HttpResponseInfo* response = trans->GetResponseInfo();
3809 ASSERT_TRUE(response != NULL);
3810 ASSERT_FALSE(response->headers.get() == NULL);
3811 EXPECT_EQ(407, response->headers->response_code());
3812 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3813 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3815 TestCompletionCallback callback2;
3817 rv = trans->RestartWithAuth(
3818 AuthCredentials(kFoo, kBar), callback2.callback());
3819 EXPECT_EQ(ERR_IO_PENDING, rv);
3821 rv = callback2.WaitForResult();
3822 EXPECT_EQ(OK, rv);
3824 load_timing_info = LoadTimingInfo();
3825 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3826 // Retrying with HTTP AUTH is considered to be reusing a socket.
3827 TestLoadTimingReused(load_timing_info);
3829 response = trans->GetResponseInfo();
3830 ASSERT_TRUE(response != NULL);
3832 EXPECT_TRUE(response->headers->IsKeepAlive());
3833 EXPECT_EQ(200, response->headers->response_code());
3834 EXPECT_EQ(100, response->headers->GetContentLength());
3835 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3837 // The password prompt info should not be set.
3838 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3841 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3842 const MockRead& status, int expected_status) {
3843 HttpRequestInfo request;
3844 request.method = "GET";
3845 request.url = GURL("https://www.google.com/");
3846 request.load_flags = 0;
3848 // Configure against proxy server "myproxy:70".
3849 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3850 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3852 // Since we have proxy, should try to establish tunnel.
3853 MockWrite data_writes[] = {
3854 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3855 "Host: www.google.com\r\n"
3856 "Proxy-Connection: keep-alive\r\n\r\n"),
3859 MockRead data_reads[] = {
3860 status,
3861 MockRead("Content-Length: 10\r\n\r\n"),
3862 // No response body because the test stops reading here.
3863 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3866 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3867 data_writes, arraysize(data_writes));
3868 session_deps_.socket_factory->AddSocketDataProvider(&data);
3870 TestCompletionCallback callback;
3872 scoped_ptr<HttpTransaction> trans(
3873 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3875 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3876 EXPECT_EQ(ERR_IO_PENDING, rv);
3878 rv = callback.WaitForResult();
3879 EXPECT_EQ(expected_status, rv);
3882 void HttpNetworkTransactionTest::ConnectStatusHelper(
3883 const MockRead& status) {
3884 ConnectStatusHelperWithExpectedStatus(
3885 status, ERR_TUNNEL_CONNECTION_FAILED);
3888 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3889 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3892 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3893 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3896 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3897 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3900 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3901 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3904 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
3905 ConnectStatusHelper(
3906 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3909 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
3910 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3913 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
3914 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3917 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
3918 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3921 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
3922 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3925 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
3926 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3929 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
3930 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3933 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
3934 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3937 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
3938 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3941 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
3942 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3945 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
3946 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3949 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
3950 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3953 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
3954 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
3957 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
3958 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3961 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
3962 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3965 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
3966 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3969 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
3970 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3973 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
3974 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3977 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
3978 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3981 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
3982 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3985 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
3986 ConnectStatusHelperWithExpectedStatus(
3987 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3988 ERR_PROXY_AUTH_UNSUPPORTED);
3991 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
3992 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3995 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
3996 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3999 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4000 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4003 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4004 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4007 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4008 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4011 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4012 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4015 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4016 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4019 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4020 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4023 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4024 ConnectStatusHelper(
4025 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4028 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4029 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4032 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4033 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4036 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4037 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4040 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4041 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4044 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4045 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4048 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4049 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4052 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4053 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4056 // Test the flow when both the proxy server AND origin server require
4057 // authentication. Again, this uses basic auth for both since that is
4058 // the simplest to mock.
4059 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4060 HttpRequestInfo request;
4061 request.method = "GET";
4062 request.url = GURL("http://www.google.com/");
4063 request.load_flags = 0;
4065 // Configure against proxy server "myproxy:70".
4066 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4067 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4069 scoped_ptr<HttpTransaction> trans(
4070 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4072 MockWrite data_writes1[] = {
4073 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4074 "Host: www.google.com\r\n"
4075 "Proxy-Connection: keep-alive\r\n\r\n"),
4078 MockRead data_reads1[] = {
4079 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4080 // Give a couple authenticate options (only the middle one is actually
4081 // supported).
4082 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4083 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4084 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4085 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4086 // Large content-length -- won't matter, as connection will be reset.
4087 MockRead("Content-Length: 10000\r\n\r\n"),
4088 MockRead(SYNCHRONOUS, ERR_FAILED),
4091 // After calling trans->RestartWithAuth() the first time, this is the
4092 // request we should be issuing -- the final header line contains the
4093 // proxy's credentials.
4094 MockWrite data_writes2[] = {
4095 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4096 "Host: www.google.com\r\n"
4097 "Proxy-Connection: keep-alive\r\n"
4098 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4101 // Now the proxy server lets the request pass through to origin server.
4102 // The origin server responds with a 401.
4103 MockRead data_reads2[] = {
4104 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4105 // Note: We are using the same realm-name as the proxy server. This is
4106 // completely valid, as realms are unique across hosts.
4107 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4109 MockRead("Content-Length: 2000\r\n\r\n"),
4110 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4113 // After calling trans->RestartWithAuth() the second time, we should send
4114 // the credentials for both the proxy and origin server.
4115 MockWrite data_writes3[] = {
4116 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4117 "Host: www.google.com\r\n"
4118 "Proxy-Connection: keep-alive\r\n"
4119 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4120 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4123 // Lastly we get the desired content.
4124 MockRead data_reads3[] = {
4125 MockRead("HTTP/1.0 200 OK\r\n"),
4126 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4127 MockRead("Content-Length: 100\r\n\r\n"),
4128 MockRead(SYNCHRONOUS, OK),
4131 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4132 data_writes1, arraysize(data_writes1));
4133 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4134 data_writes2, arraysize(data_writes2));
4135 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4136 data_writes3, arraysize(data_writes3));
4137 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4138 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4139 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4141 TestCompletionCallback callback1;
4143 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4144 EXPECT_EQ(ERR_IO_PENDING, rv);
4146 rv = callback1.WaitForResult();
4147 EXPECT_EQ(OK, rv);
4149 const HttpResponseInfo* response = trans->GetResponseInfo();
4150 ASSERT_TRUE(response != NULL);
4151 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4153 TestCompletionCallback callback2;
4155 rv = trans->RestartWithAuth(
4156 AuthCredentials(kFoo, kBar), callback2.callback());
4157 EXPECT_EQ(ERR_IO_PENDING, rv);
4159 rv = callback2.WaitForResult();
4160 EXPECT_EQ(OK, rv);
4162 response = trans->GetResponseInfo();
4163 ASSERT_TRUE(response != NULL);
4164 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4166 TestCompletionCallback callback3;
4168 rv = trans->RestartWithAuth(
4169 AuthCredentials(kFoo2, kBar2), callback3.callback());
4170 EXPECT_EQ(ERR_IO_PENDING, rv);
4172 rv = callback3.WaitForResult();
4173 EXPECT_EQ(OK, rv);
4175 response = trans->GetResponseInfo();
4176 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4177 EXPECT_EQ(100, response->headers->GetContentLength());
4180 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4181 // can't hook into its internals to cause it to generate predictable NTLM
4182 // authorization headers.
4183 #if defined(NTLM_PORTABLE)
4184 // The NTLM authentication unit tests were generated by capturing the HTTP
4185 // requests and responses using Fiddler 2 and inspecting the generated random
4186 // bytes in the debugger.
4188 // Enter the correct password and authenticate successfully.
4189 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4190 HttpRequestInfo request;
4191 request.method = "GET";
4192 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4194 // Ensure load is not disrupted by flags which suppress behaviour specific
4195 // to other auth schemes.
4196 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4198 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4199 MockGetHostName);
4200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4202 MockWrite data_writes1[] = {
4203 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4204 "Host: 172.22.68.17\r\n"
4205 "Connection: keep-alive\r\n\r\n"),
4208 MockRead data_reads1[] = {
4209 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4210 // Negotiate and NTLM are often requested together. However, we only want
4211 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4212 // the header that requests Negotiate for this test.
4213 MockRead("WWW-Authenticate: NTLM\r\n"),
4214 MockRead("Connection: close\r\n"),
4215 MockRead("Content-Length: 42\r\n"),
4216 MockRead("Content-Type: text/html\r\n\r\n"),
4217 // Missing content -- won't matter, as connection will be reset.
4218 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4221 MockWrite data_writes2[] = {
4222 // After restarting with a null identity, this is the
4223 // request we should be issuing -- the final header line contains a Type
4224 // 1 message.
4225 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4226 "Host: 172.22.68.17\r\n"
4227 "Connection: keep-alive\r\n"
4228 "Authorization: NTLM "
4229 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4231 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4232 // (the credentials for the origin server). The second request continues
4233 // on the same connection.
4234 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4235 "Host: 172.22.68.17\r\n"
4236 "Connection: keep-alive\r\n"
4237 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4238 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4239 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4240 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4241 "ahlhx5I=\r\n\r\n"),
4244 MockRead data_reads2[] = {
4245 // The origin server responds with a Type 2 message.
4246 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4247 MockRead("WWW-Authenticate: NTLM "
4248 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4249 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4250 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4251 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4252 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4253 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4254 "BtAAAAAAA=\r\n"),
4255 MockRead("Content-Length: 42\r\n"),
4256 MockRead("Content-Type: text/html\r\n\r\n"),
4257 MockRead("You are not authorized to view this page\r\n"),
4259 // Lastly we get the desired content.
4260 MockRead("HTTP/1.1 200 OK\r\n"),
4261 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4262 MockRead("Content-Length: 13\r\n\r\n"),
4263 MockRead("Please Login\r\n"),
4264 MockRead(SYNCHRONOUS, OK),
4267 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4268 data_writes1, arraysize(data_writes1));
4269 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4270 data_writes2, arraysize(data_writes2));
4271 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4272 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4274 TestCompletionCallback callback1;
4276 scoped_ptr<HttpTransaction> trans(
4277 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4279 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4280 EXPECT_EQ(ERR_IO_PENDING, rv);
4282 rv = callback1.WaitForResult();
4283 EXPECT_EQ(OK, rv);
4285 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4287 const HttpResponseInfo* response = trans->GetResponseInfo();
4288 ASSERT_FALSE(response == NULL);
4289 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4291 TestCompletionCallback callback2;
4293 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4294 callback2.callback());
4295 EXPECT_EQ(ERR_IO_PENDING, rv);
4297 rv = callback2.WaitForResult();
4298 EXPECT_EQ(OK, rv);
4300 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4302 response = trans->GetResponseInfo();
4303 ASSERT_TRUE(response != NULL);
4304 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4306 TestCompletionCallback callback3;
4308 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4309 EXPECT_EQ(ERR_IO_PENDING, rv);
4311 rv = callback3.WaitForResult();
4312 EXPECT_EQ(OK, rv);
4314 response = trans->GetResponseInfo();
4315 ASSERT_TRUE(response != NULL);
4316 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4317 EXPECT_EQ(13, response->headers->GetContentLength());
4320 // Enter a wrong password, and then the correct one.
4321 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4322 HttpRequestInfo request;
4323 request.method = "GET";
4324 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4325 request.load_flags = 0;
4327 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4328 MockGetHostName);
4329 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4331 MockWrite data_writes1[] = {
4332 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4333 "Host: 172.22.68.17\r\n"
4334 "Connection: keep-alive\r\n\r\n"),
4337 MockRead data_reads1[] = {
4338 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4339 // Negotiate and NTLM are often requested together. However, we only want
4340 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4341 // the header that requests Negotiate for this test.
4342 MockRead("WWW-Authenticate: NTLM\r\n"),
4343 MockRead("Connection: close\r\n"),
4344 MockRead("Content-Length: 42\r\n"),
4345 MockRead("Content-Type: text/html\r\n\r\n"),
4346 // Missing content -- won't matter, as connection will be reset.
4347 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4350 MockWrite data_writes2[] = {
4351 // After restarting with a null identity, this is the
4352 // request we should be issuing -- the final header line contains a Type
4353 // 1 message.
4354 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4355 "Host: 172.22.68.17\r\n"
4356 "Connection: keep-alive\r\n"
4357 "Authorization: NTLM "
4358 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4360 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4361 // (the credentials for the origin server). The second request continues
4362 // on the same connection.
4363 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4364 "Host: 172.22.68.17\r\n"
4365 "Connection: keep-alive\r\n"
4366 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4367 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4368 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4369 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4370 "4Ww7b7E=\r\n\r\n"),
4373 MockRead data_reads2[] = {
4374 // The origin server responds with a Type 2 message.
4375 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4376 MockRead("WWW-Authenticate: NTLM "
4377 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4378 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4379 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4380 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4381 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4382 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4383 "BtAAAAAAA=\r\n"),
4384 MockRead("Content-Length: 42\r\n"),
4385 MockRead("Content-Type: text/html\r\n\r\n"),
4386 MockRead("You are not authorized to view this page\r\n"),
4388 // Wrong password.
4389 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4390 MockRead("WWW-Authenticate: NTLM\r\n"),
4391 MockRead("Connection: close\r\n"),
4392 MockRead("Content-Length: 42\r\n"),
4393 MockRead("Content-Type: text/html\r\n\r\n"),
4394 // Missing content -- won't matter, as connection will be reset.
4395 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4398 MockWrite data_writes3[] = {
4399 // After restarting with a null identity, this is the
4400 // request we should be issuing -- the final header line contains a Type
4401 // 1 message.
4402 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4403 "Host: 172.22.68.17\r\n"
4404 "Connection: keep-alive\r\n"
4405 "Authorization: NTLM "
4406 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4408 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4409 // (the credentials for the origin server). The second request continues
4410 // on the same connection.
4411 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4412 "Host: 172.22.68.17\r\n"
4413 "Connection: keep-alive\r\n"
4414 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4415 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4416 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4417 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4418 "+4MUm7c=\r\n\r\n"),
4421 MockRead data_reads3[] = {
4422 // The origin server responds with a Type 2 message.
4423 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4424 MockRead("WWW-Authenticate: NTLM "
4425 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4426 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4427 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4428 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4429 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4430 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4431 "BtAAAAAAA=\r\n"),
4432 MockRead("Content-Length: 42\r\n"),
4433 MockRead("Content-Type: text/html\r\n\r\n"),
4434 MockRead("You are not authorized to view this page\r\n"),
4436 // Lastly we get the desired content.
4437 MockRead("HTTP/1.1 200 OK\r\n"),
4438 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4439 MockRead("Content-Length: 13\r\n\r\n"),
4440 MockRead("Please Login\r\n"),
4441 MockRead(SYNCHRONOUS, OK),
4444 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4445 data_writes1, arraysize(data_writes1));
4446 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4447 data_writes2, arraysize(data_writes2));
4448 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4449 data_writes3, arraysize(data_writes3));
4450 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4451 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4452 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4454 TestCompletionCallback callback1;
4456 scoped_ptr<HttpTransaction> trans(
4457 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4459 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4460 EXPECT_EQ(ERR_IO_PENDING, rv);
4462 rv = callback1.WaitForResult();
4463 EXPECT_EQ(OK, rv);
4465 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4467 const HttpResponseInfo* response = trans->GetResponseInfo();
4468 ASSERT_TRUE(response != NULL);
4469 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4471 TestCompletionCallback callback2;
4473 // Enter the wrong password.
4474 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4475 callback2.callback());
4476 EXPECT_EQ(ERR_IO_PENDING, rv);
4478 rv = callback2.WaitForResult();
4479 EXPECT_EQ(OK, rv);
4481 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4482 TestCompletionCallback callback3;
4483 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4484 EXPECT_EQ(ERR_IO_PENDING, rv);
4485 rv = callback3.WaitForResult();
4486 EXPECT_EQ(OK, rv);
4487 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4489 response = trans->GetResponseInfo();
4490 ASSERT_FALSE(response == NULL);
4491 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4493 TestCompletionCallback callback4;
4495 // Now enter the right password.
4496 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4497 callback4.callback());
4498 EXPECT_EQ(ERR_IO_PENDING, rv);
4500 rv = callback4.WaitForResult();
4501 EXPECT_EQ(OK, rv);
4503 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4505 TestCompletionCallback callback5;
4507 // One more roundtrip
4508 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4509 EXPECT_EQ(ERR_IO_PENDING, rv);
4511 rv = callback5.WaitForResult();
4512 EXPECT_EQ(OK, rv);
4514 response = trans->GetResponseInfo();
4515 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4516 EXPECT_EQ(13, response->headers->GetContentLength());
4518 #endif // NTLM_PORTABLE
4520 // Test reading a server response which has only headers, and no body.
4521 // After some maximum number of bytes is consumed, the transaction should
4522 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4523 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4524 HttpRequestInfo request;
4525 request.method = "GET";
4526 request.url = GURL("http://www.google.com/");
4527 request.load_flags = 0;
4529 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4530 scoped_ptr<HttpTransaction> trans(
4531 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4533 // Respond with 300 kb of headers (we should fail after 256 kb).
4534 std::string large_headers_string;
4535 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4537 MockRead data_reads[] = {
4538 MockRead("HTTP/1.0 200 OK\r\n"),
4539 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4540 MockRead("\r\nBODY"),
4541 MockRead(SYNCHRONOUS, OK),
4543 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4544 session_deps_.socket_factory->AddSocketDataProvider(&data);
4546 TestCompletionCallback callback;
4548 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4549 EXPECT_EQ(ERR_IO_PENDING, rv);
4551 rv = callback.WaitForResult();
4552 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4554 const HttpResponseInfo* response = trans->GetResponseInfo();
4555 EXPECT_TRUE(response == NULL);
4558 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4559 // establish tunnel.
4560 // http://code.google.com/p/chromium/issues/detail?id=3772
4561 TEST_P(HttpNetworkTransactionTest,
4562 DontRecycleTransportSocketForSSLTunnel) {
4563 HttpRequestInfo request;
4564 request.method = "GET";
4565 request.url = GURL("https://www.google.com/");
4566 request.load_flags = 0;
4568 // Configure against proxy server "myproxy:70".
4569 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4571 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4573 scoped_ptr<HttpTransaction> trans(
4574 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4576 // Since we have proxy, should try to establish tunnel.
4577 MockWrite data_writes1[] = {
4578 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4579 "Host: www.google.com\r\n"
4580 "Proxy-Connection: keep-alive\r\n\r\n"),
4583 // The proxy responds to the connect with a 404, using a persistent
4584 // connection. Usually a proxy would return 501 (not implemented),
4585 // or 200 (tunnel established).
4586 MockRead data_reads1[] = {
4587 MockRead("HTTP/1.1 404 Not Found\r\n"),
4588 MockRead("Content-Length: 10\r\n\r\n"),
4589 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4592 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4593 data_writes1, arraysize(data_writes1));
4594 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4596 TestCompletionCallback callback1;
4598 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4599 EXPECT_EQ(ERR_IO_PENDING, rv);
4601 rv = callback1.WaitForResult();
4602 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4604 const HttpResponseInfo* response = trans->GetResponseInfo();
4605 EXPECT_TRUE(response == NULL);
4607 // Empty the current queue. This is necessary because idle sockets are
4608 // added to the connection pool asynchronously with a PostTask.
4609 base::MessageLoop::current()->RunUntilIdle();
4611 // We now check to make sure the TCPClientSocket was not added back to
4612 // the pool.
4613 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4614 trans.reset();
4615 base::MessageLoop::current()->RunUntilIdle();
4616 // Make sure that the socket didn't get recycled after calling the destructor.
4617 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4620 // Make sure that we recycle a socket after reading all of the response body.
4621 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4622 HttpRequestInfo request;
4623 request.method = "GET";
4624 request.url = GURL("http://www.google.com/");
4625 request.load_flags = 0;
4627 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4629 scoped_ptr<HttpTransaction> trans(
4630 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4632 MockRead data_reads[] = {
4633 // A part of the response body is received with the response headers.
4634 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4635 // The rest of the response body is received in two parts.
4636 MockRead("lo"),
4637 MockRead(" world"),
4638 MockRead("junk"), // Should not be read!!
4639 MockRead(SYNCHRONOUS, OK),
4642 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4643 session_deps_.socket_factory->AddSocketDataProvider(&data);
4645 TestCompletionCallback callback;
4647 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4648 EXPECT_EQ(ERR_IO_PENDING, rv);
4650 rv = callback.WaitForResult();
4651 EXPECT_EQ(OK, rv);
4653 const HttpResponseInfo* response = trans->GetResponseInfo();
4654 ASSERT_TRUE(response != NULL);
4656 EXPECT_TRUE(response->headers.get() != NULL);
4657 std::string status_line = response->headers->GetStatusLine();
4658 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4660 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4662 std::string response_data;
4663 rv = ReadTransaction(trans.get(), &response_data);
4664 EXPECT_EQ(OK, rv);
4665 EXPECT_EQ("hello world", response_data);
4667 // Empty the current queue. This is necessary because idle sockets are
4668 // added to the connection pool asynchronously with a PostTask.
4669 base::MessageLoop::current()->RunUntilIdle();
4671 // We now check to make sure the socket was added back to the pool.
4672 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4675 // Make sure that we recycle a SSL socket after reading all of the response
4676 // body.
4677 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4678 HttpRequestInfo request;
4679 request.method = "GET";
4680 request.url = GURL("https://www.google.com/");
4681 request.load_flags = 0;
4683 MockWrite data_writes[] = {
4684 MockWrite("GET / HTTP/1.1\r\n"
4685 "Host: www.google.com\r\n"
4686 "Connection: keep-alive\r\n\r\n"),
4689 MockRead data_reads[] = {
4690 MockRead("HTTP/1.1 200 OK\r\n"),
4691 MockRead("Content-Length: 11\r\n\r\n"),
4692 MockRead("hello world"),
4693 MockRead(SYNCHRONOUS, OK),
4696 SSLSocketDataProvider ssl(ASYNC, OK);
4697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4699 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4700 data_writes, arraysize(data_writes));
4701 session_deps_.socket_factory->AddSocketDataProvider(&data);
4703 TestCompletionCallback callback;
4705 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4706 scoped_ptr<HttpTransaction> trans(
4707 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4709 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4711 EXPECT_EQ(ERR_IO_PENDING, rv);
4712 EXPECT_EQ(OK, callback.WaitForResult());
4714 const HttpResponseInfo* response = trans->GetResponseInfo();
4715 ASSERT_TRUE(response != NULL);
4716 ASSERT_TRUE(response->headers.get() != NULL);
4717 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4719 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4721 std::string response_data;
4722 rv = ReadTransaction(trans.get(), &response_data);
4723 EXPECT_EQ(OK, rv);
4724 EXPECT_EQ("hello world", response_data);
4726 // Empty the current queue. This is necessary because idle sockets are
4727 // added to the connection pool asynchronously with a PostTask.
4728 base::MessageLoop::current()->RunUntilIdle();
4730 // We now check to make sure the socket was added back to the pool.
4731 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4734 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4735 // from the pool and make sure that we recover okay.
4736 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4737 HttpRequestInfo request;
4738 request.method = "GET";
4739 request.url = GURL("https://www.google.com/");
4740 request.load_flags = 0;
4742 MockWrite data_writes[] = {
4743 MockWrite("GET / HTTP/1.1\r\n"
4744 "Host: www.google.com\r\n"
4745 "Connection: keep-alive\r\n\r\n"),
4746 MockWrite("GET / HTTP/1.1\r\n"
4747 "Host: www.google.com\r\n"
4748 "Connection: keep-alive\r\n\r\n"),
4751 MockRead data_reads[] = {
4752 MockRead("HTTP/1.1 200 OK\r\n"),
4753 MockRead("Content-Length: 11\r\n\r\n"),
4754 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4755 MockRead("hello world"),
4756 MockRead(ASYNC, 0, 0) // EOF
4759 SSLSocketDataProvider ssl(ASYNC, OK);
4760 SSLSocketDataProvider ssl2(ASYNC, OK);
4761 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4762 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4764 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4765 data_writes, arraysize(data_writes));
4766 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4767 data_writes, arraysize(data_writes));
4768 session_deps_.socket_factory->AddSocketDataProvider(&data);
4769 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4771 TestCompletionCallback callback;
4773 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4774 scoped_ptr<HttpTransaction> trans(
4775 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4777 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4779 EXPECT_EQ(ERR_IO_PENDING, rv);
4780 EXPECT_EQ(OK, callback.WaitForResult());
4782 const HttpResponseInfo* response = trans->GetResponseInfo();
4783 ASSERT_TRUE(response != NULL);
4784 ASSERT_TRUE(response->headers.get() != NULL);
4785 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4787 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4789 std::string response_data;
4790 rv = ReadTransaction(trans.get(), &response_data);
4791 EXPECT_EQ(OK, rv);
4792 EXPECT_EQ("hello world", response_data);
4794 // Empty the current queue. This is necessary because idle sockets are
4795 // added to the connection pool asynchronously with a PostTask.
4796 base::MessageLoop::current()->RunUntilIdle();
4798 // We now check to make sure the socket was added back to the pool.
4799 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4801 // Now start the second transaction, which should reuse the previous socket.
4803 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4805 rv = trans->Start(&request, callback.callback(), BoundNetLog());
4807 EXPECT_EQ(ERR_IO_PENDING, rv);
4808 EXPECT_EQ(OK, callback.WaitForResult());
4810 response = trans->GetResponseInfo();
4811 ASSERT_TRUE(response != NULL);
4812 ASSERT_TRUE(response->headers.get() != NULL);
4813 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4815 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4817 rv = ReadTransaction(trans.get(), &response_data);
4818 EXPECT_EQ(OK, rv);
4819 EXPECT_EQ("hello world", response_data);
4821 // Empty the current queue. This is necessary because idle sockets are
4822 // added to the connection pool asynchronously with a PostTask.
4823 base::MessageLoop::current()->RunUntilIdle();
4825 // We now check to make sure the socket was added back to the pool.
4826 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4829 // Make sure that we recycle a socket after a zero-length response.
4830 // http://crbug.com/9880
4831 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4832 HttpRequestInfo request;
4833 request.method = "GET";
4834 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4835 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4836 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4837 "rt=prt.2642,ol.2649,xjs.2951");
4838 request.load_flags = 0;
4840 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4842 scoped_ptr<HttpTransaction> trans(
4843 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4845 MockRead data_reads[] = {
4846 MockRead("HTTP/1.1 204 No Content\r\n"
4847 "Content-Length: 0\r\n"
4848 "Content-Type: text/html\r\n\r\n"),
4849 MockRead("junk"), // Should not be read!!
4850 MockRead(SYNCHRONOUS, OK),
4853 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4854 session_deps_.socket_factory->AddSocketDataProvider(&data);
4856 TestCompletionCallback callback;
4858 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4859 EXPECT_EQ(ERR_IO_PENDING, rv);
4861 rv = callback.WaitForResult();
4862 EXPECT_EQ(OK, rv);
4864 const HttpResponseInfo* response = trans->GetResponseInfo();
4865 ASSERT_TRUE(response != NULL);
4867 EXPECT_TRUE(response->headers.get() != NULL);
4868 std::string status_line = response->headers->GetStatusLine();
4869 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4871 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4873 std::string response_data;
4874 rv = ReadTransaction(trans.get(), &response_data);
4875 EXPECT_EQ(OK, rv);
4876 EXPECT_EQ("", response_data);
4878 // Empty the current queue. This is necessary because idle sockets are
4879 // added to the connection pool asynchronously with a PostTask.
4880 base::MessageLoop::current()->RunUntilIdle();
4882 // We now check to make sure the socket was added back to the pool.
4883 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4886 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
4887 ScopedVector<UploadElementReader> element_readers;
4888 element_readers.push_back(new UploadBytesElementReader("foo", 3));
4889 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
4891 HttpRequestInfo request[2];
4892 // Transaction 1: a GET request that succeeds. The socket is recycled
4893 // after use.
4894 request[0].method = "GET";
4895 request[0].url = GURL("http://www.google.com/");
4896 request[0].load_flags = 0;
4897 // Transaction 2: a POST request. Reuses the socket kept alive from
4898 // transaction 1. The first attempts fails when writing the POST data.
4899 // This causes the transaction to retry with a new socket. The second
4900 // attempt succeeds.
4901 request[1].method = "POST";
4902 request[1].url = GURL("http://www.google.com/login.cgi");
4903 request[1].upload_data_stream = &upload_data_stream;
4904 request[1].load_flags = 0;
4906 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4908 // The first socket is used for transaction 1 and the first attempt of
4909 // transaction 2.
4911 // The response of transaction 1.
4912 MockRead data_reads1[] = {
4913 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4914 MockRead("hello world"),
4915 MockRead(SYNCHRONOUS, OK),
4917 // The mock write results of transaction 1 and the first attempt of
4918 // transaction 2.
4919 MockWrite data_writes1[] = {
4920 MockWrite(SYNCHRONOUS, 64), // GET
4921 MockWrite(SYNCHRONOUS, 93), // POST
4922 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
4924 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4925 data_writes1, arraysize(data_writes1));
4927 // The second socket is used for the second attempt of transaction 2.
4929 // The response of transaction 2.
4930 MockRead data_reads2[] = {
4931 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4932 MockRead("welcome"),
4933 MockRead(SYNCHRONOUS, OK),
4935 // The mock write results of the second attempt of transaction 2.
4936 MockWrite data_writes2[] = {
4937 MockWrite(SYNCHRONOUS, 93), // POST
4938 MockWrite(SYNCHRONOUS, 3), // POST data
4940 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4941 data_writes2, arraysize(data_writes2));
4943 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4944 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4946 const char* kExpectedResponseData[] = {
4947 "hello world", "welcome"
4950 for (int i = 0; i < 2; ++i) {
4951 scoped_ptr<HttpTransaction> trans(
4952 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4954 TestCompletionCallback callback;
4956 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
4957 EXPECT_EQ(ERR_IO_PENDING, rv);
4959 rv = callback.WaitForResult();
4960 EXPECT_EQ(OK, rv);
4962 const HttpResponseInfo* response = trans->GetResponseInfo();
4963 ASSERT_TRUE(response != NULL);
4965 EXPECT_TRUE(response->headers.get() != NULL);
4966 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4968 std::string response_data;
4969 rv = ReadTransaction(trans.get(), &response_data);
4970 EXPECT_EQ(OK, rv);
4971 EXPECT_EQ(kExpectedResponseData[i], response_data);
4975 // Test the request-challenge-retry sequence for basic auth when there is
4976 // an identity in the URL. The request should be sent as normal, but when
4977 // it fails the identity from the URL is used to answer the challenge.
4978 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
4979 HttpRequestInfo request;
4980 request.method = "GET";
4981 request.url = GURL("http://foo:b@r@www.google.com/");
4982 request.load_flags = LOAD_NORMAL;
4984 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4985 scoped_ptr<HttpTransaction> trans(
4986 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4988 // The password contains an escaped character -- for this test to pass it
4989 // will need to be unescaped by HttpNetworkTransaction.
4990 EXPECT_EQ("b%40r", request.url.password());
4992 MockWrite data_writes1[] = {
4993 MockWrite("GET / HTTP/1.1\r\n"
4994 "Host: www.google.com\r\n"
4995 "Connection: keep-alive\r\n\r\n"),
4998 MockRead data_reads1[] = {
4999 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5000 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5001 MockRead("Content-Length: 10\r\n\r\n"),
5002 MockRead(SYNCHRONOUS, ERR_FAILED),
5005 // After the challenge above, the transaction will be restarted using the
5006 // identity from the url (foo, b@r) to answer the challenge.
5007 MockWrite data_writes2[] = {
5008 MockWrite("GET / HTTP/1.1\r\n"
5009 "Host: www.google.com\r\n"
5010 "Connection: keep-alive\r\n"
5011 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5014 MockRead data_reads2[] = {
5015 MockRead("HTTP/1.0 200 OK\r\n"),
5016 MockRead("Content-Length: 100\r\n\r\n"),
5017 MockRead(SYNCHRONOUS, OK),
5020 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5021 data_writes1, arraysize(data_writes1));
5022 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5023 data_writes2, arraysize(data_writes2));
5024 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5025 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5027 TestCompletionCallback callback1;
5028 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5029 EXPECT_EQ(ERR_IO_PENDING, rv);
5030 rv = callback1.WaitForResult();
5031 EXPECT_EQ(OK, rv);
5032 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5034 TestCompletionCallback callback2;
5035 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5036 EXPECT_EQ(ERR_IO_PENDING, rv);
5037 rv = callback2.WaitForResult();
5038 EXPECT_EQ(OK, rv);
5039 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5041 const HttpResponseInfo* response = trans->GetResponseInfo();
5042 ASSERT_TRUE(response != NULL);
5044 // There is no challenge info, since the identity in URL worked.
5045 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5047 EXPECT_EQ(100, response->headers->GetContentLength());
5049 // Empty the current queue.
5050 base::MessageLoop::current()->RunUntilIdle();
5053 // Test the request-challenge-retry sequence for basic auth when there is an
5054 // incorrect identity in the URL. The identity from the URL should be used only
5055 // once.
5056 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5057 HttpRequestInfo request;
5058 request.method = "GET";
5059 // Note: the URL has a username:password in it. The password "baz" is
5060 // wrong (should be "bar").
5061 request.url = GURL("http://foo:baz@www.google.com/");
5063 request.load_flags = LOAD_NORMAL;
5065 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5066 scoped_ptr<HttpTransaction> trans(
5067 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5069 MockWrite data_writes1[] = {
5070 MockWrite("GET / HTTP/1.1\r\n"
5071 "Host: www.google.com\r\n"
5072 "Connection: keep-alive\r\n\r\n"),
5075 MockRead data_reads1[] = {
5076 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5077 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5078 MockRead("Content-Length: 10\r\n\r\n"),
5079 MockRead(SYNCHRONOUS, ERR_FAILED),
5082 // After the challenge above, the transaction will be restarted using the
5083 // identity from the url (foo, baz) to answer the challenge.
5084 MockWrite data_writes2[] = {
5085 MockWrite("GET / HTTP/1.1\r\n"
5086 "Host: www.google.com\r\n"
5087 "Connection: keep-alive\r\n"
5088 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5091 MockRead data_reads2[] = {
5092 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5093 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5094 MockRead("Content-Length: 10\r\n\r\n"),
5095 MockRead(SYNCHRONOUS, ERR_FAILED),
5098 // After the challenge above, the transaction will be restarted using the
5099 // identity supplied by the user (foo, bar) to answer the challenge.
5100 MockWrite data_writes3[] = {
5101 MockWrite("GET / HTTP/1.1\r\n"
5102 "Host: www.google.com\r\n"
5103 "Connection: keep-alive\r\n"
5104 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5107 MockRead data_reads3[] = {
5108 MockRead("HTTP/1.0 200 OK\r\n"),
5109 MockRead("Content-Length: 100\r\n\r\n"),
5110 MockRead(SYNCHRONOUS, OK),
5113 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5114 data_writes1, arraysize(data_writes1));
5115 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5116 data_writes2, arraysize(data_writes2));
5117 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5118 data_writes3, arraysize(data_writes3));
5119 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5120 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5121 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5123 TestCompletionCallback callback1;
5125 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5126 EXPECT_EQ(ERR_IO_PENDING, rv);
5128 rv = callback1.WaitForResult();
5129 EXPECT_EQ(OK, rv);
5131 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5132 TestCompletionCallback callback2;
5133 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5134 EXPECT_EQ(ERR_IO_PENDING, rv);
5135 rv = callback2.WaitForResult();
5136 EXPECT_EQ(OK, rv);
5137 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5139 const HttpResponseInfo* response = trans->GetResponseInfo();
5140 ASSERT_TRUE(response != NULL);
5141 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5143 TestCompletionCallback callback3;
5144 rv = trans->RestartWithAuth(
5145 AuthCredentials(kFoo, kBar), callback3.callback());
5146 EXPECT_EQ(ERR_IO_PENDING, rv);
5147 rv = callback3.WaitForResult();
5148 EXPECT_EQ(OK, rv);
5149 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5151 response = trans->GetResponseInfo();
5152 ASSERT_TRUE(response != NULL);
5154 // There is no challenge info, since the identity worked.
5155 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5157 EXPECT_EQ(100, response->headers->GetContentLength());
5159 // Empty the current queue.
5160 base::MessageLoop::current()->RunUntilIdle();
5164 // Test the request-challenge-retry sequence for basic auth when there is a
5165 // correct identity in the URL, but its use is being suppressed. The identity
5166 // from the URL should never be used.
5167 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5168 HttpRequestInfo request;
5169 request.method = "GET";
5170 request.url = GURL("http://foo:bar@www.google.com/");
5171 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5173 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5174 scoped_ptr<HttpTransaction> trans(
5175 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5177 MockWrite data_writes1[] = {
5178 MockWrite("GET / HTTP/1.1\r\n"
5179 "Host: www.google.com\r\n"
5180 "Connection: keep-alive\r\n\r\n"),
5183 MockRead data_reads1[] = {
5184 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5185 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5186 MockRead("Content-Length: 10\r\n\r\n"),
5187 MockRead(SYNCHRONOUS, ERR_FAILED),
5190 // After the challenge above, the transaction will be restarted using the
5191 // identity supplied by the user, not the one in the URL, to answer the
5192 // challenge.
5193 MockWrite data_writes3[] = {
5194 MockWrite("GET / HTTP/1.1\r\n"
5195 "Host: www.google.com\r\n"
5196 "Connection: keep-alive\r\n"
5197 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5200 MockRead data_reads3[] = {
5201 MockRead("HTTP/1.0 200 OK\r\n"),
5202 MockRead("Content-Length: 100\r\n\r\n"),
5203 MockRead(SYNCHRONOUS, OK),
5206 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5207 data_writes1, arraysize(data_writes1));
5208 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5209 data_writes3, arraysize(data_writes3));
5210 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5211 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5213 TestCompletionCallback callback1;
5214 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5215 EXPECT_EQ(ERR_IO_PENDING, rv);
5216 rv = callback1.WaitForResult();
5217 EXPECT_EQ(OK, rv);
5218 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5220 const HttpResponseInfo* response = trans->GetResponseInfo();
5221 ASSERT_TRUE(response != NULL);
5222 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5224 TestCompletionCallback callback3;
5225 rv = trans->RestartWithAuth(
5226 AuthCredentials(kFoo, kBar), callback3.callback());
5227 EXPECT_EQ(ERR_IO_PENDING, rv);
5228 rv = callback3.WaitForResult();
5229 EXPECT_EQ(OK, rv);
5230 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5232 response = trans->GetResponseInfo();
5233 ASSERT_TRUE(response != NULL);
5235 // There is no challenge info, since the identity worked.
5236 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5237 EXPECT_EQ(100, response->headers->GetContentLength());
5239 // Empty the current queue.
5240 base::MessageLoop::current()->RunUntilIdle();
5243 // Test that previously tried username/passwords for a realm get re-used.
5244 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5245 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5247 // Transaction 1: authenticate (foo, bar) on MyRealm1
5249 HttpRequestInfo request;
5250 request.method = "GET";
5251 request.url = GURL("http://www.google.com/x/y/z");
5252 request.load_flags = 0;
5254 scoped_ptr<HttpTransaction> trans(
5255 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5257 MockWrite data_writes1[] = {
5258 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5259 "Host: www.google.com\r\n"
5260 "Connection: keep-alive\r\n\r\n"),
5263 MockRead data_reads1[] = {
5264 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5265 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5266 MockRead("Content-Length: 10000\r\n\r\n"),
5267 MockRead(SYNCHRONOUS, ERR_FAILED),
5270 // Resend with authorization (username=foo, password=bar)
5271 MockWrite data_writes2[] = {
5272 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5273 "Host: www.google.com\r\n"
5274 "Connection: keep-alive\r\n"
5275 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5278 // Sever accepts the authorization.
5279 MockRead data_reads2[] = {
5280 MockRead("HTTP/1.0 200 OK\r\n"),
5281 MockRead("Content-Length: 100\r\n\r\n"),
5282 MockRead(SYNCHRONOUS, OK),
5285 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5286 data_writes1, arraysize(data_writes1));
5287 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5288 data_writes2, arraysize(data_writes2));
5289 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5290 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5292 TestCompletionCallback callback1;
5294 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5295 EXPECT_EQ(ERR_IO_PENDING, rv);
5297 rv = callback1.WaitForResult();
5298 EXPECT_EQ(OK, rv);
5300 const HttpResponseInfo* response = trans->GetResponseInfo();
5301 ASSERT_TRUE(response != NULL);
5302 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5304 TestCompletionCallback callback2;
5306 rv = trans->RestartWithAuth(
5307 AuthCredentials(kFoo, kBar), callback2.callback());
5308 EXPECT_EQ(ERR_IO_PENDING, rv);
5310 rv = callback2.WaitForResult();
5311 EXPECT_EQ(OK, rv);
5313 response = trans->GetResponseInfo();
5314 ASSERT_TRUE(response != NULL);
5315 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5316 EXPECT_EQ(100, response->headers->GetContentLength());
5319 // ------------------------------------------------------------------------
5321 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5323 HttpRequestInfo request;
5324 request.method = "GET";
5325 // Note that Transaction 1 was at /x/y/z, so this is in the same
5326 // protection space as MyRealm1.
5327 request.url = GURL("http://www.google.com/x/y/a/b");
5328 request.load_flags = 0;
5330 scoped_ptr<HttpTransaction> trans(
5331 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5333 MockWrite data_writes1[] = {
5334 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5335 "Host: www.google.com\r\n"
5336 "Connection: keep-alive\r\n"
5337 // Send preemptive authorization for MyRealm1
5338 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5341 // The server didn't like the preemptive authorization, and
5342 // challenges us for a different realm (MyRealm2).
5343 MockRead data_reads1[] = {
5344 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5345 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5346 MockRead("Content-Length: 10000\r\n\r\n"),
5347 MockRead(SYNCHRONOUS, ERR_FAILED),
5350 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5351 MockWrite data_writes2[] = {
5352 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5353 "Host: www.google.com\r\n"
5354 "Connection: keep-alive\r\n"
5355 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5358 // Sever accepts the authorization.
5359 MockRead data_reads2[] = {
5360 MockRead("HTTP/1.0 200 OK\r\n"),
5361 MockRead("Content-Length: 100\r\n\r\n"),
5362 MockRead(SYNCHRONOUS, OK),
5365 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5366 data_writes1, arraysize(data_writes1));
5367 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5368 data_writes2, arraysize(data_writes2));
5369 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5370 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5372 TestCompletionCallback callback1;
5374 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5375 EXPECT_EQ(ERR_IO_PENDING, rv);
5377 rv = callback1.WaitForResult();
5378 EXPECT_EQ(OK, rv);
5380 const HttpResponseInfo* response = trans->GetResponseInfo();
5381 ASSERT_TRUE(response != NULL);
5382 ASSERT_TRUE(response->auth_challenge.get());
5383 EXPECT_FALSE(response->auth_challenge->is_proxy);
5384 EXPECT_EQ("www.google.com:80",
5385 response->auth_challenge->challenger.ToString());
5386 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5387 EXPECT_EQ("basic", response->auth_challenge->scheme);
5389 TestCompletionCallback callback2;
5391 rv = trans->RestartWithAuth(
5392 AuthCredentials(kFoo2, kBar2), callback2.callback());
5393 EXPECT_EQ(ERR_IO_PENDING, rv);
5395 rv = callback2.WaitForResult();
5396 EXPECT_EQ(OK, rv);
5398 response = trans->GetResponseInfo();
5399 ASSERT_TRUE(response != NULL);
5400 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5401 EXPECT_EQ(100, response->headers->GetContentLength());
5404 // ------------------------------------------------------------------------
5406 // Transaction 3: Resend a request in MyRealm's protection space --
5407 // succeed with preemptive authorization.
5409 HttpRequestInfo request;
5410 request.method = "GET";
5411 request.url = GURL("http://www.google.com/x/y/z2");
5412 request.load_flags = 0;
5414 scoped_ptr<HttpTransaction> trans(
5415 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5417 MockWrite data_writes1[] = {
5418 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5419 "Host: www.google.com\r\n"
5420 "Connection: keep-alive\r\n"
5421 // The authorization for MyRealm1 gets sent preemptively
5422 // (since the url is in the same protection space)
5423 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5426 // Sever accepts the preemptive authorization
5427 MockRead data_reads1[] = {
5428 MockRead("HTTP/1.0 200 OK\r\n"),
5429 MockRead("Content-Length: 100\r\n\r\n"),
5430 MockRead(SYNCHRONOUS, OK),
5433 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5434 data_writes1, arraysize(data_writes1));
5435 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5437 TestCompletionCallback callback1;
5439 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5440 EXPECT_EQ(ERR_IO_PENDING, rv);
5442 rv = callback1.WaitForResult();
5443 EXPECT_EQ(OK, rv);
5445 const HttpResponseInfo* response = trans->GetResponseInfo();
5446 ASSERT_TRUE(response != NULL);
5448 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5449 EXPECT_EQ(100, response->headers->GetContentLength());
5452 // ------------------------------------------------------------------------
5454 // Transaction 4: request another URL in MyRealm (however the
5455 // url is not known to belong to the protection space, so no pre-auth).
5457 HttpRequestInfo request;
5458 request.method = "GET";
5459 request.url = GURL("http://www.google.com/x/1");
5460 request.load_flags = 0;
5462 scoped_ptr<HttpTransaction> trans(
5463 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5465 MockWrite data_writes1[] = {
5466 MockWrite("GET /x/1 HTTP/1.1\r\n"
5467 "Host: www.google.com\r\n"
5468 "Connection: keep-alive\r\n\r\n"),
5471 MockRead data_reads1[] = {
5472 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5473 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5474 MockRead("Content-Length: 10000\r\n\r\n"),
5475 MockRead(SYNCHRONOUS, ERR_FAILED),
5478 // Resend with authorization from MyRealm's cache.
5479 MockWrite data_writes2[] = {
5480 MockWrite("GET /x/1 HTTP/1.1\r\n"
5481 "Host: www.google.com\r\n"
5482 "Connection: keep-alive\r\n"
5483 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5486 // Sever accepts the authorization.
5487 MockRead data_reads2[] = {
5488 MockRead("HTTP/1.0 200 OK\r\n"),
5489 MockRead("Content-Length: 100\r\n\r\n"),
5490 MockRead(SYNCHRONOUS, OK),
5493 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5494 data_writes1, arraysize(data_writes1));
5495 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5496 data_writes2, arraysize(data_writes2));
5497 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5498 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5500 TestCompletionCallback callback1;
5502 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5503 EXPECT_EQ(ERR_IO_PENDING, rv);
5505 rv = callback1.WaitForResult();
5506 EXPECT_EQ(OK, rv);
5508 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5509 TestCompletionCallback callback2;
5510 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5511 EXPECT_EQ(ERR_IO_PENDING, rv);
5512 rv = callback2.WaitForResult();
5513 EXPECT_EQ(OK, rv);
5514 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5516 const HttpResponseInfo* response = trans->GetResponseInfo();
5517 ASSERT_TRUE(response != NULL);
5518 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5519 EXPECT_EQ(100, response->headers->GetContentLength());
5522 // ------------------------------------------------------------------------
5524 // Transaction 5: request a URL in MyRealm, but the server rejects the
5525 // cached identity. Should invalidate and re-prompt.
5527 HttpRequestInfo request;
5528 request.method = "GET";
5529 request.url = GURL("http://www.google.com/p/q/t");
5530 request.load_flags = 0;
5532 scoped_ptr<HttpTransaction> trans(
5533 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5535 MockWrite data_writes1[] = {
5536 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5537 "Host: www.google.com\r\n"
5538 "Connection: keep-alive\r\n\r\n"),
5541 MockRead data_reads1[] = {
5542 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5543 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5544 MockRead("Content-Length: 10000\r\n\r\n"),
5545 MockRead(SYNCHRONOUS, ERR_FAILED),
5548 // Resend with authorization from cache for MyRealm.
5549 MockWrite data_writes2[] = {
5550 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5551 "Host: www.google.com\r\n"
5552 "Connection: keep-alive\r\n"
5553 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5556 // Sever rejects the authorization.
5557 MockRead data_reads2[] = {
5558 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5559 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5560 MockRead("Content-Length: 10000\r\n\r\n"),
5561 MockRead(SYNCHRONOUS, ERR_FAILED),
5564 // At this point we should prompt for new credentials for MyRealm.
5565 // Restart with username=foo3, password=foo4.
5566 MockWrite data_writes3[] = {
5567 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5568 "Host: www.google.com\r\n"
5569 "Connection: keep-alive\r\n"
5570 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5573 // Sever accepts the authorization.
5574 MockRead data_reads3[] = {
5575 MockRead("HTTP/1.0 200 OK\r\n"),
5576 MockRead("Content-Length: 100\r\n\r\n"),
5577 MockRead(SYNCHRONOUS, OK),
5580 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5581 data_writes1, arraysize(data_writes1));
5582 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5583 data_writes2, arraysize(data_writes2));
5584 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5585 data_writes3, arraysize(data_writes3));
5586 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5587 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5588 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5590 TestCompletionCallback callback1;
5592 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5593 EXPECT_EQ(ERR_IO_PENDING, rv);
5595 rv = callback1.WaitForResult();
5596 EXPECT_EQ(OK, rv);
5598 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5599 TestCompletionCallback callback2;
5600 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5601 EXPECT_EQ(ERR_IO_PENDING, rv);
5602 rv = callback2.WaitForResult();
5603 EXPECT_EQ(OK, rv);
5604 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5606 const HttpResponseInfo* response = trans->GetResponseInfo();
5607 ASSERT_TRUE(response != NULL);
5608 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5610 TestCompletionCallback callback3;
5612 rv = trans->RestartWithAuth(
5613 AuthCredentials(kFoo3, kBar3), callback3.callback());
5614 EXPECT_EQ(ERR_IO_PENDING, rv);
5616 rv = callback3.WaitForResult();
5617 EXPECT_EQ(OK, rv);
5619 response = trans->GetResponseInfo();
5620 ASSERT_TRUE(response != NULL);
5621 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5622 EXPECT_EQ(100, response->headers->GetContentLength());
5626 // Tests that nonce count increments when multiple auth attempts
5627 // are started with the same nonce.
5628 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5629 HttpAuthHandlerDigest::Factory* digest_factory =
5630 new HttpAuthHandlerDigest::Factory();
5631 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5632 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5633 digest_factory->set_nonce_generator(nonce_generator);
5634 session_deps_.http_auth_handler_factory.reset(digest_factory);
5635 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5637 // Transaction 1: authenticate (foo, bar) on MyRealm1
5639 HttpRequestInfo request;
5640 request.method = "GET";
5641 request.url = GURL("http://www.google.com/x/y/z");
5642 request.load_flags = 0;
5644 scoped_ptr<HttpTransaction> trans(
5645 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5647 MockWrite data_writes1[] = {
5648 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5649 "Host: www.google.com\r\n"
5650 "Connection: keep-alive\r\n\r\n"),
5653 MockRead data_reads1[] = {
5654 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5655 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5656 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5657 MockRead(SYNCHRONOUS, OK),
5660 // Resend with authorization (username=foo, password=bar)
5661 MockWrite data_writes2[] = {
5662 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5663 "Host: www.google.com\r\n"
5664 "Connection: keep-alive\r\n"
5665 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5666 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5667 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5668 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5671 // Sever accepts the authorization.
5672 MockRead data_reads2[] = {
5673 MockRead("HTTP/1.0 200 OK\r\n"),
5674 MockRead(SYNCHRONOUS, OK),
5677 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5678 data_writes1, arraysize(data_writes1));
5679 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5680 data_writes2, arraysize(data_writes2));
5681 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5682 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5684 TestCompletionCallback callback1;
5686 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5687 EXPECT_EQ(ERR_IO_PENDING, rv);
5689 rv = callback1.WaitForResult();
5690 EXPECT_EQ(OK, rv);
5692 const HttpResponseInfo* response = trans->GetResponseInfo();
5693 ASSERT_TRUE(response != NULL);
5694 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5696 TestCompletionCallback callback2;
5698 rv = trans->RestartWithAuth(
5699 AuthCredentials(kFoo, kBar), callback2.callback());
5700 EXPECT_EQ(ERR_IO_PENDING, rv);
5702 rv = callback2.WaitForResult();
5703 EXPECT_EQ(OK, rv);
5705 response = trans->GetResponseInfo();
5706 ASSERT_TRUE(response != NULL);
5707 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5710 // ------------------------------------------------------------------------
5712 // Transaction 2: Request another resource in digestive's protection space.
5713 // This will preemptively add an Authorization header which should have an
5714 // "nc" value of 2 (as compared to 1 in the first use.
5716 HttpRequestInfo request;
5717 request.method = "GET";
5718 // Note that Transaction 1 was at /x/y/z, so this is in the same
5719 // protection space as digest.
5720 request.url = GURL("http://www.google.com/x/y/a/b");
5721 request.load_flags = 0;
5723 scoped_ptr<HttpTransaction> trans(
5724 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5726 MockWrite data_writes1[] = {
5727 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5728 "Host: www.google.com\r\n"
5729 "Connection: keep-alive\r\n"
5730 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5731 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5732 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5733 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5736 // Sever accepts the authorization.
5737 MockRead data_reads1[] = {
5738 MockRead("HTTP/1.0 200 OK\r\n"),
5739 MockRead("Content-Length: 100\r\n\r\n"),
5740 MockRead(SYNCHRONOUS, OK),
5743 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5744 data_writes1, arraysize(data_writes1));
5745 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5747 TestCompletionCallback callback1;
5749 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5750 EXPECT_EQ(ERR_IO_PENDING, rv);
5752 rv = callback1.WaitForResult();
5753 EXPECT_EQ(OK, rv);
5755 const HttpResponseInfo* response = trans->GetResponseInfo();
5756 ASSERT_TRUE(response != NULL);
5757 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5761 // Test the ResetStateForRestart() private method.
5762 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5763 // Create a transaction (the dependencies aren't important).
5764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5765 scoped_ptr<HttpNetworkTransaction> trans(
5766 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5768 // Setup some state (which we expect ResetStateForRestart() will clear).
5769 trans->read_buf_ = new IOBuffer(15);
5770 trans->read_buf_len_ = 15;
5771 trans->request_headers_.SetHeader("Authorization", "NTLM");
5773 // Setup state in response_
5774 HttpResponseInfo* response = &trans->response_;
5775 response->auth_challenge = new AuthChallengeInfo();
5776 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
5777 response->response_time = base::Time::Now();
5778 response->was_cached = true; // (Wouldn't ever actually be true...)
5780 { // Setup state for response_.vary_data
5781 HttpRequestInfo request;
5782 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5783 std::replace(temp.begin(), temp.end(), '\n', '\0');
5784 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5785 request.extra_headers.SetHeader("Foo", "1");
5786 request.extra_headers.SetHeader("bar", "23");
5787 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5790 // Cause the above state to be reset.
5791 trans->ResetStateForRestart();
5793 // Verify that the state that needed to be reset, has been reset.
5794 EXPECT_TRUE(trans->read_buf_.get() == NULL);
5795 EXPECT_EQ(0, trans->read_buf_len_);
5796 EXPECT_TRUE(trans->request_headers_.IsEmpty());
5797 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5798 EXPECT_TRUE(response->headers.get() == NULL);
5799 EXPECT_FALSE(response->was_cached);
5800 EXPECT_EQ(0U, response->ssl_info.cert_status);
5801 EXPECT_FALSE(response->vary_data.is_valid());
5804 // Test HTTPS connections to a site with a bad certificate
5805 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5806 HttpRequestInfo request;
5807 request.method = "GET";
5808 request.url = GURL("https://www.google.com/");
5809 request.load_flags = 0;
5811 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5812 scoped_ptr<HttpTransaction> trans(
5813 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5815 MockWrite data_writes[] = {
5816 MockWrite("GET / HTTP/1.1\r\n"
5817 "Host: www.google.com\r\n"
5818 "Connection: keep-alive\r\n\r\n"),
5821 MockRead data_reads[] = {
5822 MockRead("HTTP/1.0 200 OK\r\n"),
5823 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5824 MockRead("Content-Length: 100\r\n\r\n"),
5825 MockRead(SYNCHRONOUS, OK),
5828 StaticSocketDataProvider ssl_bad_certificate;
5829 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5830 data_writes, arraysize(data_writes));
5831 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5832 SSLSocketDataProvider ssl(ASYNC, OK);
5834 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5835 session_deps_.socket_factory->AddSocketDataProvider(&data);
5836 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5837 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5839 TestCompletionCallback callback;
5841 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5842 EXPECT_EQ(ERR_IO_PENDING, rv);
5844 rv = callback.WaitForResult();
5845 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5847 rv = trans->RestartIgnoringLastError(callback.callback());
5848 EXPECT_EQ(ERR_IO_PENDING, rv);
5850 rv = callback.WaitForResult();
5851 EXPECT_EQ(OK, rv);
5853 const HttpResponseInfo* response = trans->GetResponseInfo();
5855 ASSERT_TRUE(response != NULL);
5856 EXPECT_EQ(100, response->headers->GetContentLength());
5859 // Test HTTPS connections to a site with a bad certificate, going through a
5860 // proxy
5861 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5862 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5864 HttpRequestInfo request;
5865 request.method = "GET";
5866 request.url = GURL("https://www.google.com/");
5867 request.load_flags = 0;
5869 MockWrite proxy_writes[] = {
5870 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5871 "Host: www.google.com\r\n"
5872 "Proxy-Connection: keep-alive\r\n\r\n"),
5875 MockRead proxy_reads[] = {
5876 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5877 MockRead(SYNCHRONOUS, OK)
5880 MockWrite data_writes[] = {
5881 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5882 "Host: www.google.com\r\n"
5883 "Proxy-Connection: keep-alive\r\n\r\n"),
5884 MockWrite("GET / HTTP/1.1\r\n"
5885 "Host: www.google.com\r\n"
5886 "Connection: keep-alive\r\n\r\n"),
5889 MockRead data_reads[] = {
5890 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5891 MockRead("HTTP/1.0 200 OK\r\n"),
5892 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5893 MockRead("Content-Length: 100\r\n\r\n"),
5894 MockRead(SYNCHRONOUS, OK),
5897 StaticSocketDataProvider ssl_bad_certificate(
5898 proxy_reads, arraysize(proxy_reads),
5899 proxy_writes, arraysize(proxy_writes));
5900 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5901 data_writes, arraysize(data_writes));
5902 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5903 SSLSocketDataProvider ssl(ASYNC, OK);
5905 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5906 session_deps_.socket_factory->AddSocketDataProvider(&data);
5907 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5908 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5910 TestCompletionCallback callback;
5912 for (int i = 0; i < 2; i++) {
5913 session_deps_.socket_factory->ResetNextMockIndexes();
5915 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5916 scoped_ptr<HttpTransaction> trans(
5917 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5919 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5920 EXPECT_EQ(ERR_IO_PENDING, rv);
5922 rv = callback.WaitForResult();
5923 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5925 rv = trans->RestartIgnoringLastError(callback.callback());
5926 EXPECT_EQ(ERR_IO_PENDING, rv);
5928 rv = callback.WaitForResult();
5929 EXPECT_EQ(OK, rv);
5931 const HttpResponseInfo* response = trans->GetResponseInfo();
5933 ASSERT_TRUE(response != NULL);
5934 EXPECT_EQ(100, response->headers->GetContentLength());
5939 // Test HTTPS connections to a site, going through an HTTPS proxy
5940 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
5941 session_deps_.proxy_service.reset(
5942 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5943 CapturingNetLog net_log;
5944 session_deps_.net_log = &net_log;
5946 HttpRequestInfo request;
5947 request.method = "GET";
5948 request.url = GURL("https://www.google.com/");
5949 request.load_flags = 0;
5951 MockWrite data_writes[] = {
5952 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5953 "Host: www.google.com\r\n"
5954 "Proxy-Connection: keep-alive\r\n\r\n"),
5955 MockWrite("GET / HTTP/1.1\r\n"
5956 "Host: www.google.com\r\n"
5957 "Connection: keep-alive\r\n\r\n"),
5960 MockRead data_reads[] = {
5961 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5962 MockRead("HTTP/1.1 200 OK\r\n"),
5963 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5964 MockRead("Content-Length: 100\r\n\r\n"),
5965 MockRead(SYNCHRONOUS, OK),
5968 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5969 data_writes, arraysize(data_writes));
5970 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5971 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
5973 session_deps_.socket_factory->AddSocketDataProvider(&data);
5974 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5975 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
5977 TestCompletionCallback callback;
5979 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5980 scoped_ptr<HttpTransaction> trans(
5981 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5983 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5984 EXPECT_EQ(ERR_IO_PENDING, rv);
5986 rv = callback.WaitForResult();
5987 EXPECT_EQ(OK, rv);
5988 const HttpResponseInfo* response = trans->GetResponseInfo();
5990 ASSERT_TRUE(response != NULL);
5992 EXPECT_TRUE(response->headers->IsKeepAlive());
5993 EXPECT_EQ(200, response->headers->response_code());
5994 EXPECT_EQ(100, response->headers->GetContentLength());
5995 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5997 LoadTimingInfo load_timing_info;
5998 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5999 TestLoadTimingNotReusedWithPac(load_timing_info,
6000 CONNECT_TIMING_HAS_SSL_TIMES);
6003 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6004 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6005 session_deps_.proxy_service.reset(
6006 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6007 CapturingNetLog net_log;
6008 session_deps_.net_log = &net_log;
6010 HttpRequestInfo request;
6011 request.method = "GET";
6012 request.url = GURL("https://www.google.com/");
6013 request.load_flags = 0;
6015 MockWrite data_writes[] = {
6016 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6017 "Host: www.google.com\r\n"
6018 "Proxy-Connection: keep-alive\r\n\r\n"),
6021 MockRead data_reads[] = {
6022 MockRead("HTTP/1.1 302 Redirect\r\n"),
6023 MockRead("Location: http://login.example.com/\r\n"),
6024 MockRead("Content-Length: 0\r\n\r\n"),
6025 MockRead(SYNCHRONOUS, OK),
6028 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6029 data_writes, arraysize(data_writes));
6030 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6032 session_deps_.socket_factory->AddSocketDataProvider(&data);
6033 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6035 TestCompletionCallback callback;
6037 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6038 scoped_ptr<HttpTransaction> trans(
6039 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6041 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6042 EXPECT_EQ(ERR_IO_PENDING, rv);
6044 rv = callback.WaitForResult();
6045 EXPECT_EQ(OK, rv);
6046 const HttpResponseInfo* response = trans->GetResponseInfo();
6048 ASSERT_TRUE(response != NULL);
6050 EXPECT_EQ(302, response->headers->response_code());
6051 std::string url;
6052 EXPECT_TRUE(response->headers->IsRedirect(&url));
6053 EXPECT_EQ("http://login.example.com/", url);
6055 // In the case of redirects from proxies, HttpNetworkTransaction returns
6056 // timing for the proxy connection instead of the connection to the host,
6057 // and no send / receive times.
6058 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6059 LoadTimingInfo load_timing_info;
6060 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6062 EXPECT_FALSE(load_timing_info.socket_reused);
6063 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6065 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6066 EXPECT_LE(load_timing_info.proxy_resolve_start,
6067 load_timing_info.proxy_resolve_end);
6068 EXPECT_LE(load_timing_info.proxy_resolve_end,
6069 load_timing_info.connect_timing.connect_start);
6070 ExpectConnectTimingHasTimes(
6071 load_timing_info.connect_timing,
6072 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6074 EXPECT_TRUE(load_timing_info.send_start.is_null());
6075 EXPECT_TRUE(load_timing_info.send_end.is_null());
6076 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6079 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6080 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6081 session_deps_.proxy_service.reset(
6082 ProxyService::CreateFixed("https://proxy:70"));
6084 HttpRequestInfo request;
6085 request.method = "GET";
6086 request.url = GURL("https://www.google.com/");
6087 request.load_flags = 0;
6089 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6090 LOWEST));
6091 scoped_ptr<SpdyFrame> goaway(
6092 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6093 MockWrite data_writes[] = {
6094 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6095 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
6098 static const char* const kExtraHeaders[] = {
6099 "location",
6100 "http://login.example.com/",
6102 scoped_ptr<SpdyFrame> resp(
6103 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6104 arraysize(kExtraHeaders)/2, 1));
6105 MockRead data_reads[] = {
6106 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6107 MockRead(ASYNC, 0, 2), // EOF
6110 DelayedSocketData data(
6111 1, // wait for one write to finish before reading.
6112 data_reads, arraysize(data_reads),
6113 data_writes, arraysize(data_writes));
6114 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6115 proxy_ssl.SetNextProto(GetParam());
6117 session_deps_.socket_factory->AddSocketDataProvider(&data);
6118 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6120 TestCompletionCallback callback;
6122 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6123 scoped_ptr<HttpTransaction> trans(
6124 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6126 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6127 EXPECT_EQ(ERR_IO_PENDING, rv);
6129 rv = callback.WaitForResult();
6130 EXPECT_EQ(OK, rv);
6131 const HttpResponseInfo* response = trans->GetResponseInfo();
6133 ASSERT_TRUE(response != NULL);
6135 EXPECT_EQ(302, response->headers->response_code());
6136 std::string url;
6137 EXPECT_TRUE(response->headers->IsRedirect(&url));
6138 EXPECT_EQ("http://login.example.com/", url);
6141 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6142 TEST_P(HttpNetworkTransactionTest,
6143 ErrorResponseToHttpsConnectViaHttpsProxy) {
6144 session_deps_.proxy_service.reset(
6145 ProxyService::CreateFixed("https://proxy:70"));
6147 HttpRequestInfo request;
6148 request.method = "GET";
6149 request.url = GURL("https://www.google.com/");
6150 request.load_flags = 0;
6152 MockWrite data_writes[] = {
6153 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6154 "Host: www.google.com\r\n"
6155 "Proxy-Connection: keep-alive\r\n\r\n"),
6158 MockRead data_reads[] = {
6159 MockRead("HTTP/1.1 404 Not Found\r\n"),
6160 MockRead("Content-Length: 23\r\n\r\n"),
6161 MockRead("The host does not exist"),
6162 MockRead(SYNCHRONOUS, OK),
6165 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6166 data_writes, arraysize(data_writes));
6167 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6169 session_deps_.socket_factory->AddSocketDataProvider(&data);
6170 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6172 TestCompletionCallback callback;
6174 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6175 scoped_ptr<HttpTransaction> trans(
6176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6179 EXPECT_EQ(ERR_IO_PENDING, rv);
6181 rv = callback.WaitForResult();
6182 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6184 // TODO(ttuttle): Anything else to check here?
6187 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6188 TEST_P(HttpNetworkTransactionTest,
6189 ErrorResponseToHttpsConnectViaSpdyProxy) {
6190 session_deps_.proxy_service.reset(
6191 ProxyService::CreateFixed("https://proxy:70"));
6193 HttpRequestInfo request;
6194 request.method = "GET";
6195 request.url = GURL("https://www.google.com/");
6196 request.load_flags = 0;
6198 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6199 LOWEST));
6200 scoped_ptr<SpdyFrame> rst(
6201 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6202 MockWrite data_writes[] = {
6203 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6204 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6207 static const char* const kExtraHeaders[] = {
6208 "location",
6209 "http://login.example.com/",
6211 scoped_ptr<SpdyFrame> resp(
6212 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6213 arraysize(kExtraHeaders)/2, 1));
6214 scoped_ptr<SpdyFrame> body(
6215 spdy_util_.ConstructSpdyBodyFrame(
6216 1, "The host does not exist", 23, true));
6217 MockRead data_reads[] = {
6218 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6219 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6220 MockRead(ASYNC, 0, 4), // EOF
6223 DelayedSocketData data(
6224 1, // wait for one write to finish before reading.
6225 data_reads, arraysize(data_reads),
6226 data_writes, arraysize(data_writes));
6227 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6228 proxy_ssl.SetNextProto(GetParam());
6230 session_deps_.socket_factory->AddSocketDataProvider(&data);
6231 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6233 TestCompletionCallback callback;
6235 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6236 scoped_ptr<HttpTransaction> trans(
6237 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6239 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6240 EXPECT_EQ(ERR_IO_PENDING, rv);
6242 rv = callback.WaitForResult();
6243 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6245 // TODO(ttuttle): Anything else to check here?
6248 // Test the request-challenge-retry sequence for basic auth, through
6249 // a SPDY proxy over a single SPDY session.
6250 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6251 HttpRequestInfo request;
6252 request.method = "GET";
6253 request.url = GURL("https://www.google.com/");
6254 // when the no authentication data flag is set.
6255 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
6257 // Configure against https proxy server "myproxy:70".
6258 session_deps_.proxy_service.reset(
6259 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6260 CapturingBoundNetLog log;
6261 session_deps_.net_log = log.bound().net_log();
6262 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6264 // Since we have proxy, should try to establish tunnel.
6265 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6266 LOWEST));
6267 scoped_ptr<SpdyFrame> rst(
6268 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6270 // After calling trans->RestartWithAuth(), this is the request we should
6271 // be issuing -- the final header line contains the credentials.
6272 const char* const kAuthCredentials[] = {
6273 "proxy-authorization", "Basic Zm9vOmJhcg==",
6275 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6276 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
6277 // fetch https://www.google.com/ via HTTP
6278 const char get[] = "GET / HTTP/1.1\r\n"
6279 "Host: www.google.com\r\n"
6280 "Connection: keep-alive\r\n\r\n";
6281 scoped_ptr<SpdyFrame> wrapped_get(
6282 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6284 MockWrite spdy_writes[] = {
6285 CreateMockWrite(*req, 1, ASYNC),
6286 CreateMockWrite(*rst, 4, ASYNC),
6287 CreateMockWrite(*connect2, 5),
6288 CreateMockWrite(*wrapped_get, 8),
6291 // The proxy responds to the connect with a 407, using a persistent
6292 // connection.
6293 const char* const kAuthChallenge[] = {
6294 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
6295 spdy_util_.GetVersionKey(), "HTTP/1.1",
6296 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6299 scoped_ptr<SpdyFrame> conn_auth_resp(
6300 spdy_util_.ConstructSpdyControlFrame(NULL,
6302 false,
6304 LOWEST,
6305 SYN_REPLY,
6306 CONTROL_FLAG_NONE,
6307 kAuthChallenge,
6308 arraysize(kAuthChallenge),
6309 0));
6311 scoped_ptr<SpdyFrame> conn_resp(
6312 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6313 const char resp[] = "HTTP/1.1 200 OK\r\n"
6314 "Content-Length: 5\r\n\r\n";
6316 scoped_ptr<SpdyFrame> wrapped_get_resp(
6317 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6318 scoped_ptr<SpdyFrame> wrapped_body(
6319 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6320 MockRead spdy_reads[] = {
6321 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6322 CreateMockRead(*conn_resp, 6, ASYNC),
6323 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6324 CreateMockRead(*wrapped_body, 10, ASYNC),
6325 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6328 OrderedSocketData spdy_data(
6329 spdy_reads, arraysize(spdy_reads),
6330 spdy_writes, arraysize(spdy_writes));
6331 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6332 // Negotiate SPDY to the proxy
6333 SSLSocketDataProvider proxy(ASYNC, OK);
6334 proxy.SetNextProto(GetParam());
6335 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6336 // Vanilla SSL to the server
6337 SSLSocketDataProvider server(ASYNC, OK);
6338 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6340 TestCompletionCallback callback1;
6342 scoped_ptr<HttpTransaction> trans(
6343 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6345 int rv = trans->Start(&request, callback1.callback(), log.bound());
6346 EXPECT_EQ(ERR_IO_PENDING, rv);
6348 rv = callback1.WaitForResult();
6349 EXPECT_EQ(OK, rv);
6350 net::CapturingNetLog::CapturedEntryList entries;
6351 log.GetEntries(&entries);
6352 size_t pos = ExpectLogContainsSomewhere(
6353 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6354 NetLog::PHASE_NONE);
6355 ExpectLogContainsSomewhere(
6356 entries, pos,
6357 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6358 NetLog::PHASE_NONE);
6360 const HttpResponseInfo* response = trans->GetResponseInfo();
6361 ASSERT_TRUE(response != NULL);
6362 ASSERT_FALSE(response->headers.get() == NULL);
6363 EXPECT_EQ(407, response->headers->response_code());
6364 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6365 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6366 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6368 TestCompletionCallback callback2;
6370 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6371 callback2.callback());
6372 EXPECT_EQ(ERR_IO_PENDING, rv);
6374 rv = callback2.WaitForResult();
6375 EXPECT_EQ(OK, rv);
6377 response = trans->GetResponseInfo();
6378 ASSERT_TRUE(response != NULL);
6380 EXPECT_TRUE(response->headers->IsKeepAlive());
6381 EXPECT_EQ(200, response->headers->response_code());
6382 EXPECT_EQ(5, response->headers->GetContentLength());
6383 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6385 // The password prompt info should not be set.
6386 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6388 LoadTimingInfo load_timing_info;
6389 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6390 TestLoadTimingNotReusedWithPac(load_timing_info,
6391 CONNECT_TIMING_HAS_SSL_TIMES);
6393 trans.reset();
6394 session->CloseAllConnections();
6397 // Test that an explicitly trusted SPDY proxy can push a resource from an
6398 // origin that is different from that of its associated resource.
6399 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6400 HttpRequestInfo request;
6401 HttpRequestInfo push_request;
6403 request.method = "GET";
6404 request.url = GURL("http://www.google.com/");
6405 push_request.method = "GET";
6406 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6408 // Configure against https proxy server "myproxy:70".
6409 session_deps_.proxy_service.reset(
6410 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6411 CapturingBoundNetLog log;
6412 session_deps_.net_log = log.bound().net_log();
6414 // Enable cross-origin push.
6415 session_deps_.trusted_spdy_proxy = "myproxy:70";
6417 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6419 scoped_ptr<SpdyFrame> stream1_syn(
6420 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6422 MockWrite spdy_writes[] = {
6423 CreateMockWrite(*stream1_syn, 1, ASYNC),
6426 scoped_ptr<SpdyFrame>
6427 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6429 scoped_ptr<SpdyFrame>
6430 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6432 scoped_ptr<SpdyFrame>
6433 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6437 "http://www.another-origin.com/foo.dat"));
6438 const char kPushedData[] = "pushed";
6439 scoped_ptr<SpdyFrame> stream2_body(
6440 spdy_util_.ConstructSpdyBodyFrame(
6441 2, kPushedData, strlen(kPushedData), true));
6443 MockRead spdy_reads[] = {
6444 CreateMockRead(*stream1_reply, 2, ASYNC),
6445 CreateMockRead(*stream2_syn, 3, ASYNC),
6446 CreateMockRead(*stream1_body, 4, ASYNC),
6447 CreateMockRead(*stream2_body, 5, ASYNC),
6448 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6451 OrderedSocketData spdy_data(
6452 spdy_reads, arraysize(spdy_reads),
6453 spdy_writes, arraysize(spdy_writes));
6454 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6455 // Negotiate SPDY to the proxy
6456 SSLSocketDataProvider proxy(ASYNC, OK);
6457 proxy.SetNextProto(GetParam());
6458 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6460 scoped_ptr<HttpTransaction> trans(
6461 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6462 TestCompletionCallback callback;
6463 int rv = trans->Start(&request, callback.callback(), log.bound());
6464 EXPECT_EQ(ERR_IO_PENDING, rv);
6466 rv = callback.WaitForResult();
6467 EXPECT_EQ(OK, rv);
6468 const HttpResponseInfo* response = trans->GetResponseInfo();
6470 scoped_ptr<HttpTransaction> push_trans(
6471 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6472 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6473 EXPECT_EQ(ERR_IO_PENDING, rv);
6475 rv = callback.WaitForResult();
6476 EXPECT_EQ(OK, rv);
6477 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6479 ASSERT_TRUE(response != NULL);
6480 EXPECT_TRUE(response->headers->IsKeepAlive());
6482 EXPECT_EQ(200, response->headers->response_code());
6483 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6485 std::string response_data;
6486 rv = ReadTransaction(trans.get(), &response_data);
6487 EXPECT_EQ(OK, rv);
6488 EXPECT_EQ("hello!", response_data);
6490 LoadTimingInfo load_timing_info;
6491 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6492 TestLoadTimingNotReusedWithPac(load_timing_info,
6493 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6495 // Verify the pushed stream.
6496 EXPECT_TRUE(push_response->headers.get() != NULL);
6497 EXPECT_EQ(200, push_response->headers->response_code());
6499 rv = ReadTransaction(push_trans.get(), &response_data);
6500 EXPECT_EQ(OK, rv);
6501 EXPECT_EQ("pushed", response_data);
6503 LoadTimingInfo push_load_timing_info;
6504 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6505 TestLoadTimingReusedWithPac(push_load_timing_info);
6506 // The transactions should share a socket ID, despite being for different
6507 // origins.
6508 EXPECT_EQ(load_timing_info.socket_log_id,
6509 push_load_timing_info.socket_log_id);
6511 trans.reset();
6512 push_trans.reset();
6513 session->CloseAllConnections();
6516 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6517 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6518 HttpRequestInfo request;
6520 request.method = "GET";
6521 request.url = GURL("http://www.google.com/");
6523 // Configure against https proxy server "myproxy:70".
6524 session_deps_.proxy_service.reset(
6525 ProxyService::CreateFixed("https://myproxy:70"));
6526 CapturingBoundNetLog log;
6527 session_deps_.net_log = log.bound().net_log();
6529 // Enable cross-origin push.
6530 session_deps_.trusted_spdy_proxy = "myproxy:70";
6532 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6534 scoped_ptr<SpdyFrame> stream1_syn(
6535 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6537 scoped_ptr<SpdyFrame> push_rst(
6538 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6540 MockWrite spdy_writes[] = {
6541 CreateMockWrite(*stream1_syn, 1, ASYNC),
6542 CreateMockWrite(*push_rst, 4),
6545 scoped_ptr<SpdyFrame>
6546 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6548 scoped_ptr<SpdyFrame>
6549 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6551 scoped_ptr<SpdyFrame>
6552 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6556 "https://www.another-origin.com/foo.dat"));
6558 MockRead spdy_reads[] = {
6559 CreateMockRead(*stream1_reply, 2, ASYNC),
6560 CreateMockRead(*stream2_syn, 3, ASYNC),
6561 CreateMockRead(*stream1_body, 5, ASYNC),
6562 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6565 OrderedSocketData spdy_data(
6566 spdy_reads, arraysize(spdy_reads),
6567 spdy_writes, arraysize(spdy_writes));
6568 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6569 // Negotiate SPDY to the proxy
6570 SSLSocketDataProvider proxy(ASYNC, OK);
6571 proxy.SetNextProto(GetParam());
6572 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6574 scoped_ptr<HttpTransaction> trans(
6575 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6576 TestCompletionCallback callback;
6577 int rv = trans->Start(&request, callback.callback(), log.bound());
6578 EXPECT_EQ(ERR_IO_PENDING, rv);
6580 rv = callback.WaitForResult();
6581 EXPECT_EQ(OK, rv);
6582 const HttpResponseInfo* response = trans->GetResponseInfo();
6584 ASSERT_TRUE(response != NULL);
6585 EXPECT_TRUE(response->headers->IsKeepAlive());
6587 EXPECT_EQ(200, response->headers->response_code());
6588 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6590 std::string response_data;
6591 rv = ReadTransaction(trans.get(), &response_data);
6592 EXPECT_EQ(OK, rv);
6593 EXPECT_EQ("hello!", response_data);
6595 trans.reset();
6596 session->CloseAllConnections();
6599 // Test HTTPS connections to a site with a bad certificate, going through an
6600 // HTTPS proxy
6601 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6602 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6603 "https://proxy:70"));
6605 HttpRequestInfo request;
6606 request.method = "GET";
6607 request.url = GURL("https://www.google.com/");
6608 request.load_flags = 0;
6610 // Attempt to fetch the URL from a server with a bad cert
6611 MockWrite bad_cert_writes[] = {
6612 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6613 "Host: www.google.com\r\n"
6614 "Proxy-Connection: keep-alive\r\n\r\n"),
6617 MockRead bad_cert_reads[] = {
6618 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6619 MockRead(SYNCHRONOUS, OK)
6622 // Attempt to fetch the URL with a good cert
6623 MockWrite good_data_writes[] = {
6624 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6625 "Host: www.google.com\r\n"
6626 "Proxy-Connection: keep-alive\r\n\r\n"),
6627 MockWrite("GET / HTTP/1.1\r\n"
6628 "Host: www.google.com\r\n"
6629 "Connection: keep-alive\r\n\r\n"),
6632 MockRead good_cert_reads[] = {
6633 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6634 MockRead("HTTP/1.0 200 OK\r\n"),
6635 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6636 MockRead("Content-Length: 100\r\n\r\n"),
6637 MockRead(SYNCHRONOUS, OK),
6640 StaticSocketDataProvider ssl_bad_certificate(
6641 bad_cert_reads, arraysize(bad_cert_reads),
6642 bad_cert_writes, arraysize(bad_cert_writes));
6643 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6644 good_data_writes, arraysize(good_data_writes));
6645 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6646 SSLSocketDataProvider ssl(ASYNC, OK);
6648 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6649 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6650 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6651 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6653 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6654 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6655 session_deps_.socket_factory->AddSocketDataProvider(&data);
6656 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6658 TestCompletionCallback callback;
6660 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6661 scoped_ptr<HttpTransaction> trans(
6662 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6664 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6665 EXPECT_EQ(ERR_IO_PENDING, rv);
6667 rv = callback.WaitForResult();
6668 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6670 rv = trans->RestartIgnoringLastError(callback.callback());
6671 EXPECT_EQ(ERR_IO_PENDING, rv);
6673 rv = callback.WaitForResult();
6674 EXPECT_EQ(OK, rv);
6676 const HttpResponseInfo* response = trans->GetResponseInfo();
6678 ASSERT_TRUE(response != NULL);
6679 EXPECT_EQ(100, response->headers->GetContentLength());
6682 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6683 HttpRequestInfo request;
6684 request.method = "GET";
6685 request.url = GURL("http://www.google.com/");
6686 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6687 "Chromium Ultra Awesome X Edition");
6689 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6690 scoped_ptr<HttpTransaction> trans(
6691 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6693 MockWrite data_writes[] = {
6694 MockWrite("GET / HTTP/1.1\r\n"
6695 "Host: www.google.com\r\n"
6696 "Connection: keep-alive\r\n"
6697 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6700 // Lastly, the server responds with the actual content.
6701 MockRead data_reads[] = {
6702 MockRead("HTTP/1.0 200 OK\r\n"),
6703 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6704 MockRead("Content-Length: 100\r\n\r\n"),
6705 MockRead(SYNCHRONOUS, OK),
6708 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6709 data_writes, arraysize(data_writes));
6710 session_deps_.socket_factory->AddSocketDataProvider(&data);
6712 TestCompletionCallback callback;
6714 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6715 EXPECT_EQ(ERR_IO_PENDING, rv);
6717 rv = callback.WaitForResult();
6718 EXPECT_EQ(OK, rv);
6721 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6722 HttpRequestInfo request;
6723 request.method = "GET";
6724 request.url = GURL("https://www.google.com/");
6725 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6726 "Chromium Ultra Awesome X Edition");
6728 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6729 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6730 scoped_ptr<HttpTransaction> trans(
6731 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6733 MockWrite data_writes[] = {
6734 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6735 "Host: www.google.com\r\n"
6736 "Proxy-Connection: keep-alive\r\n"
6737 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6739 MockRead data_reads[] = {
6740 // Return an error, so the transaction stops here (this test isn't
6741 // interested in the rest).
6742 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6743 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6744 MockRead("Proxy-Connection: close\r\n\r\n"),
6747 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6748 data_writes, arraysize(data_writes));
6749 session_deps_.socket_factory->AddSocketDataProvider(&data);
6751 TestCompletionCallback callback;
6753 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6754 EXPECT_EQ(ERR_IO_PENDING, rv);
6756 rv = callback.WaitForResult();
6757 EXPECT_EQ(OK, rv);
6760 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6761 HttpRequestInfo request;
6762 request.method = "GET";
6763 request.url = GURL("http://www.google.com/");
6764 request.load_flags = 0;
6765 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6766 "http://the.previous.site.com/");
6768 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6769 scoped_ptr<HttpTransaction> trans(
6770 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6772 MockWrite data_writes[] = {
6773 MockWrite("GET / HTTP/1.1\r\n"
6774 "Host: www.google.com\r\n"
6775 "Connection: keep-alive\r\n"
6776 "Referer: http://the.previous.site.com/\r\n\r\n"),
6779 // Lastly, the server responds with the actual content.
6780 MockRead data_reads[] = {
6781 MockRead("HTTP/1.0 200 OK\r\n"),
6782 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6783 MockRead("Content-Length: 100\r\n\r\n"),
6784 MockRead(SYNCHRONOUS, OK),
6787 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6788 data_writes, arraysize(data_writes));
6789 session_deps_.socket_factory->AddSocketDataProvider(&data);
6791 TestCompletionCallback callback;
6793 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6794 EXPECT_EQ(ERR_IO_PENDING, rv);
6796 rv = callback.WaitForResult();
6797 EXPECT_EQ(OK, rv);
6800 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6801 HttpRequestInfo request;
6802 request.method = "POST";
6803 request.url = GURL("http://www.google.com/");
6805 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6806 scoped_ptr<HttpTransaction> trans(
6807 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6809 MockWrite data_writes[] = {
6810 MockWrite("POST / HTTP/1.1\r\n"
6811 "Host: www.google.com\r\n"
6812 "Connection: keep-alive\r\n"
6813 "Content-Length: 0\r\n\r\n"),
6816 // Lastly, the server responds with the actual content.
6817 MockRead data_reads[] = {
6818 MockRead("HTTP/1.0 200 OK\r\n"),
6819 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6820 MockRead("Content-Length: 100\r\n\r\n"),
6821 MockRead(SYNCHRONOUS, OK),
6824 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6825 data_writes, arraysize(data_writes));
6826 session_deps_.socket_factory->AddSocketDataProvider(&data);
6828 TestCompletionCallback callback;
6830 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6831 EXPECT_EQ(ERR_IO_PENDING, rv);
6833 rv = callback.WaitForResult();
6834 EXPECT_EQ(OK, rv);
6837 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6838 HttpRequestInfo request;
6839 request.method = "PUT";
6840 request.url = GURL("http://www.google.com/");
6842 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6843 scoped_ptr<HttpTransaction> trans(
6844 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6846 MockWrite data_writes[] = {
6847 MockWrite("PUT / HTTP/1.1\r\n"
6848 "Host: www.google.com\r\n"
6849 "Connection: keep-alive\r\n"
6850 "Content-Length: 0\r\n\r\n"),
6853 // Lastly, the server responds with the actual content.
6854 MockRead data_reads[] = {
6855 MockRead("HTTP/1.0 200 OK\r\n"),
6856 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6857 MockRead("Content-Length: 100\r\n\r\n"),
6858 MockRead(SYNCHRONOUS, OK),
6861 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6862 data_writes, arraysize(data_writes));
6863 session_deps_.socket_factory->AddSocketDataProvider(&data);
6865 TestCompletionCallback callback;
6867 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6868 EXPECT_EQ(ERR_IO_PENDING, rv);
6870 rv = callback.WaitForResult();
6871 EXPECT_EQ(OK, rv);
6874 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6875 HttpRequestInfo request;
6876 request.method = "HEAD";
6877 request.url = GURL("http://www.google.com/");
6879 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6880 scoped_ptr<HttpTransaction> trans(
6881 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6883 MockWrite data_writes[] = {
6884 MockWrite("HEAD / HTTP/1.1\r\n"
6885 "Host: www.google.com\r\n"
6886 "Connection: keep-alive\r\n"
6887 "Content-Length: 0\r\n\r\n"),
6890 // Lastly, the server responds with the actual content.
6891 MockRead data_reads[] = {
6892 MockRead("HTTP/1.0 200 OK\r\n"),
6893 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6894 MockRead("Content-Length: 100\r\n\r\n"),
6895 MockRead(SYNCHRONOUS, OK),
6898 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6899 data_writes, arraysize(data_writes));
6900 session_deps_.socket_factory->AddSocketDataProvider(&data);
6902 TestCompletionCallback callback;
6904 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6905 EXPECT_EQ(ERR_IO_PENDING, rv);
6907 rv = callback.WaitForResult();
6908 EXPECT_EQ(OK, rv);
6911 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
6912 HttpRequestInfo request;
6913 request.method = "GET";
6914 request.url = GURL("http://www.google.com/");
6915 request.load_flags = LOAD_BYPASS_CACHE;
6917 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6918 scoped_ptr<HttpTransaction> trans(
6919 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6921 MockWrite data_writes[] = {
6922 MockWrite("GET / HTTP/1.1\r\n"
6923 "Host: www.google.com\r\n"
6924 "Connection: keep-alive\r\n"
6925 "Pragma: no-cache\r\n"
6926 "Cache-Control: no-cache\r\n\r\n"),
6929 // Lastly, the server responds with the actual content.
6930 MockRead data_reads[] = {
6931 MockRead("HTTP/1.0 200 OK\r\n"),
6932 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6933 MockRead("Content-Length: 100\r\n\r\n"),
6934 MockRead(SYNCHRONOUS, OK),
6937 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6938 data_writes, arraysize(data_writes));
6939 session_deps_.socket_factory->AddSocketDataProvider(&data);
6941 TestCompletionCallback callback;
6943 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6944 EXPECT_EQ(ERR_IO_PENDING, rv);
6946 rv = callback.WaitForResult();
6947 EXPECT_EQ(OK, rv);
6950 TEST_P(HttpNetworkTransactionTest,
6951 BuildRequest_CacheControlValidateCache) {
6952 HttpRequestInfo request;
6953 request.method = "GET";
6954 request.url = GURL("http://www.google.com/");
6955 request.load_flags = LOAD_VALIDATE_CACHE;
6957 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6958 scoped_ptr<HttpTransaction> trans(
6959 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6961 MockWrite data_writes[] = {
6962 MockWrite("GET / HTTP/1.1\r\n"
6963 "Host: www.google.com\r\n"
6964 "Connection: keep-alive\r\n"
6965 "Cache-Control: max-age=0\r\n\r\n"),
6968 // Lastly, the server responds with the actual content.
6969 MockRead data_reads[] = {
6970 MockRead("HTTP/1.0 200 OK\r\n"),
6971 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6972 MockRead("Content-Length: 100\r\n\r\n"),
6973 MockRead(SYNCHRONOUS, OK),
6976 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6977 data_writes, arraysize(data_writes));
6978 session_deps_.socket_factory->AddSocketDataProvider(&data);
6980 TestCompletionCallback callback;
6982 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6983 EXPECT_EQ(ERR_IO_PENDING, rv);
6985 rv = callback.WaitForResult();
6986 EXPECT_EQ(OK, rv);
6989 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
6990 HttpRequestInfo request;
6991 request.method = "GET";
6992 request.url = GURL("http://www.google.com/");
6993 request.extra_headers.SetHeader("FooHeader", "Bar");
6995 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6996 scoped_ptr<HttpTransaction> trans(
6997 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6999 MockWrite data_writes[] = {
7000 MockWrite("GET / HTTP/1.1\r\n"
7001 "Host: www.google.com\r\n"
7002 "Connection: keep-alive\r\n"
7003 "FooHeader: Bar\r\n\r\n"),
7006 // Lastly, the server responds with the actual content.
7007 MockRead data_reads[] = {
7008 MockRead("HTTP/1.0 200 OK\r\n"),
7009 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7010 MockRead("Content-Length: 100\r\n\r\n"),
7011 MockRead(SYNCHRONOUS, OK),
7014 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7015 data_writes, arraysize(data_writes));
7016 session_deps_.socket_factory->AddSocketDataProvider(&data);
7018 TestCompletionCallback callback;
7020 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7021 EXPECT_EQ(ERR_IO_PENDING, rv);
7023 rv = callback.WaitForResult();
7024 EXPECT_EQ(OK, rv);
7027 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7028 HttpRequestInfo request;
7029 request.method = "GET";
7030 request.url = GURL("http://www.google.com/");
7031 request.extra_headers.SetHeader("referer", "www.foo.com");
7032 request.extra_headers.SetHeader("hEllo", "Kitty");
7033 request.extra_headers.SetHeader("FoO", "bar");
7035 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7036 scoped_ptr<HttpTransaction> trans(
7037 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7039 MockWrite data_writes[] = {
7040 MockWrite("GET / HTTP/1.1\r\n"
7041 "Host: www.google.com\r\n"
7042 "Connection: keep-alive\r\n"
7043 "referer: www.foo.com\r\n"
7044 "hEllo: Kitty\r\n"
7045 "FoO: bar\r\n\r\n"),
7048 // Lastly, the server responds with the actual content.
7049 MockRead data_reads[] = {
7050 MockRead("HTTP/1.0 200 OK\r\n"),
7051 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7052 MockRead("Content-Length: 100\r\n\r\n"),
7053 MockRead(SYNCHRONOUS, OK),
7056 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7057 data_writes, arraysize(data_writes));
7058 session_deps_.socket_factory->AddSocketDataProvider(&data);
7060 TestCompletionCallback callback;
7062 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7063 EXPECT_EQ(ERR_IO_PENDING, rv);
7065 rv = callback.WaitForResult();
7066 EXPECT_EQ(OK, rv);
7069 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7070 HttpRequestInfo request;
7071 request.method = "GET";
7072 request.url = GURL("http://www.google.com/");
7073 request.load_flags = 0;
7075 session_deps_.proxy_service.reset(
7076 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7077 CapturingNetLog net_log;
7078 session_deps_.net_log = &net_log;
7080 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7081 scoped_ptr<HttpTransaction> trans(
7082 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7084 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7085 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7087 MockWrite data_writes[] = {
7088 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7089 MockWrite("GET / HTTP/1.1\r\n"
7090 "Host: www.google.com\r\n"
7091 "Connection: keep-alive\r\n\r\n")
7094 MockRead data_reads[] = {
7095 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7096 MockRead("HTTP/1.0 200 OK\r\n"),
7097 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7098 MockRead("Payload"),
7099 MockRead(SYNCHRONOUS, OK)
7102 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7103 data_writes, arraysize(data_writes));
7104 session_deps_.socket_factory->AddSocketDataProvider(&data);
7106 TestCompletionCallback callback;
7108 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7109 EXPECT_EQ(ERR_IO_PENDING, rv);
7111 rv = callback.WaitForResult();
7112 EXPECT_EQ(OK, rv);
7114 const HttpResponseInfo* response = trans->GetResponseInfo();
7115 ASSERT_TRUE(response != NULL);
7117 LoadTimingInfo load_timing_info;
7118 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7119 TestLoadTimingNotReusedWithPac(load_timing_info,
7120 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7122 std::string response_text;
7123 rv = ReadTransaction(trans.get(), &response_text);
7124 EXPECT_EQ(OK, rv);
7125 EXPECT_EQ("Payload", response_text);
7128 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7129 HttpRequestInfo request;
7130 request.method = "GET";
7131 request.url = GURL("https://www.google.com/");
7132 request.load_flags = 0;
7134 session_deps_.proxy_service.reset(
7135 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7136 CapturingNetLog net_log;
7137 session_deps_.net_log = &net_log;
7139 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7140 scoped_ptr<HttpTransaction> trans(
7141 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7143 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7144 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7146 MockWrite data_writes[] = {
7147 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7148 arraysize(write_buffer)),
7149 MockWrite("GET / HTTP/1.1\r\n"
7150 "Host: www.google.com\r\n"
7151 "Connection: keep-alive\r\n\r\n")
7154 MockRead data_reads[] = {
7155 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7156 arraysize(read_buffer)),
7157 MockRead("HTTP/1.0 200 OK\r\n"),
7158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7159 MockRead("Payload"),
7160 MockRead(SYNCHRONOUS, OK)
7163 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7164 data_writes, arraysize(data_writes));
7165 session_deps_.socket_factory->AddSocketDataProvider(&data);
7167 SSLSocketDataProvider ssl(ASYNC, OK);
7168 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7170 TestCompletionCallback callback;
7172 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7173 EXPECT_EQ(ERR_IO_PENDING, rv);
7175 rv = callback.WaitForResult();
7176 EXPECT_EQ(OK, rv);
7178 LoadTimingInfo load_timing_info;
7179 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7180 TestLoadTimingNotReusedWithPac(load_timing_info,
7181 CONNECT_TIMING_HAS_SSL_TIMES);
7183 const HttpResponseInfo* response = trans->GetResponseInfo();
7184 ASSERT_TRUE(response != NULL);
7186 std::string response_text;
7187 rv = ReadTransaction(trans.get(), &response_text);
7188 EXPECT_EQ(OK, rv);
7189 EXPECT_EQ("Payload", response_text);
7192 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7193 HttpRequestInfo request;
7194 request.method = "GET";
7195 request.url = GURL("http://www.google.com/");
7196 request.load_flags = 0;
7198 session_deps_.proxy_service.reset(
7199 ProxyService::CreateFixed("socks4://myproxy:1080"));
7200 CapturingNetLog net_log;
7201 session_deps_.net_log = &net_log;
7203 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7204 scoped_ptr<HttpTransaction> trans(
7205 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7207 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7208 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7210 MockWrite data_writes[] = {
7211 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7212 MockWrite("GET / HTTP/1.1\r\n"
7213 "Host: www.google.com\r\n"
7214 "Connection: keep-alive\r\n\r\n")
7217 MockRead data_reads[] = {
7218 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7219 MockRead("HTTP/1.0 200 OK\r\n"),
7220 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7221 MockRead("Payload"),
7222 MockRead(SYNCHRONOUS, OK)
7225 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7226 data_writes, arraysize(data_writes));
7227 session_deps_.socket_factory->AddSocketDataProvider(&data);
7229 TestCompletionCallback callback;
7231 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7232 EXPECT_EQ(ERR_IO_PENDING, rv);
7234 rv = callback.WaitForResult();
7235 EXPECT_EQ(OK, rv);
7237 const HttpResponseInfo* response = trans->GetResponseInfo();
7238 ASSERT_TRUE(response != NULL);
7240 LoadTimingInfo load_timing_info;
7241 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7242 TestLoadTimingNotReused(load_timing_info,
7243 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7245 std::string response_text;
7246 rv = ReadTransaction(trans.get(), &response_text);
7247 EXPECT_EQ(OK, rv);
7248 EXPECT_EQ("Payload", response_text);
7251 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7252 HttpRequestInfo request;
7253 request.method = "GET";
7254 request.url = GURL("http://www.google.com/");
7255 request.load_flags = 0;
7257 session_deps_.proxy_service.reset(
7258 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7259 CapturingNetLog net_log;
7260 session_deps_.net_log = &net_log;
7262 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7263 scoped_ptr<HttpTransaction> trans(
7264 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7266 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7267 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7268 const char kSOCKS5OkRequest[] = {
7269 0x05, // Version
7270 0x01, // Command (CONNECT)
7271 0x00, // Reserved.
7272 0x03, // Address type (DOMAINNAME).
7273 0x0E, // Length of domain (14)
7274 // Domain string:
7275 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7276 0x00, 0x50, // 16-bit port (80)
7278 const char kSOCKS5OkResponse[] =
7279 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7281 MockWrite data_writes[] = {
7282 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7283 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7284 MockWrite("GET / HTTP/1.1\r\n"
7285 "Host: www.google.com\r\n"
7286 "Connection: keep-alive\r\n\r\n")
7289 MockRead data_reads[] = {
7290 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7291 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7292 MockRead("HTTP/1.0 200 OK\r\n"),
7293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7294 MockRead("Payload"),
7295 MockRead(SYNCHRONOUS, OK)
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);
7310 const HttpResponseInfo* response = trans->GetResponseInfo();
7311 ASSERT_TRUE(response != NULL);
7313 LoadTimingInfo load_timing_info;
7314 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7315 TestLoadTimingNotReusedWithPac(load_timing_info,
7316 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7318 std::string response_text;
7319 rv = ReadTransaction(trans.get(), &response_text);
7320 EXPECT_EQ(OK, rv);
7321 EXPECT_EQ("Payload", response_text);
7324 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7325 HttpRequestInfo request;
7326 request.method = "GET";
7327 request.url = GURL("https://www.google.com/");
7328 request.load_flags = 0;
7330 session_deps_.proxy_service.reset(
7331 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7332 CapturingNetLog net_log;
7333 session_deps_.net_log = &net_log;
7335 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7336 scoped_ptr<HttpTransaction> trans(
7337 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7339 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7340 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7341 const unsigned char kSOCKS5OkRequest[] = {
7342 0x05, // Version
7343 0x01, // Command (CONNECT)
7344 0x00, // Reserved.
7345 0x03, // Address type (DOMAINNAME).
7346 0x0E, // Length of domain (14)
7347 // Domain string:
7348 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7349 0x01, 0xBB, // 16-bit port (443)
7352 const char kSOCKS5OkResponse[] =
7353 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7355 MockWrite data_writes[] = {
7356 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7357 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7358 arraysize(kSOCKS5OkRequest)),
7359 MockWrite("GET / HTTP/1.1\r\n"
7360 "Host: www.google.com\r\n"
7361 "Connection: keep-alive\r\n\r\n")
7364 MockRead data_reads[] = {
7365 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7366 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7367 MockRead("HTTP/1.0 200 OK\r\n"),
7368 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7369 MockRead("Payload"),
7370 MockRead(SYNCHRONOUS, OK)
7373 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7374 data_writes, arraysize(data_writes));
7375 session_deps_.socket_factory->AddSocketDataProvider(&data);
7377 SSLSocketDataProvider ssl(ASYNC, OK);
7378 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7380 TestCompletionCallback callback;
7382 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7383 EXPECT_EQ(ERR_IO_PENDING, rv);
7385 rv = callback.WaitForResult();
7386 EXPECT_EQ(OK, rv);
7388 const HttpResponseInfo* response = trans->GetResponseInfo();
7389 ASSERT_TRUE(response != NULL);
7391 LoadTimingInfo load_timing_info;
7392 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7393 TestLoadTimingNotReusedWithPac(load_timing_info,
7394 CONNECT_TIMING_HAS_SSL_TIMES);
7396 std::string response_text;
7397 rv = ReadTransaction(trans.get(), &response_text);
7398 EXPECT_EQ(OK, rv);
7399 EXPECT_EQ("Payload", response_text);
7402 namespace {
7404 // Tests that for connection endpoints the group names are correctly set.
7406 struct GroupNameTest {
7407 std::string proxy_server;
7408 std::string url;
7409 std::string expected_group_name;
7410 bool ssl;
7413 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7414 NextProto next_proto,
7415 SpdySessionDependencies* session_deps_) {
7416 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7418 base::WeakPtr<HttpServerProperties> http_server_properties =
7419 session->http_server_properties();
7420 http_server_properties->SetAlternateProtocol(
7421 HostPortPair("host.with.alternate", 80), 443,
7422 AlternateProtocolFromNextProto(next_proto));
7424 return session;
7427 int GroupNameTransactionHelper(
7428 const std::string& url,
7429 const scoped_refptr<HttpNetworkSession>& session) {
7430 HttpRequestInfo request;
7431 request.method = "GET";
7432 request.url = GURL(url);
7433 request.load_flags = 0;
7435 scoped_ptr<HttpTransaction> trans(
7436 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7438 TestCompletionCallback callback;
7440 // We do not complete this request, the dtor will clean the transaction up.
7441 return trans->Start(&request, callback.callback(), BoundNetLog());
7444 } // namespace
7446 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7447 const GroupNameTest tests[] = {
7449 "", // unused
7450 "http://www.google.com/direct",
7451 "www.google.com:80",
7452 false,
7455 "", // unused
7456 "http://[2001:1418:13:1::25]/direct",
7457 "[2001:1418:13:1::25]:80",
7458 false,
7461 // SSL Tests
7463 "", // unused
7464 "https://www.google.com/direct_ssl",
7465 "ssl/www.google.com:443",
7466 true,
7469 "", // unused
7470 "https://[2001:1418:13:1::25]/direct",
7471 "ssl/[2001:1418:13:1::25]:443",
7472 true,
7475 "", // unused
7476 "http://host.with.alternate/direct",
7477 "ssl/host.with.alternate:443",
7478 true,
7482 HttpStreamFactory::set_use_alternate_protocols(true);
7484 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7485 session_deps_.proxy_service.reset(
7486 ProxyService::CreateFixed(tests[i].proxy_server));
7487 scoped_refptr<HttpNetworkSession> session(
7488 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7490 HttpNetworkSessionPeer peer(session);
7491 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7492 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7493 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7494 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7495 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7496 new MockClientSocketPoolManager);
7497 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7498 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7499 peer.SetClientSocketPoolManager(
7500 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7502 EXPECT_EQ(ERR_IO_PENDING,
7503 GroupNameTransactionHelper(tests[i].url, session));
7504 if (tests[i].ssl)
7505 EXPECT_EQ(tests[i].expected_group_name,
7506 ssl_conn_pool->last_group_name_received());
7507 else
7508 EXPECT_EQ(tests[i].expected_group_name,
7509 transport_conn_pool->last_group_name_received());
7514 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7515 const GroupNameTest tests[] = {
7517 "http_proxy",
7518 "http://www.google.com/http_proxy_normal",
7519 "www.google.com:80",
7520 false,
7523 // SSL Tests
7525 "http_proxy",
7526 "https://www.google.com/http_connect_ssl",
7527 "ssl/www.google.com:443",
7528 true,
7532 "http_proxy",
7533 "http://host.with.alternate/direct",
7534 "ssl/host.with.alternate:443",
7535 true,
7539 "http_proxy",
7540 "ftp://ftp.google.com/http_proxy_normal",
7541 "ftp/ftp.google.com:21",
7542 false,
7546 HttpStreamFactory::set_use_alternate_protocols(true);
7548 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7549 session_deps_.proxy_service.reset(
7550 ProxyService::CreateFixed(tests[i].proxy_server));
7551 scoped_refptr<HttpNetworkSession> session(
7552 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7554 HttpNetworkSessionPeer peer(session);
7556 HostPortPair proxy_host("http_proxy", 80);
7557 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7558 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7559 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7560 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7562 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7563 new MockClientSocketPoolManager);
7564 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7565 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7566 peer.SetClientSocketPoolManager(
7567 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7569 EXPECT_EQ(ERR_IO_PENDING,
7570 GroupNameTransactionHelper(tests[i].url, session));
7571 if (tests[i].ssl)
7572 EXPECT_EQ(tests[i].expected_group_name,
7573 ssl_conn_pool->last_group_name_received());
7574 else
7575 EXPECT_EQ(tests[i].expected_group_name,
7576 http_proxy_pool->last_group_name_received());
7580 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7581 const GroupNameTest tests[] = {
7583 "socks4://socks_proxy:1080",
7584 "http://www.google.com/socks4_direct",
7585 "socks4/www.google.com:80",
7586 false,
7589 "socks5://socks_proxy:1080",
7590 "http://www.google.com/socks5_direct",
7591 "socks5/www.google.com:80",
7592 false,
7595 // SSL Tests
7597 "socks4://socks_proxy:1080",
7598 "https://www.google.com/socks4_ssl",
7599 "socks4/ssl/www.google.com:443",
7600 true,
7603 "socks5://socks_proxy:1080",
7604 "https://www.google.com/socks5_ssl",
7605 "socks5/ssl/www.google.com:443",
7606 true,
7610 "socks4://socks_proxy:1080",
7611 "http://host.with.alternate/direct",
7612 "socks4/ssl/host.with.alternate:443",
7613 true,
7617 HttpStreamFactory::set_use_alternate_protocols(true);
7619 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7620 session_deps_.proxy_service.reset(
7621 ProxyService::CreateFixed(tests[i].proxy_server));
7622 scoped_refptr<HttpNetworkSession> session(
7623 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7625 HttpNetworkSessionPeer peer(session);
7627 HostPortPair proxy_host("socks_proxy", 1080);
7628 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7629 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7630 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7631 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7633 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7634 new MockClientSocketPoolManager);
7635 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7636 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7637 peer.SetClientSocketPoolManager(
7638 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7640 scoped_ptr<HttpTransaction> trans(
7641 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7643 EXPECT_EQ(ERR_IO_PENDING,
7644 GroupNameTransactionHelper(tests[i].url, session));
7645 if (tests[i].ssl)
7646 EXPECT_EQ(tests[i].expected_group_name,
7647 ssl_conn_pool->last_group_name_received());
7648 else
7649 EXPECT_EQ(tests[i].expected_group_name,
7650 socks_conn_pool->last_group_name_received());
7654 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7655 HttpRequestInfo request;
7656 request.method = "GET";
7657 request.url = GURL("http://www.google.com/");
7659 session_deps_.proxy_service.reset(
7660 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7662 // This simulates failure resolving all hostnames; that means we will fail
7663 // connecting to both proxies (myproxy:70 and foobar:80).
7664 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7666 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7667 scoped_ptr<HttpTransaction> trans(
7668 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7670 TestCompletionCallback callback;
7672 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7673 EXPECT_EQ(ERR_IO_PENDING, rv);
7675 rv = callback.WaitForResult();
7676 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7679 // Base test to make sure that when the load flags for a request specify to
7680 // bypass the cache, the DNS cache is not used.
7681 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7682 int load_flags) {
7683 // Issue a request, asking to bypass the cache(s).
7684 HttpRequestInfo request;
7685 request.method = "GET";
7686 request.load_flags = load_flags;
7687 request.url = GURL("http://www.google.com/");
7689 // Select a host resolver that does caching.
7690 session_deps_.host_resolver.reset(new MockCachingHostResolver);
7692 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7693 scoped_ptr<HttpTransaction> trans(
7694 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7696 // Warm up the host cache so it has an entry for "www.google.com".
7697 AddressList addrlist;
7698 TestCompletionCallback callback;
7699 int rv = session_deps_.host_resolver->Resolve(
7700 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7701 DEFAULT_PRIORITY,
7702 &addrlist,
7703 callback.callback(),
7704 NULL,
7705 BoundNetLog());
7706 EXPECT_EQ(ERR_IO_PENDING, rv);
7707 rv = callback.WaitForResult();
7708 EXPECT_EQ(OK, rv);
7710 // Verify that it was added to host cache, by doing a subsequent async lookup
7711 // and confirming it completes synchronously.
7712 rv = session_deps_.host_resolver->Resolve(
7713 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7714 DEFAULT_PRIORITY,
7715 &addrlist,
7716 callback.callback(),
7717 NULL,
7718 BoundNetLog());
7719 ASSERT_EQ(OK, rv);
7721 // Inject a failure the next time that "www.google.com" is resolved. This way
7722 // we can tell if the next lookup hit the cache, or the "network".
7723 // (cache --> success, "network" --> failure).
7724 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7726 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7727 // first read -- this won't be reached as the host resolution will fail first.
7728 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7729 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7730 session_deps_.socket_factory->AddSocketDataProvider(&data);
7732 // Run the request.
7733 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7734 ASSERT_EQ(ERR_IO_PENDING, rv);
7735 rv = callback.WaitForResult();
7737 // If we bypassed the cache, we would have gotten a failure while resolving
7738 // "www.google.com".
7739 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7742 // There are multiple load flags that should trigger the host cache bypass.
7743 // Test each in isolation:
7744 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7745 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7748 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7749 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7752 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7753 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7756 // Make sure we can handle an error when writing the request.
7757 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7758 HttpRequestInfo request;
7759 request.method = "GET";
7760 request.url = GURL("http://www.foo.com/");
7761 request.load_flags = 0;
7763 MockWrite write_failure[] = {
7764 MockWrite(ASYNC, ERR_CONNECTION_RESET),
7766 StaticSocketDataProvider data(NULL, 0,
7767 write_failure, arraysize(write_failure));
7768 session_deps_.socket_factory->AddSocketDataProvider(&data);
7769 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7771 TestCompletionCallback callback;
7773 scoped_ptr<HttpTransaction> trans(
7774 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7776 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7777 EXPECT_EQ(ERR_IO_PENDING, rv);
7779 rv = callback.WaitForResult();
7780 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7783 // Check that a connection closed after the start of the headers finishes ok.
7784 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7785 HttpRequestInfo request;
7786 request.method = "GET";
7787 request.url = GURL("http://www.foo.com/");
7788 request.load_flags = 0;
7790 MockRead data_reads[] = {
7791 MockRead("HTTP/1."),
7792 MockRead(SYNCHRONOUS, OK),
7795 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7796 session_deps_.socket_factory->AddSocketDataProvider(&data);
7797 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7799 TestCompletionCallback callback;
7801 scoped_ptr<HttpTransaction> trans(
7802 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7804 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7805 EXPECT_EQ(ERR_IO_PENDING, rv);
7807 rv = callback.WaitForResult();
7808 EXPECT_EQ(OK, rv);
7810 const HttpResponseInfo* response = trans->GetResponseInfo();
7811 ASSERT_TRUE(response != NULL);
7813 EXPECT_TRUE(response->headers.get() != NULL);
7814 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7816 std::string response_data;
7817 rv = ReadTransaction(trans.get(), &response_data);
7818 EXPECT_EQ(OK, rv);
7819 EXPECT_EQ("", response_data);
7822 // Make sure that a dropped connection while draining the body for auth
7823 // restart does the right thing.
7824 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7825 HttpRequestInfo request;
7826 request.method = "GET";
7827 request.url = GURL("http://www.google.com/");
7828 request.load_flags = 0;
7830 MockWrite data_writes1[] = {
7831 MockWrite("GET / HTTP/1.1\r\n"
7832 "Host: www.google.com\r\n"
7833 "Connection: keep-alive\r\n\r\n"),
7836 MockRead data_reads1[] = {
7837 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7838 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7839 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7840 MockRead("Content-Length: 14\r\n\r\n"),
7841 MockRead("Unauth"),
7842 MockRead(ASYNC, ERR_CONNECTION_RESET),
7845 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7846 data_writes1, arraysize(data_writes1));
7847 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7849 // After calling trans->RestartWithAuth(), this is the request we should
7850 // be issuing -- the final header line contains the credentials.
7851 MockWrite data_writes2[] = {
7852 MockWrite("GET / HTTP/1.1\r\n"
7853 "Host: www.google.com\r\n"
7854 "Connection: keep-alive\r\n"
7855 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7858 // Lastly, the server responds with the actual content.
7859 MockRead data_reads2[] = {
7860 MockRead("HTTP/1.1 200 OK\r\n"),
7861 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7862 MockRead("Content-Length: 100\r\n\r\n"),
7863 MockRead(SYNCHRONOUS, OK),
7866 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7867 data_writes2, arraysize(data_writes2));
7868 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7869 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7871 TestCompletionCallback callback1;
7873 scoped_ptr<HttpTransaction> trans(
7874 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7876 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7877 EXPECT_EQ(ERR_IO_PENDING, rv);
7879 rv = callback1.WaitForResult();
7880 EXPECT_EQ(OK, rv);
7882 const HttpResponseInfo* response = trans->GetResponseInfo();
7883 ASSERT_TRUE(response != NULL);
7884 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7886 TestCompletionCallback callback2;
7888 rv = trans->RestartWithAuth(
7889 AuthCredentials(kFoo, kBar), callback2.callback());
7890 EXPECT_EQ(ERR_IO_PENDING, rv);
7892 rv = callback2.WaitForResult();
7893 EXPECT_EQ(OK, rv);
7895 response = trans->GetResponseInfo();
7896 ASSERT_TRUE(response != NULL);
7897 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7898 EXPECT_EQ(100, response->headers->GetContentLength());
7901 // Test HTTPS connections going through a proxy that sends extra data.
7902 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
7903 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7905 HttpRequestInfo request;
7906 request.method = "GET";
7907 request.url = GURL("https://www.google.com/");
7908 request.load_flags = 0;
7910 MockRead proxy_reads[] = {
7911 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7912 MockRead(SYNCHRONOUS, OK)
7915 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
7916 SSLSocketDataProvider ssl(ASYNC, OK);
7918 session_deps_.socket_factory->AddSocketDataProvider(&data);
7919 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7921 TestCompletionCallback callback;
7923 session_deps_.socket_factory->ResetNextMockIndexes();
7925 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7926 scoped_ptr<HttpTransaction> trans(
7927 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7929 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7930 EXPECT_EQ(ERR_IO_PENDING, rv);
7932 rv = callback.WaitForResult();
7933 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
7936 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
7937 HttpRequestInfo request;
7938 request.method = "GET";
7939 request.url = GURL("http://www.google.com/");
7940 request.load_flags = 0;
7942 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7943 scoped_ptr<HttpTransaction> trans(
7944 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7946 MockRead data_reads[] = {
7947 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7948 MockRead(SYNCHRONOUS, OK),
7951 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7952 session_deps_.socket_factory->AddSocketDataProvider(&data);
7954 TestCompletionCallback callback;
7956 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7957 EXPECT_EQ(ERR_IO_PENDING, rv);
7959 EXPECT_EQ(OK, callback.WaitForResult());
7961 const HttpResponseInfo* response = trans->GetResponseInfo();
7962 ASSERT_TRUE(response != NULL);
7964 EXPECT_TRUE(response->headers.get() != NULL);
7965 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7967 std::string response_data;
7968 rv = ReadTransaction(trans.get(), &response_data);
7969 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
7972 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
7973 base::FilePath temp_file_path;
7974 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
7975 const uint64 kFakeSize = 100000; // file is actually blank
7976 UploadFileElementReader::ScopedOverridingContentLengthForTests
7977 overriding_content_length(kFakeSize);
7979 ScopedVector<UploadElementReader> element_readers;
7980 element_readers.push_back(
7981 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7982 temp_file_path,
7984 kuint64max,
7985 base::Time()));
7986 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7988 HttpRequestInfo request;
7989 request.method = "POST";
7990 request.url = GURL("http://www.google.com/upload");
7991 request.upload_data_stream = &upload_data_stream;
7992 request.load_flags = 0;
7994 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7995 scoped_ptr<HttpTransaction> trans(
7996 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7998 MockRead data_reads[] = {
7999 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8000 MockRead("hello world"),
8001 MockRead(SYNCHRONOUS, OK),
8003 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8004 session_deps_.socket_factory->AddSocketDataProvider(&data);
8006 TestCompletionCallback callback;
8008 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8009 EXPECT_EQ(ERR_IO_PENDING, rv);
8011 rv = callback.WaitForResult();
8012 EXPECT_EQ(OK, rv);
8014 const HttpResponseInfo* response = trans->GetResponseInfo();
8015 ASSERT_TRUE(response != NULL);
8017 EXPECT_TRUE(response->headers.get() != NULL);
8018 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8020 std::string response_data;
8021 rv = ReadTransaction(trans.get(), &response_data);
8022 EXPECT_EQ(OK, rv);
8023 EXPECT_EQ("hello world", response_data);
8025 base::DeleteFile(temp_file_path, false);
8028 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8029 base::FilePath temp_file;
8030 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8031 std::string temp_file_content("Unreadable file.");
8032 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8033 temp_file_content.length()));
8034 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
8036 ScopedVector<UploadElementReader> element_readers;
8037 element_readers.push_back(
8038 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8039 temp_file,
8041 kuint64max,
8042 base::Time()));
8043 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8045 HttpRequestInfo request;
8046 request.method = "POST";
8047 request.url = GURL("http://www.google.com/upload");
8048 request.upload_data_stream = &upload_data_stream;
8049 request.load_flags = 0;
8051 // If we try to upload an unreadable file, the transaction should fail.
8052 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8053 scoped_ptr<HttpTransaction> trans(
8054 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8056 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8057 session_deps_.socket_factory->AddSocketDataProvider(&data);
8059 TestCompletionCallback callback;
8061 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8062 EXPECT_EQ(ERR_IO_PENDING, rv);
8064 rv = callback.WaitForResult();
8065 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8067 const HttpResponseInfo* response = trans->GetResponseInfo();
8068 EXPECT_FALSE(response);
8070 base::DeleteFile(temp_file, false);
8073 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8074 class FakeUploadElementReader : public UploadElementReader {
8075 public:
8076 FakeUploadElementReader() {}
8077 virtual ~FakeUploadElementReader() {}
8079 const CompletionCallback& callback() const { return callback_; }
8081 // UploadElementReader overrides:
8082 virtual int Init(const CompletionCallback& callback) OVERRIDE {
8083 callback_ = callback;
8084 return ERR_IO_PENDING;
8086 virtual uint64 GetContentLength() const OVERRIDE { return 0; }
8087 virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
8088 virtual int Read(IOBuffer* buf,
8089 int buf_length,
8090 const CompletionCallback& callback) OVERRIDE {
8091 return ERR_FAILED;
8094 private:
8095 CompletionCallback callback_;
8098 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8099 ScopedVector<UploadElementReader> element_readers;
8100 element_readers.push_back(fake_reader);
8101 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8103 HttpRequestInfo request;
8104 request.method = "POST";
8105 request.url = GURL("http://www.google.com/upload");
8106 request.upload_data_stream = &upload_data_stream;
8107 request.load_flags = 0;
8109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8110 scoped_ptr<HttpTransaction> trans(
8111 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8113 StaticSocketDataProvider data;
8114 session_deps_.socket_factory->AddSocketDataProvider(&data);
8116 TestCompletionCallback callback;
8117 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8118 EXPECT_EQ(ERR_IO_PENDING, rv);
8119 base::MessageLoop::current()->RunUntilIdle();
8121 // Transaction is pending on request body initialization.
8122 ASSERT_FALSE(fake_reader->callback().is_null());
8124 // Return Init()'s result after the transaction gets destroyed.
8125 trans.reset();
8126 fake_reader->callback().Run(OK); // Should not crash.
8129 // Tests that changes to Auth realms are treated like auth rejections.
8130 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8132 HttpRequestInfo request;
8133 request.method = "GET";
8134 request.url = GURL("http://www.google.com/");
8135 request.load_flags = 0;
8137 // First transaction will request a resource and receive a Basic challenge
8138 // with realm="first_realm".
8139 MockWrite data_writes1[] = {
8140 MockWrite("GET / HTTP/1.1\r\n"
8141 "Host: www.google.com\r\n"
8142 "Connection: keep-alive\r\n"
8143 "\r\n"),
8145 MockRead data_reads1[] = {
8146 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8147 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8148 "\r\n"),
8151 // After calling trans->RestartWithAuth(), provide an Authentication header
8152 // for first_realm. The server will reject and provide a challenge with
8153 // second_realm.
8154 MockWrite data_writes2[] = {
8155 MockWrite("GET / HTTP/1.1\r\n"
8156 "Host: www.google.com\r\n"
8157 "Connection: keep-alive\r\n"
8158 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8159 "\r\n"),
8161 MockRead data_reads2[] = {
8162 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8163 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8164 "\r\n"),
8167 // This again fails, and goes back to first_realm. Make sure that the
8168 // entry is removed from cache.
8169 MockWrite data_writes3[] = {
8170 MockWrite("GET / HTTP/1.1\r\n"
8171 "Host: www.google.com\r\n"
8172 "Connection: keep-alive\r\n"
8173 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8174 "\r\n"),
8176 MockRead data_reads3[] = {
8177 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8178 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8179 "\r\n"),
8182 // Try one last time (with the correct password) and get the resource.
8183 MockWrite data_writes4[] = {
8184 MockWrite("GET / HTTP/1.1\r\n"
8185 "Host: www.google.com\r\n"
8186 "Connection: keep-alive\r\n"
8187 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8188 "\r\n"),
8190 MockRead data_reads4[] = {
8191 MockRead("HTTP/1.1 200 OK\r\n"
8192 "Content-Type: text/html; charset=iso-8859-1\r\n"
8193 "Content-Length: 5\r\n"
8194 "\r\n"
8195 "hello"),
8198 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8199 data_writes1, arraysize(data_writes1));
8200 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8201 data_writes2, arraysize(data_writes2));
8202 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8203 data_writes3, arraysize(data_writes3));
8204 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8205 data_writes4, arraysize(data_writes4));
8206 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8207 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8208 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8209 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8211 TestCompletionCallback callback1;
8213 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8214 scoped_ptr<HttpTransaction> trans(
8215 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8217 // Issue the first request with Authorize headers. There should be a
8218 // password prompt for first_realm waiting to be filled in after the
8219 // transaction completes.
8220 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8221 EXPECT_EQ(ERR_IO_PENDING, rv);
8222 rv = callback1.WaitForResult();
8223 EXPECT_EQ(OK, rv);
8224 const HttpResponseInfo* response = trans->GetResponseInfo();
8225 ASSERT_TRUE(response != NULL);
8226 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8227 ASSERT_FALSE(challenge == NULL);
8228 EXPECT_FALSE(challenge->is_proxy);
8229 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8230 EXPECT_EQ("first_realm", challenge->realm);
8231 EXPECT_EQ("basic", challenge->scheme);
8233 // Issue the second request with an incorrect password. There should be a
8234 // password prompt for second_realm waiting to be filled in after the
8235 // transaction completes.
8236 TestCompletionCallback callback2;
8237 rv = trans->RestartWithAuth(
8238 AuthCredentials(kFirst, kBaz), callback2.callback());
8239 EXPECT_EQ(ERR_IO_PENDING, rv);
8240 rv = callback2.WaitForResult();
8241 EXPECT_EQ(OK, rv);
8242 response = trans->GetResponseInfo();
8243 ASSERT_TRUE(response != NULL);
8244 challenge = response->auth_challenge.get();
8245 ASSERT_FALSE(challenge == NULL);
8246 EXPECT_FALSE(challenge->is_proxy);
8247 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8248 EXPECT_EQ("second_realm", challenge->realm);
8249 EXPECT_EQ("basic", challenge->scheme);
8251 // Issue the third request with another incorrect password. There should be
8252 // a password prompt for first_realm waiting to be filled in. If the password
8253 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8254 // first_realm was not correctly removed.
8255 TestCompletionCallback callback3;
8256 rv = trans->RestartWithAuth(
8257 AuthCredentials(kSecond, kFou), callback3.callback());
8258 EXPECT_EQ(ERR_IO_PENDING, rv);
8259 rv = callback3.WaitForResult();
8260 EXPECT_EQ(OK, rv);
8261 response = trans->GetResponseInfo();
8262 ASSERT_TRUE(response != NULL);
8263 challenge = response->auth_challenge.get();
8264 ASSERT_FALSE(challenge == NULL);
8265 EXPECT_FALSE(challenge->is_proxy);
8266 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8267 EXPECT_EQ("first_realm", challenge->realm);
8268 EXPECT_EQ("basic", challenge->scheme);
8270 // Issue the fourth request with the correct password and username.
8271 TestCompletionCallback callback4;
8272 rv = trans->RestartWithAuth(
8273 AuthCredentials(kFirst, kBar), callback4.callback());
8274 EXPECT_EQ(ERR_IO_PENDING, rv);
8275 rv = callback4.WaitForResult();
8276 EXPECT_EQ(OK, rv);
8277 response = trans->GetResponseInfo();
8278 ASSERT_TRUE(response != NULL);
8279 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8282 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8283 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8284 HttpStreamFactory::set_use_alternate_protocols(true);
8286 std::string alternate_protocol_http_header =
8287 GetAlternateProtocolHttpHeader();
8289 MockRead data_reads[] = {
8290 MockRead("HTTP/1.1 200 OK\r\n"),
8291 MockRead(alternate_protocol_http_header.c_str()),
8292 MockRead("hello world"),
8293 MockRead(SYNCHRONOUS, OK),
8296 HttpRequestInfo request;
8297 request.method = "GET";
8298 request.url = GURL("http://www.google.com/");
8299 request.load_flags = 0;
8301 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8303 session_deps_.socket_factory->AddSocketDataProvider(&data);
8305 TestCompletionCallback callback;
8307 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8308 scoped_ptr<HttpTransaction> trans(
8309 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8311 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8312 EXPECT_EQ(ERR_IO_PENDING, rv);
8314 HostPortPair http_host_port_pair("www.google.com", 80);
8315 HttpServerProperties& http_server_properties =
8316 *session->http_server_properties();
8317 EXPECT_FALSE(
8318 http_server_properties.HasAlternateProtocol(http_host_port_pair));
8320 EXPECT_EQ(OK, callback.WaitForResult());
8322 const HttpResponseInfo* response = trans->GetResponseInfo();
8323 ASSERT_TRUE(response != NULL);
8324 ASSERT_TRUE(response->headers.get() != NULL);
8325 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8326 EXPECT_FALSE(response->was_fetched_via_spdy);
8327 EXPECT_FALSE(response->was_npn_negotiated);
8329 std::string response_data;
8330 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8331 EXPECT_EQ("hello world", response_data);
8333 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
8334 const PortAlternateProtocolPair alternate =
8335 http_server_properties.GetAlternateProtocol(http_host_port_pair);
8336 PortAlternateProtocolPair expected_alternate;
8337 expected_alternate.port = 443;
8338 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
8339 EXPECT_TRUE(expected_alternate.Equals(alternate));
8342 TEST_P(HttpNetworkTransactionTest,
8343 MarkBrokenAlternateProtocolAndFallback) {
8344 HttpStreamFactory::set_use_alternate_protocols(true);
8346 HttpRequestInfo request;
8347 request.method = "GET";
8348 request.url = GURL("http://www.google.com/");
8349 request.load_flags = 0;
8351 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8352 StaticSocketDataProvider first_data;
8353 first_data.set_connect_data(mock_connect);
8354 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8356 MockRead data_reads[] = {
8357 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8358 MockRead("hello world"),
8359 MockRead(ASYNC, OK),
8361 StaticSocketDataProvider second_data(
8362 data_reads, arraysize(data_reads), NULL, 0);
8363 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8365 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8367 base::WeakPtr<HttpServerProperties> http_server_properties =
8368 session->http_server_properties();
8369 // Port must be < 1024, or the header will be ignored (since initial port was
8370 // port 80 (another restricted port).
8371 http_server_properties->SetAlternateProtocol(
8372 HostPortPair::FromURL(request.url),
8373 666 /* port is ignored by MockConnect anyway */,
8374 AlternateProtocolFromNextProto(GetParam()));
8376 scoped_ptr<HttpTransaction> trans(
8377 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8378 TestCompletionCallback callback;
8380 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8381 EXPECT_EQ(ERR_IO_PENDING, rv);
8382 EXPECT_EQ(OK, callback.WaitForResult());
8384 const HttpResponseInfo* response = trans->GetResponseInfo();
8385 ASSERT_TRUE(response != NULL);
8386 ASSERT_TRUE(response->headers.get() != NULL);
8387 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8389 std::string response_data;
8390 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8391 EXPECT_EQ("hello world", response_data);
8393 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8394 HostPortPair::FromURL(request.url)));
8395 const PortAlternateProtocolPair alternate =
8396 http_server_properties->GetAlternateProtocol(
8397 HostPortPair::FromURL(request.url));
8398 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8401 TEST_P(HttpNetworkTransactionTest,
8402 AlternateProtocolPortRestrictedBlocked) {
8403 // Ensure that we're not allowed to redirect traffic via an alternate
8404 // protocol to an unrestricted (port >= 1024) when the original traffic was
8405 // on a restricted port (port < 1024). Ensure that we can redirect in all
8406 // other cases.
8407 HttpStreamFactory::set_use_alternate_protocols(true);
8409 HttpRequestInfo restricted_port_request;
8410 restricted_port_request.method = "GET";
8411 restricted_port_request.url = GURL("http://www.google.com:1023/");
8412 restricted_port_request.load_flags = 0;
8414 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8415 StaticSocketDataProvider first_data;
8416 first_data.set_connect_data(mock_connect);
8417 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8419 MockRead data_reads[] = {
8420 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8421 MockRead("hello world"),
8422 MockRead(ASYNC, OK),
8424 StaticSocketDataProvider second_data(
8425 data_reads, arraysize(data_reads), NULL, 0);
8426 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8428 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8430 base::WeakPtr<HttpServerProperties> http_server_properties =
8431 session->http_server_properties();
8432 const int kUnrestrictedAlternatePort = 1024;
8433 http_server_properties->SetAlternateProtocol(
8434 HostPortPair::FromURL(restricted_port_request.url),
8435 kUnrestrictedAlternatePort,
8436 AlternateProtocolFromNextProto(GetParam()));
8438 scoped_ptr<HttpTransaction> trans(
8439 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8440 TestCompletionCallback callback;
8442 int rv = trans->Start(
8443 &restricted_port_request,
8444 callback.callback(), BoundNetLog());
8445 EXPECT_EQ(ERR_IO_PENDING, rv);
8446 // Invalid change to unrestricted port should fail.
8447 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8450 TEST_P(HttpNetworkTransactionTest,
8451 AlternateProtocolPortRestrictedPermitted) {
8452 // Ensure that we're allowed to redirect traffic via an alternate
8453 // protocol to an unrestricted (port >= 1024) when the original traffic was
8454 // on a restricted port (port < 1024) if we set
8455 // enable_user_alternate_protocol_ports.
8457 HttpStreamFactory::set_use_alternate_protocols(true);
8458 session_deps_.enable_user_alternate_protocol_ports = true;
8460 HttpRequestInfo restricted_port_request;
8461 restricted_port_request.method = "GET";
8462 restricted_port_request.url = GURL("http://www.google.com:1023/");
8463 restricted_port_request.load_flags = 0;
8465 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8466 StaticSocketDataProvider first_data;
8467 first_data.set_connect_data(mock_connect);
8468 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8470 MockRead data_reads[] = {
8471 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8472 MockRead("hello world"),
8473 MockRead(ASYNC, OK),
8475 StaticSocketDataProvider second_data(
8476 data_reads, arraysize(data_reads), NULL, 0);
8477 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8479 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8481 base::WeakPtr<HttpServerProperties> http_server_properties =
8482 session->http_server_properties();
8483 const int kUnrestrictedAlternatePort = 1024;
8484 http_server_properties->SetAlternateProtocol(
8485 HostPortPair::FromURL(restricted_port_request.url),
8486 kUnrestrictedAlternatePort,
8487 AlternateProtocolFromNextProto(GetParam()));
8489 scoped_ptr<HttpTransaction> trans(
8490 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8491 TestCompletionCallback callback;
8493 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8494 &restricted_port_request,
8495 callback.callback(), BoundNetLog()));
8496 // Change to unrestricted port should succeed.
8497 EXPECT_EQ(OK, callback.WaitForResult());
8500 TEST_P(HttpNetworkTransactionTest,
8501 AlternateProtocolPortRestrictedAllowed) {
8502 // Ensure that we're not allowed to redirect traffic via an alternate
8503 // protocol to an unrestricted (port >= 1024) when the original traffic was
8504 // on a restricted port (port < 1024). Ensure that we can redirect in all
8505 // other cases.
8506 HttpStreamFactory::set_use_alternate_protocols(true);
8508 HttpRequestInfo restricted_port_request;
8509 restricted_port_request.method = "GET";
8510 restricted_port_request.url = GURL("http://www.google.com:1023/");
8511 restricted_port_request.load_flags = 0;
8513 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8514 StaticSocketDataProvider first_data;
8515 first_data.set_connect_data(mock_connect);
8516 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8518 MockRead data_reads[] = {
8519 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8520 MockRead("hello world"),
8521 MockRead(ASYNC, OK),
8523 StaticSocketDataProvider second_data(
8524 data_reads, arraysize(data_reads), NULL, 0);
8525 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8527 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8529 base::WeakPtr<HttpServerProperties> http_server_properties =
8530 session->http_server_properties();
8531 const int kRestrictedAlternatePort = 80;
8532 http_server_properties->SetAlternateProtocol(
8533 HostPortPair::FromURL(restricted_port_request.url),
8534 kRestrictedAlternatePort,
8535 AlternateProtocolFromNextProto(GetParam()));
8537 scoped_ptr<HttpTransaction> trans(
8538 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8539 TestCompletionCallback callback;
8541 int rv = trans->Start(
8542 &restricted_port_request,
8543 callback.callback(), BoundNetLog());
8544 EXPECT_EQ(ERR_IO_PENDING, rv);
8545 // Valid change to restricted port should pass.
8546 EXPECT_EQ(OK, callback.WaitForResult());
8549 TEST_P(HttpNetworkTransactionTest,
8550 AlternateProtocolPortUnrestrictedAllowed1) {
8551 // Ensure that we're not allowed to redirect traffic via an alternate
8552 // protocol to an unrestricted (port >= 1024) when the original traffic was
8553 // on a restricted port (port < 1024). Ensure that we can redirect in all
8554 // other cases.
8555 HttpStreamFactory::set_use_alternate_protocols(true);
8557 HttpRequestInfo unrestricted_port_request;
8558 unrestricted_port_request.method = "GET";
8559 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8560 unrestricted_port_request.load_flags = 0;
8562 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8563 StaticSocketDataProvider first_data;
8564 first_data.set_connect_data(mock_connect);
8565 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8567 MockRead data_reads[] = {
8568 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8569 MockRead("hello world"),
8570 MockRead(ASYNC, OK),
8572 StaticSocketDataProvider second_data(
8573 data_reads, arraysize(data_reads), NULL, 0);
8574 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8576 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8578 base::WeakPtr<HttpServerProperties> http_server_properties =
8579 session->http_server_properties();
8580 const int kRestrictedAlternatePort = 80;
8581 http_server_properties->SetAlternateProtocol(
8582 HostPortPair::FromURL(unrestricted_port_request.url),
8583 kRestrictedAlternatePort,
8584 AlternateProtocolFromNextProto(GetParam()));
8586 scoped_ptr<HttpTransaction> trans(
8587 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8588 TestCompletionCallback callback;
8590 int rv = trans->Start(
8591 &unrestricted_port_request, callback.callback(), BoundNetLog());
8592 EXPECT_EQ(ERR_IO_PENDING, rv);
8593 // Valid change to restricted port should pass.
8594 EXPECT_EQ(OK, callback.WaitForResult());
8597 TEST_P(HttpNetworkTransactionTest,
8598 AlternateProtocolPortUnrestrictedAllowed2) {
8599 // Ensure that we're not allowed to redirect traffic via an alternate
8600 // protocol to an unrestricted (port >= 1024) when the original traffic was
8601 // on a restricted port (port < 1024). Ensure that we can redirect in all
8602 // other cases.
8603 HttpStreamFactory::set_use_alternate_protocols(true);
8605 HttpRequestInfo unrestricted_port_request;
8606 unrestricted_port_request.method = "GET";
8607 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8608 unrestricted_port_request.load_flags = 0;
8610 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8611 StaticSocketDataProvider first_data;
8612 first_data.set_connect_data(mock_connect);
8613 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8615 MockRead data_reads[] = {
8616 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8617 MockRead("hello world"),
8618 MockRead(ASYNC, OK),
8620 StaticSocketDataProvider second_data(
8621 data_reads, arraysize(data_reads), NULL, 0);
8622 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8624 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8626 base::WeakPtr<HttpServerProperties> http_server_properties =
8627 session->http_server_properties();
8628 const int kUnrestrictedAlternatePort = 1024;
8629 http_server_properties->SetAlternateProtocol(
8630 HostPortPair::FromURL(unrestricted_port_request.url),
8631 kUnrestrictedAlternatePort,
8632 AlternateProtocolFromNextProto(GetParam()));
8634 scoped_ptr<HttpTransaction> trans(
8635 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8636 TestCompletionCallback callback;
8638 int rv = trans->Start(
8639 &unrestricted_port_request, callback.callback(), BoundNetLog());
8640 EXPECT_EQ(ERR_IO_PENDING, rv);
8641 // Valid change to an unrestricted port should pass.
8642 EXPECT_EQ(OK, callback.WaitForResult());
8645 TEST_P(HttpNetworkTransactionTest,
8646 AlternateProtocolUnsafeBlocked) {
8647 // Ensure that we're not allowed to redirect traffic via an alternate
8648 // protocol to an unsafe port, and that we resume the second
8649 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8650 HttpStreamFactory::set_use_alternate_protocols(true);
8652 HttpRequestInfo request;
8653 request.method = "GET";
8654 request.url = GURL("http://www.google.com/");
8655 request.load_flags = 0;
8657 // The alternate protocol request will error out before we attempt to connect,
8658 // so only the standard HTTP request will try to connect.
8659 MockRead data_reads[] = {
8660 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8661 MockRead("hello world"),
8662 MockRead(ASYNC, OK),
8664 StaticSocketDataProvider data(
8665 data_reads, arraysize(data_reads), NULL, 0);
8666 session_deps_.socket_factory->AddSocketDataProvider(&data);
8668 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8670 base::WeakPtr<HttpServerProperties> http_server_properties =
8671 session->http_server_properties();
8672 const int kUnsafePort = 7;
8673 http_server_properties->SetAlternateProtocol(
8674 HostPortPair::FromURL(request.url),
8675 kUnsafePort,
8676 AlternateProtocolFromNextProto(GetParam()));
8678 scoped_ptr<HttpTransaction> trans(
8679 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8680 TestCompletionCallback callback;
8682 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8683 EXPECT_EQ(ERR_IO_PENDING, rv);
8684 // The HTTP request should succeed.
8685 EXPECT_EQ(OK, callback.WaitForResult());
8687 // Disable alternate protocol before the asserts.
8688 HttpStreamFactory::set_use_alternate_protocols(false);
8690 const HttpResponseInfo* response = trans->GetResponseInfo();
8691 ASSERT_TRUE(response != NULL);
8692 ASSERT_TRUE(response->headers.get() != NULL);
8693 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8695 std::string response_data;
8696 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8697 EXPECT_EQ("hello world", response_data);
8700 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8701 HttpStreamFactory::set_use_alternate_protocols(true);
8702 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8704 HttpRequestInfo request;
8705 request.method = "GET";
8706 request.url = GURL("http://www.google.com/");
8707 request.load_flags = 0;
8709 std::string alternate_protocol_http_header =
8710 GetAlternateProtocolHttpHeader();
8712 MockRead data_reads[] = {
8713 MockRead("HTTP/1.1 200 OK\r\n"),
8714 MockRead(alternate_protocol_http_header.c_str()),
8715 MockRead("hello world"),
8716 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8717 MockRead(ASYNC, OK)
8720 StaticSocketDataProvider first_transaction(
8721 data_reads, arraysize(data_reads), NULL, 0);
8722 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8724 SSLSocketDataProvider ssl(ASYNC, OK);
8725 ssl.SetNextProto(GetParam());
8726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8728 scoped_ptr<SpdyFrame> req(
8729 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8730 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8732 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8733 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8734 MockRead spdy_reads[] = {
8735 CreateMockRead(*resp),
8736 CreateMockRead(*data),
8737 MockRead(ASYNC, 0, 0),
8740 DelayedSocketData spdy_data(
8741 1, // wait for one write to finish before reading.
8742 spdy_reads, arraysize(spdy_reads),
8743 spdy_writes, arraysize(spdy_writes));
8744 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8746 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8747 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8748 NULL, 0, NULL, 0);
8749 hanging_non_alternate_protocol_socket.set_connect_data(
8750 never_finishing_connect);
8751 session_deps_.socket_factory->AddSocketDataProvider(
8752 &hanging_non_alternate_protocol_socket);
8754 TestCompletionCallback callback;
8756 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8757 scoped_ptr<HttpTransaction> trans(
8758 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8760 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8761 EXPECT_EQ(ERR_IO_PENDING, rv);
8762 EXPECT_EQ(OK, callback.WaitForResult());
8764 const HttpResponseInfo* response = trans->GetResponseInfo();
8765 ASSERT_TRUE(response != NULL);
8766 ASSERT_TRUE(response->headers.get() != NULL);
8767 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8769 std::string response_data;
8770 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8771 EXPECT_EQ("hello world", response_data);
8773 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8775 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8776 EXPECT_EQ(ERR_IO_PENDING, rv);
8777 EXPECT_EQ(OK, callback.WaitForResult());
8779 response = trans->GetResponseInfo();
8780 ASSERT_TRUE(response != NULL);
8781 ASSERT_TRUE(response->headers.get() != NULL);
8782 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8783 EXPECT_TRUE(response->was_fetched_via_spdy);
8784 EXPECT_TRUE(response->was_npn_negotiated);
8786 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8787 EXPECT_EQ("hello!", response_data);
8790 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8791 HttpStreamFactory::set_use_alternate_protocols(true);
8792 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8794 HttpRequestInfo request;
8795 request.method = "GET";
8796 request.url = GURL("http://www.google.com/");
8797 request.load_flags = 0;
8799 std::string alternate_protocol_http_header =
8800 GetAlternateProtocolHttpHeader();
8802 MockRead data_reads[] = {
8803 MockRead("HTTP/1.1 200 OK\r\n"),
8804 MockRead(alternate_protocol_http_header.c_str()),
8805 MockRead("hello world"),
8806 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8807 MockRead(ASYNC, OK),
8810 StaticSocketDataProvider first_transaction(
8811 data_reads, arraysize(data_reads), NULL, 0);
8812 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8813 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8815 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8816 StaticSocketDataProvider hanging_socket(
8817 NULL, 0, NULL, 0);
8818 hanging_socket.set_connect_data(never_finishing_connect);
8819 // Socket 2 and 3 are the hanging Alternate-Protocol and
8820 // non-Alternate-Protocol jobs from the 2nd transaction.
8821 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8822 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8824 SSLSocketDataProvider ssl(ASYNC, OK);
8825 ssl.SetNextProto(GetParam());
8826 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8828 scoped_ptr<SpdyFrame> req1(
8829 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8830 scoped_ptr<SpdyFrame> req2(
8831 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8832 MockWrite spdy_writes[] = {
8833 CreateMockWrite(*req1),
8834 CreateMockWrite(*req2),
8836 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8837 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8838 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8839 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8840 MockRead spdy_reads[] = {
8841 CreateMockRead(*resp1),
8842 CreateMockRead(*data1),
8843 CreateMockRead(*resp2),
8844 CreateMockRead(*data2),
8845 MockRead(ASYNC, 0, 0),
8848 DelayedSocketData spdy_data(
8849 2, // wait for writes to finish before reading.
8850 spdy_reads, arraysize(spdy_reads),
8851 spdy_writes, arraysize(spdy_writes));
8852 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8853 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8855 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8856 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8858 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8859 TestCompletionCallback callback1;
8860 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8862 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8863 EXPECT_EQ(ERR_IO_PENDING, rv);
8864 EXPECT_EQ(OK, callback1.WaitForResult());
8866 const HttpResponseInfo* response = trans1.GetResponseInfo();
8867 ASSERT_TRUE(response != NULL);
8868 ASSERT_TRUE(response->headers.get() != NULL);
8869 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8871 std::string response_data;
8872 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8873 EXPECT_EQ("hello world", response_data);
8875 TestCompletionCallback callback2;
8876 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8877 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8878 EXPECT_EQ(ERR_IO_PENDING, rv);
8880 TestCompletionCallback callback3;
8881 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8882 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8883 EXPECT_EQ(ERR_IO_PENDING, rv);
8885 EXPECT_EQ(OK, callback2.WaitForResult());
8886 EXPECT_EQ(OK, callback3.WaitForResult());
8888 response = trans2.GetResponseInfo();
8889 ASSERT_TRUE(response != NULL);
8890 ASSERT_TRUE(response->headers.get() != NULL);
8891 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8892 EXPECT_TRUE(response->was_fetched_via_spdy);
8893 EXPECT_TRUE(response->was_npn_negotiated);
8894 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8895 EXPECT_EQ("hello!", response_data);
8897 response = trans3.GetResponseInfo();
8898 ASSERT_TRUE(response != NULL);
8899 ASSERT_TRUE(response->headers.get() != NULL);
8900 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8901 EXPECT_TRUE(response->was_fetched_via_spdy);
8902 EXPECT_TRUE(response->was_npn_negotiated);
8903 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
8904 EXPECT_EQ("hello!", response_data);
8907 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
8908 HttpStreamFactory::set_use_alternate_protocols(true);
8909 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8911 HttpRequestInfo request;
8912 request.method = "GET";
8913 request.url = GURL("http://www.google.com/");
8914 request.load_flags = 0;
8916 std::string alternate_protocol_http_header =
8917 GetAlternateProtocolHttpHeader();
8919 MockRead data_reads[] = {
8920 MockRead("HTTP/1.1 200 OK\r\n"),
8921 MockRead(alternate_protocol_http_header.c_str()),
8922 MockRead("hello world"),
8923 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8924 MockRead(ASYNC, OK),
8927 StaticSocketDataProvider first_transaction(
8928 data_reads, arraysize(data_reads), NULL, 0);
8929 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8931 SSLSocketDataProvider ssl(ASYNC, OK);
8932 ssl.SetNextProto(GetParam());
8933 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8935 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8936 StaticSocketDataProvider hanging_alternate_protocol_socket(
8937 NULL, 0, NULL, 0);
8938 hanging_alternate_protocol_socket.set_connect_data(
8939 never_finishing_connect);
8940 session_deps_.socket_factory->AddSocketDataProvider(
8941 &hanging_alternate_protocol_socket);
8943 // 2nd request is just a copy of the first one, over HTTP again.
8944 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8946 TestCompletionCallback callback;
8948 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8949 scoped_ptr<HttpTransaction> trans(
8950 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8952 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8953 EXPECT_EQ(ERR_IO_PENDING, rv);
8954 EXPECT_EQ(OK, callback.WaitForResult());
8956 const HttpResponseInfo* response = trans->GetResponseInfo();
8957 ASSERT_TRUE(response != NULL);
8958 ASSERT_TRUE(response->headers.get() != NULL);
8959 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8961 std::string response_data;
8962 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8963 EXPECT_EQ("hello world", response_data);
8965 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8967 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8968 EXPECT_EQ(ERR_IO_PENDING, rv);
8969 EXPECT_EQ(OK, callback.WaitForResult());
8971 response = trans->GetResponseInfo();
8972 ASSERT_TRUE(response != NULL);
8973 ASSERT_TRUE(response->headers.get() != NULL);
8974 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8975 EXPECT_FALSE(response->was_fetched_via_spdy);
8976 EXPECT_FALSE(response->was_npn_negotiated);
8978 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8979 EXPECT_EQ("hello world", response_data);
8982 class CapturingProxyResolver : public ProxyResolver {
8983 public:
8984 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8985 virtual ~CapturingProxyResolver() {}
8987 virtual int GetProxyForURL(const GURL& url,
8988 ProxyInfo* results,
8989 const CompletionCallback& callback,
8990 RequestHandle* request,
8991 const BoundNetLog& net_log) OVERRIDE {
8992 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
8993 HostPortPair("myproxy", 80));
8994 results->UseProxyServer(proxy_server);
8995 resolved_.push_back(url);
8996 return OK;
8999 virtual void CancelRequest(RequestHandle request) OVERRIDE {
9000 NOTREACHED();
9003 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
9004 NOTREACHED();
9005 return LOAD_STATE_IDLE;
9008 virtual void CancelSetPacScript() OVERRIDE {
9009 NOTREACHED();
9012 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9013 const CompletionCallback& /*callback*/) OVERRIDE {
9014 return OK;
9017 const std::vector<GURL>& resolved() const { return resolved_; }
9019 private:
9020 std::vector<GURL> resolved_;
9022 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9025 TEST_P(HttpNetworkTransactionTest,
9026 UseAlternateProtocolForTunneledNpnSpdy) {
9027 HttpStreamFactory::set_use_alternate_protocols(true);
9028 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9030 ProxyConfig proxy_config;
9031 proxy_config.set_auto_detect(true);
9032 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9034 CapturingProxyResolver* capturing_proxy_resolver =
9035 new CapturingProxyResolver();
9036 session_deps_.proxy_service.reset(new ProxyService(
9037 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
9038 NULL));
9039 CapturingNetLog net_log;
9040 session_deps_.net_log = &net_log;
9042 HttpRequestInfo request;
9043 request.method = "GET";
9044 request.url = GURL("http://www.google.com/");
9045 request.load_flags = 0;
9047 std::string alternate_protocol_http_header =
9048 GetAlternateProtocolHttpHeader();
9050 MockRead data_reads[] = {
9051 MockRead("HTTP/1.1 200 OK\r\n"),
9052 MockRead(alternate_protocol_http_header.c_str()),
9053 MockRead("hello world"),
9054 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9055 MockRead(ASYNC, OK),
9058 StaticSocketDataProvider first_transaction(
9059 data_reads, arraysize(data_reads), NULL, 0);
9060 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9062 SSLSocketDataProvider ssl(ASYNC, OK);
9063 ssl.SetNextProto(GetParam());
9064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9066 scoped_ptr<SpdyFrame> req(
9067 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9068 MockWrite spdy_writes[] = {
9069 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9070 "Host: www.google.com\r\n"
9071 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9072 CreateMockWrite(*req), // 3
9075 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9077 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9078 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9079 MockRead spdy_reads[] = {
9080 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
9081 CreateMockRead(*resp.get(), 4), // 2, 4
9082 CreateMockRead(*data.get(), 4), // 5
9083 MockRead(ASYNC, 0, 0, 4), // 6
9086 OrderedSocketData spdy_data(
9087 spdy_reads, arraysize(spdy_reads),
9088 spdy_writes, arraysize(spdy_writes));
9089 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9091 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9092 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9093 NULL, 0, NULL, 0);
9094 hanging_non_alternate_protocol_socket.set_connect_data(
9095 never_finishing_connect);
9096 session_deps_.socket_factory->AddSocketDataProvider(
9097 &hanging_non_alternate_protocol_socket);
9099 TestCompletionCallback callback;
9101 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9102 scoped_ptr<HttpTransaction> trans(
9103 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9105 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9106 EXPECT_EQ(ERR_IO_PENDING, rv);
9107 EXPECT_EQ(OK, callback.WaitForResult());
9109 const HttpResponseInfo* response = trans->GetResponseInfo();
9110 ASSERT_TRUE(response != NULL);
9111 ASSERT_TRUE(response->headers.get() != NULL);
9112 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9113 EXPECT_FALSE(response->was_fetched_via_spdy);
9114 EXPECT_FALSE(response->was_npn_negotiated);
9116 std::string response_data;
9117 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9118 EXPECT_EQ("hello world", response_data);
9120 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9122 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9123 EXPECT_EQ(ERR_IO_PENDING, rv);
9124 EXPECT_EQ(OK, callback.WaitForResult());
9126 response = trans->GetResponseInfo();
9127 ASSERT_TRUE(response != NULL);
9128 ASSERT_TRUE(response->headers.get() != NULL);
9129 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9130 EXPECT_TRUE(response->was_fetched_via_spdy);
9131 EXPECT_TRUE(response->was_npn_negotiated);
9133 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9134 EXPECT_EQ("hello!", response_data);
9135 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
9136 EXPECT_EQ("http://www.google.com/",
9137 capturing_proxy_resolver->resolved()[0].spec());
9138 EXPECT_EQ("https://www.google.com/",
9139 capturing_proxy_resolver->resolved()[1].spec());
9141 LoadTimingInfo load_timing_info;
9142 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9143 TestLoadTimingNotReusedWithPac(load_timing_info,
9144 CONNECT_TIMING_HAS_SSL_TIMES);
9147 TEST_P(HttpNetworkTransactionTest,
9148 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9149 HttpStreamFactory::set_use_alternate_protocols(true);
9150 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9152 HttpRequestInfo request;
9153 request.method = "GET";
9154 request.url = GURL("http://www.google.com/");
9155 request.load_flags = 0;
9157 std::string alternate_protocol_http_header =
9158 GetAlternateProtocolHttpHeader();
9160 MockRead data_reads[] = {
9161 MockRead("HTTP/1.1 200 OK\r\n"),
9162 MockRead(alternate_protocol_http_header.c_str()),
9163 MockRead("hello world"),
9164 MockRead(ASYNC, OK),
9167 StaticSocketDataProvider first_transaction(
9168 data_reads, arraysize(data_reads), NULL, 0);
9169 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9171 SSLSocketDataProvider ssl(ASYNC, OK);
9172 ssl.SetNextProto(GetParam());
9173 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9175 scoped_ptr<SpdyFrame> req(
9176 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9177 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9179 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9180 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9181 MockRead spdy_reads[] = {
9182 CreateMockRead(*resp),
9183 CreateMockRead(*data),
9184 MockRead(ASYNC, 0, 0),
9187 DelayedSocketData spdy_data(
9188 1, // wait for one write to finish before reading.
9189 spdy_reads, arraysize(spdy_reads),
9190 spdy_writes, arraysize(spdy_writes));
9191 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9193 TestCompletionCallback callback;
9195 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9197 scoped_ptr<HttpTransaction> trans(
9198 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9200 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9201 EXPECT_EQ(ERR_IO_PENDING, rv);
9202 EXPECT_EQ(OK, callback.WaitForResult());
9204 const HttpResponseInfo* response = trans->GetResponseInfo();
9205 ASSERT_TRUE(response != NULL);
9206 ASSERT_TRUE(response->headers.get() != NULL);
9207 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9209 std::string response_data;
9210 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9211 EXPECT_EQ("hello world", response_data);
9213 // Set up an initial SpdySession in the pool to reuse.
9214 HostPortPair host_port_pair("www.google.com", 443);
9215 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9216 PRIVACY_MODE_DISABLED);
9217 base::WeakPtr<SpdySession> spdy_session =
9218 CreateSecureSpdySession(session, key, BoundNetLog());
9220 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9222 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9223 EXPECT_EQ(ERR_IO_PENDING, rv);
9224 EXPECT_EQ(OK, callback.WaitForResult());
9226 response = trans->GetResponseInfo();
9227 ASSERT_TRUE(response != NULL);
9228 ASSERT_TRUE(response->headers.get() != NULL);
9229 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9230 EXPECT_TRUE(response->was_fetched_via_spdy);
9231 EXPECT_TRUE(response->was_npn_negotiated);
9233 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9234 EXPECT_EQ("hello!", response_data);
9237 // GenerateAuthToken is a mighty big test.
9238 // It tests all permutation of GenerateAuthToken behavior:
9239 // - Synchronous and Asynchronous completion.
9240 // - OK or error on completion.
9241 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9242 // - HTTP or HTTPS backend (to include proxy tunneling).
9243 // - Non-authenticating and authenticating backend.
9245 // In all, there are 44 reasonable permuations (for example, if there are
9246 // problems generating an auth token for an authenticating proxy, we don't
9247 // need to test all permutations of the backend server).
9249 // The test proceeds by going over each of the configuration cases, and
9250 // potentially running up to three rounds in each of the tests. The TestConfig
9251 // specifies both the configuration for the test as well as the expectations
9252 // for the results.
9253 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9254 static const char kServer[] = "http://www.example.com";
9255 static const char kSecureServer[] = "https://www.example.com";
9256 static const char kProxy[] = "myproxy:70";
9257 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9259 enum AuthTiming {
9260 AUTH_NONE,
9261 AUTH_SYNC,
9262 AUTH_ASYNC,
9265 const MockWrite kGet(
9266 "GET / HTTP/1.1\r\n"
9267 "Host: www.example.com\r\n"
9268 "Connection: keep-alive\r\n\r\n");
9269 const MockWrite kGetProxy(
9270 "GET http://www.example.com/ HTTP/1.1\r\n"
9271 "Host: www.example.com\r\n"
9272 "Proxy-Connection: keep-alive\r\n\r\n");
9273 const MockWrite kGetAuth(
9274 "GET / HTTP/1.1\r\n"
9275 "Host: www.example.com\r\n"
9276 "Connection: keep-alive\r\n"
9277 "Authorization: auth_token\r\n\r\n");
9278 const MockWrite kGetProxyAuth(
9279 "GET http://www.example.com/ HTTP/1.1\r\n"
9280 "Host: www.example.com\r\n"
9281 "Proxy-Connection: keep-alive\r\n"
9282 "Proxy-Authorization: auth_token\r\n\r\n");
9283 const MockWrite kGetAuthThroughProxy(
9284 "GET http://www.example.com/ HTTP/1.1\r\n"
9285 "Host: www.example.com\r\n"
9286 "Proxy-Connection: keep-alive\r\n"
9287 "Authorization: auth_token\r\n\r\n");
9288 const MockWrite kGetAuthWithProxyAuth(
9289 "GET http://www.example.com/ HTTP/1.1\r\n"
9290 "Host: www.example.com\r\n"
9291 "Proxy-Connection: keep-alive\r\n"
9292 "Proxy-Authorization: auth_token\r\n"
9293 "Authorization: auth_token\r\n\r\n");
9294 const MockWrite kConnect(
9295 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9296 "Host: www.example.com\r\n"
9297 "Proxy-Connection: keep-alive\r\n\r\n");
9298 const MockWrite kConnectProxyAuth(
9299 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9300 "Host: www.example.com\r\n"
9301 "Proxy-Connection: keep-alive\r\n"
9302 "Proxy-Authorization: auth_token\r\n\r\n");
9304 const MockRead kSuccess(
9305 "HTTP/1.1 200 OK\r\n"
9306 "Content-Type: text/html; charset=iso-8859-1\r\n"
9307 "Content-Length: 3\r\n\r\n"
9308 "Yes");
9309 const MockRead kFailure(
9310 "Should not be called.");
9311 const MockRead kServerChallenge(
9312 "HTTP/1.1 401 Unauthorized\r\n"
9313 "WWW-Authenticate: Mock realm=server\r\n"
9314 "Content-Type: text/html; charset=iso-8859-1\r\n"
9315 "Content-Length: 14\r\n\r\n"
9316 "Unauthorized\r\n");
9317 const MockRead kProxyChallenge(
9318 "HTTP/1.1 407 Unauthorized\r\n"
9319 "Proxy-Authenticate: Mock realm=proxy\r\n"
9320 "Proxy-Connection: close\r\n"
9321 "Content-Type: text/html; charset=iso-8859-1\r\n"
9322 "Content-Length: 14\r\n\r\n"
9323 "Unauthorized\r\n");
9324 const MockRead kProxyConnected(
9325 "HTTP/1.1 200 Connection Established\r\n\r\n");
9327 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9328 // no constructors, but the C++ compiler on Windows warns about
9329 // unspecified data in compound literals. So, moved to using constructors,
9330 // and TestRound's created with the default constructor should not be used.
9331 struct TestRound {
9332 TestRound()
9333 : expected_rv(ERR_UNEXPECTED),
9334 extra_write(NULL),
9335 extra_read(NULL) {
9337 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9338 int expected_rv_arg)
9339 : write(write_arg),
9340 read(read_arg),
9341 expected_rv(expected_rv_arg),
9342 extra_write(NULL),
9343 extra_read(NULL) {
9345 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9346 int expected_rv_arg, const MockWrite* extra_write_arg,
9347 const MockRead* extra_read_arg)
9348 : write(write_arg),
9349 read(read_arg),
9350 expected_rv(expected_rv_arg),
9351 extra_write(extra_write_arg),
9352 extra_read(extra_read_arg) {
9354 MockWrite write;
9355 MockRead read;
9356 int expected_rv;
9357 const MockWrite* extra_write;
9358 const MockRead* extra_read;
9361 static const int kNoSSL = 500;
9363 struct TestConfig {
9364 const char* proxy_url;
9365 AuthTiming proxy_auth_timing;
9366 int proxy_auth_rv;
9367 const char* server_url;
9368 AuthTiming server_auth_timing;
9369 int server_auth_rv;
9370 int num_auth_rounds;
9371 int first_ssl_round;
9372 TestRound rounds[3];
9373 } test_configs[] = {
9374 // Non-authenticating HTTP server with a direct connection.
9375 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9376 { TestRound(kGet, kSuccess, OK)}},
9377 // Authenticating HTTP server with a direct connection.
9378 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9379 { TestRound(kGet, kServerChallenge, OK),
9380 TestRound(kGetAuth, kSuccess, OK)}},
9381 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9382 { TestRound(kGet, kServerChallenge, OK),
9383 TestRound(kGetAuth, kFailure, kAuthErr)}},
9384 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9385 { TestRound(kGet, kServerChallenge, OK),
9386 TestRound(kGetAuth, kSuccess, OK)}},
9387 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9388 { TestRound(kGet, kServerChallenge, OK),
9389 TestRound(kGetAuth, kFailure, kAuthErr)}},
9390 // Non-authenticating HTTP server through a non-authenticating proxy.
9391 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9392 { TestRound(kGetProxy, kSuccess, OK)}},
9393 // Authenticating HTTP server through a non-authenticating proxy.
9394 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9395 { TestRound(kGetProxy, kServerChallenge, OK),
9396 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9397 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9398 { TestRound(kGetProxy, kServerChallenge, OK),
9399 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9400 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9401 { TestRound(kGetProxy, kServerChallenge, OK),
9402 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9403 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9404 { TestRound(kGetProxy, kServerChallenge, OK),
9405 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9406 // Non-authenticating HTTP server through an authenticating proxy.
9407 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9408 { TestRound(kGetProxy, kProxyChallenge, OK),
9409 TestRound(kGetProxyAuth, kSuccess, OK)}},
9410 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9411 { TestRound(kGetProxy, kProxyChallenge, OK),
9412 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9413 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9414 { TestRound(kGetProxy, kProxyChallenge, OK),
9415 TestRound(kGetProxyAuth, kSuccess, OK)}},
9416 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9417 { TestRound(kGetProxy, kProxyChallenge, OK),
9418 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9419 // Authenticating HTTP server through an authenticating proxy.
9420 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9421 { TestRound(kGetProxy, kProxyChallenge, OK),
9422 TestRound(kGetProxyAuth, kServerChallenge, OK),
9423 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9424 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9425 { TestRound(kGetProxy, kProxyChallenge, OK),
9426 TestRound(kGetProxyAuth, kServerChallenge, OK),
9427 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9428 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9429 { TestRound(kGetProxy, kProxyChallenge, OK),
9430 TestRound(kGetProxyAuth, kServerChallenge, OK),
9431 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9432 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9433 { TestRound(kGetProxy, kProxyChallenge, OK),
9434 TestRound(kGetProxyAuth, kServerChallenge, OK),
9435 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9436 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9437 { TestRound(kGetProxy, kProxyChallenge, OK),
9438 TestRound(kGetProxyAuth, kServerChallenge, OK),
9439 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9440 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9441 { TestRound(kGetProxy, kProxyChallenge, OK),
9442 TestRound(kGetProxyAuth, kServerChallenge, OK),
9443 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9444 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9445 { TestRound(kGetProxy, kProxyChallenge, OK),
9446 TestRound(kGetProxyAuth, kServerChallenge, OK),
9447 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9448 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9449 { TestRound(kGetProxy, kProxyChallenge, OK),
9450 TestRound(kGetProxyAuth, kServerChallenge, OK),
9451 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9452 // Non-authenticating HTTPS server with a direct connection.
9453 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9454 { TestRound(kGet, kSuccess, OK)}},
9455 // Authenticating HTTPS server with a direct connection.
9456 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9457 { TestRound(kGet, kServerChallenge, OK),
9458 TestRound(kGetAuth, kSuccess, OK)}},
9459 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9460 { TestRound(kGet, kServerChallenge, OK),
9461 TestRound(kGetAuth, kFailure, kAuthErr)}},
9462 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9463 { TestRound(kGet, kServerChallenge, OK),
9464 TestRound(kGetAuth, kSuccess, OK)}},
9465 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9466 { TestRound(kGet, kServerChallenge, OK),
9467 TestRound(kGetAuth, kFailure, kAuthErr)}},
9468 // Non-authenticating HTTPS server with a non-authenticating proxy.
9469 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9470 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9471 // Authenticating HTTPS server through a non-authenticating proxy.
9472 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9473 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9474 TestRound(kGetAuth, kSuccess, OK)}},
9475 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9476 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9477 TestRound(kGetAuth, kFailure, kAuthErr)}},
9478 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9479 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9480 TestRound(kGetAuth, kSuccess, OK)}},
9481 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9482 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9483 TestRound(kGetAuth, kFailure, kAuthErr)}},
9484 // Non-Authenticating HTTPS server through an authenticating proxy.
9485 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9486 { TestRound(kConnect, kProxyChallenge, OK),
9487 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9488 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9489 { TestRound(kConnect, kProxyChallenge, OK),
9490 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9491 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9492 { TestRound(kConnect, kProxyChallenge, OK),
9493 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9494 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9495 { TestRound(kConnect, kProxyChallenge, OK),
9496 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9497 // Authenticating HTTPS server through an authenticating proxy.
9498 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9499 { TestRound(kConnect, kProxyChallenge, OK),
9500 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9501 &kGet, &kServerChallenge),
9502 TestRound(kGetAuth, kSuccess, OK)}},
9503 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9504 { TestRound(kConnect, kProxyChallenge, OK),
9505 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9506 &kGet, &kServerChallenge),
9507 TestRound(kGetAuth, kFailure, kAuthErr)}},
9508 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9509 { TestRound(kConnect, kProxyChallenge, OK),
9510 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9511 &kGet, &kServerChallenge),
9512 TestRound(kGetAuth, kSuccess, OK)}},
9513 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9514 { TestRound(kConnect, kProxyChallenge, OK),
9515 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9516 &kGet, &kServerChallenge),
9517 TestRound(kGetAuth, kFailure, kAuthErr)}},
9518 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9519 { TestRound(kConnect, kProxyChallenge, OK),
9520 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9521 &kGet, &kServerChallenge),
9522 TestRound(kGetAuth, kSuccess, OK)}},
9523 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9524 { TestRound(kConnect, kProxyChallenge, OK),
9525 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9526 &kGet, &kServerChallenge),
9527 TestRound(kGetAuth, kFailure, kAuthErr)}},
9528 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9529 { TestRound(kConnect, kProxyChallenge, OK),
9530 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9531 &kGet, &kServerChallenge),
9532 TestRound(kGetAuth, kSuccess, OK)}},
9533 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9534 { TestRound(kConnect, kProxyChallenge, OK),
9535 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9536 &kGet, &kServerChallenge),
9537 TestRound(kGetAuth, kFailure, kAuthErr)}},
9540 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9541 HttpAuthHandlerMock::Factory* auth_factory(
9542 new HttpAuthHandlerMock::Factory());
9543 session_deps_.http_auth_handler_factory.reset(auth_factory);
9544 const TestConfig& test_config = test_configs[i];
9546 // Set up authentication handlers as necessary.
9547 if (test_config.proxy_auth_timing != AUTH_NONE) {
9548 for (int n = 0; n < 2; n++) {
9549 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9550 std::string auth_challenge = "Mock realm=proxy";
9551 GURL origin(test_config.proxy_url);
9552 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9553 auth_challenge.end());
9554 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9555 origin, BoundNetLog());
9556 auth_handler->SetGenerateExpectation(
9557 test_config.proxy_auth_timing == AUTH_ASYNC,
9558 test_config.proxy_auth_rv);
9559 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9562 if (test_config.server_auth_timing != AUTH_NONE) {
9563 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9564 std::string auth_challenge = "Mock realm=server";
9565 GURL origin(test_config.server_url);
9566 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9567 auth_challenge.end());
9568 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9569 origin, BoundNetLog());
9570 auth_handler->SetGenerateExpectation(
9571 test_config.server_auth_timing == AUTH_ASYNC,
9572 test_config.server_auth_rv);
9573 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9575 if (test_config.proxy_url) {
9576 session_deps_.proxy_service.reset(
9577 ProxyService::CreateFixed(test_config.proxy_url));
9578 } else {
9579 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9582 HttpRequestInfo request;
9583 request.method = "GET";
9584 request.url = GURL(test_config.server_url);
9585 request.load_flags = 0;
9587 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9588 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
9590 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9591 const TestRound& read_write_round = test_config.rounds[round];
9593 // Set up expected reads and writes.
9594 MockRead reads[2];
9595 reads[0] = read_write_round.read;
9596 size_t length_reads = 1;
9597 if (read_write_round.extra_read) {
9598 reads[1] = *read_write_round.extra_read;
9599 length_reads = 2;
9602 MockWrite writes[2];
9603 writes[0] = read_write_round.write;
9604 size_t length_writes = 1;
9605 if (read_write_round.extra_write) {
9606 writes[1] = *read_write_round.extra_write;
9607 length_writes = 2;
9609 StaticSocketDataProvider data_provider(
9610 reads, length_reads, writes, length_writes);
9611 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9613 // Add an SSL sequence if necessary.
9614 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9615 if (round >= test_config.first_ssl_round)
9616 session_deps_.socket_factory->AddSSLSocketDataProvider(
9617 &ssl_socket_data_provider);
9619 // Start or restart the transaction.
9620 TestCompletionCallback callback;
9621 int rv;
9622 if (round == 0) {
9623 rv = trans.Start(&request, callback.callback(), BoundNetLog());
9624 } else {
9625 rv = trans.RestartWithAuth(
9626 AuthCredentials(kFoo, kBar), callback.callback());
9628 if (rv == ERR_IO_PENDING)
9629 rv = callback.WaitForResult();
9631 // Compare results with expected data.
9632 EXPECT_EQ(read_write_round.expected_rv, rv);
9633 const HttpResponseInfo* response = trans.GetResponseInfo();
9634 if (read_write_round.expected_rv == OK) {
9635 ASSERT_TRUE(response != NULL);
9636 } else {
9637 EXPECT_TRUE(response == NULL);
9638 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9639 continue;
9641 if (round + 1 < test_config.num_auth_rounds) {
9642 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9643 } else {
9644 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9650 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9651 // Do multi-round authentication and make sure it works correctly.
9652 HttpAuthHandlerMock::Factory* auth_factory(
9653 new HttpAuthHandlerMock::Factory());
9654 session_deps_.http_auth_handler_factory.reset(auth_factory);
9655 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9656 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9657 session_deps_.host_resolver->set_synchronous_mode(true);
9659 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9660 auth_handler->set_connection_based(true);
9661 std::string auth_challenge = "Mock realm=server";
9662 GURL origin("http://www.example.com");
9663 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9664 auth_challenge.end());
9665 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9666 origin, BoundNetLog());
9667 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9669 int rv = OK;
9670 const HttpResponseInfo* response = NULL;
9671 HttpRequestInfo request;
9672 request.method = "GET";
9673 request.url = origin;
9674 request.load_flags = 0;
9676 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9678 // Use a TCP Socket Pool with only one connection per group. This is used
9679 // to validate that the TCP socket is not released to the pool between
9680 // each round of multi-round authentication.
9681 HttpNetworkSessionPeer session_peer(session);
9682 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9683 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9684 50, // Max sockets for pool
9685 1, // Max sockets per group
9686 &transport_pool_histograms,
9687 session_deps_.host_resolver.get(),
9688 session_deps_.socket_factory.get(),
9689 session_deps_.net_log);
9690 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
9691 new MockClientSocketPoolManager);
9692 mock_pool_manager->SetTransportSocketPool(transport_pool);
9693 session_peer.SetClientSocketPoolManager(
9694 mock_pool_manager.PassAs<ClientSocketPoolManager>());
9696 scoped_ptr<HttpTransaction> trans(
9697 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9698 TestCompletionCallback callback;
9700 const MockWrite kGet(
9701 "GET / HTTP/1.1\r\n"
9702 "Host: www.example.com\r\n"
9703 "Connection: keep-alive\r\n\r\n");
9704 const MockWrite kGetAuth(
9705 "GET / HTTP/1.1\r\n"
9706 "Host: www.example.com\r\n"
9707 "Connection: keep-alive\r\n"
9708 "Authorization: auth_token\r\n\r\n");
9710 const MockRead kServerChallenge(
9711 "HTTP/1.1 401 Unauthorized\r\n"
9712 "WWW-Authenticate: Mock realm=server\r\n"
9713 "Content-Type: text/html; charset=iso-8859-1\r\n"
9714 "Content-Length: 14\r\n\r\n"
9715 "Unauthorized\r\n");
9716 const MockRead kSuccess(
9717 "HTTP/1.1 200 OK\r\n"
9718 "Content-Type: text/html; charset=iso-8859-1\r\n"
9719 "Content-Length: 3\r\n\r\n"
9720 "Yes");
9722 MockWrite writes[] = {
9723 // First round
9724 kGet,
9725 // Second round
9726 kGetAuth,
9727 // Third round
9728 kGetAuth,
9729 // Fourth round
9730 kGetAuth,
9731 // Competing request
9732 kGet,
9734 MockRead reads[] = {
9735 // First round
9736 kServerChallenge,
9737 // Second round
9738 kServerChallenge,
9739 // Third round
9740 kServerChallenge,
9741 // Fourth round
9742 kSuccess,
9743 // Competing response
9744 kSuccess,
9746 StaticSocketDataProvider data_provider(reads, arraysize(reads),
9747 writes, arraysize(writes));
9748 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9750 const char* const kSocketGroup = "www.example.com:80";
9752 // First round of authentication.
9753 auth_handler->SetGenerateExpectation(false, OK);
9754 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9755 if (rv == ERR_IO_PENDING)
9756 rv = callback.WaitForResult();
9757 EXPECT_EQ(OK, rv);
9758 response = trans->GetResponseInfo();
9759 ASSERT_TRUE(response != NULL);
9760 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9761 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9763 // In between rounds, another request comes in for the same domain.
9764 // It should not be able to grab the TCP socket that trans has already
9765 // claimed.
9766 scoped_ptr<HttpTransaction> trans_compete(
9767 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9768 TestCompletionCallback callback_compete;
9769 rv = trans_compete->Start(
9770 &request, callback_compete.callback(), BoundNetLog());
9771 EXPECT_EQ(ERR_IO_PENDING, rv);
9772 // callback_compete.WaitForResult at this point would stall forever,
9773 // since the HttpNetworkTransaction does not release the request back to
9774 // the pool until after authentication completes.
9776 // Second round of authentication.
9777 auth_handler->SetGenerateExpectation(false, OK);
9778 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9779 if (rv == ERR_IO_PENDING)
9780 rv = callback.WaitForResult();
9781 EXPECT_EQ(OK, rv);
9782 response = trans->GetResponseInfo();
9783 ASSERT_TRUE(response != NULL);
9784 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9785 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9787 // Third round of authentication.
9788 auth_handler->SetGenerateExpectation(false, OK);
9789 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9790 if (rv == ERR_IO_PENDING)
9791 rv = callback.WaitForResult();
9792 EXPECT_EQ(OK, rv);
9793 response = trans->GetResponseInfo();
9794 ASSERT_TRUE(response != NULL);
9795 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9796 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9798 // Fourth round of authentication, which completes successfully.
9799 auth_handler->SetGenerateExpectation(false, OK);
9800 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9801 if (rv == ERR_IO_PENDING)
9802 rv = callback.WaitForResult();
9803 EXPECT_EQ(OK, rv);
9804 response = trans->GetResponseInfo();
9805 ASSERT_TRUE(response != NULL);
9806 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9807 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9809 // Read the body since the fourth round was successful. This will also
9810 // release the socket back to the pool.
9811 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9812 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9813 if (rv == ERR_IO_PENDING)
9814 rv = callback.WaitForResult();
9815 EXPECT_EQ(3, rv);
9816 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9817 EXPECT_EQ(0, rv);
9818 // There are still 0 idle sockets, since the trans_compete transaction
9819 // will be handed it immediately after trans releases it to the group.
9820 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9822 // The competing request can now finish. Wait for the headers and then
9823 // read the body.
9824 rv = callback_compete.WaitForResult();
9825 EXPECT_EQ(OK, rv);
9826 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9827 if (rv == ERR_IO_PENDING)
9828 rv = callback.WaitForResult();
9829 EXPECT_EQ(3, rv);
9830 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9831 EXPECT_EQ(0, rv);
9833 // Finally, the socket is released to the group.
9834 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9837 // This tests the case that a request is issued via http instead of spdy after
9838 // npn is negotiated.
9839 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9840 HttpStreamFactory::set_use_alternate_protocols(true);
9841 std::vector<NextProto> next_protos;
9842 next_protos.push_back(kProtoHTTP11);
9843 HttpStreamFactory::SetNextProtos(next_protos);
9844 HttpRequestInfo request;
9845 request.method = "GET";
9846 request.url = GURL("https://www.google.com/");
9847 request.load_flags = 0;
9849 MockWrite data_writes[] = {
9850 MockWrite("GET / HTTP/1.1\r\n"
9851 "Host: www.google.com\r\n"
9852 "Connection: keep-alive\r\n\r\n"),
9855 std::string alternate_protocol_http_header =
9856 GetAlternateProtocolHttpHeader();
9858 MockRead data_reads[] = {
9859 MockRead("HTTP/1.1 200 OK\r\n"),
9860 MockRead(alternate_protocol_http_header.c_str()),
9861 MockRead("hello world"),
9862 MockRead(SYNCHRONOUS, OK),
9865 SSLSocketDataProvider ssl(ASYNC, OK);
9866 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9867 ssl.next_proto = "http/1.1";
9868 ssl.protocol_negotiated = kProtoHTTP11;
9870 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9872 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9873 data_writes, arraysize(data_writes));
9874 session_deps_.socket_factory->AddSocketDataProvider(&data);
9876 TestCompletionCallback callback;
9878 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9879 scoped_ptr<HttpTransaction> trans(
9880 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9882 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9884 EXPECT_EQ(ERR_IO_PENDING, rv);
9885 EXPECT_EQ(OK, callback.WaitForResult());
9887 const HttpResponseInfo* response = trans->GetResponseInfo();
9888 ASSERT_TRUE(response != NULL);
9889 ASSERT_TRUE(response->headers.get() != NULL);
9890 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9892 std::string response_data;
9893 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9894 EXPECT_EQ("hello world", response_data);
9896 EXPECT_FALSE(response->was_fetched_via_spdy);
9897 EXPECT_TRUE(response->was_npn_negotiated);
9900 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
9901 // Simulate the SSL handshake completing with an NPN negotiation
9902 // followed by an immediate server closing of the socket.
9903 // Fix crash: http://crbug.com/46369
9904 HttpStreamFactory::set_use_alternate_protocols(true);
9905 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9907 HttpRequestInfo request;
9908 request.method = "GET";
9909 request.url = GURL("https://www.google.com/");
9910 request.load_flags = 0;
9912 SSLSocketDataProvider ssl(ASYNC, OK);
9913 ssl.SetNextProto(GetParam());
9914 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9916 scoped_ptr<SpdyFrame> req(
9917 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9918 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9920 MockRead spdy_reads[] = {
9921 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
9924 DelayedSocketData spdy_data(
9925 0, // don't wait in this case, immediate hangup.
9926 spdy_reads, arraysize(spdy_reads),
9927 spdy_writes, arraysize(spdy_writes));
9928 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9930 TestCompletionCallback callback;
9932 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9933 scoped_ptr<HttpTransaction> trans(
9934 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9936 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9937 EXPECT_EQ(ERR_IO_PENDING, rv);
9938 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
9941 // A subclass of HttpAuthHandlerMock that records the request URL when
9942 // it gets it. This is needed since the auth handler may get destroyed
9943 // before we get a chance to query it.
9944 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
9945 public:
9946 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
9948 virtual ~UrlRecordingHttpAuthHandlerMock() {}
9950 protected:
9951 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
9952 const HttpRequestInfo* request,
9953 const CompletionCallback& callback,
9954 std::string* auth_token) OVERRIDE {
9955 *url_ = request->url;
9956 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9957 credentials, request, callback, auth_token);
9960 private:
9961 GURL* url_;
9964 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
9965 // This test ensures that the URL passed into the proxy is upgraded
9966 // to https when doing an Alternate Protocol upgrade.
9967 HttpStreamFactory::set_use_alternate_protocols(true);
9968 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9970 session_deps_.proxy_service.reset(
9971 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9972 CapturingNetLog net_log;
9973 session_deps_.net_log = &net_log;
9974 GURL request_url;
9976 HttpAuthHandlerMock::Factory* auth_factory =
9977 new HttpAuthHandlerMock::Factory();
9978 UrlRecordingHttpAuthHandlerMock* auth_handler =
9979 new UrlRecordingHttpAuthHandlerMock(&request_url);
9980 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9981 auth_factory->set_do_init_from_challenge(true);
9982 session_deps_.http_auth_handler_factory.reset(auth_factory);
9985 HttpRequestInfo request;
9986 request.method = "GET";
9987 request.url = GURL("http://www.google.com");
9988 request.load_flags = 0;
9990 // First round goes unauthenticated through the proxy.
9991 MockWrite data_writes_1[] = {
9992 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9993 "Host: www.google.com\r\n"
9994 "Proxy-Connection: keep-alive\r\n"
9995 "\r\n"),
9997 MockRead data_reads_1[] = {
9998 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9999 MockRead("HTTP/1.1 200 OK\r\n"
10000 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10001 "Proxy-Connection: close\r\n"
10002 "\r\n"),
10004 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10005 data_writes_1, arraysize(data_writes_1));
10007 // Second round tries to tunnel to www.google.com due to the
10008 // Alternate-Protocol announcement in the first round. It fails due
10009 // to a proxy authentication challenge.
10010 // After the failure, a tunnel is established to www.google.com using
10011 // Proxy-Authorization headers. There is then a SPDY request round.
10013 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10014 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10015 // does a Disconnect and Connect on the same socket, rather than trying
10016 // to obtain a new one.
10018 // NOTE: Originally, the proxy response to the second CONNECT request
10019 // simply returned another 407 so the unit test could skip the SSL connection
10020 // establishment and SPDY framing issues. Alas, the
10021 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10022 // complicated to set up expectations for than the SPDY session.
10024 scoped_ptr<SpdyFrame> req(
10025 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10026 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10027 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10029 MockWrite data_writes_2[] = {
10030 // First connection attempt without Proxy-Authorization.
10031 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10032 "Host: www.google.com\r\n"
10033 "Proxy-Connection: keep-alive\r\n"
10034 "\r\n"),
10036 // Second connection attempt with Proxy-Authorization.
10037 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10038 "Host: www.google.com\r\n"
10039 "Proxy-Connection: keep-alive\r\n"
10040 "Proxy-Authorization: auth_token\r\n"
10041 "\r\n"),
10043 // SPDY request
10044 CreateMockWrite(*req),
10046 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10047 "Proxy-Authenticate: Mock\r\n"
10048 "Proxy-Connection: close\r\n"
10049 "\r\n");
10050 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10051 MockRead data_reads_2[] = {
10052 // First connection attempt fails
10053 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
10054 MockRead(ASYNC, kRejectConnectResponse,
10055 arraysize(kRejectConnectResponse) - 1, 1),
10057 // Second connection attempt passes
10058 MockRead(ASYNC, kAcceptConnectResponse,
10059 arraysize(kAcceptConnectResponse) -1, 4),
10061 // SPDY response
10062 CreateMockRead(*resp.get(), 6),
10063 CreateMockRead(*data.get(), 6),
10064 MockRead(ASYNC, 0, 0, 6),
10066 OrderedSocketData data_2(
10067 data_reads_2, arraysize(data_reads_2),
10068 data_writes_2, arraysize(data_writes_2));
10070 SSLSocketDataProvider ssl(ASYNC, OK);
10071 ssl.SetNextProto(GetParam());
10073 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10074 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10075 NULL, 0, NULL, 0);
10076 hanging_non_alternate_protocol_socket.set_connect_data(
10077 never_finishing_connect);
10079 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10080 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10081 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10082 session_deps_.socket_factory->AddSocketDataProvider(
10083 &hanging_non_alternate_protocol_socket);
10084 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10086 // First round should work and provide the Alternate-Protocol state.
10087 TestCompletionCallback callback_1;
10088 scoped_ptr<HttpTransaction> trans_1(
10089 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10090 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10091 EXPECT_EQ(ERR_IO_PENDING, rv);
10092 EXPECT_EQ(OK, callback_1.WaitForResult());
10094 // Second round should attempt a tunnel connect and get an auth challenge.
10095 TestCompletionCallback callback_2;
10096 scoped_ptr<HttpTransaction> trans_2(
10097 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10098 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10099 EXPECT_EQ(ERR_IO_PENDING, rv);
10100 EXPECT_EQ(OK, callback_2.WaitForResult());
10101 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10102 ASSERT_TRUE(response != NULL);
10103 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10105 // Restart with auth. Tunnel should work and response received.
10106 TestCompletionCallback callback_3;
10107 rv = trans_2->RestartWithAuth(
10108 AuthCredentials(kFoo, kBar), callback_3.callback());
10109 EXPECT_EQ(ERR_IO_PENDING, rv);
10110 EXPECT_EQ(OK, callback_3.WaitForResult());
10112 // After all that work, these two lines (or actually, just the scheme) are
10113 // what this test is all about. Make sure it happens correctly.
10114 EXPECT_EQ("https", request_url.scheme());
10115 EXPECT_EQ("www.google.com", request_url.host());
10117 LoadTimingInfo load_timing_info;
10118 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10119 TestLoadTimingNotReusedWithPac(load_timing_info,
10120 CONNECT_TIMING_HAS_SSL_TIMES);
10123 // Test that if we cancel the transaction as the connection is completing, that
10124 // everything tears down correctly.
10125 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10126 // Setup everything about the connection to complete synchronously, so that
10127 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10128 // for is the callback from the HttpStreamRequest.
10129 // Then cancel the transaction.
10130 // Verify that we don't crash.
10131 MockConnect mock_connect(SYNCHRONOUS, OK);
10132 MockRead data_reads[] = {
10133 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10134 MockRead(SYNCHRONOUS, "hello world"),
10135 MockRead(SYNCHRONOUS, OK),
10138 HttpRequestInfo request;
10139 request.method = "GET";
10140 request.url = GURL("http://www.google.com/");
10141 request.load_flags = 0;
10143 session_deps_.host_resolver->set_synchronous_mode(true);
10144 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10145 scoped_ptr<HttpTransaction> trans(
10146 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
10148 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10149 data.set_connect_data(mock_connect);
10150 session_deps_.socket_factory->AddSocketDataProvider(&data);
10152 TestCompletionCallback callback;
10154 CapturingBoundNetLog log;
10155 int rv = trans->Start(&request, callback.callback(), log.bound());
10156 EXPECT_EQ(ERR_IO_PENDING, rv);
10157 trans.reset(); // Cancel the transaction here.
10159 base::MessageLoop::current()->RunUntilIdle();
10162 // Test a basic GET request through a proxy.
10163 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10164 session_deps_.proxy_service.reset(
10165 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10166 CapturingBoundNetLog log;
10167 session_deps_.net_log = log.bound().net_log();
10168 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10170 HttpRequestInfo request;
10171 request.method = "GET";
10172 request.url = GURL("http://www.google.com/");
10174 MockWrite data_writes1[] = {
10175 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10176 "Host: www.google.com\r\n"
10177 "Proxy-Connection: keep-alive\r\n\r\n"),
10180 MockRead data_reads1[] = {
10181 MockRead("HTTP/1.1 200 OK\r\n"),
10182 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10183 MockRead("Content-Length: 100\r\n\r\n"),
10184 MockRead(SYNCHRONOUS, OK),
10187 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10188 data_writes1, arraysize(data_writes1));
10189 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10191 TestCompletionCallback callback1;
10193 scoped_ptr<HttpTransaction> trans(
10194 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10196 int rv = trans->Start(&request, callback1.callback(), log.bound());
10197 EXPECT_EQ(ERR_IO_PENDING, rv);
10199 rv = callback1.WaitForResult();
10200 EXPECT_EQ(OK, rv);
10202 const HttpResponseInfo* response = trans->GetResponseInfo();
10203 ASSERT_TRUE(response != NULL);
10205 EXPECT_TRUE(response->headers->IsKeepAlive());
10206 EXPECT_EQ(200, response->headers->response_code());
10207 EXPECT_EQ(100, response->headers->GetContentLength());
10208 EXPECT_TRUE(response->was_fetched_via_proxy);
10209 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10211 LoadTimingInfo load_timing_info;
10212 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10213 TestLoadTimingNotReusedWithPac(load_timing_info,
10214 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10217 // Test a basic HTTPS GET request through a proxy.
10218 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10219 session_deps_.proxy_service.reset(
10220 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10221 CapturingBoundNetLog log;
10222 session_deps_.net_log = log.bound().net_log();
10223 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10225 HttpRequestInfo request;
10226 request.method = "GET";
10227 request.url = GURL("https://www.google.com/");
10229 // Since we have proxy, should try to establish tunnel.
10230 MockWrite data_writes1[] = {
10231 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10232 "Host: www.google.com\r\n"
10233 "Proxy-Connection: keep-alive\r\n\r\n"),
10235 MockWrite("GET / HTTP/1.1\r\n"
10236 "Host: www.google.com\r\n"
10237 "Connection: keep-alive\r\n\r\n"),
10240 MockRead data_reads1[] = {
10241 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10243 MockRead("HTTP/1.1 200 OK\r\n"),
10244 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10245 MockRead("Content-Length: 100\r\n\r\n"),
10246 MockRead(SYNCHRONOUS, OK),
10249 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10250 data_writes1, arraysize(data_writes1));
10251 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10252 SSLSocketDataProvider ssl(ASYNC, OK);
10253 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10255 TestCompletionCallback callback1;
10257 scoped_ptr<HttpTransaction> trans(
10258 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10260 int rv = trans->Start(&request, callback1.callback(), log.bound());
10261 EXPECT_EQ(ERR_IO_PENDING, rv);
10263 rv = callback1.WaitForResult();
10264 EXPECT_EQ(OK, rv);
10265 net::CapturingNetLog::CapturedEntryList entries;
10266 log.GetEntries(&entries);
10267 size_t pos = ExpectLogContainsSomewhere(
10268 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10269 NetLog::PHASE_NONE);
10270 ExpectLogContainsSomewhere(
10271 entries, pos,
10272 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10273 NetLog::PHASE_NONE);
10275 const HttpResponseInfo* response = trans->GetResponseInfo();
10276 ASSERT_TRUE(response != NULL);
10278 EXPECT_TRUE(response->headers->IsKeepAlive());
10279 EXPECT_EQ(200, response->headers->response_code());
10280 EXPECT_EQ(100, response->headers->GetContentLength());
10281 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10282 EXPECT_TRUE(response->was_fetched_via_proxy);
10284 LoadTimingInfo load_timing_info;
10285 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10286 TestLoadTimingNotReusedWithPac(load_timing_info,
10287 CONNECT_TIMING_HAS_SSL_TIMES);
10290 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10291 // while establishing the tunnel.
10292 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10293 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10294 CapturingBoundNetLog log;
10295 session_deps_.net_log = log.bound().net_log();
10296 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10298 HttpRequestInfo request;
10299 request.method = "GET";
10300 request.url = GURL("https://www.google.com/");
10302 // Since we have proxy, should try to establish tunnel.
10303 MockWrite data_writes1[] = {
10304 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10305 "Host: www.google.com\r\n"
10306 "Proxy-Connection: keep-alive\r\n\r\n"),
10308 MockWrite("GET / HTTP/1.1\r\n"
10309 "Host: www.google.com\r\n"
10310 "Connection: keep-alive\r\n\r\n"),
10313 MockRead data_reads1[] = {
10314 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10315 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10316 MockRead(ASYNC, 0, 0), // EOF
10319 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10320 data_writes1, arraysize(data_writes1));
10321 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10322 SSLSocketDataProvider ssl(ASYNC, OK);
10323 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10325 TestCompletionCallback callback1;
10327 scoped_ptr<HttpTransaction> trans(
10328 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10330 int rv = trans->Start(&request, callback1.callback(), log.bound());
10331 EXPECT_EQ(ERR_IO_PENDING, rv);
10333 rv = callback1.WaitForResult();
10334 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10335 net::CapturingNetLog::CapturedEntryList entries;
10336 log.GetEntries(&entries);
10337 size_t pos = ExpectLogContainsSomewhere(
10338 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10339 NetLog::PHASE_NONE);
10340 ExpectLogContainsSomewhere(
10341 entries, pos,
10342 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10343 NetLog::PHASE_NONE);
10346 // Test for crbug.com/55424.
10347 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10348 scoped_ptr<SpdyFrame> req(
10349 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10350 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10352 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10353 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10354 MockRead spdy_reads[] = {
10355 CreateMockRead(*resp),
10356 CreateMockRead(*data),
10357 MockRead(ASYNC, 0, 0),
10360 DelayedSocketData spdy_data(
10361 1, // wait for one write to finish before reading.
10362 spdy_reads, arraysize(spdy_reads),
10363 spdy_writes, arraysize(spdy_writes));
10364 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10366 SSLSocketDataProvider ssl(ASYNC, OK);
10367 ssl.SetNextProto(GetParam());
10368 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10370 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10372 // Set up an initial SpdySession in the pool to reuse.
10373 HostPortPair host_port_pair("www.google.com", 443);
10374 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10375 PRIVACY_MODE_DISABLED);
10376 base::WeakPtr<SpdySession> spdy_session =
10377 CreateInsecureSpdySession(session, key, BoundNetLog());
10379 HttpRequestInfo request;
10380 request.method = "GET";
10381 request.url = GURL("https://www.google.com/");
10382 request.load_flags = 0;
10384 // This is the important line that marks this as a preconnect.
10385 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10387 scoped_ptr<HttpTransaction> trans(
10388 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10390 TestCompletionCallback callback;
10391 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10392 EXPECT_EQ(ERR_IO_PENDING, rv);
10393 EXPECT_EQ(OK, callback.WaitForResult());
10396 // Given a net error, cause that error to be returned from the first Write()
10397 // call and verify that the HttpTransaction fails with that error.
10398 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10399 int error, IoMode mode) {
10400 net::HttpRequestInfo request_info;
10401 request_info.url = GURL("https://www.example.com/");
10402 request_info.method = "GET";
10403 request_info.load_flags = net::LOAD_NORMAL;
10405 SSLSocketDataProvider ssl_data(mode, OK);
10406 net::MockWrite data_writes[] = {
10407 net::MockWrite(mode, error),
10409 net::StaticSocketDataProvider data(NULL, 0,
10410 data_writes, arraysize(data_writes));
10411 session_deps_.socket_factory->AddSocketDataProvider(&data);
10412 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10414 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10415 scoped_ptr<HttpTransaction> trans(
10416 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10418 TestCompletionCallback callback;
10419 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10420 if (rv == net::ERR_IO_PENDING)
10421 rv = callback.WaitForResult();
10422 ASSERT_EQ(error, rv);
10425 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10426 // Just check a grab bag of cert errors.
10427 static const int kErrors[] = {
10428 ERR_CERT_COMMON_NAME_INVALID,
10429 ERR_CERT_AUTHORITY_INVALID,
10430 ERR_CERT_DATE_INVALID,
10432 for (size_t i = 0; i < arraysize(kErrors); i++) {
10433 CheckErrorIsPassedBack(kErrors[i], ASYNC);
10434 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10438 // Ensure that a client certificate is removed from the SSL client auth
10439 // cache when:
10440 // 1) No proxy is involved.
10441 // 2) TLS False Start is disabled.
10442 // 3) The initial TLS handshake requests a client certificate.
10443 // 4) The client supplies an invalid/unacceptable certificate.
10444 TEST_P(HttpNetworkTransactionTest,
10445 ClientAuthCertCache_Direct_NoFalseStart) {
10446 net::HttpRequestInfo request_info;
10447 request_info.url = GURL("https://www.example.com/");
10448 request_info.method = "GET";
10449 request_info.load_flags = net::LOAD_NORMAL;
10451 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10452 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10454 // [ssl_]data1 contains the data for the first SSL handshake. When a
10455 // CertificateRequest is received for the first time, the handshake will
10456 // be aborted to allow the caller to provide a certificate.
10457 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10458 ssl_data1.cert_request_info = cert_request.get();
10459 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10460 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10461 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10463 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10464 // False Start is not being used, the result of the SSL handshake will be
10465 // returned as part of the SSLClientSocket::Connect() call. This test
10466 // matches the result of a server sending a handshake_failure alert,
10467 // rather than a Finished message, because it requires a client
10468 // certificate and none was supplied.
10469 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10470 ssl_data2.cert_request_info = cert_request.get();
10471 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10472 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10473 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10475 // [ssl_]data3 contains the data for the third SSL handshake. When a
10476 // connection to a server fails during an SSL handshake,
10477 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10478 // connection was attempted with TLSv1.1. This is transparent to the caller
10479 // of the HttpNetworkTransaction. Because this test failure is due to
10480 // requiring a client certificate, this fallback handshake should also
10481 // fail.
10482 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10483 ssl_data3.cert_request_info = cert_request.get();
10484 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10485 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10486 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10488 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10489 // connection to a server fails during an SSL handshake,
10490 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10491 // connection was attempted with TLSv1. This is transparent to the caller
10492 // of the HttpNetworkTransaction. Because this test failure is due to
10493 // requiring a client certificate, this fallback handshake should also
10494 // fail.
10495 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10496 ssl_data4.cert_request_info = cert_request.get();
10497 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10498 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10499 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10501 // Need one more if TLSv1.2 is enabled.
10502 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10503 ssl_data5.cert_request_info = cert_request.get();
10504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10505 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10506 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10508 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10509 scoped_ptr<HttpTransaction> trans(
10510 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10512 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10513 TestCompletionCallback callback;
10514 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10515 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10517 // Complete the SSL handshake, which should abort due to requiring a
10518 // client certificate.
10519 rv = callback.WaitForResult();
10520 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10522 // Indicate that no certificate should be supplied. From the perspective
10523 // of SSLClientCertCache, NULL is just as meaningful as a real
10524 // certificate, so this is the same as supply a
10525 // legitimate-but-unacceptable certificate.
10526 rv = trans->RestartWithCertificate(NULL, callback.callback());
10527 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10529 // Ensure the certificate was added to the client auth cache before
10530 // allowing the connection to continue restarting.
10531 scoped_refptr<X509Certificate> client_cert;
10532 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10533 HostPortPair("www.example.com", 443), &client_cert));
10534 ASSERT_EQ(NULL, client_cert.get());
10536 // Restart the handshake. This will consume ssl_data2, which fails, and
10537 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10538 // The result code is checked against what ssl_data4 should return.
10539 rv = callback.WaitForResult();
10540 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10542 // Ensure that the client certificate is removed from the cache on a
10543 // handshake failure.
10544 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10545 HostPortPair("www.example.com", 443), &client_cert));
10548 // Ensure that a client certificate is removed from the SSL client auth
10549 // cache when:
10550 // 1) No proxy is involved.
10551 // 2) TLS False Start is enabled.
10552 // 3) The initial TLS handshake requests a client certificate.
10553 // 4) The client supplies an invalid/unacceptable certificate.
10554 TEST_P(HttpNetworkTransactionTest,
10555 ClientAuthCertCache_Direct_FalseStart) {
10556 net::HttpRequestInfo request_info;
10557 request_info.url = GURL("https://www.example.com/");
10558 request_info.method = "GET";
10559 request_info.load_flags = net::LOAD_NORMAL;
10561 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10562 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10564 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10565 // return successfully after reading up to the peer's Certificate message.
10566 // This is to allow the caller to call SSLClientSocket::Write(), which can
10567 // enqueue application data to be sent in the same packet as the
10568 // ChangeCipherSpec and Finished messages.
10569 // The actual handshake will be finished when SSLClientSocket::Read() is
10570 // called, which expects to process the peer's ChangeCipherSpec and
10571 // Finished messages. If there was an error negotiating with the peer,
10572 // such as due to the peer requiring a client certificate when none was
10573 // supplied, the alert sent by the peer won't be processed until Read() is
10574 // called.
10576 // Like the non-False Start case, when a client certificate is requested by
10577 // the peer, the handshake is aborted during the Connect() call.
10578 // [ssl_]data1 represents the initial SSL handshake with the peer.
10579 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10580 ssl_data1.cert_request_info = cert_request.get();
10581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10582 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10583 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10585 // When a client certificate is supplied, Connect() will not be aborted
10586 // when the peer requests the certificate. Instead, the handshake will
10587 // artificially succeed, allowing the caller to write the HTTP request to
10588 // the socket. The handshake messages are not processed until Read() is
10589 // called, which then detects that the handshake was aborted, due to the
10590 // peer sending a handshake_failure because it requires a client
10591 // certificate.
10592 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10593 ssl_data2.cert_request_info = cert_request.get();
10594 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10595 net::MockRead data2_reads[] = {
10596 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10598 net::StaticSocketDataProvider data2(
10599 data2_reads, arraysize(data2_reads), NULL, 0);
10600 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10602 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10603 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10604 // TLSv1. It has the same behaviour as [ssl_]data2.
10605 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10606 ssl_data3.cert_request_info = cert_request.get();
10607 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10608 net::StaticSocketDataProvider data3(
10609 data2_reads, arraysize(data2_reads), NULL, 0);
10610 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10612 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10613 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10614 SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10615 ssl_data4.cert_request_info = cert_request.get();
10616 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10617 net::StaticSocketDataProvider data4(
10618 data2_reads, arraysize(data2_reads), NULL, 0);
10619 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10621 // Need one more if TLSv1.2 is enabled.
10622 SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10623 ssl_data5.cert_request_info = cert_request.get();
10624 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10625 net::StaticSocketDataProvider data5(
10626 data2_reads, arraysize(data2_reads), NULL, 0);
10627 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10629 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10630 scoped_ptr<HttpTransaction> trans(
10631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10633 // Begin the initial SSL handshake.
10634 TestCompletionCallback callback;
10635 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10636 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10638 // Complete the SSL handshake, which should abort due to requiring a
10639 // client certificate.
10640 rv = callback.WaitForResult();
10641 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10643 // Indicate that no certificate should be supplied. From the perspective
10644 // of SSLClientCertCache, NULL is just as meaningful as a real
10645 // certificate, so this is the same as supply a
10646 // legitimate-but-unacceptable certificate.
10647 rv = trans->RestartWithCertificate(NULL, callback.callback());
10648 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10650 // Ensure the certificate was added to the client auth cache before
10651 // allowing the connection to continue restarting.
10652 scoped_refptr<X509Certificate> client_cert;
10653 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10654 HostPortPair("www.example.com", 443), &client_cert));
10655 ASSERT_EQ(NULL, client_cert.get());
10657 // Restart the handshake. This will consume ssl_data2, which fails, and
10658 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10659 // The result code is checked against what ssl_data4 should return.
10660 rv = callback.WaitForResult();
10661 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10663 // Ensure that the client certificate is removed from the cache on a
10664 // handshake failure.
10665 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10666 HostPortPair("www.example.com", 443), &client_cert));
10669 // Ensure that a client certificate is removed from the SSL client auth
10670 // cache when:
10671 // 1) An HTTPS proxy is involved.
10672 // 3) The HTTPS proxy requests a client certificate.
10673 // 4) The client supplies an invalid/unacceptable certificate for the
10674 // proxy.
10675 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10676 // then for connecting to an HTTP endpoint.
10677 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10678 session_deps_.proxy_service.reset(
10679 ProxyService::CreateFixed("https://proxy:70"));
10680 CapturingBoundNetLog log;
10681 session_deps_.net_log = log.bound().net_log();
10683 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10684 cert_request->host_and_port = HostPortPair("proxy", 70);
10686 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10687 // [ssl_]data[1-3]. Rather than represending the endpoint
10688 // (www.example.com:443), they represent failures with the HTTPS proxy
10689 // (proxy:70).
10690 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10691 ssl_data1.cert_request_info = cert_request.get();
10692 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10693 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10694 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10696 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10697 ssl_data2.cert_request_info = cert_request.get();
10698 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10699 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10700 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10702 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10703 #if 0
10704 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10705 ssl_data3.cert_request_info = cert_request.get();
10706 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10707 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10708 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10709 #endif
10711 net::HttpRequestInfo requests[2];
10712 requests[0].url = GURL("https://www.example.com/");
10713 requests[0].method = "GET";
10714 requests[0].load_flags = net::LOAD_NORMAL;
10716 requests[1].url = GURL("http://www.example.com/");
10717 requests[1].method = "GET";
10718 requests[1].load_flags = net::LOAD_NORMAL;
10720 for (size_t i = 0; i < arraysize(requests); ++i) {
10721 session_deps_.socket_factory->ResetNextMockIndexes();
10722 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10723 scoped_ptr<HttpNetworkTransaction> trans(
10724 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10726 // Begin the SSL handshake with the proxy.
10727 TestCompletionCallback callback;
10728 int rv = trans->Start(
10729 &requests[i], callback.callback(), net::BoundNetLog());
10730 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10732 // Complete the SSL handshake, which should abort due to requiring a
10733 // client certificate.
10734 rv = callback.WaitForResult();
10735 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10737 // Indicate that no certificate should be supplied. From the perspective
10738 // of SSLClientCertCache, NULL is just as meaningful as a real
10739 // certificate, so this is the same as supply a
10740 // legitimate-but-unacceptable certificate.
10741 rv = trans->RestartWithCertificate(NULL, callback.callback());
10742 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10744 // Ensure the certificate was added to the client auth cache before
10745 // allowing the connection to continue restarting.
10746 scoped_refptr<X509Certificate> client_cert;
10747 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10748 HostPortPair("proxy", 70), &client_cert));
10749 ASSERT_EQ(NULL, client_cert.get());
10750 // Ensure the certificate was NOT cached for the endpoint. This only
10751 // applies to HTTPS requests, but is fine to check for HTTP requests.
10752 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10753 HostPortPair("www.example.com", 443), &client_cert));
10755 // Restart the handshake. This will consume ssl_data2, which fails, and
10756 // then consume ssl_data3, which should also fail. The result code is
10757 // checked against what ssl_data3 should return.
10758 rv = callback.WaitForResult();
10759 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10761 // Now that the new handshake has failed, ensure that the client
10762 // certificate was removed from the client auth cache.
10763 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10764 HostPortPair("proxy", 70), &client_cert));
10765 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10766 HostPortPair("www.example.com", 443), &client_cert));
10770 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10771 // TEST_P is a macro that expands directly to code that stringizes the
10772 // arguments. As a result, macros passed as parameters (such as prefix
10773 // or test_case_name) will not be expanded by the preprocessor. To
10774 // work around this, indirect the macro for TEST_P, so that the
10775 // pre-processor will expand macros such as MAYBE_test_name before
10776 // instantiating the test.
10777 #define WRAPPED_TEST_P(test_case_name, test_name) \
10778 TEST_P(test_case_name, test_name)
10780 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10781 #if defined(OS_WIN)
10782 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10783 #else
10784 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10785 #endif
10786 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10787 HttpStreamFactory::set_use_alternate_protocols(true);
10788 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10790 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10791 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10792 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10793 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10794 pool_peer.DisableDomainAuthenticationVerification();
10796 SSLSocketDataProvider ssl(ASYNC, OK);
10797 ssl.SetNextProto(GetParam());
10798 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10800 scoped_ptr<SpdyFrame> host1_req(
10801 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10802 scoped_ptr<SpdyFrame> host2_req(
10803 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10804 MockWrite spdy_writes[] = {
10805 CreateMockWrite(*host1_req, 1),
10806 CreateMockWrite(*host2_req, 4),
10808 scoped_ptr<SpdyFrame> host1_resp(
10809 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10810 scoped_ptr<SpdyFrame> host1_resp_body(
10811 spdy_util_.ConstructSpdyBodyFrame(1, true));
10812 scoped_ptr<SpdyFrame> host2_resp(
10813 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10814 scoped_ptr<SpdyFrame> host2_resp_body(
10815 spdy_util_.ConstructSpdyBodyFrame(3, true));
10816 MockRead spdy_reads[] = {
10817 CreateMockRead(*host1_resp, 2),
10818 CreateMockRead(*host1_resp_body, 3),
10819 CreateMockRead(*host2_resp, 5),
10820 CreateMockRead(*host2_resp_body, 6),
10821 MockRead(ASYNC, 0, 7),
10824 IPAddressNumber ip;
10825 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10826 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10827 MockConnect connect(ASYNC, OK, peer_addr);
10828 OrderedSocketData spdy_data(
10829 connect,
10830 spdy_reads, arraysize(spdy_reads),
10831 spdy_writes, arraysize(spdy_writes));
10832 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10834 TestCompletionCallback callback;
10835 HttpRequestInfo request1;
10836 request1.method = "GET";
10837 request1.url = GURL("https://www.google.com/");
10838 request1.load_flags = 0;
10839 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10841 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10842 EXPECT_EQ(ERR_IO_PENDING, rv);
10843 EXPECT_EQ(OK, callback.WaitForResult());
10845 const HttpResponseInfo* response = trans1.GetResponseInfo();
10846 ASSERT_TRUE(response != NULL);
10847 ASSERT_TRUE(response->headers.get() != NULL);
10848 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10850 std::string response_data;
10851 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10852 EXPECT_EQ("hello!", response_data);
10854 // Preload www.gmail.com into HostCache.
10855 HostPortPair host_port("www.gmail.com", 443);
10856 HostResolver::RequestInfo resolve_info(host_port);
10857 AddressList ignored;
10858 rv = session_deps_.host_resolver->Resolve(resolve_info,
10859 DEFAULT_PRIORITY,
10860 &ignored,
10861 callback.callback(),
10862 NULL,
10863 BoundNetLog());
10864 EXPECT_EQ(ERR_IO_PENDING, rv);
10865 rv = callback.WaitForResult();
10866 EXPECT_EQ(OK, rv);
10868 HttpRequestInfo request2;
10869 request2.method = "GET";
10870 request2.url = GURL("https://www.gmail.com/");
10871 request2.load_flags = 0;
10872 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10874 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10875 EXPECT_EQ(ERR_IO_PENDING, rv);
10876 EXPECT_EQ(OK, callback.WaitForResult());
10878 response = trans2.GetResponseInfo();
10879 ASSERT_TRUE(response != NULL);
10880 ASSERT_TRUE(response->headers.get() != NULL);
10881 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10882 EXPECT_TRUE(response->was_fetched_via_spdy);
10883 EXPECT_TRUE(response->was_npn_negotiated);
10884 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10885 EXPECT_EQ("hello!", response_data);
10887 #undef MAYBE_UseIPConnectionPooling
10889 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
10890 HttpStreamFactory::set_use_alternate_protocols(true);
10891 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10893 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10894 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10895 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10896 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10897 pool_peer.DisableDomainAuthenticationVerification();
10899 SSLSocketDataProvider ssl(ASYNC, OK);
10900 ssl.SetNextProto(GetParam());
10901 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10903 scoped_ptr<SpdyFrame> host1_req(
10904 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10905 scoped_ptr<SpdyFrame> host2_req(
10906 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10907 MockWrite spdy_writes[] = {
10908 CreateMockWrite(*host1_req, 1),
10909 CreateMockWrite(*host2_req, 4),
10911 scoped_ptr<SpdyFrame> host1_resp(
10912 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10913 scoped_ptr<SpdyFrame> host1_resp_body(
10914 spdy_util_.ConstructSpdyBodyFrame(1, true));
10915 scoped_ptr<SpdyFrame> host2_resp(
10916 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10917 scoped_ptr<SpdyFrame> host2_resp_body(
10918 spdy_util_.ConstructSpdyBodyFrame(3, true));
10919 MockRead spdy_reads[] = {
10920 CreateMockRead(*host1_resp, 2),
10921 CreateMockRead(*host1_resp_body, 3),
10922 CreateMockRead(*host2_resp, 5),
10923 CreateMockRead(*host2_resp_body, 6),
10924 MockRead(ASYNC, 0, 7),
10927 IPAddressNumber ip;
10928 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10929 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10930 MockConnect connect(ASYNC, OK, peer_addr);
10931 OrderedSocketData spdy_data(
10932 connect,
10933 spdy_reads, arraysize(spdy_reads),
10934 spdy_writes, arraysize(spdy_writes));
10935 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10937 TestCompletionCallback callback;
10938 HttpRequestInfo request1;
10939 request1.method = "GET";
10940 request1.url = GURL("https://www.google.com/");
10941 request1.load_flags = 0;
10942 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10944 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10945 EXPECT_EQ(ERR_IO_PENDING, rv);
10946 EXPECT_EQ(OK, callback.WaitForResult());
10948 const HttpResponseInfo* response = trans1.GetResponseInfo();
10949 ASSERT_TRUE(response != NULL);
10950 ASSERT_TRUE(response->headers.get() != NULL);
10951 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10953 std::string response_data;
10954 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10955 EXPECT_EQ("hello!", response_data);
10957 HttpRequestInfo request2;
10958 request2.method = "GET";
10959 request2.url = GURL("https://www.gmail.com/");
10960 request2.load_flags = 0;
10961 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10963 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10964 EXPECT_EQ(ERR_IO_PENDING, rv);
10965 EXPECT_EQ(OK, callback.WaitForResult());
10967 response = trans2.GetResponseInfo();
10968 ASSERT_TRUE(response != NULL);
10969 ASSERT_TRUE(response->headers.get() != NULL);
10970 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10971 EXPECT_TRUE(response->was_fetched_via_spdy);
10972 EXPECT_TRUE(response->was_npn_negotiated);
10973 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10974 EXPECT_EQ("hello!", response_data);
10977 class OneTimeCachingHostResolver : public net::HostResolver {
10978 public:
10979 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
10980 : host_port_(host_port) {}
10981 virtual ~OneTimeCachingHostResolver() {}
10983 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
10985 // HostResolver methods:
10986 virtual int Resolve(const RequestInfo& info,
10987 RequestPriority priority,
10988 AddressList* addresses,
10989 const CompletionCallback& callback,
10990 RequestHandle* out_req,
10991 const BoundNetLog& net_log) OVERRIDE {
10992 return host_resolver_.Resolve(
10993 info, priority, addresses, callback, out_req, net_log);
10996 virtual int ResolveFromCache(const RequestInfo& info,
10997 AddressList* addresses,
10998 const BoundNetLog& net_log) OVERRIDE {
10999 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11000 if (rv == OK && info.host_port_pair().Equals(host_port_))
11001 host_resolver_.GetHostCache()->clear();
11002 return rv;
11005 virtual void CancelRequest(RequestHandle req) OVERRIDE {
11006 host_resolver_.CancelRequest(req);
11009 MockCachingHostResolver* GetMockHostResolver() {
11010 return &host_resolver_;
11013 private:
11014 MockCachingHostResolver host_resolver_;
11015 const HostPortPair host_port_;
11018 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11019 #if defined(OS_WIN)
11020 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11021 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11022 #else
11023 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11024 UseIPConnectionPoolingWithHostCacheExpiration
11025 #endif
11026 WRAPPED_TEST_P(HttpNetworkTransactionTest,
11027 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
11028 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11029 // prefix doesn't work with parametrized tests).
11030 #if defined(OS_WIN)
11031 return;
11032 #else
11033 HttpStreamFactory::set_use_alternate_protocols(true);
11034 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11036 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11037 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11038 HttpNetworkSession::Params params =
11039 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11040 params.host_resolver = &host_resolver;
11041 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11042 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11043 pool_peer.DisableDomainAuthenticationVerification();
11045 SSLSocketDataProvider ssl(ASYNC, OK);
11046 ssl.SetNextProto(GetParam());
11047 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11049 scoped_ptr<SpdyFrame> host1_req(
11050 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
11051 scoped_ptr<SpdyFrame> host2_req(
11052 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11053 MockWrite spdy_writes[] = {
11054 CreateMockWrite(*host1_req, 1),
11055 CreateMockWrite(*host2_req, 4),
11057 scoped_ptr<SpdyFrame> host1_resp(
11058 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11059 scoped_ptr<SpdyFrame> host1_resp_body(
11060 spdy_util_.ConstructSpdyBodyFrame(1, true));
11061 scoped_ptr<SpdyFrame> host2_resp(
11062 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11063 scoped_ptr<SpdyFrame> host2_resp_body(
11064 spdy_util_.ConstructSpdyBodyFrame(3, true));
11065 MockRead spdy_reads[] = {
11066 CreateMockRead(*host1_resp, 2),
11067 CreateMockRead(*host1_resp_body, 3),
11068 CreateMockRead(*host2_resp, 5),
11069 CreateMockRead(*host2_resp_body, 6),
11070 MockRead(ASYNC, 0, 7),
11073 IPAddressNumber ip;
11074 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11075 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11076 MockConnect connect(ASYNC, OK, peer_addr);
11077 OrderedSocketData spdy_data(
11078 connect,
11079 spdy_reads, arraysize(spdy_reads),
11080 spdy_writes, arraysize(spdy_writes));
11081 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11083 TestCompletionCallback callback;
11084 HttpRequestInfo request1;
11085 request1.method = "GET";
11086 request1.url = GURL("https://www.google.com/");
11087 request1.load_flags = 0;
11088 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11090 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11091 EXPECT_EQ(ERR_IO_PENDING, rv);
11092 EXPECT_EQ(OK, callback.WaitForResult());
11094 const HttpResponseInfo* response = trans1.GetResponseInfo();
11095 ASSERT_TRUE(response != NULL);
11096 ASSERT_TRUE(response->headers.get() != NULL);
11097 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11099 std::string response_data;
11100 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11101 EXPECT_EQ("hello!", response_data);
11103 // Preload cache entries into HostCache.
11104 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11105 AddressList ignored;
11106 rv = host_resolver.Resolve(resolve_info,
11107 DEFAULT_PRIORITY,
11108 &ignored,
11109 callback.callback(),
11110 NULL,
11111 BoundNetLog());
11112 EXPECT_EQ(ERR_IO_PENDING, rv);
11113 rv = callback.WaitForResult();
11114 EXPECT_EQ(OK, rv);
11116 HttpRequestInfo request2;
11117 request2.method = "GET";
11118 request2.url = GURL("https://www.gmail.com/");
11119 request2.load_flags = 0;
11120 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11122 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11123 EXPECT_EQ(ERR_IO_PENDING, rv);
11124 EXPECT_EQ(OK, callback.WaitForResult());
11126 response = trans2.GetResponseInfo();
11127 ASSERT_TRUE(response != NULL);
11128 ASSERT_TRUE(response->headers.get() != NULL);
11129 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11130 EXPECT_TRUE(response->was_fetched_via_spdy);
11131 EXPECT_TRUE(response->was_npn_negotiated);
11132 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11133 EXPECT_EQ("hello!", response_data);
11134 #endif
11136 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11138 TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
11139 MockRead data_reads1[] = {
11140 MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
11142 MockRead data_reads2[] = {
11143 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11144 MockRead("hello world"),
11145 MockRead(SYNCHRONOUS, OK),
11147 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
11148 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
11149 StaticSocketDataProvider* data[] = { &data1, &data2 };
11151 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
11153 EXPECT_EQ(OK, out.rv);
11154 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
11155 EXPECT_EQ("hello world", out.response_data);
11158 TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
11159 MockWrite data_writes1[] = {
11160 MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
11162 MockWrite data_writes2[] = {
11163 MockWrite("GET / HTTP/1.1\r\n"
11164 "Host: www.google.com\r\n"
11165 "Connection: keep-alive\r\n\r\n"),
11167 MockRead data_reads2[] = {
11168 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11169 MockRead("hello world"),
11170 MockRead(SYNCHRONOUS, OK),
11172 StaticSocketDataProvider data1(NULL, 0,
11173 data_writes1, arraysize(data_writes1));
11174 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
11175 data_writes2, arraysize(data_writes2));
11176 StaticSocketDataProvider* data[] = { &data1, &data2 };
11178 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
11180 EXPECT_EQ(OK, out.rv);
11181 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
11182 EXPECT_EQ("hello world", out.response_data);
11185 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11186 const std::string https_url = "https://www.google.com/";
11187 const std::string http_url = "http://www.google.com:443/";
11189 // SPDY GET for HTTPS URL
11190 scoped_ptr<SpdyFrame> req1(
11191 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11193 MockWrite writes1[] = {
11194 CreateMockWrite(*req1, 0),
11197 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11198 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11199 MockRead reads1[] = {
11200 CreateMockRead(*resp1, 1),
11201 CreateMockRead(*body1, 2),
11202 MockRead(ASYNC, ERR_IO_PENDING, 3)
11205 DelayedSocketData data1(
11206 1, reads1, arraysize(reads1),
11207 writes1, arraysize(writes1));
11208 MockConnect connect_data1(ASYNC, OK);
11209 data1.set_connect_data(connect_data1);
11211 // HTTP GET for the HTTP URL
11212 MockWrite writes2[] = {
11213 MockWrite(ASYNC, 4,
11214 "GET / HTTP/1.1\r\n"
11215 "Host: www.google.com:443\r\n"
11216 "Connection: keep-alive\r\n\r\n"),
11219 MockRead reads2[] = {
11220 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11221 MockRead(ASYNC, 6, "hello"),
11222 MockRead(ASYNC, 7, OK),
11225 DelayedSocketData data2(
11226 1, reads2, arraysize(reads2),
11227 writes2, arraysize(writes2));
11229 SSLSocketDataProvider ssl(ASYNC, OK);
11230 ssl.SetNextProto(GetParam());
11231 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11232 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11233 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11235 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11237 // Start the first transaction to set up the SpdySession
11238 HttpRequestInfo request1;
11239 request1.method = "GET";
11240 request1.url = GURL(https_url);
11241 request1.load_flags = 0;
11242 HttpNetworkTransaction trans1(LOWEST, session.get());
11243 TestCompletionCallback callback1;
11244 EXPECT_EQ(ERR_IO_PENDING,
11245 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11246 base::MessageLoop::current()->RunUntilIdle();
11248 EXPECT_EQ(OK, callback1.WaitForResult());
11249 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11251 // Now, start the HTTP request
11252 HttpRequestInfo request2;
11253 request2.method = "GET";
11254 request2.url = GURL(http_url);
11255 request2.load_flags = 0;
11256 HttpNetworkTransaction trans2(MEDIUM, session.get());
11257 TestCompletionCallback callback2;
11258 EXPECT_EQ(ERR_IO_PENDING,
11259 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11260 base::MessageLoop::current()->RunUntilIdle();
11262 EXPECT_EQ(OK, callback2.WaitForResult());
11263 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11266 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
11267 const std::string https_url = "https://www.google.com/";
11268 const std::string http_url = "http://www.google.com:443/";
11270 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11271 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
11272 LOWEST));
11273 scoped_ptr<SpdyFrame> req1(
11274 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11275 scoped_ptr<SpdyFrame> wrapped_req1(
11276 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
11278 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11279 SpdySynStreamIR req2_ir(3);
11280 spdy_util_.SetPriority(MEDIUM, &req2_ir);
11281 req2_ir.set_fin(true);
11282 req2_ir.SetHeader(spdy_util_.GetMethodKey(), "GET");
11283 req2_ir.SetHeader(spdy_util_.GetPathKey(),
11284 spdy_util_.is_spdy2() ? http_url.c_str() : "/");
11285 req2_ir.SetHeader(spdy_util_.GetHostKey(), "www.google.com:443");
11286 req2_ir.SetHeader(spdy_util_.GetSchemeKey(), "http");
11287 spdy_util_.MaybeAddVersionHeader(&req2_ir);
11288 scoped_ptr<SpdyFrame> req2(
11289 spdy_util_.CreateFramer(false)->SerializeFrame(req2_ir));
11291 MockWrite writes1[] = {
11292 CreateMockWrite(*connect, 0),
11293 CreateMockWrite(*wrapped_req1, 2),
11294 CreateMockWrite(*req2, 5),
11297 scoped_ptr<SpdyFrame> conn_resp(
11298 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11299 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11300 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11301 scoped_ptr<SpdyFrame> wrapped_resp1(
11302 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
11303 scoped_ptr<SpdyFrame> wrapped_body1(
11304 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
11305 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11306 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11307 MockRead reads1[] = {
11308 CreateMockRead(*conn_resp, 1),
11309 CreateMockRead(*wrapped_resp1, 3),
11310 CreateMockRead(*wrapped_body1, 4),
11311 CreateMockRead(*resp2, 6),
11312 CreateMockRead(*body2, 7),
11313 MockRead(ASYNC, ERR_IO_PENDING, 8)
11316 DeterministicSocketData data1(reads1, arraysize(reads1),
11317 writes1, arraysize(writes1));
11318 MockConnect connect_data1(ASYNC, OK);
11319 data1.set_connect_data(connect_data1);
11321 session_deps_.proxy_service.reset(
11322 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11323 CapturingNetLog log;
11324 session_deps_.net_log = &log;
11325 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11326 ssl1.SetNextProto(GetParam());
11327 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11328 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11329 ssl2.SetNextProto(GetParam());
11330 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11331 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
11333 scoped_refptr<HttpNetworkSession> session(
11334 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11336 // Start the first transaction to set up the SpdySession
11337 HttpRequestInfo request1;
11338 request1.method = "GET";
11339 request1.url = GURL(https_url);
11340 request1.load_flags = 0;
11341 HttpNetworkTransaction trans1(LOWEST, session.get());
11342 TestCompletionCallback callback1;
11343 EXPECT_EQ(ERR_IO_PENDING,
11344 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11345 base::MessageLoop::current()->RunUntilIdle();
11346 data1.RunFor(4);
11348 EXPECT_EQ(OK, callback1.WaitForResult());
11349 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11351 LoadTimingInfo load_timing_info1;
11352 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
11353 TestLoadTimingNotReusedWithPac(load_timing_info1,
11354 CONNECT_TIMING_HAS_SSL_TIMES);
11356 // Now, start the HTTP request
11357 HttpRequestInfo request2;
11358 request2.method = "GET";
11359 request2.url = GURL(http_url);
11360 request2.load_flags = 0;
11361 HttpNetworkTransaction trans2(MEDIUM, session.get());
11362 TestCompletionCallback callback2;
11363 EXPECT_EQ(ERR_IO_PENDING,
11364 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11365 base::MessageLoop::current()->RunUntilIdle();
11366 data1.RunFor(3);
11368 EXPECT_EQ(OK, callback2.WaitForResult());
11369 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11371 LoadTimingInfo load_timing_info2;
11372 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
11373 // The established SPDY sessions is considered reused by the HTTP request.
11374 TestLoadTimingReusedWithPac(load_timing_info2);
11375 // HTTP requests over a SPDY session should have a different connection
11376 // socket_log_id than requests over a tunnel.
11377 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
11380 TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
11381 HttpStreamFactory::set_force_spdy_always(true);
11382 const std::string https_url = "https://www.google.com/";
11383 const std::string http_url = "http://www.google.com:443/";
11385 // SPDY GET for HTTPS URL
11386 scoped_ptr<SpdyFrame> req1(
11387 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11388 // SPDY GET for the HTTP URL
11389 scoped_ptr<SpdyFrame> req2(
11390 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11392 MockWrite writes[] = {
11393 CreateMockWrite(*req1, 1),
11394 CreateMockWrite(*req2, 4),
11397 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11398 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11399 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11400 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11401 MockRead reads[] = {
11402 CreateMockRead(*resp1, 2),
11403 CreateMockRead(*body1, 3),
11404 CreateMockRead(*resp2, 5),
11405 CreateMockRead(*body2, 6),
11406 MockRead(ASYNC, ERR_IO_PENDING, 7)
11409 OrderedSocketData data(reads, arraysize(reads),
11410 writes, arraysize(writes));
11412 SSLSocketDataProvider ssl(ASYNC, OK);
11413 ssl.SetNextProto(GetParam());
11414 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11415 session_deps_.socket_factory->AddSocketDataProvider(&data);
11417 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11419 // Start the first transaction to set up the SpdySession
11420 HttpRequestInfo request1;
11421 request1.method = "GET";
11422 request1.url = GURL(https_url);
11423 request1.load_flags = 0;
11424 HttpNetworkTransaction trans1(LOWEST, session.get());
11425 TestCompletionCallback callback1;
11426 EXPECT_EQ(ERR_IO_PENDING,
11427 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11428 base::MessageLoop::current()->RunUntilIdle();
11430 EXPECT_EQ(OK, callback1.WaitForResult());
11431 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11433 // Now, start the HTTP request
11434 HttpRequestInfo request2;
11435 request2.method = "GET";
11436 request2.url = GURL(http_url);
11437 request2.load_flags = 0;
11438 HttpNetworkTransaction trans2(MEDIUM, session.get());
11439 TestCompletionCallback callback2;
11440 EXPECT_EQ(ERR_IO_PENDING,
11441 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11442 base::MessageLoop::current()->RunUntilIdle();
11444 EXPECT_EQ(OK, callback2.WaitForResult());
11445 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11448 // Test that in the case where we have a SPDY session to a SPDY proxy
11449 // that we do not pool other origins that resolve to the same IP when
11450 // the certificate does not match the new origin.
11451 // http://crbug.com/134690
11452 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11453 const std::string url1 = "http://www.google.com/";
11454 const std::string url2 = "https://mail.google.com/";
11455 const std::string ip_addr = "1.2.3.4";
11457 // SPDY GET for HTTP URL (through SPDY proxy)
11458 scoped_ptr<SpdyHeaderBlock> headers(
11459 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11460 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
11461 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
11463 MockWrite writes1[] = {
11464 CreateMockWrite(*req1, 0),
11467 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11468 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11469 MockRead reads1[] = {
11470 CreateMockRead(*resp1, 1),
11471 CreateMockRead(*body1, 2),
11472 MockRead(ASYNC, OK, 3) // EOF
11475 scoped_ptr<DeterministicSocketData> data1(
11476 new DeterministicSocketData(reads1, arraysize(reads1),
11477 writes1, arraysize(writes1)));
11478 IPAddressNumber ip;
11479 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11480 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11481 MockConnect connect_data1(ASYNC, OK, peer_addr);
11482 data1->set_connect_data(connect_data1);
11484 // SPDY GET for HTTPS URL (direct)
11485 scoped_ptr<SpdyFrame> req2(
11486 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11488 MockWrite writes2[] = {
11489 CreateMockWrite(*req2, 0),
11492 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11493 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11494 MockRead reads2[] = {
11495 CreateMockRead(*resp2, 1),
11496 CreateMockRead(*body2, 2),
11497 MockRead(ASYNC, OK, 3) // EOF
11500 scoped_ptr<DeterministicSocketData> data2(
11501 new DeterministicSocketData(reads2, arraysize(reads2),
11502 writes2, arraysize(writes2)));
11503 MockConnect connect_data2(ASYNC, OK);
11504 data2->set_connect_data(connect_data2);
11506 // Set up a proxy config that sends HTTP requests to a proxy, and
11507 // all others direct.
11508 ProxyConfig proxy_config;
11509 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11510 CapturingProxyResolver* capturing_proxy_resolver =
11511 new CapturingProxyResolver();
11512 session_deps_.proxy_service.reset(new ProxyService(
11513 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11514 NULL));
11516 // Load a valid cert. Note, that this does not need to
11517 // be valid for proxy because the MockSSLClientSocket does
11518 // not actually verify it. But SpdySession will use this
11519 // to see if it is valid for the new origin
11520 base::FilePath certs_dir = GetTestCertsDirectory();
11521 scoped_refptr<X509Certificate> server_cert(
11522 ImportCertFromFile(certs_dir, "ok_cert.pem"));
11523 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11525 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11526 ssl1.SetNextProto(GetParam());
11527 ssl1.cert = server_cert;
11528 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11529 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11530 data1.get());
11532 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11533 ssl2.SetNextProto(GetParam());
11534 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11535 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11536 data2.get());
11538 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11539 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11540 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11542 scoped_refptr<HttpNetworkSession> session(
11543 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11545 // Start the first transaction to set up the SpdySession
11546 HttpRequestInfo request1;
11547 request1.method = "GET";
11548 request1.url = GURL(url1);
11549 request1.load_flags = 0;
11550 HttpNetworkTransaction trans1(LOWEST, session.get());
11551 TestCompletionCallback callback1;
11552 ASSERT_EQ(ERR_IO_PENDING,
11553 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11554 data1->RunFor(3);
11556 ASSERT_TRUE(callback1.have_result());
11557 EXPECT_EQ(OK, callback1.WaitForResult());
11558 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11560 // Now, start the HTTP request
11561 HttpRequestInfo request2;
11562 request2.method = "GET";
11563 request2.url = GURL(url2);
11564 request2.load_flags = 0;
11565 HttpNetworkTransaction trans2(MEDIUM, session.get());
11566 TestCompletionCallback callback2;
11567 EXPECT_EQ(ERR_IO_PENDING,
11568 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11569 base::MessageLoop::current()->RunUntilIdle();
11570 data2->RunFor(3);
11572 ASSERT_TRUE(callback2.have_result());
11573 EXPECT_EQ(OK, callback2.WaitForResult());
11574 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11577 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11578 // error) in SPDY session, removes the socket from pool and closes the SPDY
11579 // session. Verify that new url's from the same HttpNetworkSession (and a new
11580 // SpdySession) do work. http://crbug.com/224701
11581 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11582 const std::string https_url = "https://www.google.com/";
11584 MockRead reads1[] = {
11585 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11588 scoped_ptr<DeterministicSocketData> data1(
11589 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11590 data1->SetStop(1);
11592 scoped_ptr<SpdyFrame> req2(
11593 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11594 MockWrite writes2[] = {
11595 CreateMockWrite(*req2, 0),
11598 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11599 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11600 MockRead reads2[] = {
11601 CreateMockRead(*resp2, 1),
11602 CreateMockRead(*body2, 2),
11603 MockRead(ASYNC, OK, 3) // EOF
11606 scoped_ptr<DeterministicSocketData> data2(
11607 new DeterministicSocketData(reads2, arraysize(reads2),
11608 writes2, arraysize(writes2)));
11610 SSLSocketDataProvider ssl1(ASYNC, OK);
11611 ssl1.SetNextProto(GetParam());
11612 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11613 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11614 data1.get());
11616 SSLSocketDataProvider ssl2(ASYNC, OK);
11617 ssl2.SetNextProto(GetParam());
11618 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11619 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11620 data2.get());
11622 scoped_refptr<HttpNetworkSession> session(
11623 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11625 // Start the first transaction to set up the SpdySession and verify that
11626 // connection was closed.
11627 HttpRequestInfo request1;
11628 request1.method = "GET";
11629 request1.url = GURL(https_url);
11630 request1.load_flags = 0;
11631 HttpNetworkTransaction trans1(MEDIUM, session.get());
11632 TestCompletionCallback callback1;
11633 EXPECT_EQ(ERR_IO_PENDING,
11634 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11635 base::MessageLoop::current()->RunUntilIdle();
11636 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11638 // Now, start the second request and make sure it succeeds.
11639 HttpRequestInfo request2;
11640 request2.method = "GET";
11641 request2.url = GURL(https_url);
11642 request2.load_flags = 0;
11643 HttpNetworkTransaction trans2(MEDIUM, session.get());
11644 TestCompletionCallback callback2;
11645 EXPECT_EQ(ERR_IO_PENDING,
11646 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11647 base::MessageLoop::current()->RunUntilIdle();
11648 data2->RunFor(3);
11650 ASSERT_TRUE(callback2.have_result());
11651 EXPECT_EQ(OK, callback2.WaitForResult());
11652 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11655 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11656 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11657 ClientSocketPoolManager::set_max_sockets_per_group(
11658 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11659 ClientSocketPoolManager::set_max_sockets_per_pool(
11660 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11662 // Use two different hosts with different IPs so they don't get pooled.
11663 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11664 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11665 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11667 SSLSocketDataProvider ssl1(ASYNC, OK);
11668 ssl1.SetNextProto(GetParam());
11669 SSLSocketDataProvider ssl2(ASYNC, OK);
11670 ssl2.SetNextProto(GetParam());
11671 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11674 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11675 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11676 MockWrite spdy1_writes[] = {
11677 CreateMockWrite(*host1_req, 1),
11679 scoped_ptr<SpdyFrame> host1_resp(
11680 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11681 scoped_ptr<SpdyFrame> host1_resp_body(
11682 spdy_util_.ConstructSpdyBodyFrame(1, true));
11683 MockRead spdy1_reads[] = {
11684 CreateMockRead(*host1_resp, 2),
11685 CreateMockRead(*host1_resp_body, 3),
11686 MockRead(ASYNC, ERR_IO_PENDING, 4),
11689 scoped_ptr<OrderedSocketData> spdy1_data(
11690 new OrderedSocketData(
11691 spdy1_reads, arraysize(spdy1_reads),
11692 spdy1_writes, arraysize(spdy1_writes)));
11693 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11695 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11696 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11697 MockWrite spdy2_writes[] = {
11698 CreateMockWrite(*host2_req, 1),
11700 scoped_ptr<SpdyFrame> host2_resp(
11701 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11702 scoped_ptr<SpdyFrame> host2_resp_body(
11703 spdy_util_.ConstructSpdyBodyFrame(1, true));
11704 MockRead spdy2_reads[] = {
11705 CreateMockRead(*host2_resp, 2),
11706 CreateMockRead(*host2_resp_body, 3),
11707 MockRead(ASYNC, ERR_IO_PENDING, 4),
11710 scoped_ptr<OrderedSocketData> spdy2_data(
11711 new OrderedSocketData(
11712 spdy2_reads, arraysize(spdy2_reads),
11713 spdy2_writes, arraysize(spdy2_writes)));
11714 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11716 MockWrite http_write[] = {
11717 MockWrite("GET / HTTP/1.1\r\n"
11718 "Host: www.a.com\r\n"
11719 "Connection: keep-alive\r\n\r\n"),
11722 MockRead http_read[] = {
11723 MockRead("HTTP/1.1 200 OK\r\n"),
11724 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11725 MockRead("Content-Length: 6\r\n\r\n"),
11726 MockRead("hello!"),
11728 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11729 http_write, arraysize(http_write));
11730 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11732 HostPortPair host_port_pair_a("www.a.com", 443);
11733 SpdySessionKey spdy_session_key_a(
11734 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11735 EXPECT_FALSE(
11736 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11738 TestCompletionCallback callback;
11739 HttpRequestInfo request1;
11740 request1.method = "GET";
11741 request1.url = GURL("https://www.a.com/");
11742 request1.load_flags = 0;
11743 scoped_ptr<HttpNetworkTransaction> trans(
11744 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11746 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11747 EXPECT_EQ(ERR_IO_PENDING, rv);
11748 EXPECT_EQ(OK, callback.WaitForResult());
11750 const HttpResponseInfo* response = trans->GetResponseInfo();
11751 ASSERT_TRUE(response != NULL);
11752 ASSERT_TRUE(response->headers.get() != NULL);
11753 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11754 EXPECT_TRUE(response->was_fetched_via_spdy);
11755 EXPECT_TRUE(response->was_npn_negotiated);
11757 std::string response_data;
11758 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11759 EXPECT_EQ("hello!", response_data);
11760 trans.reset();
11761 EXPECT_TRUE(
11762 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11764 HostPortPair host_port_pair_b("www.b.com", 443);
11765 SpdySessionKey spdy_session_key_b(
11766 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11767 EXPECT_FALSE(
11768 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11769 HttpRequestInfo request2;
11770 request2.method = "GET";
11771 request2.url = GURL("https://www.b.com/");
11772 request2.load_flags = 0;
11773 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11775 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11776 EXPECT_EQ(ERR_IO_PENDING, rv);
11777 EXPECT_EQ(OK, callback.WaitForResult());
11779 response = trans->GetResponseInfo();
11780 ASSERT_TRUE(response != NULL);
11781 ASSERT_TRUE(response->headers.get() != NULL);
11782 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11783 EXPECT_TRUE(response->was_fetched_via_spdy);
11784 EXPECT_TRUE(response->was_npn_negotiated);
11785 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11786 EXPECT_EQ("hello!", response_data);
11787 EXPECT_FALSE(
11788 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11789 EXPECT_TRUE(
11790 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11792 HostPortPair host_port_pair_a1("www.a.com", 80);
11793 SpdySessionKey spdy_session_key_a1(
11794 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11795 EXPECT_FALSE(
11796 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11797 HttpRequestInfo request3;
11798 request3.method = "GET";
11799 request3.url = GURL("http://www.a.com/");
11800 request3.load_flags = 0;
11801 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11803 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11804 EXPECT_EQ(ERR_IO_PENDING, rv);
11805 EXPECT_EQ(OK, callback.WaitForResult());
11807 response = trans->GetResponseInfo();
11808 ASSERT_TRUE(response != NULL);
11809 ASSERT_TRUE(response->headers.get() != NULL);
11810 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11811 EXPECT_FALSE(response->was_fetched_via_spdy);
11812 EXPECT_FALSE(response->was_npn_negotiated);
11813 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11814 EXPECT_EQ("hello!", response_data);
11815 EXPECT_FALSE(
11816 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11817 EXPECT_FALSE(
11818 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11821 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11822 HttpRequestInfo request;
11823 request.method = "GET";
11824 request.url = GURL("http://www.google.com/");
11825 request.load_flags = 0;
11827 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11828 scoped_ptr<HttpTransaction> trans(
11829 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11831 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11832 StaticSocketDataProvider data;
11833 data.set_connect_data(mock_connect);
11834 session_deps_.socket_factory->AddSocketDataProvider(&data);
11836 TestCompletionCallback callback;
11838 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11839 EXPECT_EQ(ERR_IO_PENDING, rv);
11841 rv = callback.WaitForResult();
11842 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11844 EXPECT_EQ(NULL, trans->GetResponseInfo());
11846 // We don't care whether this succeeds or fails, but it shouldn't crash.
11847 HttpRequestHeaders request_headers;
11848 trans->GetFullRequestHeaders(&request_headers);
11851 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11852 HttpRequestInfo request;
11853 request.method = "GET";
11854 request.url = GURL("http://www.google.com/");
11855 request.load_flags = 0;
11857 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11858 scoped_ptr<HttpTransaction> trans(
11859 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11861 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11862 StaticSocketDataProvider data;
11863 data.set_connect_data(mock_connect);
11864 session_deps_.socket_factory->AddSocketDataProvider(&data);
11866 TestCompletionCallback callback;
11868 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11869 EXPECT_EQ(ERR_IO_PENDING, rv);
11871 rv = callback.WaitForResult();
11872 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11874 EXPECT_EQ(NULL, trans->GetResponseInfo());
11876 // We don't care whether this succeeds or fails, but it shouldn't crash.
11877 HttpRequestHeaders request_headers;
11878 trans->GetFullRequestHeaders(&request_headers);
11881 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
11882 HttpRequestInfo request;
11883 request.method = "GET";
11884 request.url = GURL("http://www.google.com/");
11885 request.load_flags = 0;
11887 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11888 scoped_ptr<HttpTransaction> trans(
11889 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11891 MockWrite data_writes[] = {
11892 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
11894 MockRead data_reads[] = {
11895 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11898 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11899 data_writes, arraysize(data_writes));
11900 session_deps_.socket_factory->AddSocketDataProvider(&data);
11902 TestCompletionCallback callback;
11904 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11905 EXPECT_EQ(ERR_IO_PENDING, rv);
11907 rv = callback.WaitForResult();
11908 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11910 EXPECT_EQ(NULL, trans->GetResponseInfo());
11912 HttpRequestHeaders request_headers;
11913 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11914 EXPECT_TRUE(request_headers.HasHeader("Host"));
11917 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
11918 HttpRequestInfo request;
11919 request.method = "GET";
11920 request.url = GURL("http://www.google.com/");
11921 request.load_flags = 0;
11923 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11924 scoped_ptr<HttpTransaction> trans(
11925 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11927 MockWrite data_writes[] = {
11928 MockWrite(ASYNC, ERR_CONNECTION_RESET),
11930 MockRead data_reads[] = {
11931 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11934 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11935 data_writes, arraysize(data_writes));
11936 session_deps_.socket_factory->AddSocketDataProvider(&data);
11938 TestCompletionCallback callback;
11940 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11941 EXPECT_EQ(ERR_IO_PENDING, rv);
11943 rv = callback.WaitForResult();
11944 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11946 EXPECT_EQ(NULL, trans->GetResponseInfo());
11948 HttpRequestHeaders request_headers;
11949 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11950 EXPECT_TRUE(request_headers.HasHeader("Host"));
11953 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
11954 HttpRequestInfo request;
11955 request.method = "GET";
11956 request.url = GURL("http://www.google.com/");
11957 request.load_flags = 0;
11959 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11960 scoped_ptr<HttpTransaction> trans(
11961 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11963 MockWrite data_writes[] = {
11964 MockWrite("GET / HTTP/1.1\r\n"
11965 "Host: www.google.com\r\n"
11966 "Connection: keep-alive\r\n\r\n"),
11968 MockRead data_reads[] = {
11969 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
11972 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11973 data_writes, arraysize(data_writes));
11974 session_deps_.socket_factory->AddSocketDataProvider(&data);
11976 TestCompletionCallback callback;
11978 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11979 EXPECT_EQ(ERR_IO_PENDING, rv);
11981 rv = callback.WaitForResult();
11982 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11984 EXPECT_EQ(NULL, trans->GetResponseInfo());
11986 HttpRequestHeaders request_headers;
11987 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11988 EXPECT_TRUE(request_headers.HasHeader("Host"));
11991 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
11992 HttpRequestInfo request;
11993 request.method = "GET";
11994 request.url = GURL("http://www.google.com/");
11995 request.load_flags = 0;
11997 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11998 scoped_ptr<HttpTransaction> trans(
11999 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12001 MockWrite data_writes[] = {
12002 MockWrite("GET / HTTP/1.1\r\n"
12003 "Host: www.google.com\r\n"
12004 "Connection: keep-alive\r\n\r\n"),
12006 MockRead data_reads[] = {
12007 MockRead(ASYNC, ERR_CONNECTION_RESET),
12010 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12011 data_writes, arraysize(data_writes));
12012 session_deps_.socket_factory->AddSocketDataProvider(&data);
12014 TestCompletionCallback callback;
12016 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12017 EXPECT_EQ(ERR_IO_PENDING, rv);
12019 rv = callback.WaitForResult();
12020 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12022 EXPECT_EQ(NULL, trans->GetResponseInfo());
12024 HttpRequestHeaders request_headers;
12025 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12026 EXPECT_TRUE(request_headers.HasHeader("Host"));
12029 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12030 HttpRequestInfo request;
12031 request.method = "GET";
12032 request.url = GURL("http://www.google.com/");
12033 request.load_flags = 0;
12034 request.extra_headers.SetHeader("X-Foo", "bar");
12036 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12037 scoped_ptr<HttpTransaction> trans(
12038 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12040 MockWrite data_writes[] = {
12041 MockWrite("GET / HTTP/1.1\r\n"
12042 "Host: www.google.com\r\n"
12043 "Connection: keep-alive\r\n"
12044 "X-Foo: bar\r\n\r\n"),
12046 MockRead data_reads[] = {
12047 MockRead("HTTP/1.1 200 OK\r\n"
12048 "Content-Length: 5\r\n\r\n"
12049 "hello"),
12050 MockRead(ASYNC, ERR_UNEXPECTED),
12053 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12054 data_writes, arraysize(data_writes));
12055 session_deps_.socket_factory->AddSocketDataProvider(&data);
12057 TestCompletionCallback callback;
12059 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12060 EXPECT_EQ(ERR_IO_PENDING, rv);
12062 rv = callback.WaitForResult();
12063 EXPECT_EQ(OK, rv);
12065 HttpRequestHeaders request_headers;
12066 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12067 std::string foo;
12068 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12069 EXPECT_EQ("bar", foo);
12072 namespace {
12074 // Fake HttpStreamBase that simply records calls to SetPriority().
12075 class FakeStream : public HttpStreamBase,
12076 public base::SupportsWeakPtr<FakeStream> {
12077 public:
12078 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12079 virtual ~FakeStream() {}
12081 RequestPriority priority() const { return priority_; }
12083 virtual int InitializeStream(const HttpRequestInfo* request_info,
12084 RequestPriority priority,
12085 const BoundNetLog& net_log,
12086 const CompletionCallback& callback) OVERRIDE {
12087 return ERR_IO_PENDING;
12090 virtual int SendRequest(const HttpRequestHeaders& request_headers,
12091 HttpResponseInfo* response,
12092 const CompletionCallback& callback) OVERRIDE {
12093 ADD_FAILURE();
12094 return ERR_UNEXPECTED;
12097 virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
12098 ADD_FAILURE();
12099 return ERR_UNEXPECTED;
12102 virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
12103 ADD_FAILURE();
12104 return NULL;
12107 virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
12108 const CompletionCallback& callback) OVERRIDE {
12109 ADD_FAILURE();
12110 return ERR_UNEXPECTED;
12113 virtual void Close(bool not_reusable) OVERRIDE {}
12115 virtual bool IsResponseBodyComplete() const OVERRIDE {
12116 ADD_FAILURE();
12117 return false;
12120 virtual bool CanFindEndOfResponse() const OVERRIDE {
12121 return false;
12124 virtual bool IsConnectionReused() const OVERRIDE {
12125 ADD_FAILURE();
12126 return false;
12129 virtual void SetConnectionReused() OVERRIDE {
12130 ADD_FAILURE();
12133 virtual bool IsConnectionReusable() const OVERRIDE {
12134 ADD_FAILURE();
12135 return false;
12138 virtual int64 GetTotalReceivedBytes() const OVERRIDE {
12139 ADD_FAILURE();
12140 return 0;
12143 virtual bool GetLoadTimingInfo(
12144 LoadTimingInfo* load_timing_info) const OVERRIDE {
12145 ADD_FAILURE();
12146 return false;
12149 virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
12150 ADD_FAILURE();
12153 virtual void GetSSLCertRequestInfo(
12154 SSLCertRequestInfo* cert_request_info) OVERRIDE {
12155 ADD_FAILURE();
12158 virtual bool IsSpdyHttpStream() const OVERRIDE {
12159 ADD_FAILURE();
12160 return false;
12163 virtual void Drain(HttpNetworkSession* session) OVERRIDE {
12164 ADD_FAILURE();
12167 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12168 priority_ = priority;
12171 private:
12172 RequestPriority priority_;
12174 DISALLOW_COPY_AND_ASSIGN(FakeStream);
12177 // Fake HttpStreamRequest that simply records calls to SetPriority()
12178 // and vends FakeStreams with its current priority.
12179 class FakeStreamRequest : public HttpStreamRequest,
12180 public base::SupportsWeakPtr<FakeStreamRequest> {
12181 public:
12182 FakeStreamRequest(RequestPriority priority,
12183 HttpStreamRequest::Delegate* delegate)
12184 : priority_(priority),
12185 delegate_(delegate),
12186 websocket_stream_create_helper_(NULL) {}
12188 FakeStreamRequest(RequestPriority priority,
12189 HttpStreamRequest::Delegate* delegate,
12190 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
12191 : priority_(priority),
12192 delegate_(delegate),
12193 websocket_stream_create_helper_(create_helper) {}
12195 virtual ~FakeStreamRequest() {}
12197 RequestPriority priority() const { return priority_; }
12199 const WebSocketHandshakeStreamBase::CreateHelper*
12200 websocket_stream_create_helper() const {
12201 return websocket_stream_create_helper_;
12204 // Create a new FakeStream and pass it to the request's
12205 // delegate. Returns a weak pointer to the FakeStream.
12206 base::WeakPtr<FakeStream> FinishStreamRequest() {
12207 FakeStream* fake_stream = new FakeStream(priority_);
12208 // Do this before calling OnStreamReady() as OnStreamReady() may
12209 // immediately delete |fake_stream|.
12210 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
12211 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
12212 return weak_stream;
12215 virtual int RestartTunnelWithProxyAuth(
12216 const AuthCredentials& credentials) OVERRIDE {
12217 ADD_FAILURE();
12218 return ERR_UNEXPECTED;
12221 virtual LoadState GetLoadState() const OVERRIDE {
12222 ADD_FAILURE();
12223 return LoadState();
12226 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12227 priority_ = priority;
12230 virtual bool was_npn_negotiated() const OVERRIDE {
12231 return false;
12234 virtual NextProto protocol_negotiated() const OVERRIDE {
12235 return kProtoUnknown;
12238 virtual bool using_spdy() const OVERRIDE {
12239 return false;
12242 private:
12243 RequestPriority priority_;
12244 HttpStreamRequest::Delegate* const delegate_;
12245 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
12247 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12250 // Fake HttpStreamFactory that vends FakeStreamRequests.
12251 class FakeStreamFactory : public HttpStreamFactory {
12252 public:
12253 FakeStreamFactory() {}
12254 virtual ~FakeStreamFactory() {}
12256 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12257 // RequestStream() (which may be NULL if it was destroyed already).
12258 base::WeakPtr<FakeStreamRequest> last_stream_request() {
12259 return last_stream_request_;
12262 virtual HttpStreamRequest* RequestStream(
12263 const HttpRequestInfo& info,
12264 RequestPriority priority,
12265 const SSLConfig& server_ssl_config,
12266 const SSLConfig& proxy_ssl_config,
12267 HttpStreamRequest::Delegate* delegate,
12268 const BoundNetLog& net_log) OVERRIDE {
12269 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12270 last_stream_request_ = fake_request->AsWeakPtr();
12271 return fake_request;
12274 virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
12275 const HttpRequestInfo& info,
12276 RequestPriority priority,
12277 const SSLConfig& server_ssl_config,
12278 const SSLConfig& proxy_ssl_config,
12279 HttpStreamRequest::Delegate* delegate,
12280 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
12281 const BoundNetLog& net_log) OVERRIDE {
12282 FakeStreamRequest* fake_request =
12283 new FakeStreamRequest(priority, delegate, create_helper);
12284 last_stream_request_ = fake_request->AsWeakPtr();
12285 return fake_request;
12288 virtual void PreconnectStreams(int num_streams,
12289 const HttpRequestInfo& info,
12290 RequestPriority priority,
12291 const SSLConfig& server_ssl_config,
12292 const SSLConfig& proxy_ssl_config) OVERRIDE {
12293 ADD_FAILURE();
12296 virtual base::Value* PipelineInfoToValue() const OVERRIDE {
12297 ADD_FAILURE();
12298 return NULL;
12301 virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
12302 ADD_FAILURE();
12303 return NULL;
12306 private:
12307 base::WeakPtr<FakeStreamRequest> last_stream_request_;
12309 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12312 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12313 // worth doing.
12314 class FakeWebSocketStreamCreateHelper :
12315 public WebSocketHandshakeStreamBase::CreateHelper {
12316 public:
12317 virtual WebSocketHandshakeStreamBase* CreateBasicStream(
12318 scoped_ptr<ClientSocketHandle> connection,
12319 bool using_proxy) OVERRIDE {
12320 NOTREACHED();
12321 return NULL;
12324 virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
12325 const base::WeakPtr<SpdySession>& session,
12326 bool use_relative_url) OVERRIDE {
12327 NOTREACHED();
12328 return NULL;
12331 virtual ~FakeWebSocketStreamCreateHelper() {}
12333 virtual scoped_ptr<WebSocketStream> Upgrade() {
12334 NOTREACHED();
12335 return scoped_ptr<WebSocketStream>();
12339 } // namespace
12341 // Make sure that HttpNetworkTransaction passes on its priority to its
12342 // stream request on start.
12343 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
12344 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12345 HttpNetworkSessionPeer peer(session);
12346 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12347 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12349 HttpNetworkTransaction trans(LOW, session);
12351 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
12353 HttpRequestInfo request;
12354 TestCompletionCallback callback;
12355 EXPECT_EQ(ERR_IO_PENDING,
12356 trans.Start(&request, callback.callback(), BoundNetLog()));
12358 base::WeakPtr<FakeStreamRequest> fake_request =
12359 fake_factory->last_stream_request();
12360 ASSERT_TRUE(fake_request != NULL);
12361 EXPECT_EQ(LOW, fake_request->priority());
12364 // Make sure that HttpNetworkTransaction passes on its priority
12365 // updates to its stream request.
12366 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
12367 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12368 HttpNetworkSessionPeer peer(session);
12369 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12370 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12372 HttpNetworkTransaction trans(LOW, session);
12374 HttpRequestInfo request;
12375 TestCompletionCallback callback;
12376 EXPECT_EQ(ERR_IO_PENDING,
12377 trans.Start(&request, callback.callback(), BoundNetLog()));
12379 base::WeakPtr<FakeStreamRequest> fake_request =
12380 fake_factory->last_stream_request();
12381 ASSERT_TRUE(fake_request != NULL);
12382 EXPECT_EQ(LOW, fake_request->priority());
12384 trans.SetPriority(LOWEST);
12385 ASSERT_TRUE(fake_request != NULL);
12386 EXPECT_EQ(LOWEST, fake_request->priority());
12389 // Make sure that HttpNetworkTransaction passes on its priority
12390 // updates to its stream.
12391 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
12392 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12393 HttpNetworkSessionPeer peer(session);
12394 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12395 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12397 HttpNetworkTransaction trans(LOW, session);
12399 HttpRequestInfo request;
12400 TestCompletionCallback callback;
12401 EXPECT_EQ(ERR_IO_PENDING,
12402 trans.Start(&request, callback.callback(), BoundNetLog()));
12404 base::WeakPtr<FakeStreamRequest> fake_request =
12405 fake_factory->last_stream_request();
12406 ASSERT_TRUE(fake_request != NULL);
12407 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
12408 ASSERT_TRUE(fake_stream != NULL);
12409 EXPECT_EQ(LOW, fake_stream->priority());
12411 trans.SetPriority(LOWEST);
12412 EXPECT_EQ(LOWEST, fake_stream->priority());
12415 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
12416 // The same logic needs to be tested for both ws: and wss: schemes, but this
12417 // test is already parameterised on NextProto, so it uses a loop to verify
12418 // that the different schemes work.
12419 std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"};
12420 for (size_t i = 0; i < arraysize(test_cases); ++i) {
12421 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12422 HttpNetworkSessionPeer peer(session);
12423 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12424 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
12425 peer.SetHttpStreamFactoryForWebSocket(
12426 scoped_ptr<HttpStreamFactory>(fake_factory));
12428 HttpNetworkTransaction trans(LOW, session);
12429 trans.SetWebSocketHandshakeStreamCreateHelper(
12430 &websocket_stream_create_helper);
12432 HttpRequestInfo request;
12433 TestCompletionCallback callback;
12434 request.method = "GET";
12435 request.url = GURL(test_cases[i]);
12437 EXPECT_EQ(ERR_IO_PENDING,
12438 trans.Start(&request, callback.callback(), BoundNetLog()));
12440 base::WeakPtr<FakeStreamRequest> fake_request =
12441 fake_factory->last_stream_request();
12442 ASSERT_TRUE(fake_request != NULL);
12443 EXPECT_EQ(&websocket_stream_create_helper,
12444 fake_request->websocket_stream_create_helper());
12448 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12449 // if the transport socket pool is stalled on the global socket limit.
12450 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
12451 ClientSocketPoolManager::set_max_sockets_per_group(
12452 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12453 ClientSocketPoolManager::set_max_sockets_per_pool(
12454 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12456 // Set up SSL request.
12458 HttpRequestInfo ssl_request;
12459 ssl_request.method = "GET";
12460 ssl_request.url = GURL("https://www.google.com/");
12462 MockWrite ssl_writes[] = {
12463 MockWrite("GET / HTTP/1.1\r\n"
12464 "Host: www.google.com\r\n"
12465 "Connection: keep-alive\r\n\r\n"),
12467 MockRead ssl_reads[] = {
12468 MockRead("HTTP/1.1 200 OK\r\n"),
12469 MockRead("Content-Length: 11\r\n\r\n"),
12470 MockRead("hello world"),
12471 MockRead(SYNCHRONOUS, OK),
12473 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
12474 ssl_writes, arraysize(ssl_writes));
12475 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12477 SSLSocketDataProvider ssl(ASYNC, OK);
12478 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12480 // Set up HTTP request.
12482 HttpRequestInfo http_request;
12483 http_request.method = "GET";
12484 http_request.url = GURL("http://www.google.com/");
12486 MockWrite http_writes[] = {
12487 MockWrite("GET / HTTP/1.1\r\n"
12488 "Host: www.google.com\r\n"
12489 "Connection: keep-alive\r\n\r\n"),
12491 MockRead http_reads[] = {
12492 MockRead("HTTP/1.1 200 OK\r\n"),
12493 MockRead("Content-Length: 7\r\n\r\n"),
12494 MockRead("falafel"),
12495 MockRead(SYNCHRONOUS, OK),
12497 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12498 http_writes, arraysize(http_writes));
12499 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12501 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12503 // Start the SSL request.
12504 TestCompletionCallback ssl_callback;
12505 scoped_ptr<HttpTransaction> ssl_trans(
12506 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12507 ASSERT_EQ(ERR_IO_PENDING,
12508 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
12509 BoundNetLog()));
12511 // Start the HTTP request. Pool should stall.
12512 TestCompletionCallback http_callback;
12513 scoped_ptr<HttpTransaction> http_trans(
12514 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12515 ASSERT_EQ(ERR_IO_PENDING,
12516 http_trans->Start(&http_request, http_callback.callback(),
12517 BoundNetLog()));
12518 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12520 // Wait for response from SSL request.
12521 ASSERT_EQ(OK, ssl_callback.WaitForResult());
12522 std::string response_data;
12523 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
12524 EXPECT_EQ("hello world", response_data);
12526 // The SSL socket should automatically be closed, so the HTTP request can
12527 // start.
12528 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12529 ASSERT_FALSE(IsTransportSocketPoolStalled(session));
12531 // The HTTP request can now complete.
12532 ASSERT_EQ(OK, http_callback.WaitForResult());
12533 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12534 EXPECT_EQ("falafel", response_data);
12536 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12539 // Tests that when a SSL connection is established but there's no corresponding
12540 // request that needs it, the new socket is closed if the transport socket pool
12541 // is stalled on the global socket limit.
12542 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
12543 ClientSocketPoolManager::set_max_sockets_per_group(
12544 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12545 ClientSocketPoolManager::set_max_sockets_per_pool(
12546 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12548 // Set up an ssl request.
12550 HttpRequestInfo ssl_request;
12551 ssl_request.method = "GET";
12552 ssl_request.url = GURL("https://www.foopy.com/");
12554 // No data will be sent on the SSL socket.
12555 StaticSocketDataProvider ssl_data;
12556 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12558 SSLSocketDataProvider ssl(ASYNC, OK);
12559 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12561 // Set up HTTP request.
12563 HttpRequestInfo http_request;
12564 http_request.method = "GET";
12565 http_request.url = GURL("http://www.google.com/");
12567 MockWrite http_writes[] = {
12568 MockWrite("GET / HTTP/1.1\r\n"
12569 "Host: www.google.com\r\n"
12570 "Connection: keep-alive\r\n\r\n"),
12572 MockRead http_reads[] = {
12573 MockRead("HTTP/1.1 200 OK\r\n"),
12574 MockRead("Content-Length: 7\r\n\r\n"),
12575 MockRead("falafel"),
12576 MockRead(SYNCHRONOUS, OK),
12578 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12579 http_writes, arraysize(http_writes));
12580 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12582 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12584 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12585 // cancelled when a normal transaction is cancelled.
12586 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
12587 net::SSLConfig ssl_config;
12588 session->ssl_config_service()->GetSSLConfig(&ssl_config);
12589 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
12590 ssl_config, ssl_config);
12591 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12593 // Start the HTTP request. Pool should stall.
12594 TestCompletionCallback http_callback;
12595 scoped_ptr<HttpTransaction> http_trans(
12596 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12597 ASSERT_EQ(ERR_IO_PENDING,
12598 http_trans->Start(&http_request, http_callback.callback(),
12599 BoundNetLog()));
12600 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12602 // The SSL connection will automatically be closed once the connection is
12603 // established, to let the HTTP request start.
12604 ASSERT_EQ(OK, http_callback.WaitForResult());
12605 std::string response_data;
12606 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12607 EXPECT_EQ("falafel", response_data);
12609 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12612 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
12613 ScopedVector<UploadElementReader> element_readers;
12614 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12615 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12617 HttpRequestInfo request;
12618 request.method = "POST";
12619 request.url = GURL("http://www.foo.com/");
12620 request.upload_data_stream = &upload_data_stream;
12621 request.load_flags = 0;
12623 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12624 scoped_ptr<HttpTransaction> trans(
12625 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12626 // Send headers successfully, but get an error while sending the body.
12627 MockWrite data_writes[] = {
12628 MockWrite("POST / HTTP/1.1\r\n"
12629 "Host: www.foo.com\r\n"
12630 "Connection: keep-alive\r\n"
12631 "Content-Length: 3\r\n\r\n"),
12632 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12635 MockRead data_reads[] = {
12636 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12637 MockRead("hello world"),
12638 MockRead(SYNCHRONOUS, OK),
12640 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12641 arraysize(data_writes));
12642 session_deps_.socket_factory->AddSocketDataProvider(&data);
12644 TestCompletionCallback callback;
12646 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12647 EXPECT_EQ(ERR_IO_PENDING, rv);
12649 rv = callback.WaitForResult();
12650 EXPECT_EQ(OK, rv);
12652 const HttpResponseInfo* response = trans->GetResponseInfo();
12653 ASSERT_TRUE(response != NULL);
12655 EXPECT_TRUE(response->headers.get() != NULL);
12656 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12658 std::string response_data;
12659 rv = ReadTransaction(trans.get(), &response_data);
12660 EXPECT_EQ(OK, rv);
12661 EXPECT_EQ("hello world", response_data);
12664 // This test makes sure the retry logic doesn't trigger when reading an error
12665 // response from a server that rejected a POST with a CONNECTION_RESET.
12666 TEST_P(HttpNetworkTransactionTest,
12667 PostReadsErrorResponseAfterResetOnReusedSocket) {
12668 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12669 MockWrite data_writes[] = {
12670 MockWrite("GET / HTTP/1.1\r\n"
12671 "Host: www.foo.com\r\n"
12672 "Connection: keep-alive\r\n\r\n"),
12673 MockWrite("POST / HTTP/1.1\r\n"
12674 "Host: www.foo.com\r\n"
12675 "Connection: keep-alive\r\n"
12676 "Content-Length: 3\r\n\r\n"),
12677 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12680 MockRead data_reads[] = {
12681 MockRead("HTTP/1.1 200 Peachy\r\n"
12682 "Content-Length: 14\r\n\r\n"),
12683 MockRead("first response"),
12684 MockRead("HTTP/1.1 400 Not OK\r\n"
12685 "Content-Length: 15\r\n\r\n"),
12686 MockRead("second response"),
12687 MockRead(SYNCHRONOUS, OK),
12689 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12690 arraysize(data_writes));
12691 session_deps_.socket_factory->AddSocketDataProvider(&data);
12693 TestCompletionCallback callback;
12694 HttpRequestInfo request1;
12695 request1.method = "GET";
12696 request1.url = GURL("http://www.foo.com/");
12697 request1.load_flags = 0;
12699 scoped_ptr<HttpTransaction> trans1(
12700 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12701 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
12702 EXPECT_EQ(ERR_IO_PENDING, rv);
12704 rv = callback.WaitForResult();
12705 EXPECT_EQ(OK, rv);
12707 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12708 ASSERT_TRUE(response1 != NULL);
12710 EXPECT_TRUE(response1->headers.get() != NULL);
12711 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
12713 std::string response_data1;
12714 rv = ReadTransaction(trans1.get(), &response_data1);
12715 EXPECT_EQ(OK, rv);
12716 EXPECT_EQ("first response", response_data1);
12717 // Delete the transaction to release the socket back into the socket pool.
12718 trans1.reset();
12720 ScopedVector<UploadElementReader> element_readers;
12721 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12722 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12724 HttpRequestInfo request2;
12725 request2.method = "POST";
12726 request2.url = GURL("http://www.foo.com/");
12727 request2.upload_data_stream = &upload_data_stream;
12728 request2.load_flags = 0;
12730 scoped_ptr<HttpTransaction> trans2(
12731 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12732 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
12733 EXPECT_EQ(ERR_IO_PENDING, rv);
12735 rv = callback.WaitForResult();
12736 EXPECT_EQ(OK, rv);
12738 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
12739 ASSERT_TRUE(response2 != NULL);
12741 EXPECT_TRUE(response2->headers.get() != NULL);
12742 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
12744 std::string response_data2;
12745 rv = ReadTransaction(trans2.get(), &response_data2);
12746 EXPECT_EQ(OK, rv);
12747 EXPECT_EQ("second response", response_data2);
12750 TEST_P(HttpNetworkTransactionTest,
12751 PostReadsErrorResponseAfterResetPartialBodySent) {
12752 ScopedVector<UploadElementReader> element_readers;
12753 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12754 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12756 HttpRequestInfo request;
12757 request.method = "POST";
12758 request.url = GURL("http://www.foo.com/");
12759 request.upload_data_stream = &upload_data_stream;
12760 request.load_flags = 0;
12762 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12763 scoped_ptr<HttpTransaction> trans(
12764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12765 // Send headers successfully, but get an error while sending the body.
12766 MockWrite data_writes[] = {
12767 MockWrite("POST / HTTP/1.1\r\n"
12768 "Host: www.foo.com\r\n"
12769 "Connection: keep-alive\r\n"
12770 "Content-Length: 3\r\n\r\n"
12771 "fo"),
12772 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12775 MockRead data_reads[] = {
12776 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12777 MockRead("hello world"),
12778 MockRead(SYNCHRONOUS, OK),
12780 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12781 arraysize(data_writes));
12782 session_deps_.socket_factory->AddSocketDataProvider(&data);
12784 TestCompletionCallback callback;
12786 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12787 EXPECT_EQ(ERR_IO_PENDING, rv);
12789 rv = callback.WaitForResult();
12790 EXPECT_EQ(OK, rv);
12792 const HttpResponseInfo* response = trans->GetResponseInfo();
12793 ASSERT_TRUE(response != NULL);
12795 EXPECT_TRUE(response->headers.get() != NULL);
12796 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12798 std::string response_data;
12799 rv = ReadTransaction(trans.get(), &response_data);
12800 EXPECT_EQ(OK, rv);
12801 EXPECT_EQ("hello world", response_data);
12804 // This tests the more common case than the previous test, where headers and
12805 // body are not merged into a single request.
12806 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
12807 ScopedVector<UploadElementReader> element_readers;
12808 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12809 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
12811 HttpRequestInfo request;
12812 request.method = "POST";
12813 request.url = GURL("http://www.foo.com/");
12814 request.upload_data_stream = &upload_data_stream;
12815 request.load_flags = 0;
12817 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12818 scoped_ptr<HttpTransaction> trans(
12819 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12820 // Send headers successfully, but get an error while sending the body.
12821 MockWrite data_writes[] = {
12822 MockWrite("POST / HTTP/1.1\r\n"
12823 "Host: www.foo.com\r\n"
12824 "Connection: keep-alive\r\n"
12825 "Transfer-Encoding: chunked\r\n\r\n"),
12826 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12829 MockRead data_reads[] = {
12830 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12831 MockRead("hello world"),
12832 MockRead(SYNCHRONOUS, OK),
12834 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12835 arraysize(data_writes));
12836 session_deps_.socket_factory->AddSocketDataProvider(&data);
12838 TestCompletionCallback callback;
12840 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12841 EXPECT_EQ(ERR_IO_PENDING, rv);
12842 // Make sure the headers are sent before adding a chunk. This ensures that
12843 // they can't be merged with the body in a single send. Not currently
12844 // necessary since a chunked body is never merged with headers, but this makes
12845 // the test more future proof.
12846 base::RunLoop().RunUntilIdle();
12848 upload_data_stream.AppendChunk("last chunk", 10, true);
12850 rv = callback.WaitForResult();
12851 EXPECT_EQ(OK, rv);
12853 const HttpResponseInfo* response = trans->GetResponseInfo();
12854 ASSERT_TRUE(response != NULL);
12856 EXPECT_TRUE(response->headers.get() != NULL);
12857 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12859 std::string response_data;
12860 rv = ReadTransaction(trans.get(), &response_data);
12861 EXPECT_EQ(OK, rv);
12862 EXPECT_EQ("hello world", response_data);
12865 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
12866 ScopedVector<UploadElementReader> element_readers;
12867 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12868 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12870 HttpRequestInfo request;
12871 request.method = "POST";
12872 request.url = GURL("http://www.foo.com/");
12873 request.upload_data_stream = &upload_data_stream;
12874 request.load_flags = 0;
12876 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12877 scoped_ptr<HttpTransaction> trans(
12878 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12880 MockWrite data_writes[] = {
12881 MockWrite("POST / HTTP/1.1\r\n"
12882 "Host: www.foo.com\r\n"
12883 "Connection: keep-alive\r\n"
12884 "Content-Length: 3\r\n\r\n"),
12885 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12888 MockRead data_reads[] = {
12889 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12890 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12891 MockRead("hello world"),
12892 MockRead(SYNCHRONOUS, OK),
12894 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12895 arraysize(data_writes));
12896 session_deps_.socket_factory->AddSocketDataProvider(&data);
12898 TestCompletionCallback callback;
12900 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12901 EXPECT_EQ(ERR_IO_PENDING, rv);
12903 rv = callback.WaitForResult();
12904 EXPECT_EQ(OK, rv);
12906 const HttpResponseInfo* response = trans->GetResponseInfo();
12907 ASSERT_TRUE(response != NULL);
12909 EXPECT_TRUE(response->headers.get() != NULL);
12910 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12912 std::string response_data;
12913 rv = ReadTransaction(trans.get(), &response_data);
12914 EXPECT_EQ(OK, rv);
12915 EXPECT_EQ("hello world", response_data);
12918 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
12919 ScopedVector<UploadElementReader> element_readers;
12920 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12921 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12923 HttpRequestInfo request;
12924 request.method = "POST";
12925 request.url = GURL("http://www.foo.com/");
12926 request.upload_data_stream = &upload_data_stream;
12927 request.load_flags = 0;
12929 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12930 scoped_ptr<HttpTransaction> trans(
12931 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12932 // Send headers successfully, but get an error while sending the body.
12933 MockWrite data_writes[] = {
12934 MockWrite("POST / HTTP/1.1\r\n"
12935 "Host: www.foo.com\r\n"
12936 "Connection: keep-alive\r\n"
12937 "Content-Length: 3\r\n\r\n"),
12938 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12941 MockRead data_reads[] = {
12942 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
12943 MockRead("hello world"),
12944 MockRead(SYNCHRONOUS, OK),
12946 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12947 arraysize(data_writes));
12948 session_deps_.socket_factory->AddSocketDataProvider(&data);
12950 TestCompletionCallback callback;
12952 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12953 EXPECT_EQ(ERR_IO_PENDING, rv);
12955 rv = callback.WaitForResult();
12956 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12958 const HttpResponseInfo* response = trans->GetResponseInfo();
12959 EXPECT_TRUE(response == NULL);
12962 TEST_P(HttpNetworkTransactionTest,
12963 PostIgnoresNonErrorResponseAfterResetAnd100) {
12964 ScopedVector<UploadElementReader> element_readers;
12965 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12966 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12968 HttpRequestInfo request;
12969 request.method = "POST";
12970 request.url = GURL("http://www.foo.com/");
12971 request.upload_data_stream = &upload_data_stream;
12972 request.load_flags = 0;
12974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12975 scoped_ptr<HttpTransaction> trans(
12976 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12977 // Send headers successfully, but get an error while sending the body.
12978 MockWrite data_writes[] = {
12979 MockWrite("POST / HTTP/1.1\r\n"
12980 "Host: www.foo.com\r\n"
12981 "Connection: keep-alive\r\n"
12982 "Content-Length: 3\r\n\r\n"),
12983 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12986 MockRead data_reads[] = {
12987 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12988 MockRead("HTTP/1.0 302 Redirect\r\n"),
12989 MockRead("Location: http://somewhere-else.com/\r\n"),
12990 MockRead("Content-Length: 0\r\n\r\n"),
12991 MockRead(SYNCHRONOUS, OK),
12993 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12994 arraysize(data_writes));
12995 session_deps_.socket_factory->AddSocketDataProvider(&data);
12997 TestCompletionCallback callback;
12999 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13000 EXPECT_EQ(ERR_IO_PENDING, rv);
13002 rv = callback.WaitForResult();
13003 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13005 const HttpResponseInfo* response = trans->GetResponseInfo();
13006 EXPECT_TRUE(response == NULL);
13009 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
13010 ScopedVector<UploadElementReader> element_readers;
13011 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13012 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13014 HttpRequestInfo request;
13015 request.method = "POST";
13016 request.url = GURL("http://www.foo.com/");
13017 request.upload_data_stream = &upload_data_stream;
13018 request.load_flags = 0;
13020 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13021 scoped_ptr<HttpTransaction> trans(
13022 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13023 // Send headers successfully, but get an error while sending the body.
13024 MockWrite data_writes[] = {
13025 MockWrite("POST / HTTP/1.1\r\n"
13026 "Host: www.foo.com\r\n"
13027 "Connection: keep-alive\r\n"
13028 "Content-Length: 3\r\n\r\n"),
13029 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13032 MockRead data_reads[] = {
13033 MockRead("HTTP 0.9 rocks!"),
13034 MockRead(SYNCHRONOUS, OK),
13036 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13037 arraysize(data_writes));
13038 session_deps_.socket_factory->AddSocketDataProvider(&data);
13040 TestCompletionCallback callback;
13042 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13043 EXPECT_EQ(ERR_IO_PENDING, rv);
13045 rv = callback.WaitForResult();
13046 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13048 const HttpResponseInfo* response = trans->GetResponseInfo();
13049 EXPECT_TRUE(response == NULL);
13052 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
13053 ScopedVector<UploadElementReader> element_readers;
13054 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13055 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13057 HttpRequestInfo request;
13058 request.method = "POST";
13059 request.url = GURL("http://www.foo.com/");
13060 request.upload_data_stream = &upload_data_stream;
13061 request.load_flags = 0;
13063 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13064 scoped_ptr<HttpTransaction> trans(
13065 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13066 // Send headers successfully, but get an error while sending the body.
13067 MockWrite data_writes[] = {
13068 MockWrite("POST / HTTP/1.1\r\n"
13069 "Host: www.foo.com\r\n"
13070 "Connection: keep-alive\r\n"
13071 "Content-Length: 3\r\n\r\n"),
13072 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13075 MockRead data_reads[] = {
13076 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13077 MockRead(SYNCHRONOUS, OK),
13079 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13080 arraysize(data_writes));
13081 session_deps_.socket_factory->AddSocketDataProvider(&data);
13083 TestCompletionCallback callback;
13085 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13086 EXPECT_EQ(ERR_IO_PENDING, rv);
13088 rv = callback.WaitForResult();
13089 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13091 const HttpResponseInfo* response = trans->GetResponseInfo();
13092 EXPECT_TRUE(response == NULL);
13095 } // namespace net