Windows should animate when they are about to get docked at screen edges.
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blob5f8dac2f87db6b6f3c1121fb3c5a6b00f5747882
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/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/test/test_file_util.h"
21 #include "net/base/auth.h"
22 #include "net/base/capturing_net_log.h"
23 #include "net/base/completion_callback.h"
24 #include "net/base/load_timing_info.h"
25 #include "net/base/load_timing_info_test_util.h"
26 #include "net/base/net_log.h"
27 #include "net/base/net_log_unittest.h"
28 #include "net/base/request_priority.h"
29 #include "net/base/test_completion_callback.h"
30 #include "net/base/test_data_directory.h"
31 #include "net/base/upload_bytes_element_reader.h"
32 #include "net/base/upload_data_stream.h"
33 #include "net/base/upload_file_element_reader.h"
34 #include "net/cert/mock_cert_verifier.h"
35 #include "net/dns/host_cache.h"
36 #include "net/dns/mock_host_resolver.h"
37 #include "net/http/http_auth_handler_digest.h"
38 #include "net/http/http_auth_handler_mock.h"
39 #include "net/http/http_auth_handler_ntlm.h"
40 #include "net/http/http_basic_stream.h"
41 #include "net/http/http_network_session.h"
42 #include "net/http/http_network_session_peer.h"
43 #include "net/http/http_server_properties_impl.h"
44 #include "net/http/http_stream.h"
45 #include "net/http/http_stream_factory.h"
46 #include "net/http/http_transaction_unittest.h"
47 #include "net/proxy/proxy_config_service_fixed.h"
48 #include "net/proxy/proxy_resolver.h"
49 #include "net/proxy/proxy_service.h"
50 #include "net/socket/client_socket_factory.h"
51 #include "net/socket/client_socket_pool_manager.h"
52 #include "net/socket/mock_client_socket_pool_manager.h"
53 #include "net/socket/next_proto.h"
54 #include "net/socket/socket_test_util.h"
55 #include "net/socket/ssl_client_socket.h"
56 #include "net/spdy/spdy_framer.h"
57 #include "net/spdy/spdy_session.h"
58 #include "net/spdy/spdy_session_pool.h"
59 #include "net/spdy/spdy_test_util_common.h"
60 #include "net/ssl/ssl_cert_request_info.h"
61 #include "net/ssl/ssl_config_service_defaults.h"
62 #include "net/ssl/ssl_info.h"
63 #include "net/test/cert_test_util.h"
64 #include "testing/gtest/include/gtest/gtest.h"
65 #include "testing/platform_test.h"
66 #include "url/gurl.h"
68 //-----------------------------------------------------------------------------
70 namespace {
72 const base::string16 kBar(ASCIIToUTF16("bar"));
73 const base::string16 kBar2(ASCIIToUTF16("bar2"));
74 const base::string16 kBar3(ASCIIToUTF16("bar3"));
75 const base::string16 kBaz(ASCIIToUTF16("baz"));
76 const base::string16 kFirst(ASCIIToUTF16("first"));
77 const base::string16 kFoo(ASCIIToUTF16("foo"));
78 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
79 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
80 const base::string16 kFou(ASCIIToUTF16("fou"));
81 const base::string16 kSecond(ASCIIToUTF16("second"));
82 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
83 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
85 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
86 return session->GetTransportSocketPool(
87 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
90 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
91 return session->GetSSLSocketPool(
92 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
95 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
96 // a JSONified list of headers as a single string. Uses single quotes instead
97 // of double quotes for easier comparison. Returns false on failure.
98 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
99 if (!params)
100 return false;
101 base::ListValue* header_list;
102 if (!params->GetList("headers", &header_list))
103 return false;
104 std::string double_quote_headers;
105 base::JSONWriter::Write(header_list, &double_quote_headers);
106 ReplaceChars(double_quote_headers, "\"", "'", headers);
107 return true;
110 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
111 // used.
112 void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
113 EXPECT_TRUE(load_timing_info.socket_reused);
114 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
116 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
117 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
119 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
120 EXPECT_FALSE(load_timing_info.send_start.is_null());
122 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
124 // Set at a higher level.
125 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
126 EXPECT_TRUE(load_timing_info.request_start.is_null());
127 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
130 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
131 // used.
132 void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
133 int connect_timing_flags) {
134 EXPECT_FALSE(load_timing_info.socket_reused);
135 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
137 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
138 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
140 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
141 connect_timing_flags);
142 EXPECT_LE(load_timing_info.connect_timing.connect_end,
143 load_timing_info.send_start);
145 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
147 // Set at a higher level.
148 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
149 EXPECT_TRUE(load_timing_info.request_start.is_null());
150 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
153 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
154 // used.
155 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
156 EXPECT_TRUE(load_timing_info.socket_reused);
157 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
159 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
161 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
162 EXPECT_LE(load_timing_info.proxy_resolve_start,
163 load_timing_info.proxy_resolve_end);
164 EXPECT_LE(load_timing_info.proxy_resolve_end,
165 load_timing_info.send_start);
166 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
168 // Set at a higher level.
169 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
170 EXPECT_TRUE(load_timing_info.request_start.is_null());
171 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
174 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
175 // used.
176 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
177 int connect_timing_flags) {
178 EXPECT_FALSE(load_timing_info.socket_reused);
179 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
181 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
182 EXPECT_LE(load_timing_info.proxy_resolve_start,
183 load_timing_info.proxy_resolve_end);
184 EXPECT_LE(load_timing_info.proxy_resolve_end,
185 load_timing_info.connect_timing.connect_start);
186 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
187 connect_timing_flags);
188 EXPECT_LE(load_timing_info.connect_timing.connect_end,
189 load_timing_info.send_start);
191 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
193 // Set at a higher level.
194 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
195 EXPECT_TRUE(load_timing_info.request_start.is_null());
196 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
199 } // namespace
201 namespace net {
203 namespace {
205 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
206 return SpdySessionDependencies::SpdyCreateSession(session_deps);
209 } // namespace
211 class HttpNetworkTransactionTest
212 : public PlatformTest,
213 public ::testing::WithParamInterface<NextProto> {
214 public:
215 virtual ~HttpNetworkTransactionTest() {
216 // Important to restore the per-pool limit first, since the pool limit must
217 // always be greater than group limit, and the tests reduce both limits.
218 ClientSocketPoolManager::set_max_sockets_per_pool(
219 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
220 ClientSocketPoolManager::set_max_sockets_per_group(
221 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
224 protected:
225 HttpNetworkTransactionTest()
226 : spdy_util_(GetParam()),
227 session_deps_(GetParam()),
228 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
229 HttpNetworkSession::NORMAL_SOCKET_POOL)),
230 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
231 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
234 struct SimpleGetHelperResult {
235 int rv;
236 std::string status_line;
237 std::string response_data;
238 LoadTimingInfo load_timing_info;
241 virtual void SetUp() {
242 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
243 base::MessageLoop::current()->RunUntilIdle();
246 virtual void TearDown() {
247 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
248 base::MessageLoop::current()->RunUntilIdle();
249 // Empty the current queue.
250 base::MessageLoop::current()->RunUntilIdle();
251 PlatformTest::TearDown();
252 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
253 base::MessageLoop::current()->RunUntilIdle();
254 HttpStreamFactory::set_use_alternate_protocols(false);
255 HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
258 // This is the expected return from a current server advertising SPDY.
259 std::string GetAlternateProtocolHttpHeader() {
260 return
261 std::string("Alternate-Protocol: 443:") +
262 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
263 "\r\n\r\n";
266 // Either |write_failure| specifies a write failure or |read_failure|
267 // specifies a read failure when using a reused socket. In either case, the
268 // failure should cause the network transaction to resend the request, and the
269 // other argument should be NULL.
270 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
271 const MockRead* read_failure);
273 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
274 size_t data_count) {
275 SimpleGetHelperResult out;
277 HttpRequestInfo request;
278 request.method = "GET";
279 request.url = GURL("http://www.google.com/");
280 request.load_flags = 0;
282 CapturingBoundNetLog log;
283 session_deps_.net_log = log.bound().net_log();
284 scoped_ptr<HttpTransaction> trans(
285 new HttpNetworkTransaction(DEFAULT_PRIORITY,
286 CreateSession(&session_deps_)));
288 for (size_t i = 0; i < data_count; ++i) {
289 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
292 TestCompletionCallback callback;
294 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
295 int rv = trans->Start(&request, callback.callback(), log.bound());
296 EXPECT_EQ(ERR_IO_PENDING, rv);
298 out.rv = callback.WaitForResult();
300 // Even in the failure cases that use this function, connections are always
301 // successfully established before the error.
302 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
303 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
305 if (out.rv != OK)
306 return out;
308 const HttpResponseInfo* response = trans->GetResponseInfo();
309 // Can't use ASSERT_* inside helper functions like this, so
310 // return an error.
311 if (response == NULL || response->headers.get() == NULL) {
312 out.rv = ERR_UNEXPECTED;
313 return out;
315 out.status_line = response->headers->GetStatusLine();
317 EXPECT_EQ("127.0.0.1", response->socket_address.host());
318 EXPECT_EQ(80, response->socket_address.port());
320 rv = ReadTransaction(trans.get(), &out.response_data);
321 EXPECT_EQ(OK, rv);
323 net::CapturingNetLog::CapturedEntryList entries;
324 log.GetEntries(&entries);
325 size_t pos = ExpectLogContainsSomewhere(
326 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
327 NetLog::PHASE_NONE);
328 ExpectLogContainsSomewhere(
329 entries, pos,
330 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
331 NetLog::PHASE_NONE);
333 std::string line;
334 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
335 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
337 HttpRequestHeaders request_headers;
338 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
339 std::string value;
340 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
341 EXPECT_EQ("www.google.com", value);
342 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
343 EXPECT_EQ("keep-alive", value);
345 std::string response_headers;
346 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
347 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
348 response_headers);
350 return out;
353 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
354 size_t reads_count) {
355 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
356 StaticSocketDataProvider* data[] = { &reads };
357 return SimpleGetHelperForData(data, 1);
360 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
361 int expected_status);
363 void ConnectStatusHelper(const MockRead& status);
365 void BypassHostCacheOnRefreshHelper(int load_flags);
367 void CheckErrorIsPassedBack(int error, IoMode mode);
369 SpdyTestUtil spdy_util_;
370 SpdySessionDependencies session_deps_;
372 // Original socket limits. Some tests set these. Safest to always restore
373 // them once each test has been run.
374 int old_max_group_sockets_;
375 int old_max_pool_sockets_;
378 INSTANTIATE_TEST_CASE_P(
379 NextProto,
380 HttpNetworkTransactionTest,
381 testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
382 kProtoHTTP2Draft04));
384 namespace {
386 // Fill |str| with a long header list that consumes >= |size| bytes.
387 void FillLargeHeadersString(std::string* str, int size) {
388 const char* row =
389 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
390 const int sizeof_row = strlen(row);
391 const int num_rows = static_cast<int>(
392 ceil(static_cast<float>(size) / sizeof_row));
393 const int sizeof_data = num_rows * sizeof_row;
394 DCHECK(sizeof_data >= size);
395 str->reserve(sizeof_data);
397 for (int i = 0; i < num_rows; ++i)
398 str->append(row, sizeof_row);
401 // Alternative functions that eliminate randomness and dependency on the local
402 // host name so that the generated NTLM messages are reproducible.
403 void MockGenerateRandom1(uint8* output, size_t n) {
404 static const uint8 bytes[] = {
405 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
407 static size_t current_byte = 0;
408 for (size_t i = 0; i < n; ++i) {
409 output[i] = bytes[current_byte++];
410 current_byte %= arraysize(bytes);
414 void MockGenerateRandom2(uint8* output, size_t n) {
415 static const uint8 bytes[] = {
416 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
417 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
419 static size_t current_byte = 0;
420 for (size_t i = 0; i < n; ++i) {
421 output[i] = bytes[current_byte++];
422 current_byte %= arraysize(bytes);
426 std::string MockGetHostName() {
427 return "WTC-WIN7";
430 template<typename ParentPool>
431 class CaptureGroupNameSocketPool : public ParentPool {
432 public:
433 CaptureGroupNameSocketPool(HostResolver* host_resolver,
434 CertVerifier* cert_verifier);
436 const std::string last_group_name_received() const {
437 return last_group_name_;
440 virtual int RequestSocket(const std::string& group_name,
441 const void* socket_params,
442 RequestPriority priority,
443 ClientSocketHandle* handle,
444 const CompletionCallback& callback,
445 const BoundNetLog& net_log) {
446 last_group_name_ = group_name;
447 return ERR_IO_PENDING;
449 virtual void CancelRequest(const std::string& group_name,
450 ClientSocketHandle* handle) {}
451 virtual void ReleaseSocket(const std::string& group_name,
452 StreamSocket* socket,
453 int id) {}
454 virtual void CloseIdleSockets() {}
455 virtual int IdleSocketCount() const {
456 return 0;
458 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
459 return 0;
461 virtual LoadState GetLoadState(const std::string& group_name,
462 const ClientSocketHandle* handle) const {
463 return LOAD_STATE_IDLE;
465 virtual base::TimeDelta ConnectionTimeout() const {
466 return base::TimeDelta();
469 private:
470 std::string last_group_name_;
473 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
474 CaptureGroupNameTransportSocketPool;
475 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
476 CaptureGroupNameHttpProxySocketPool;
477 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
478 CaptureGroupNameSOCKSSocketPool;
479 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
480 CaptureGroupNameSSLSocketPool;
482 template<typename ParentPool>
483 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
484 HostResolver* host_resolver,
485 CertVerifier* /* cert_verifier */)
486 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
488 template<>
489 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
490 HostResolver* host_resolver,
491 CertVerifier* /* cert_verifier */)
492 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
494 template <>
495 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
496 HostResolver* host_resolver,
497 CertVerifier* cert_verifier)
498 : SSLClientSocketPool(0,
500 NULL,
501 host_resolver,
502 cert_verifier,
503 NULL,
504 NULL,
505 std::string(),
506 NULL,
507 NULL,
508 NULL,
509 NULL,
510 NULL,
511 NULL) {}
513 //-----------------------------------------------------------------------------
515 // Helper functions for validating that AuthChallengeInfo's are correctly
516 // configured for common cases.
517 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
518 if (!auth_challenge)
519 return false;
520 EXPECT_FALSE(auth_challenge->is_proxy);
521 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
522 EXPECT_EQ("MyRealm1", auth_challenge->realm);
523 EXPECT_EQ("basic", auth_challenge->scheme);
524 return true;
527 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
528 if (!auth_challenge)
529 return false;
530 EXPECT_TRUE(auth_challenge->is_proxy);
531 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
532 EXPECT_EQ("MyRealm1", auth_challenge->realm);
533 EXPECT_EQ("basic", auth_challenge->scheme);
534 return true;
537 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
538 if (!auth_challenge)
539 return false;
540 EXPECT_FALSE(auth_challenge->is_proxy);
541 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
542 EXPECT_EQ("digestive", auth_challenge->realm);
543 EXPECT_EQ("digest", auth_challenge->scheme);
544 return true;
547 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
548 if (!auth_challenge)
549 return false;
550 EXPECT_FALSE(auth_challenge->is_proxy);
551 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
552 EXPECT_EQ(std::string(), auth_challenge->realm);
553 EXPECT_EQ("ntlm", auth_challenge->scheme);
554 return true;
557 } // namespace
559 TEST_P(HttpNetworkTransactionTest, Basic) {
560 scoped_ptr<HttpTransaction> trans(
561 new HttpNetworkTransaction(DEFAULT_PRIORITY,
562 CreateSession(&session_deps_)));
565 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
566 MockRead data_reads[] = {
567 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
568 MockRead("hello world"),
569 MockRead(SYNCHRONOUS, OK),
571 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
572 arraysize(data_reads));
573 EXPECT_EQ(OK, out.rv);
574 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
575 EXPECT_EQ("hello world", out.response_data);
578 // Response with no status line.
579 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
580 MockRead data_reads[] = {
581 MockRead("hello world"),
582 MockRead(SYNCHRONOUS, OK),
584 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
585 arraysize(data_reads));
586 EXPECT_EQ(OK, out.rv);
587 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
588 EXPECT_EQ("hello world", out.response_data);
591 // Allow up to 4 bytes of junk to precede status line.
592 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
593 MockRead data_reads[] = {
594 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
595 MockRead(SYNCHRONOUS, OK),
597 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
598 arraysize(data_reads));
599 EXPECT_EQ(OK, out.rv);
600 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
601 EXPECT_EQ("DATA", out.response_data);
604 // Allow up to 4 bytes of junk to precede status line.
605 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
606 MockRead data_reads[] = {
607 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
608 MockRead(SYNCHRONOUS, OK),
610 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
611 arraysize(data_reads));
612 EXPECT_EQ(OK, out.rv);
613 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
614 EXPECT_EQ("DATA", out.response_data);
617 // Beyond 4 bytes of slop and it should fail to find a status line.
618 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
619 MockRead data_reads[] = {
620 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
621 MockRead(SYNCHRONOUS, OK),
623 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
624 arraysize(data_reads));
625 EXPECT_EQ(OK, out.rv);
626 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
627 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
630 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
631 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
632 MockRead data_reads[] = {
633 MockRead("\n"),
634 MockRead("\n"),
635 MockRead("Q"),
636 MockRead("J"),
637 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
638 MockRead(SYNCHRONOUS, OK),
640 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
641 arraysize(data_reads));
642 EXPECT_EQ(OK, out.rv);
643 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
644 EXPECT_EQ("DATA", out.response_data);
647 // Close the connection before enough bytes to have a status line.
648 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
649 MockRead data_reads[] = {
650 MockRead("HTT"),
651 MockRead(SYNCHRONOUS, OK),
653 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
654 arraysize(data_reads));
655 EXPECT_EQ(OK, out.rv);
656 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
657 EXPECT_EQ("HTT", out.response_data);
660 // Simulate a 204 response, lacking a Content-Length header, sent over a
661 // persistent connection. The response should still terminate since a 204
662 // cannot have a response body.
663 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
664 MockRead data_reads[] = {
665 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
666 MockRead("junk"), // Should not be read!!
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.1 204 No Content", out.status_line);
673 EXPECT_EQ("", out.response_data);
676 // A simple request using chunked encoding with some extra data after.
677 // (Like might be seen in a pipelined response.)
678 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
679 MockRead data_reads[] = {
680 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
681 MockRead("5\r\nHello\r\n"),
682 MockRead("1\r\n"),
683 MockRead(" \r\n"),
684 MockRead("5\r\nworld\r\n"),
685 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
686 MockRead(SYNCHRONOUS, OK),
688 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
689 arraysize(data_reads));
690 EXPECT_EQ(OK, out.rv);
691 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
692 EXPECT_EQ("Hello world", out.response_data);
695 // Next tests deal with http://crbug.com/56344.
697 TEST_P(HttpNetworkTransactionTest,
698 MultipleContentLengthHeadersNoTransferEncoding) {
699 MockRead data_reads[] = {
700 MockRead("HTTP/1.1 200 OK\r\n"),
701 MockRead("Content-Length: 10\r\n"),
702 MockRead("Content-Length: 5\r\n\r\n"),
704 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
705 arraysize(data_reads));
706 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
709 TEST_P(HttpNetworkTransactionTest,
710 DuplicateContentLengthHeadersNoTransferEncoding) {
711 MockRead data_reads[] = {
712 MockRead("HTTP/1.1 200 OK\r\n"),
713 MockRead("Content-Length: 5\r\n"),
714 MockRead("Content-Length: 5\r\n\r\n"),
715 MockRead("Hello"),
717 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
718 arraysize(data_reads));
719 EXPECT_EQ(OK, out.rv);
720 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
721 EXPECT_EQ("Hello", out.response_data);
724 TEST_P(HttpNetworkTransactionTest,
725 ComplexContentLengthHeadersNoTransferEncoding) {
726 // More than 2 dupes.
728 MockRead data_reads[] = {
729 MockRead("HTTP/1.1 200 OK\r\n"),
730 MockRead("Content-Length: 5\r\n"),
731 MockRead("Content-Length: 5\r\n"),
732 MockRead("Content-Length: 5\r\n\r\n"),
733 MockRead("Hello"),
735 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
736 arraysize(data_reads));
737 EXPECT_EQ(OK, out.rv);
738 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
739 EXPECT_EQ("Hello", out.response_data);
741 // HTTP/1.0
743 MockRead data_reads[] = {
744 MockRead("HTTP/1.0 200 OK\r\n"),
745 MockRead("Content-Length: 5\r\n"),
746 MockRead("Content-Length: 5\r\n"),
747 MockRead("Content-Length: 5\r\n\r\n"),
748 MockRead("Hello"),
750 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
751 arraysize(data_reads));
752 EXPECT_EQ(OK, out.rv);
753 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
754 EXPECT_EQ("Hello", out.response_data);
756 // 2 dupes and one mismatched.
758 MockRead data_reads[] = {
759 MockRead("HTTP/1.1 200 OK\r\n"),
760 MockRead("Content-Length: 10\r\n"),
761 MockRead("Content-Length: 10\r\n"),
762 MockRead("Content-Length: 5\r\n\r\n"),
764 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
765 arraysize(data_reads));
766 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
770 TEST_P(HttpNetworkTransactionTest,
771 MultipleContentLengthHeadersTransferEncoding) {
772 MockRead data_reads[] = {
773 MockRead("HTTP/1.1 200 OK\r\n"),
774 MockRead("Content-Length: 666\r\n"),
775 MockRead("Content-Length: 1337\r\n"),
776 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
777 MockRead("5\r\nHello\r\n"),
778 MockRead("1\r\n"),
779 MockRead(" \r\n"),
780 MockRead("5\r\nworld\r\n"),
781 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
782 MockRead(SYNCHRONOUS, OK),
784 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
785 arraysize(data_reads));
786 EXPECT_EQ(OK, out.rv);
787 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
788 EXPECT_EQ("Hello world", out.response_data);
791 // Next tests deal with http://crbug.com/98895.
793 // Checks that a single Content-Disposition header results in no error.
794 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
795 MockRead data_reads[] = {
796 MockRead("HTTP/1.1 200 OK\r\n"),
797 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
798 MockRead("Content-Length: 5\r\n\r\n"),
799 MockRead("Hello"),
801 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
802 arraysize(data_reads));
803 EXPECT_EQ(OK, out.rv);
804 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
805 EXPECT_EQ("Hello", out.response_data);
808 // Checks that two identical Content-Disposition headers result in no error.
809 TEST_P(HttpNetworkTransactionTest,
810 TwoIdenticalContentDispositionHeaders) {
811 MockRead data_reads[] = {
812 MockRead("HTTP/1.1 200 OK\r\n"),
813 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
814 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
815 MockRead("Content-Length: 5\r\n\r\n"),
816 MockRead("Hello"),
818 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
819 arraysize(data_reads));
820 EXPECT_EQ(OK, out.rv);
821 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
822 EXPECT_EQ("Hello", out.response_data);
825 // Checks that two distinct Content-Disposition headers result in an error.
826 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
827 MockRead data_reads[] = {
828 MockRead("HTTP/1.1 200 OK\r\n"),
829 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
830 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
831 MockRead("Content-Length: 5\r\n\r\n"),
832 MockRead("Hello"),
834 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
835 arraysize(data_reads));
836 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
839 // Checks that two identical Location headers result in no error.
840 // Also tests Location header behavior.
841 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
842 MockRead data_reads[] = {
843 MockRead("HTTP/1.1 302 Redirect\r\n"),
844 MockRead("Location: http://good.com/\r\n"),
845 MockRead("Location: http://good.com/\r\n"),
846 MockRead("Content-Length: 0\r\n\r\n"),
847 MockRead(SYNCHRONOUS, OK),
850 HttpRequestInfo request;
851 request.method = "GET";
852 request.url = GURL("http://redirect.com/");
853 request.load_flags = 0;
855 scoped_ptr<HttpTransaction> trans(
856 new HttpNetworkTransaction(DEFAULT_PRIORITY,
857 CreateSession(&session_deps_)));
859 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
860 session_deps_.socket_factory->AddSocketDataProvider(&data);
862 TestCompletionCallback callback;
864 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
865 EXPECT_EQ(ERR_IO_PENDING, rv);
867 EXPECT_EQ(OK, callback.WaitForResult());
869 const HttpResponseInfo* response = trans->GetResponseInfo();
870 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
871 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
872 std::string url;
873 EXPECT_TRUE(response->headers->IsRedirect(&url));
874 EXPECT_EQ("http://good.com/", url);
877 // Checks that two distinct Location headers result in an error.
878 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
879 MockRead data_reads[] = {
880 MockRead("HTTP/1.1 302 Redirect\r\n"),
881 MockRead("Location: http://good.com/\r\n"),
882 MockRead("Location: http://evil.com/\r\n"),
883 MockRead("Content-Length: 0\r\n\r\n"),
884 MockRead(SYNCHRONOUS, OK),
886 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
887 arraysize(data_reads));
888 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
891 // Do a request using the HEAD method. Verify that we don't try to read the
892 // message body (since HEAD has none).
893 TEST_P(HttpNetworkTransactionTest, Head) {
894 HttpRequestInfo request;
895 request.method = "HEAD";
896 request.url = GURL("http://www.google.com/");
897 request.load_flags = 0;
899 scoped_ptr<HttpTransaction> trans(
900 new HttpNetworkTransaction(DEFAULT_PRIORITY,
901 CreateSession(&session_deps_)));
903 MockWrite data_writes1[] = {
904 MockWrite("HEAD / HTTP/1.1\r\n"
905 "Host: www.google.com\r\n"
906 "Connection: keep-alive\r\n"
907 "Content-Length: 0\r\n\r\n"),
909 MockRead data_reads1[] = {
910 MockRead("HTTP/1.1 404 Not Found\r\n"),
911 MockRead("Server: Blah\r\n"),
912 MockRead("Content-Length: 1234\r\n\r\n"),
914 // No response body because the test stops reading here.
915 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
918 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
919 data_writes1, arraysize(data_writes1));
920 session_deps_.socket_factory->AddSocketDataProvider(&data1);
922 TestCompletionCallback callback1;
924 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
925 EXPECT_EQ(ERR_IO_PENDING, rv);
927 rv = callback1.WaitForResult();
928 EXPECT_EQ(OK, rv);
930 const HttpResponseInfo* response = trans->GetResponseInfo();
931 ASSERT_TRUE(response != NULL);
933 // Check that the headers got parsed.
934 EXPECT_TRUE(response->headers.get() != NULL);
935 EXPECT_EQ(1234, response->headers->GetContentLength());
936 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
938 std::string server_header;
939 void* iter = NULL;
940 bool has_server_header = response->headers->EnumerateHeader(
941 &iter, "Server", &server_header);
942 EXPECT_TRUE(has_server_header);
943 EXPECT_EQ("Blah", server_header);
945 // Reading should give EOF right away, since there is no message body
946 // (despite non-zero content-length).
947 std::string response_data;
948 rv = ReadTransaction(trans.get(), &response_data);
949 EXPECT_EQ(OK, rv);
950 EXPECT_EQ("", response_data);
953 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
954 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
956 MockRead data_reads[] = {
957 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
958 MockRead("hello"),
959 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
960 MockRead("world"),
961 MockRead(SYNCHRONOUS, OK),
963 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
964 session_deps_.socket_factory->AddSocketDataProvider(&data);
966 const char* const kExpectedResponseData[] = {
967 "hello", "world"
970 for (int i = 0; i < 2; ++i) {
971 HttpRequestInfo request;
972 request.method = "GET";
973 request.url = GURL("http://www.google.com/");
974 request.load_flags = 0;
976 scoped_ptr<HttpTransaction> trans(
977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
979 TestCompletionCallback callback;
981 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
982 EXPECT_EQ(ERR_IO_PENDING, rv);
984 rv = callback.WaitForResult();
985 EXPECT_EQ(OK, rv);
987 const HttpResponseInfo* response = trans->GetResponseInfo();
988 ASSERT_TRUE(response != NULL);
990 EXPECT_TRUE(response->headers.get() != NULL);
991 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
993 std::string response_data;
994 rv = ReadTransaction(trans.get(), &response_data);
995 EXPECT_EQ(OK, rv);
996 EXPECT_EQ(kExpectedResponseData[i], response_data);
1000 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1001 ScopedVector<UploadElementReader> element_readers;
1002 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1003 UploadDataStream upload_data_stream(&element_readers, 0);
1005 HttpRequestInfo request;
1006 request.method = "POST";
1007 request.url = GURL("http://www.foo.com/");
1008 request.upload_data_stream = &upload_data_stream;
1009 request.load_flags = 0;
1011 scoped_ptr<HttpTransaction> trans(
1012 new HttpNetworkTransaction(DEFAULT_PRIORITY,
1013 CreateSession(&session_deps_)));
1015 MockRead data_reads[] = {
1016 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1017 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1018 MockRead("hello world"),
1019 MockRead(SYNCHRONOUS, OK),
1021 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1022 session_deps_.socket_factory->AddSocketDataProvider(&data);
1024 TestCompletionCallback callback;
1026 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1027 EXPECT_EQ(ERR_IO_PENDING, rv);
1029 rv = callback.WaitForResult();
1030 EXPECT_EQ(OK, rv);
1032 const HttpResponseInfo* response = trans->GetResponseInfo();
1033 ASSERT_TRUE(response != NULL);
1035 EXPECT_TRUE(response->headers.get() != NULL);
1036 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1038 std::string response_data;
1039 rv = ReadTransaction(trans.get(), &response_data);
1040 EXPECT_EQ(OK, rv);
1041 EXPECT_EQ("hello world", response_data);
1044 // This test is almost the same as Ignores100 above, but the response contains
1045 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1046 // HTTP/1.1 and the two status headers are read in one read.
1047 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1048 HttpRequestInfo request;
1049 request.method = "GET";
1050 request.url = GURL("http://www.foo.com/");
1051 request.load_flags = 0;
1053 scoped_ptr<HttpTransaction> trans(
1054 new HttpNetworkTransaction(DEFAULT_PRIORITY,
1055 CreateSession(&session_deps_)));
1057 MockRead data_reads[] = {
1058 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1059 "HTTP/1.1 200 OK\r\n\r\n"),
1060 MockRead("hello world"),
1061 MockRead(SYNCHRONOUS, OK),
1063 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1064 session_deps_.socket_factory->AddSocketDataProvider(&data);
1066 TestCompletionCallback callback;
1068 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1069 EXPECT_EQ(ERR_IO_PENDING, rv);
1071 rv = callback.WaitForResult();
1072 EXPECT_EQ(OK, rv);
1074 const HttpResponseInfo* response = trans->GetResponseInfo();
1075 ASSERT_TRUE(response != NULL);
1077 EXPECT_TRUE(response->headers.get() != NULL);
1078 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1080 std::string response_data;
1081 rv = ReadTransaction(trans.get(), &response_data);
1082 EXPECT_EQ(OK, rv);
1083 EXPECT_EQ("hello world", response_data);
1086 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1087 HttpRequestInfo request;
1088 request.method = "POST";
1089 request.url = GURL("http://www.foo.com/");
1090 request.load_flags = 0;
1092 scoped_ptr<HttpTransaction> trans(
1093 new HttpNetworkTransaction(DEFAULT_PRIORITY,
1094 CreateSession(&session_deps_)));
1096 MockRead data_reads[] = {
1097 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1098 MockRead(ASYNC, 0),
1100 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1101 session_deps_.socket_factory->AddSocketDataProvider(&data);
1103 TestCompletionCallback callback;
1105 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1106 EXPECT_EQ(ERR_IO_PENDING, rv);
1108 rv = callback.WaitForResult();
1109 EXPECT_EQ(OK, rv);
1111 std::string response_data;
1112 rv = ReadTransaction(trans.get(), &response_data);
1113 EXPECT_EQ(OK, rv);
1114 EXPECT_EQ("", response_data);
1117 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1118 HttpRequestInfo request;
1119 request.method = "POST";
1120 request.url = GURL("http://www.foo.com/");
1121 request.load_flags = 0;
1123 scoped_ptr<HttpTransaction> trans(
1124 new HttpNetworkTransaction(DEFAULT_PRIORITY,
1125 CreateSession(&session_deps_)));
1127 MockRead data_reads[] = {
1128 MockRead(ASYNC, 0),
1130 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1131 session_deps_.socket_factory->AddSocketDataProvider(&data);
1133 TestCompletionCallback callback;
1135 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1136 EXPECT_EQ(ERR_IO_PENDING, rv);
1138 rv = callback.WaitForResult();
1139 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1142 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1143 const MockWrite* write_failure,
1144 const MockRead* read_failure) {
1145 HttpRequestInfo request;
1146 request.method = "GET";
1147 request.url = GURL("http://www.foo.com/");
1148 request.load_flags = 0;
1150 CapturingNetLog net_log;
1151 session_deps_.net_log = &net_log;
1152 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1154 // Written data for successfully sending both requests.
1155 MockWrite data1_writes[] = {
1156 MockWrite("GET / HTTP/1.1\r\n"
1157 "Host: www.foo.com\r\n"
1158 "Connection: keep-alive\r\n\r\n"),
1159 MockWrite("GET / HTTP/1.1\r\n"
1160 "Host: www.foo.com\r\n"
1161 "Connection: keep-alive\r\n\r\n")
1164 // Read results for the first request.
1165 MockRead data1_reads[] = {
1166 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1167 MockRead("hello"),
1168 MockRead(ASYNC, OK),
1171 if (write_failure) {
1172 ASSERT_TRUE(!read_failure);
1173 data1_writes[1] = *write_failure;
1174 } else {
1175 ASSERT_TRUE(read_failure);
1176 data1_reads[2] = *read_failure;
1179 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1180 data1_writes, arraysize(data1_writes));
1181 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1183 MockRead data2_reads[] = {
1184 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1185 MockRead("world"),
1186 MockRead(ASYNC, OK),
1188 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1189 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1191 const char* kExpectedResponseData[] = {
1192 "hello", "world"
1195 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1196 for (int i = 0; i < 2; ++i) {
1197 TestCompletionCallback callback;
1199 scoped_ptr<HttpTransaction> trans(
1200 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1202 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1203 EXPECT_EQ(ERR_IO_PENDING, rv);
1205 rv = callback.WaitForResult();
1206 EXPECT_EQ(OK, rv);
1208 LoadTimingInfo load_timing_info;
1209 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1210 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1211 if (i == 0) {
1212 first_socket_log_id = load_timing_info.socket_log_id;
1213 } else {
1214 // The second request should be using a new socket.
1215 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1218 const HttpResponseInfo* response = trans->GetResponseInfo();
1219 ASSERT_TRUE(response != NULL);
1221 EXPECT_TRUE(response->headers.get() != NULL);
1222 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1224 std::string response_data;
1225 rv = ReadTransaction(trans.get(), &response_data);
1226 EXPECT_EQ(OK, rv);
1227 EXPECT_EQ(kExpectedResponseData[i], response_data);
1231 TEST_P(HttpNetworkTransactionTest,
1232 KeepAliveConnectionNotConnectedOnWrite) {
1233 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1234 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1237 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1238 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1239 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1242 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1243 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1244 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1247 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1248 HttpRequestInfo request;
1249 request.method = "GET";
1250 request.url = GURL("http://www.google.com/");
1251 request.load_flags = 0;
1253 scoped_ptr<HttpTransaction> trans(
1254 new HttpNetworkTransaction(DEFAULT_PRIORITY,
1255 CreateSession(&session_deps_)));
1257 MockRead data_reads[] = {
1258 MockRead(ASYNC, ERR_CONNECTION_RESET),
1259 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1260 MockRead("hello world"),
1261 MockRead(SYNCHRONOUS, OK),
1263 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1264 session_deps_.socket_factory->AddSocketDataProvider(&data);
1266 TestCompletionCallback callback;
1268 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1269 EXPECT_EQ(ERR_IO_PENDING, rv);
1271 rv = callback.WaitForResult();
1272 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1274 const HttpResponseInfo* response = trans->GetResponseInfo();
1275 EXPECT_TRUE(response == NULL);
1278 // What do various browsers do when the server closes a non-keepalive
1279 // connection without sending any response header or body?
1281 // IE7: error page
1282 // Safari 3.1.2 (Windows): error page
1283 // Firefox 3.0.1: blank page
1284 // Opera 9.52: after five attempts, blank page
1285 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1286 // Us: error page (EMPTY_RESPONSE)
1287 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1288 MockRead data_reads[] = {
1289 MockRead(SYNCHRONOUS, OK), // EOF
1290 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1291 MockRead("hello world"),
1292 MockRead(SYNCHRONOUS, OK),
1294 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1295 arraysize(data_reads));
1296 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1299 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1300 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1301 // destructor in such situations.
1302 // See http://crbug.com/154712 and http://crbug.com/156609.
1303 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1304 HttpRequestInfo request;
1305 request.method = "GET";
1306 request.url = GURL("http://www.google.com/");
1307 request.load_flags = 0;
1309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1310 scoped_ptr<HttpTransaction> trans(
1311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1313 MockRead data_reads[] = {
1314 MockRead("HTTP/1.0 200 OK\r\n"),
1315 MockRead("Connection: keep-alive\r\n"),
1316 MockRead("Content-Length: 100\r\n\r\n"),
1317 MockRead("hello"),
1318 MockRead(SYNCHRONOUS, 0),
1320 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1321 session_deps_.socket_factory->AddSocketDataProvider(&data);
1323 TestCompletionCallback callback;
1325 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1326 EXPECT_EQ(ERR_IO_PENDING, rv);
1328 rv = callback.WaitForResult();
1329 EXPECT_EQ(OK, rv);
1331 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1332 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1333 if (rv == ERR_IO_PENDING)
1334 rv = callback.WaitForResult();
1335 EXPECT_EQ(5, rv);
1336 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1337 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1339 trans.reset();
1340 base::MessageLoop::current()->RunUntilIdle();
1341 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1344 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1345 HttpRequestInfo request;
1346 request.method = "GET";
1347 request.url = GURL("http://www.google.com/");
1348 request.load_flags = 0;
1350 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1351 scoped_ptr<HttpTransaction> trans(
1352 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1354 MockRead data_reads[] = {
1355 MockRead("HTTP/1.0 200 OK\r\n"),
1356 MockRead("Connection: keep-alive\r\n"),
1357 MockRead("Content-Length: 100\r\n\r\n"),
1358 MockRead(SYNCHRONOUS, 0),
1360 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1361 session_deps_.socket_factory->AddSocketDataProvider(&data);
1363 TestCompletionCallback callback;
1365 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1366 EXPECT_EQ(ERR_IO_PENDING, rv);
1368 rv = callback.WaitForResult();
1369 EXPECT_EQ(OK, rv);
1371 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1372 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1373 if (rv == ERR_IO_PENDING)
1374 rv = callback.WaitForResult();
1375 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1377 trans.reset();
1378 base::MessageLoop::current()->RunUntilIdle();
1379 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1382 // Test that we correctly reuse a keep-alive connection after not explicitly
1383 // reading the body.
1384 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1385 HttpRequestInfo request;
1386 request.method = "GET";
1387 request.url = GURL("http://www.foo.com/");
1388 request.load_flags = 0;
1390 CapturingNetLog net_log;
1391 session_deps_.net_log = &net_log;
1392 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1394 // Note that because all these reads happen in the same
1395 // StaticSocketDataProvider, it shows that the same socket is being reused for
1396 // all transactions.
1397 MockRead data1_reads[] = {
1398 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1399 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1400 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1401 MockRead("HTTP/1.1 302 Found\r\n"
1402 "Content-Length: 0\r\n\r\n"),
1403 MockRead("HTTP/1.1 302 Found\r\n"
1404 "Content-Length: 5\r\n\r\n"
1405 "hello"),
1406 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1407 "Content-Length: 0\r\n\r\n"),
1408 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1409 "Content-Length: 5\r\n\r\n"
1410 "hello"),
1411 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1412 MockRead("hello"),
1414 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1415 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1417 MockRead data2_reads[] = {
1418 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1420 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1421 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1423 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1424 std::string response_lines[kNumUnreadBodies];
1426 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1427 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1428 TestCompletionCallback callback;
1430 scoped_ptr<HttpTransaction> trans(
1431 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1433 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1434 EXPECT_EQ(ERR_IO_PENDING, rv);
1436 rv = callback.WaitForResult();
1437 EXPECT_EQ(OK, rv);
1439 LoadTimingInfo load_timing_info;
1440 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1441 if (i == 0) {
1442 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1443 first_socket_log_id = load_timing_info.socket_log_id;
1444 } else {
1445 TestLoadTimingReused(load_timing_info);
1446 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1449 const HttpResponseInfo* response = trans->GetResponseInfo();
1450 ASSERT_TRUE(response != NULL);
1452 ASSERT_TRUE(response->headers.get() != NULL);
1453 response_lines[i] = response->headers->GetStatusLine();
1455 // We intentionally don't read the response bodies.
1458 const char* const kStatusLines[] = {
1459 "HTTP/1.1 204 No Content",
1460 "HTTP/1.1 205 Reset Content",
1461 "HTTP/1.1 304 Not Modified",
1462 "HTTP/1.1 302 Found",
1463 "HTTP/1.1 302 Found",
1464 "HTTP/1.1 301 Moved Permanently",
1465 "HTTP/1.1 301 Moved Permanently",
1468 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1469 forgot_to_update_kStatusLines);
1471 for (int i = 0; i < kNumUnreadBodies; ++i)
1472 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1474 TestCompletionCallback callback;
1475 scoped_ptr<HttpTransaction> trans(
1476 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1477 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1478 EXPECT_EQ(ERR_IO_PENDING, rv);
1479 rv = callback.WaitForResult();
1480 EXPECT_EQ(OK, rv);
1481 const HttpResponseInfo* response = trans->GetResponseInfo();
1482 ASSERT_TRUE(response != NULL);
1483 ASSERT_TRUE(response->headers.get() != NULL);
1484 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1485 std::string response_data;
1486 rv = ReadTransaction(trans.get(), &response_data);
1487 EXPECT_EQ(OK, rv);
1488 EXPECT_EQ("hello", response_data);
1491 // Test the request-challenge-retry sequence for basic auth.
1492 // (basic auth is the easiest to mock, because it has no randomness).
1493 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1494 HttpRequestInfo request;
1495 request.method = "GET";
1496 request.url = GURL("http://www.google.com/");
1497 request.load_flags = 0;
1499 CapturingNetLog log;
1500 session_deps_.net_log = &log;
1501 scoped_ptr<HttpTransaction> trans(
1502 new HttpNetworkTransaction(DEFAULT_PRIORITY,
1503 CreateSession(&session_deps_)));
1505 MockWrite data_writes1[] = {
1506 MockWrite("GET / HTTP/1.1\r\n"
1507 "Host: www.google.com\r\n"
1508 "Connection: keep-alive\r\n\r\n"),
1511 MockRead data_reads1[] = {
1512 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1513 // Give a couple authenticate options (only the middle one is actually
1514 // supported).
1515 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1516 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1517 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1518 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1519 // Large content-length -- won't matter, as connection will be reset.
1520 MockRead("Content-Length: 10000\r\n\r\n"),
1521 MockRead(SYNCHRONOUS, ERR_FAILED),
1524 // After calling trans->RestartWithAuth(), this is the request we should
1525 // be issuing -- the final header line contains the credentials.
1526 MockWrite data_writes2[] = {
1527 MockWrite("GET / HTTP/1.1\r\n"
1528 "Host: www.google.com\r\n"
1529 "Connection: keep-alive\r\n"
1530 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1533 // Lastly, the server responds with the actual content.
1534 MockRead data_reads2[] = {
1535 MockRead("HTTP/1.0 200 OK\r\n"),
1536 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1537 MockRead("Content-Length: 100\r\n\r\n"),
1538 MockRead(SYNCHRONOUS, OK),
1541 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1542 data_writes1, arraysize(data_writes1));
1543 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1544 data_writes2, arraysize(data_writes2));
1545 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1546 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1548 TestCompletionCallback callback1;
1550 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1551 EXPECT_EQ(ERR_IO_PENDING, rv);
1553 rv = callback1.WaitForResult();
1554 EXPECT_EQ(OK, rv);
1556 LoadTimingInfo load_timing_info1;
1557 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1558 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1560 const HttpResponseInfo* response = trans->GetResponseInfo();
1561 ASSERT_TRUE(response != NULL);
1562 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1564 TestCompletionCallback callback2;
1566 rv = trans->RestartWithAuth(
1567 AuthCredentials(kFoo, kBar), callback2.callback());
1568 EXPECT_EQ(ERR_IO_PENDING, rv);
1570 rv = callback2.WaitForResult();
1571 EXPECT_EQ(OK, rv);
1573 LoadTimingInfo load_timing_info2;
1574 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1575 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1576 // The load timing after restart should have a new socket ID, and times after
1577 // those of the first load timing.
1578 EXPECT_LE(load_timing_info1.receive_headers_end,
1579 load_timing_info2.connect_timing.connect_start);
1580 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1582 response = trans->GetResponseInfo();
1583 ASSERT_TRUE(response != NULL);
1584 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1585 EXPECT_EQ(100, response->headers->GetContentLength());
1588 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1589 HttpRequestInfo request;
1590 request.method = "GET";
1591 request.url = GURL("http://www.google.com/");
1592 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1594 scoped_ptr<HttpTransaction> trans(
1595 new HttpNetworkTransaction(DEFAULT_PRIORITY,
1596 CreateSession(&session_deps_)));
1598 MockWrite data_writes[] = {
1599 MockWrite("GET / HTTP/1.1\r\n"
1600 "Host: www.google.com\r\n"
1601 "Connection: keep-alive\r\n\r\n"),
1604 MockRead data_reads[] = {
1605 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1606 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1607 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1608 // Large content-length -- won't matter, as connection will be reset.
1609 MockRead("Content-Length: 10000\r\n\r\n"),
1610 MockRead(SYNCHRONOUS, ERR_FAILED),
1613 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1614 data_writes, arraysize(data_writes));
1615 session_deps_.socket_factory->AddSocketDataProvider(&data);
1616 TestCompletionCallback callback;
1618 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1619 EXPECT_EQ(ERR_IO_PENDING, rv);
1621 rv = callback.WaitForResult();
1622 EXPECT_EQ(0, rv);
1624 const HttpResponseInfo* response = trans->GetResponseInfo();
1625 ASSERT_TRUE(response != NULL);
1626 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1629 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1630 // connection.
1631 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1632 HttpRequestInfo request;
1633 request.method = "GET";
1634 request.url = GURL("http://www.google.com/");
1635 request.load_flags = 0;
1637 CapturingNetLog log;
1638 session_deps_.net_log = &log;
1639 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1641 MockWrite data_writes1[] = {
1642 MockWrite("GET / HTTP/1.1\r\n"
1643 "Host: www.google.com\r\n"
1644 "Connection: keep-alive\r\n\r\n"),
1646 // After calling trans->RestartWithAuth(), this is the request we should
1647 // be issuing -- the final header line contains the credentials.
1648 MockWrite("GET / HTTP/1.1\r\n"
1649 "Host: www.google.com\r\n"
1650 "Connection: keep-alive\r\n"
1651 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1654 MockRead data_reads1[] = {
1655 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1656 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1657 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1658 MockRead("Content-Length: 14\r\n\r\n"),
1659 MockRead("Unauthorized\r\n"),
1661 // Lastly, the server responds with the actual content.
1662 MockRead("HTTP/1.1 200 OK\r\n"),
1663 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1664 MockRead("Content-Length: 5\r\n\r\n"),
1665 MockRead("Hello"),
1668 // If there is a regression where we disconnect a Keep-Alive
1669 // connection during an auth roundtrip, we'll end up reading this.
1670 MockRead data_reads2[] = {
1671 MockRead(SYNCHRONOUS, ERR_FAILED),
1674 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1675 data_writes1, arraysize(data_writes1));
1676 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1677 NULL, 0);
1678 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1679 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1681 TestCompletionCallback callback1;
1683 scoped_ptr<HttpTransaction> trans(
1684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1685 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1686 EXPECT_EQ(ERR_IO_PENDING, rv);
1688 rv = callback1.WaitForResult();
1689 EXPECT_EQ(OK, rv);
1691 LoadTimingInfo load_timing_info1;
1692 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1693 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1695 const HttpResponseInfo* response = trans->GetResponseInfo();
1696 ASSERT_TRUE(response != NULL);
1697 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1699 TestCompletionCallback callback2;
1701 rv = trans->RestartWithAuth(
1702 AuthCredentials(kFoo, kBar), callback2.callback());
1703 EXPECT_EQ(ERR_IO_PENDING, rv);
1705 rv = callback2.WaitForResult();
1706 EXPECT_EQ(OK, rv);
1708 LoadTimingInfo load_timing_info2;
1709 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1710 TestLoadTimingReused(load_timing_info2);
1711 // The load timing after restart should have the same socket ID, and times
1712 // those of the first load timing.
1713 EXPECT_LE(load_timing_info1.receive_headers_end,
1714 load_timing_info2.send_start);
1715 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1717 response = trans->GetResponseInfo();
1718 ASSERT_TRUE(response != NULL);
1719 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1720 EXPECT_EQ(5, response->headers->GetContentLength());
1723 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1724 // connection and with no response body to drain.
1725 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
1726 HttpRequestInfo request;
1727 request.method = "GET";
1728 request.url = GURL("http://www.google.com/");
1729 request.load_flags = 0;
1731 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1733 MockWrite data_writes1[] = {
1734 MockWrite("GET / HTTP/1.1\r\n"
1735 "Host: www.google.com\r\n"
1736 "Connection: keep-alive\r\n\r\n"),
1738 // After calling trans->RestartWithAuth(), this is the request we should
1739 // be issuing -- the final header line contains the credentials.
1740 MockWrite("GET / HTTP/1.1\r\n"
1741 "Host: www.google.com\r\n"
1742 "Connection: keep-alive\r\n"
1743 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1746 MockRead data_reads1[] = {
1747 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1748 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1749 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
1751 // Lastly, the server responds with the actual content.
1752 MockRead("HTTP/1.1 200 OK\r\n"),
1753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1754 MockRead("Content-Length: 5\r\n\r\n"),
1755 MockRead("hello"),
1758 // An incorrect reconnect would cause this to be read.
1759 MockRead data_reads2[] = {
1760 MockRead(SYNCHRONOUS, ERR_FAILED),
1763 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1764 data_writes1, arraysize(data_writes1));
1765 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1766 NULL, 0);
1767 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1768 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1770 TestCompletionCallback callback1;
1772 scoped_ptr<HttpTransaction> trans(
1773 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1774 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1775 EXPECT_EQ(ERR_IO_PENDING, rv);
1777 rv = callback1.WaitForResult();
1778 EXPECT_EQ(OK, rv);
1780 const HttpResponseInfo* response = trans->GetResponseInfo();
1781 ASSERT_TRUE(response != NULL);
1782 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1784 TestCompletionCallback callback2;
1786 rv = trans->RestartWithAuth(
1787 AuthCredentials(kFoo, kBar), callback2.callback());
1788 EXPECT_EQ(ERR_IO_PENDING, rv);
1790 rv = callback2.WaitForResult();
1791 EXPECT_EQ(OK, rv);
1793 response = trans->GetResponseInfo();
1794 ASSERT_TRUE(response != NULL);
1795 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1796 EXPECT_EQ(5, response->headers->GetContentLength());
1799 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1800 // connection and with a large response body to drain.
1801 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
1802 HttpRequestInfo request;
1803 request.method = "GET";
1804 request.url = GURL("http://www.google.com/");
1805 request.load_flags = 0;
1807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1809 MockWrite data_writes1[] = {
1810 MockWrite("GET / HTTP/1.1\r\n"
1811 "Host: www.google.com\r\n"
1812 "Connection: keep-alive\r\n\r\n"),
1814 // After calling trans->RestartWithAuth(), this is the request we should
1815 // be issuing -- the final header line contains the credentials.
1816 MockWrite("GET / HTTP/1.1\r\n"
1817 "Host: www.google.com\r\n"
1818 "Connection: keep-alive\r\n"
1819 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1822 // Respond with 5 kb of response body.
1823 std::string large_body_string("Unauthorized");
1824 large_body_string.append(5 * 1024, ' ');
1825 large_body_string.append("\r\n");
1827 MockRead data_reads1[] = {
1828 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1829 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1830 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1831 // 5134 = 12 + 5 * 1024 + 2
1832 MockRead("Content-Length: 5134\r\n\r\n"),
1833 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
1835 // Lastly, the server responds with the actual content.
1836 MockRead("HTTP/1.1 200 OK\r\n"),
1837 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1838 MockRead("Content-Length: 5\r\n\r\n"),
1839 MockRead("hello"),
1842 // An incorrect reconnect would cause this to be read.
1843 MockRead data_reads2[] = {
1844 MockRead(SYNCHRONOUS, ERR_FAILED),
1847 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1848 data_writes1, arraysize(data_writes1));
1849 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1850 NULL, 0);
1851 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1852 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1854 TestCompletionCallback callback1;
1856 scoped_ptr<HttpTransaction> trans(
1857 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1858 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1859 EXPECT_EQ(ERR_IO_PENDING, rv);
1861 rv = callback1.WaitForResult();
1862 EXPECT_EQ(OK, rv);
1864 const HttpResponseInfo* response = trans->GetResponseInfo();
1865 ASSERT_TRUE(response != NULL);
1866 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1868 TestCompletionCallback callback2;
1870 rv = trans->RestartWithAuth(
1871 AuthCredentials(kFoo, kBar), callback2.callback());
1872 EXPECT_EQ(ERR_IO_PENDING, rv);
1874 rv = callback2.WaitForResult();
1875 EXPECT_EQ(OK, rv);
1877 response = trans->GetResponseInfo();
1878 ASSERT_TRUE(response != NULL);
1879 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1880 EXPECT_EQ(5, response->headers->GetContentLength());
1883 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1884 // connection, but the server gets impatient and closes the connection.
1885 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1886 HttpRequestInfo request;
1887 request.method = "GET";
1888 request.url = GURL("http://www.google.com/");
1889 request.load_flags = 0;
1891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1893 MockWrite data_writes1[] = {
1894 MockWrite("GET / HTTP/1.1\r\n"
1895 "Host: www.google.com\r\n"
1896 "Connection: keep-alive\r\n\r\n"),
1897 // This simulates the seemingly successful write to a closed connection
1898 // if the bug is not fixed.
1899 MockWrite("GET / HTTP/1.1\r\n"
1900 "Host: www.google.com\r\n"
1901 "Connection: keep-alive\r\n"
1902 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1905 MockRead data_reads1[] = {
1906 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1907 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1909 MockRead("Content-Length: 14\r\n\r\n"),
1910 // Tell MockTCPClientSocket to simulate the server closing the connection.
1911 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1912 MockRead("Unauthorized\r\n"),
1913 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
1916 // After calling trans->RestartWithAuth(), this is the request we should
1917 // be issuing -- the final header line contains the credentials.
1918 MockWrite data_writes2[] = {
1919 MockWrite("GET / HTTP/1.1\r\n"
1920 "Host: www.google.com\r\n"
1921 "Connection: keep-alive\r\n"
1922 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1925 // Lastly, the server responds with the actual content.
1926 MockRead data_reads2[] = {
1927 MockRead("HTTP/1.1 200 OK\r\n"),
1928 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1929 MockRead("Content-Length: 5\r\n\r\n"),
1930 MockRead("hello"),
1933 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1934 data_writes1, arraysize(data_writes1));
1935 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1936 data_writes2, arraysize(data_writes2));
1937 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1938 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1940 TestCompletionCallback callback1;
1942 scoped_ptr<HttpTransaction> trans(
1943 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1944 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1945 EXPECT_EQ(ERR_IO_PENDING, rv);
1947 rv = callback1.WaitForResult();
1948 EXPECT_EQ(OK, rv);
1950 const HttpResponseInfo* response = trans->GetResponseInfo();
1951 ASSERT_TRUE(response != NULL);
1952 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1954 TestCompletionCallback callback2;
1956 rv = trans->RestartWithAuth(
1957 AuthCredentials(kFoo, kBar), callback2.callback());
1958 EXPECT_EQ(ERR_IO_PENDING, rv);
1960 rv = callback2.WaitForResult();
1961 EXPECT_EQ(OK, rv);
1963 response = trans->GetResponseInfo();
1964 ASSERT_TRUE(response != NULL);
1965 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1966 EXPECT_EQ(5, response->headers->GetContentLength());
1969 // Test the request-challenge-retry sequence for basic auth, over a connection
1970 // that requires a restart when setting up an SSL tunnel.
1971 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1972 HttpRequestInfo request;
1973 request.method = "GET";
1974 request.url = GURL("https://www.google.com/");
1975 // when the no authentication data flag is set.
1976 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1978 // Configure against proxy server "myproxy:70".
1979 session_deps_.proxy_service.reset(
1980 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
1981 CapturingBoundNetLog log;
1982 session_deps_.net_log = log.bound().net_log();
1983 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1985 // Since we have proxy, should try to establish tunnel.
1986 MockWrite data_writes1[] = {
1987 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1988 "Host: www.google.com\r\n"
1989 "Proxy-Connection: keep-alive\r\n\r\n"),
1991 // After calling trans->RestartWithAuth(), this is the request we should
1992 // be issuing -- the final header line contains the credentials.
1993 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1994 "Host: www.google.com\r\n"
1995 "Proxy-Connection: keep-alive\r\n"
1996 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1998 MockWrite("GET / HTTP/1.1\r\n"
1999 "Host: www.google.com\r\n"
2000 "Connection: keep-alive\r\n\r\n"),
2003 // The proxy responds to the connect with a 407, using a persistent
2004 // connection.
2005 MockRead data_reads1[] = {
2006 // No credentials.
2007 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2008 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2009 MockRead("Proxy-Connection: close\r\n\r\n"),
2011 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2013 MockRead("HTTP/1.1 200 OK\r\n"),
2014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2015 MockRead("Content-Length: 5\r\n\r\n"),
2016 MockRead(SYNCHRONOUS, "hello"),
2019 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2020 data_writes1, arraysize(data_writes1));
2021 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2022 SSLSocketDataProvider ssl(ASYNC, OK);
2023 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2025 TestCompletionCallback callback1;
2027 scoped_ptr<HttpTransaction> trans(
2028 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2030 int rv = trans->Start(&request, callback1.callback(), log.bound());
2031 EXPECT_EQ(ERR_IO_PENDING, rv);
2033 rv = callback1.WaitForResult();
2034 EXPECT_EQ(OK, rv);
2035 net::CapturingNetLog::CapturedEntryList entries;
2036 log.GetEntries(&entries);
2037 size_t pos = ExpectLogContainsSomewhere(
2038 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2039 NetLog::PHASE_NONE);
2040 ExpectLogContainsSomewhere(
2041 entries, pos,
2042 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2043 NetLog::PHASE_NONE);
2045 const HttpResponseInfo* response = trans->GetResponseInfo();
2046 ASSERT_TRUE(response != NULL);
2047 ASSERT_FALSE(response->headers.get() == NULL);
2048 EXPECT_EQ(407, response->headers->response_code());
2049 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2050 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2052 LoadTimingInfo load_timing_info;
2053 // CONNECT requests and responses are handled at the connect job level, so
2054 // the transaction does not yet have a connection.
2055 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2057 TestCompletionCallback callback2;
2059 rv = trans->RestartWithAuth(
2060 AuthCredentials(kFoo, kBar), callback2.callback());
2061 EXPECT_EQ(ERR_IO_PENDING, rv);
2063 rv = callback2.WaitForResult();
2064 EXPECT_EQ(OK, rv);
2066 response = trans->GetResponseInfo();
2067 ASSERT_TRUE(response != NULL);
2069 EXPECT_TRUE(response->headers->IsKeepAlive());
2070 EXPECT_EQ(200, response->headers->response_code());
2071 EXPECT_EQ(5, response->headers->GetContentLength());
2072 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2074 // The password prompt info should not be set.
2075 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2077 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2078 TestLoadTimingNotReusedWithPac(load_timing_info,
2079 CONNECT_TIMING_HAS_SSL_TIMES);
2081 trans.reset();
2082 session->CloseAllConnections();
2085 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2086 // proxy connection, when setting up an SSL tunnel.
2087 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2088 HttpRequestInfo request;
2089 request.method = "GET";
2090 request.url = GURL("https://www.google.com/");
2091 // Ensure that proxy authentication is attempted even
2092 // when the no authentication data flag is set.
2093 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2095 // Configure against proxy server "myproxy:70".
2096 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2097 CapturingBoundNetLog log;
2098 session_deps_.net_log = log.bound().net_log();
2099 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2101 scoped_ptr<HttpTransaction> trans(
2102 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2104 // Since we have proxy, should try to establish tunnel.
2105 MockWrite data_writes1[] = {
2106 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2107 "Host: www.google.com\r\n"
2108 "Proxy-Connection: keep-alive\r\n\r\n"),
2110 // After calling trans->RestartWithAuth(), this is the request we should
2111 // be issuing -- the final header line contains the credentials.
2112 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2113 "Host: www.google.com\r\n"
2114 "Proxy-Connection: keep-alive\r\n"
2115 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2118 // The proxy responds to the connect with a 407, using a persistent
2119 // connection.
2120 MockRead data_reads1[] = {
2121 // No credentials.
2122 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2123 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2124 MockRead("Content-Length: 10\r\n\r\n"),
2125 MockRead("0123456789"),
2127 // Wrong credentials (wrong password).
2128 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2129 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2130 MockRead("Content-Length: 10\r\n\r\n"),
2131 // No response body because the test stops reading here.
2132 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2135 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2136 data_writes1, arraysize(data_writes1));
2137 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2139 TestCompletionCallback callback1;
2141 int rv = trans->Start(&request, callback1.callback(), log.bound());
2142 EXPECT_EQ(ERR_IO_PENDING, rv);
2144 rv = callback1.WaitForResult();
2145 EXPECT_EQ(OK, rv);
2146 net::CapturingNetLog::CapturedEntryList entries;
2147 log.GetEntries(&entries);
2148 size_t pos = ExpectLogContainsSomewhere(
2149 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2150 NetLog::PHASE_NONE);
2151 ExpectLogContainsSomewhere(
2152 entries, pos,
2153 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2154 NetLog::PHASE_NONE);
2156 const HttpResponseInfo* response = trans->GetResponseInfo();
2157 ASSERT_TRUE(response != NULL);
2158 ASSERT_FALSE(response->headers.get() == NULL);
2159 EXPECT_TRUE(response->headers->IsKeepAlive());
2160 EXPECT_EQ(407, response->headers->response_code());
2161 EXPECT_EQ(10, response->headers->GetContentLength());
2162 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2163 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2165 TestCompletionCallback callback2;
2167 // Wrong password (should be "bar").
2168 rv = trans->RestartWithAuth(
2169 AuthCredentials(kFoo, kBaz), callback2.callback());
2170 EXPECT_EQ(ERR_IO_PENDING, rv);
2172 rv = callback2.WaitForResult();
2173 EXPECT_EQ(OK, rv);
2175 response = trans->GetResponseInfo();
2176 ASSERT_TRUE(response != NULL);
2177 ASSERT_FALSE(response->headers.get() == NULL);
2178 EXPECT_TRUE(response->headers->IsKeepAlive());
2179 EXPECT_EQ(407, response->headers->response_code());
2180 EXPECT_EQ(10, response->headers->GetContentLength());
2181 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2182 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2184 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2185 // out of scope.
2186 session->CloseAllConnections();
2189 // Test that we don't read the response body when we fail to establish a tunnel,
2190 // even if the user cancels the proxy's auth attempt.
2191 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2192 HttpRequestInfo request;
2193 request.method = "GET";
2194 request.url = GURL("https://www.google.com/");
2195 request.load_flags = 0;
2197 // Configure against proxy server "myproxy:70".
2198 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2202 scoped_ptr<HttpTransaction> trans(
2203 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2205 // Since we have proxy, should try to establish tunnel.
2206 MockWrite data_writes[] = {
2207 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2208 "Host: www.google.com\r\n"
2209 "Proxy-Connection: keep-alive\r\n\r\n"),
2212 // The proxy responds to the connect with a 407.
2213 MockRead data_reads[] = {
2214 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2215 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2216 MockRead("Content-Length: 10\r\n\r\n"),
2217 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2220 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2221 data_writes, arraysize(data_writes));
2222 session_deps_.socket_factory->AddSocketDataProvider(&data);
2224 TestCompletionCallback callback;
2226 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2227 EXPECT_EQ(ERR_IO_PENDING, rv);
2229 rv = callback.WaitForResult();
2230 EXPECT_EQ(OK, rv);
2232 const HttpResponseInfo* response = trans->GetResponseInfo();
2233 ASSERT_TRUE(response != NULL);
2235 EXPECT_TRUE(response->headers->IsKeepAlive());
2236 EXPECT_EQ(407, response->headers->response_code());
2237 EXPECT_EQ(10, response->headers->GetContentLength());
2238 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2240 std::string response_data;
2241 rv = ReadTransaction(trans.get(), &response_data);
2242 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2244 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2245 session->CloseAllConnections();
2248 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2249 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2250 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2251 HttpRequestInfo request;
2252 request.method = "GET";
2253 request.url = GURL("http://www.google.com/");
2254 request.load_flags = 0;
2256 // We are using a DIRECT connection (i.e. no proxy) for this session.
2257 scoped_ptr<HttpTransaction> trans(
2258 new HttpNetworkTransaction(DEFAULT_PRIORITY,
2259 CreateSession(&session_deps_)));
2261 MockWrite data_writes1[] = {
2262 MockWrite("GET / HTTP/1.1\r\n"
2263 "Host: www.google.com\r\n"
2264 "Connection: keep-alive\r\n\r\n"),
2267 MockRead data_reads1[] = {
2268 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2269 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2270 // Large content-length -- won't matter, as connection will be reset.
2271 MockRead("Content-Length: 10000\r\n\r\n"),
2272 MockRead(SYNCHRONOUS, ERR_FAILED),
2275 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2276 data_writes1, arraysize(data_writes1));
2277 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2279 TestCompletionCallback callback;
2281 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2282 EXPECT_EQ(ERR_IO_PENDING, rv);
2284 rv = callback.WaitForResult();
2285 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2288 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2289 // through a non-authenticating proxy. The request should fail with
2290 // ERR_UNEXPECTED_PROXY_AUTH.
2291 // Note that it is impossible to detect if an HTTP server returns a 407 through
2292 // a non-authenticating proxy - there is nothing to indicate whether the
2293 // response came from the proxy or the server, so it is treated as if the proxy
2294 // issued the challenge.
2295 TEST_P(HttpNetworkTransactionTest,
2296 HttpsServerRequestsProxyAuthThroughProxy) {
2297 HttpRequestInfo request;
2298 request.method = "GET";
2299 request.url = GURL("https://www.google.com/");
2301 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2302 CapturingBoundNetLog log;
2303 session_deps_.net_log = log.bound().net_log();
2304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2306 // Since we have proxy, should try to establish tunnel.
2307 MockWrite data_writes1[] = {
2308 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2309 "Host: www.google.com\r\n"
2310 "Proxy-Connection: keep-alive\r\n\r\n"),
2312 MockWrite("GET / HTTP/1.1\r\n"
2313 "Host: www.google.com\r\n"
2314 "Connection: keep-alive\r\n\r\n"),
2317 MockRead data_reads1[] = {
2318 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2320 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2321 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2322 MockRead("\r\n"),
2323 MockRead(SYNCHRONOUS, OK),
2326 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2327 data_writes1, arraysize(data_writes1));
2328 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2329 SSLSocketDataProvider ssl(ASYNC, OK);
2330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2332 TestCompletionCallback callback1;
2334 scoped_ptr<HttpTransaction> trans(
2335 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2337 int rv = trans->Start(&request, callback1.callback(), log.bound());
2338 EXPECT_EQ(ERR_IO_PENDING, rv);
2340 rv = callback1.WaitForResult();
2341 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2342 net::CapturingNetLog::CapturedEntryList entries;
2343 log.GetEntries(&entries);
2344 size_t pos = ExpectLogContainsSomewhere(
2345 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2346 NetLog::PHASE_NONE);
2347 ExpectLogContainsSomewhere(
2348 entries, pos,
2349 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2350 NetLog::PHASE_NONE);
2353 // Test the load timing for HTTPS requests with an HTTP proxy.
2354 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2355 HttpRequestInfo request1;
2356 request1.method = "GET";
2357 request1.url = GURL("https://www.google.com/1");
2359 HttpRequestInfo request2;
2360 request2.method = "GET";
2361 request2.url = GURL("https://www.google.com/2");
2363 // Configure against proxy server "myproxy:70".
2364 session_deps_.proxy_service.reset(
2365 ProxyService::CreateFixed("PROXY myproxy:70"));
2366 CapturingBoundNetLog log;
2367 session_deps_.net_log = log.bound().net_log();
2368 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2370 // Since we have proxy, should try to establish tunnel.
2371 MockWrite data_writes1[] = {
2372 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2373 "Host: www.google.com\r\n"
2374 "Proxy-Connection: keep-alive\r\n\r\n"),
2376 MockWrite("GET /1 HTTP/1.1\r\n"
2377 "Host: www.google.com\r\n"
2378 "Connection: keep-alive\r\n\r\n"),
2380 MockWrite("GET /2 HTTP/1.1\r\n"
2381 "Host: www.google.com\r\n"
2382 "Connection: keep-alive\r\n\r\n"),
2385 // The proxy responds to the connect with a 407, using a persistent
2386 // connection.
2387 MockRead data_reads1[] = {
2388 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2390 MockRead("HTTP/1.1 200 OK\r\n"),
2391 MockRead("Content-Length: 1\r\n\r\n"),
2392 MockRead(SYNCHRONOUS, "1"),
2394 MockRead("HTTP/1.1 200 OK\r\n"),
2395 MockRead("Content-Length: 2\r\n\r\n"),
2396 MockRead(SYNCHRONOUS, "22"),
2399 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2400 data_writes1, arraysize(data_writes1));
2401 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2402 SSLSocketDataProvider ssl(ASYNC, OK);
2403 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2405 TestCompletionCallback callback1;
2406 scoped_ptr<HttpTransaction> trans1(
2407 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2409 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2410 EXPECT_EQ(ERR_IO_PENDING, rv);
2412 rv = callback1.WaitForResult();
2413 EXPECT_EQ(OK, rv);
2415 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2416 ASSERT_TRUE(response1 != NULL);
2417 ASSERT_TRUE(response1->headers.get() != NULL);
2418 EXPECT_EQ(1, response1->headers->GetContentLength());
2420 LoadTimingInfo load_timing_info1;
2421 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2422 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2424 trans1.reset();
2426 TestCompletionCallback callback2;
2427 scoped_ptr<HttpTransaction> trans2(
2428 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2430 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2431 EXPECT_EQ(ERR_IO_PENDING, rv);
2433 rv = callback2.WaitForResult();
2434 EXPECT_EQ(OK, rv);
2436 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2437 ASSERT_TRUE(response2 != NULL);
2438 ASSERT_TRUE(response2->headers.get() != NULL);
2439 EXPECT_EQ(2, response2->headers->GetContentLength());
2441 LoadTimingInfo load_timing_info2;
2442 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2443 TestLoadTimingReused(load_timing_info2);
2445 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2447 trans2.reset();
2448 session->CloseAllConnections();
2451 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2452 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2453 HttpRequestInfo request1;
2454 request1.method = "GET";
2455 request1.url = GURL("https://www.google.com/1");
2457 HttpRequestInfo request2;
2458 request2.method = "GET";
2459 request2.url = GURL("https://www.google.com/2");
2461 // Configure against proxy server "myproxy:70".
2462 session_deps_.proxy_service.reset(
2463 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2464 CapturingBoundNetLog log;
2465 session_deps_.net_log = log.bound().net_log();
2466 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2468 // Since we have proxy, should try to establish tunnel.
2469 MockWrite data_writes1[] = {
2470 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2471 "Host: www.google.com\r\n"
2472 "Proxy-Connection: keep-alive\r\n\r\n"),
2474 MockWrite("GET /1 HTTP/1.1\r\n"
2475 "Host: www.google.com\r\n"
2476 "Connection: keep-alive\r\n\r\n"),
2478 MockWrite("GET /2 HTTP/1.1\r\n"
2479 "Host: www.google.com\r\n"
2480 "Connection: keep-alive\r\n\r\n"),
2483 // The proxy responds to the connect with a 407, using a persistent
2484 // connection.
2485 MockRead data_reads1[] = {
2486 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2488 MockRead("HTTP/1.1 200 OK\r\n"),
2489 MockRead("Content-Length: 1\r\n\r\n"),
2490 MockRead(SYNCHRONOUS, "1"),
2492 MockRead("HTTP/1.1 200 OK\r\n"),
2493 MockRead("Content-Length: 2\r\n\r\n"),
2494 MockRead(SYNCHRONOUS, "22"),
2497 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2498 data_writes1, arraysize(data_writes1));
2499 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2500 SSLSocketDataProvider ssl(ASYNC, OK);
2501 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2503 TestCompletionCallback callback1;
2504 scoped_ptr<HttpTransaction> trans1(
2505 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2507 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2508 EXPECT_EQ(ERR_IO_PENDING, rv);
2510 rv = callback1.WaitForResult();
2511 EXPECT_EQ(OK, rv);
2513 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2514 ASSERT_TRUE(response1 != NULL);
2515 ASSERT_TRUE(response1->headers.get() != NULL);
2516 EXPECT_EQ(1, response1->headers->GetContentLength());
2518 LoadTimingInfo load_timing_info1;
2519 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2520 TestLoadTimingNotReusedWithPac(load_timing_info1,
2521 CONNECT_TIMING_HAS_SSL_TIMES);
2523 trans1.reset();
2525 TestCompletionCallback callback2;
2526 scoped_ptr<HttpTransaction> trans2(
2527 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2529 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2530 EXPECT_EQ(ERR_IO_PENDING, rv);
2532 rv = callback2.WaitForResult();
2533 EXPECT_EQ(OK, rv);
2535 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2536 ASSERT_TRUE(response2 != NULL);
2537 ASSERT_TRUE(response2->headers.get() != NULL);
2538 EXPECT_EQ(2, response2->headers->GetContentLength());
2540 LoadTimingInfo load_timing_info2;
2541 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2542 TestLoadTimingReusedWithPac(load_timing_info2);
2544 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2546 trans2.reset();
2547 session->CloseAllConnections();
2550 // Test a simple get through an HTTPS Proxy.
2551 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2552 HttpRequestInfo request;
2553 request.method = "GET";
2554 request.url = GURL("http://www.google.com/");
2556 // Configure against https proxy server "proxy:70".
2557 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2558 "https://proxy:70"));
2559 CapturingBoundNetLog log;
2560 session_deps_.net_log = log.bound().net_log();
2561 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2563 // Since we have proxy, should use full url
2564 MockWrite data_writes1[] = {
2565 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2566 "Host: www.google.com\r\n"
2567 "Proxy-Connection: keep-alive\r\n\r\n"),
2570 MockRead data_reads1[] = {
2571 MockRead("HTTP/1.1 200 OK\r\n"),
2572 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2573 MockRead("Content-Length: 100\r\n\r\n"),
2574 MockRead(SYNCHRONOUS, OK),
2577 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2578 data_writes1, arraysize(data_writes1));
2579 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2580 SSLSocketDataProvider ssl(ASYNC, OK);
2581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2583 TestCompletionCallback callback1;
2585 scoped_ptr<HttpTransaction> trans(
2586 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2588 int rv = trans->Start(&request, callback1.callback(), log.bound());
2589 EXPECT_EQ(ERR_IO_PENDING, rv);
2591 rv = callback1.WaitForResult();
2592 EXPECT_EQ(OK, rv);
2594 LoadTimingInfo load_timing_info;
2595 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2596 TestLoadTimingNotReused(load_timing_info,
2597 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2599 const HttpResponseInfo* response = trans->GetResponseInfo();
2600 ASSERT_TRUE(response != NULL);
2602 EXPECT_TRUE(response->headers->IsKeepAlive());
2603 EXPECT_EQ(200, response->headers->response_code());
2604 EXPECT_EQ(100, response->headers->GetContentLength());
2605 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2607 // The password prompt info should not be set.
2608 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2611 // Test a SPDY get through an HTTPS Proxy.
2612 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2613 HttpRequestInfo request;
2614 request.method = "GET";
2615 request.url = GURL("http://www.google.com/");
2616 request.load_flags = 0;
2618 // Configure against https proxy server "proxy:70".
2619 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2620 "https://proxy:70"));
2621 CapturingBoundNetLog log;
2622 session_deps_.net_log = log.bound().net_log();
2623 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2625 // fetch http://www.google.com/ via SPDY
2626 scoped_ptr<SpdyFrame> req(
2627 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2628 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2630 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2631 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2632 MockRead spdy_reads[] = {
2633 CreateMockRead(*resp),
2634 CreateMockRead(*data),
2635 MockRead(ASYNC, 0, 0),
2638 DelayedSocketData spdy_data(
2639 1, // wait for one write to finish before reading.
2640 spdy_reads, arraysize(spdy_reads),
2641 spdy_writes, arraysize(spdy_writes));
2642 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2644 SSLSocketDataProvider ssl(ASYNC, OK);
2645 ssl.SetNextProto(GetParam());
2646 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2648 TestCompletionCallback callback1;
2650 scoped_ptr<HttpTransaction> trans(
2651 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2653 int rv = trans->Start(&request, callback1.callback(), log.bound());
2654 EXPECT_EQ(ERR_IO_PENDING, rv);
2656 rv = callback1.WaitForResult();
2657 EXPECT_EQ(OK, rv);
2659 LoadTimingInfo load_timing_info;
2660 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2661 TestLoadTimingNotReused(load_timing_info,
2662 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2664 const HttpResponseInfo* response = trans->GetResponseInfo();
2665 ASSERT_TRUE(response != NULL);
2666 ASSERT_TRUE(response->headers.get() != NULL);
2667 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2669 std::string response_data;
2670 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2671 EXPECT_EQ(kUploadData, response_data);
2674 // Test a SPDY get through an HTTPS Proxy.
2675 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
2676 HttpRequestInfo request;
2677 request.method = "GET";
2678 request.url = GURL("http://www.google.com/");
2679 request.load_flags = 0;
2681 // Configure against https proxy server "myproxy:70".
2682 session_deps_.proxy_service.reset(
2683 ProxyService::CreateFixed("https://myproxy:70"));
2684 CapturingBoundNetLog log;
2685 session_deps_.net_log = log.bound().net_log();
2686 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2688 // The first request will be a bare GET, the second request will be a
2689 // GET with a Proxy-Authorization header.
2690 scoped_ptr<SpdyFrame> req_get(
2691 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2692 const char* const kExtraAuthorizationHeaders[] = {
2693 "proxy-authorization", "Basic Zm9vOmJhcg=="
2695 scoped_ptr<SpdyFrame> req_get_authorization(
2696 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
2697 arraysize(kExtraAuthorizationHeaders) / 2,
2698 false,
2700 LOWEST,
2701 false));
2702 MockWrite spdy_writes[] = {
2703 CreateMockWrite(*req_get, 1),
2704 CreateMockWrite(*req_get_authorization, 4),
2707 // The first response is a 407 proxy authentication challenge, and the second
2708 // response will be a 200 response since the second request includes a valid
2709 // Authorization header.
2710 const char* const kExtraAuthenticationHeaders[] = {
2711 "proxy-authenticate", "Basic realm=\"MyRealm1\""
2713 scoped_ptr<SpdyFrame> resp_authentication(
2714 spdy_util_.ConstructSpdySynReplyError(
2715 "407 Proxy Authentication Required",
2716 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2717 1));
2718 scoped_ptr<SpdyFrame> body_authentication(
2719 spdy_util_.ConstructSpdyBodyFrame(1, true));
2720 scoped_ptr<SpdyFrame> resp_data(
2721 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2722 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
2723 MockRead spdy_reads[] = {
2724 CreateMockRead(*resp_authentication, 2),
2725 CreateMockRead(*body_authentication, 3),
2726 CreateMockRead(*resp_data, 5),
2727 CreateMockRead(*body_data, 6),
2728 MockRead(ASYNC, 0, 7),
2731 OrderedSocketData data(
2732 spdy_reads, arraysize(spdy_reads),
2733 spdy_writes, arraysize(spdy_writes));
2734 session_deps_.socket_factory->AddSocketDataProvider(&data);
2736 SSLSocketDataProvider ssl(ASYNC, OK);
2737 ssl.SetNextProto(GetParam());
2738 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2740 TestCompletionCallback callback1;
2742 scoped_ptr<HttpTransaction> trans(
2743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2745 int rv = trans->Start(&request, callback1.callback(), log.bound());
2746 EXPECT_EQ(ERR_IO_PENDING, rv);
2748 rv = callback1.WaitForResult();
2749 EXPECT_EQ(OK, rv);
2751 const HttpResponseInfo* const response = trans->GetResponseInfo();
2753 ASSERT_TRUE(response != NULL);
2754 ASSERT_TRUE(response->headers.get() != NULL);
2755 EXPECT_EQ(407, response->headers->response_code());
2756 EXPECT_TRUE(response->was_fetched_via_spdy);
2757 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2759 TestCompletionCallback callback2;
2761 rv = trans->RestartWithAuth(
2762 AuthCredentials(kFoo, kBar), callback2.callback());
2763 EXPECT_EQ(ERR_IO_PENDING, rv);
2765 rv = callback2.WaitForResult();
2766 EXPECT_EQ(OK, rv);
2768 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2770 ASSERT_TRUE(response_restart != NULL);
2771 ASSERT_TRUE(response_restart->headers.get() != NULL);
2772 EXPECT_EQ(200, response_restart->headers->response_code());
2773 // The password prompt info should not be set.
2774 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2777 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2778 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
2779 HttpRequestInfo request;
2780 request.method = "GET";
2781 request.url = GURL("https://www.google.com/");
2782 request.load_flags = 0;
2784 // Configure against https proxy server "proxy:70".
2785 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2786 "https://proxy:70"));
2787 CapturingBoundNetLog log;
2788 session_deps_.net_log = log.bound().net_log();
2789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2791 scoped_ptr<HttpTransaction> trans(
2792 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2794 // CONNECT to www.google.com:443 via SPDY
2795 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
2796 // fetch https://www.google.com/ via HTTP
2798 const char get[] = "GET / HTTP/1.1\r\n"
2799 "Host: www.google.com\r\n"
2800 "Connection: keep-alive\r\n\r\n";
2801 scoped_ptr<SpdyFrame> wrapped_get(
2802 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
2803 scoped_ptr<SpdyFrame> conn_resp(
2804 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2805 const char resp[] = "HTTP/1.1 200 OK\r\n"
2806 "Content-Length: 10\r\n\r\n";
2807 scoped_ptr<SpdyFrame> wrapped_get_resp(
2808 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2809 scoped_ptr<SpdyFrame> wrapped_body(
2810 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2811 scoped_ptr<SpdyFrame> window_update(
2812 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
2814 MockWrite spdy_writes[] = {
2815 CreateMockWrite(*connect, 1),
2816 CreateMockWrite(*wrapped_get, 3),
2817 CreateMockWrite(*window_update, 5),
2820 MockRead spdy_reads[] = {
2821 CreateMockRead(*conn_resp, 2, ASYNC),
2822 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2823 CreateMockRead(*wrapped_body, 6, ASYNC),
2824 CreateMockRead(*wrapped_body, 7, ASYNC),
2825 MockRead(ASYNC, 0, 8),
2828 OrderedSocketData spdy_data(
2829 spdy_reads, arraysize(spdy_reads),
2830 spdy_writes, arraysize(spdy_writes));
2831 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2833 SSLSocketDataProvider ssl(ASYNC, OK);
2834 ssl.SetNextProto(GetParam());
2835 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2836 SSLSocketDataProvider ssl2(ASYNC, OK);
2837 ssl2.was_npn_negotiated = false;
2838 ssl2.protocol_negotiated = kProtoUnknown;
2839 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2841 TestCompletionCallback callback1;
2843 int rv = trans->Start(&request, callback1.callback(), log.bound());
2844 EXPECT_EQ(ERR_IO_PENDING, rv);
2846 rv = callback1.WaitForResult();
2847 EXPECT_EQ(OK, rv);
2849 LoadTimingInfo load_timing_info;
2850 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2851 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
2853 const HttpResponseInfo* response = trans->GetResponseInfo();
2854 ASSERT_TRUE(response != NULL);
2855 ASSERT_TRUE(response->headers.get() != NULL);
2856 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2858 std::string response_data;
2859 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2860 EXPECT_EQ("1234567890", response_data);
2863 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2864 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
2865 HttpRequestInfo request;
2866 request.method = "GET";
2867 request.url = GURL("https://www.google.com/");
2868 request.load_flags = 0;
2870 // Configure against https proxy server "proxy:70".
2871 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2872 "https://proxy:70"));
2873 CapturingBoundNetLog log;
2874 session_deps_.net_log = log.bound().net_log();
2875 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2877 scoped_ptr<HttpTransaction> trans(
2878 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2880 // CONNECT to www.google.com:443 via SPDY
2881 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
2882 // fetch https://www.google.com/ via SPDY
2883 const char* const kMyUrl = "https://www.google.com/";
2884 scoped_ptr<SpdyFrame> get(
2885 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2886 scoped_ptr<SpdyFrame> wrapped_get(
2887 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
2888 scoped_ptr<SpdyFrame> conn_resp(
2889 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2890 scoped_ptr<SpdyFrame> get_resp(
2891 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2892 scoped_ptr<SpdyFrame> wrapped_get_resp(
2893 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
2894 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2895 scoped_ptr<SpdyFrame> wrapped_body(
2896 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
2897 scoped_ptr<SpdyFrame> window_update_get_resp(
2898 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
2899 scoped_ptr<SpdyFrame> window_update_body(
2900 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
2902 MockWrite spdy_writes[] = {
2903 CreateMockWrite(*connect, 1),
2904 CreateMockWrite(*wrapped_get, 3),
2905 CreateMockWrite(*window_update_get_resp, 5),
2906 CreateMockWrite(*window_update_body, 7),
2909 MockRead spdy_reads[] = {
2910 CreateMockRead(*conn_resp, 2, ASYNC),
2911 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2912 CreateMockRead(*wrapped_body, 6, ASYNC),
2913 MockRead(ASYNC, 0, 8),
2916 OrderedSocketData spdy_data(
2917 spdy_reads, arraysize(spdy_reads),
2918 spdy_writes, arraysize(spdy_writes));
2919 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2921 SSLSocketDataProvider ssl(ASYNC, OK);
2922 ssl.SetNextProto(GetParam());
2923 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2924 SSLSocketDataProvider ssl2(ASYNC, OK);
2925 ssl2.SetNextProto(GetParam());
2926 ssl2.protocol_negotiated = GetParam();
2927 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2929 TestCompletionCallback callback1;
2931 int rv = trans->Start(&request, callback1.callback(), log.bound());
2932 EXPECT_EQ(ERR_IO_PENDING, rv);
2934 rv = callback1.WaitForResult();
2935 EXPECT_EQ(OK, rv);
2937 LoadTimingInfo load_timing_info;
2938 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2939 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
2941 const HttpResponseInfo* response = trans->GetResponseInfo();
2942 ASSERT_TRUE(response != NULL);
2943 ASSERT_TRUE(response->headers.get() != NULL);
2944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2946 std::string response_data;
2947 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2948 EXPECT_EQ(kUploadData, response_data);
2951 // Test a SPDY CONNECT failure through an HTTPS Proxy.
2952 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
2953 HttpRequestInfo request;
2954 request.method = "GET";
2955 request.url = GURL("https://www.google.com/");
2956 request.load_flags = 0;
2958 // Configure against https proxy server "proxy:70".
2959 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2960 "https://proxy:70"));
2961 CapturingBoundNetLog log;
2962 session_deps_.net_log = log.bound().net_log();
2963 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2965 scoped_ptr<HttpTransaction> trans(
2966 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2968 // CONNECT to www.google.com:443 via SPDY
2969 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
2970 scoped_ptr<SpdyFrame> get(
2971 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2973 MockWrite spdy_writes[] = {
2974 CreateMockWrite(*connect, 1),
2975 CreateMockWrite(*get, 3),
2978 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
2979 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2980 MockRead spdy_reads[] = {
2981 CreateMockRead(*resp, 2, ASYNC),
2982 MockRead(ASYNC, 0, 4),
2985 OrderedSocketData spdy_data(
2986 spdy_reads, arraysize(spdy_reads),
2987 spdy_writes, arraysize(spdy_writes));
2988 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2990 SSLSocketDataProvider ssl(ASYNC, OK);
2991 ssl.SetNextProto(GetParam());
2992 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2993 SSLSocketDataProvider ssl2(ASYNC, OK);
2994 ssl2.SetNextProto(GetParam());
2995 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2997 TestCompletionCallback callback1;
2999 int rv = trans->Start(&request, callback1.callback(), log.bound());
3000 EXPECT_EQ(ERR_IO_PENDING, rv);
3002 rv = callback1.WaitForResult();
3003 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3005 // TODO(ttuttle): Anything else to check here?
3008 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3009 // HTTPS Proxy to different servers.
3010 TEST_P(HttpNetworkTransactionTest,
3011 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3012 // Configure against https proxy server "proxy:70".
3013 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3014 "https://proxy:70"));
3015 CapturingBoundNetLog log;
3016 session_deps_.net_log = log.bound().net_log();
3017 scoped_refptr<HttpNetworkSession> session(
3018 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3020 HttpRequestInfo request1;
3021 request1.method = "GET";
3022 request1.url = GURL("https://www.google.com/");
3023 request1.load_flags = 0;
3025 HttpRequestInfo request2;
3026 request2.method = "GET";
3027 request2.url = GURL("https://news.google.com/");
3028 request2.load_flags = 0;
3030 // CONNECT to www.google.com:443 via SPDY.
3031 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
3032 scoped_ptr<SpdyFrame> conn_resp1(
3033 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3035 // Fetch https://www.google.com/ via HTTP.
3036 const char get1[] = "GET / HTTP/1.1\r\n"
3037 "Host: www.google.com\r\n"
3038 "Connection: keep-alive\r\n\r\n";
3039 scoped_ptr<SpdyFrame> wrapped_get1(
3040 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3041 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3042 "Content-Length: 1\r\n\r\n";
3043 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3044 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3045 scoped_ptr<SpdyFrame> wrapped_body1(
3046 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3047 scoped_ptr<SpdyFrame> window_update(
3048 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3050 // CONNECT to news.google.com:443 via SPDY.
3051 const char* const kConnectHeaders2[] = {
3052 spdy_util_.GetMethodKey(), "CONNECT",
3053 spdy_util_.GetPathKey(), "news.google.com:443",
3054 spdy_util_.GetHostKey(), "news.google.com",
3055 spdy_util_.GetVersionKey(), "HTTP/1.1",
3057 scoped_ptr<SpdyFrame> connect2(
3058 spdy_util_.ConstructSpdyControlFrame(NULL,
3060 /*compressed*/ false,
3062 LOWEST,
3063 SYN_STREAM,
3064 CONTROL_FLAG_NONE,
3065 kConnectHeaders2,
3066 arraysize(kConnectHeaders2),
3067 0));
3068 scoped_ptr<SpdyFrame> conn_resp2(
3069 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3071 // Fetch https://news.google.com/ via HTTP.
3072 const char get2[] = "GET / HTTP/1.1\r\n"
3073 "Host: news.google.com\r\n"
3074 "Connection: keep-alive\r\n\r\n";
3075 scoped_ptr<SpdyFrame> wrapped_get2(
3076 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3077 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3078 "Content-Length: 2\r\n\r\n";
3079 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3080 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3081 scoped_ptr<SpdyFrame> wrapped_body2(
3082 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3084 MockWrite spdy_writes[] = {
3085 CreateMockWrite(*connect1, 0),
3086 CreateMockWrite(*wrapped_get1, 2),
3087 CreateMockWrite(*connect2, 5),
3088 CreateMockWrite(*wrapped_get2, 7),
3091 MockRead spdy_reads[] = {
3092 CreateMockRead(*conn_resp1, 1, ASYNC),
3093 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3094 CreateMockRead(*wrapped_body1, 4, ASYNC),
3095 CreateMockRead(*conn_resp2, 6, ASYNC),
3096 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3097 CreateMockRead(*wrapped_body2, 9, ASYNC),
3098 MockRead(ASYNC, 0, 10),
3101 DeterministicSocketData spdy_data(
3102 spdy_reads, arraysize(spdy_reads),
3103 spdy_writes, arraysize(spdy_writes));
3104 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3106 SSLSocketDataProvider ssl(ASYNC, OK);
3107 ssl.SetNextProto(GetParam());
3108 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3109 SSLSocketDataProvider ssl2(ASYNC, OK);
3110 ssl2.was_npn_negotiated = false;
3111 ssl2.protocol_negotiated = kProtoUnknown;
3112 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3113 SSLSocketDataProvider ssl3(ASYNC, OK);
3114 ssl3.was_npn_negotiated = false;
3115 ssl3.protocol_negotiated = kProtoUnknown;
3116 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3118 TestCompletionCallback callback;
3120 scoped_ptr<HttpTransaction> trans(
3121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3122 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3123 EXPECT_EQ(ERR_IO_PENDING, rv);
3124 // The first connect and request, each of their responses, and the body.
3125 spdy_data.RunFor(5);
3127 rv = callback.WaitForResult();
3128 EXPECT_EQ(OK, rv);
3130 LoadTimingInfo load_timing_info;
3131 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3132 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3134 const HttpResponseInfo* response = trans->GetResponseInfo();
3135 ASSERT_TRUE(response != NULL);
3136 ASSERT_TRUE(response->headers.get() != NULL);
3137 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3139 std::string response_data;
3140 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3141 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3143 scoped_ptr<HttpTransaction> trans2(
3144 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3145 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3146 EXPECT_EQ(ERR_IO_PENDING, rv);
3148 // The second connect and request, each of their responses, and the body.
3149 spdy_data.RunFor(5);
3150 rv = callback.WaitForResult();
3151 EXPECT_EQ(OK, rv);
3153 LoadTimingInfo load_timing_info2;
3154 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3155 // Even though the SPDY connection is reused, a new tunnelled connection has
3156 // to be created, so the socket's load timing looks like a fresh connection.
3157 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3159 // The requests should have different IDs, since they each are using their own
3160 // separate stream.
3161 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3163 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3166 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3167 // HTTPS Proxy to the same server.
3168 TEST_P(HttpNetworkTransactionTest,
3169 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3170 // Configure against https proxy server "proxy:70".
3171 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3172 "https://proxy:70"));
3173 CapturingBoundNetLog log;
3174 session_deps_.net_log = log.bound().net_log();
3175 scoped_refptr<HttpNetworkSession> session(
3176 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3178 HttpRequestInfo request1;
3179 request1.method = "GET";
3180 request1.url = GURL("https://www.google.com/");
3181 request1.load_flags = 0;
3183 HttpRequestInfo request2;
3184 request2.method = "GET";
3185 request2.url = GURL("https://www.google.com/2");
3186 request2.load_flags = 0;
3188 // CONNECT to www.google.com:443 via SPDY.
3189 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
3190 scoped_ptr<SpdyFrame> conn_resp1(
3191 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3193 // Fetch https://www.google.com/ via HTTP.
3194 const char get1[] = "GET / HTTP/1.1\r\n"
3195 "Host: www.google.com\r\n"
3196 "Connection: keep-alive\r\n\r\n";
3197 scoped_ptr<SpdyFrame> wrapped_get1(
3198 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3199 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3200 "Content-Length: 1\r\n\r\n";
3201 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3202 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3203 scoped_ptr<SpdyFrame> wrapped_body1(
3204 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3205 scoped_ptr<SpdyFrame> window_update(
3206 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3208 // Fetch https://www.google.com/2 via HTTP.
3209 const char get2[] = "GET /2 HTTP/1.1\r\n"
3210 "Host: www.google.com\r\n"
3211 "Connection: keep-alive\r\n\r\n";
3212 scoped_ptr<SpdyFrame> wrapped_get2(
3213 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3214 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3215 "Content-Length: 2\r\n\r\n";
3216 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3217 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3218 scoped_ptr<SpdyFrame> wrapped_body2(
3219 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3221 MockWrite spdy_writes[] = {
3222 CreateMockWrite(*connect1, 0),
3223 CreateMockWrite(*wrapped_get1, 2),
3224 CreateMockWrite(*wrapped_get2, 5),
3227 MockRead spdy_reads[] = {
3228 CreateMockRead(*conn_resp1, 1, ASYNC),
3229 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3230 CreateMockRead(*wrapped_body1, 4, ASYNC),
3231 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3232 CreateMockRead(*wrapped_body2, 7, ASYNC),
3233 MockRead(ASYNC, 0, 8),
3236 DeterministicSocketData spdy_data(
3237 spdy_reads, arraysize(spdy_reads),
3238 spdy_writes, arraysize(spdy_writes));
3239 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3241 SSLSocketDataProvider ssl(ASYNC, OK);
3242 ssl.SetNextProto(GetParam());
3243 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3244 SSLSocketDataProvider ssl2(ASYNC, OK);
3245 ssl2.was_npn_negotiated = false;
3246 ssl2.protocol_negotiated = kProtoUnknown;
3247 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3249 TestCompletionCallback callback;
3251 scoped_ptr<HttpTransaction> trans(
3252 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3253 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3254 EXPECT_EQ(ERR_IO_PENDING, rv);
3255 // The first connect and request, each of their responses, and the body.
3256 spdy_data.RunFor(5);
3258 rv = callback.WaitForResult();
3259 EXPECT_EQ(OK, rv);
3261 LoadTimingInfo load_timing_info;
3262 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3263 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3265 const HttpResponseInfo* response = trans->GetResponseInfo();
3266 ASSERT_TRUE(response != NULL);
3267 ASSERT_TRUE(response->headers.get() != NULL);
3268 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3270 std::string response_data;
3271 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3272 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3273 trans.reset();
3275 scoped_ptr<HttpTransaction> trans2(
3276 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3277 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3278 EXPECT_EQ(ERR_IO_PENDING, rv);
3280 // The second request, response, and body. There should not be a second
3281 // connect.
3282 spdy_data.RunFor(3);
3283 rv = callback.WaitForResult();
3284 EXPECT_EQ(OK, rv);
3286 LoadTimingInfo load_timing_info2;
3287 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3288 TestLoadTimingReused(load_timing_info2);
3290 // The requests should have the same ID.
3291 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3293 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3296 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3297 // Proxy to different servers.
3298 TEST_P(HttpNetworkTransactionTest,
3299 HttpsProxySpdyLoadTimingTwoHttpRequests) {
3300 // Configure against https proxy server "proxy:70".
3301 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3302 "https://proxy:70"));
3303 CapturingBoundNetLog log;
3304 session_deps_.net_log = log.bound().net_log();
3305 scoped_refptr<HttpNetworkSession> session(
3306 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3308 HttpRequestInfo request1;
3309 request1.method = "GET";
3310 request1.url = GURL("http://www.google.com/");
3311 request1.load_flags = 0;
3313 HttpRequestInfo request2;
3314 request2.method = "GET";
3315 request2.url = GURL("http://news.google.com/");
3316 request2.load_flags = 0;
3318 // http://www.google.com/
3319 scoped_ptr<SpdyHeaderBlock> headers(
3320 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3321 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
3322 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3323 scoped_ptr<SpdyFrame> get_resp1(
3324 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3325 scoped_ptr<SpdyFrame> body1(
3326 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3328 // http://news.google.com/
3329 scoped_ptr<SpdyHeaderBlock> headers2(
3330 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3331 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
3332 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3333 scoped_ptr<SpdyFrame> get_resp2(
3334 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3335 scoped_ptr<SpdyFrame> body2(
3336 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3338 MockWrite spdy_writes[] = {
3339 CreateMockWrite(*get1, 0),
3340 CreateMockWrite(*get2, 3),
3343 MockRead spdy_reads[] = {
3344 CreateMockRead(*get_resp1, 1, ASYNC),
3345 CreateMockRead(*body1, 2, ASYNC),
3346 CreateMockRead(*get_resp2, 4, ASYNC),
3347 CreateMockRead(*body2, 5, ASYNC),
3348 MockRead(ASYNC, 0, 6),
3351 DeterministicSocketData spdy_data(
3352 spdy_reads, arraysize(spdy_reads),
3353 spdy_writes, arraysize(spdy_writes));
3354 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3356 SSLSocketDataProvider ssl(ASYNC, OK);
3357 ssl.SetNextProto(GetParam());
3358 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3360 TestCompletionCallback callback;
3362 scoped_ptr<HttpTransaction> trans(
3363 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3364 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3365 EXPECT_EQ(ERR_IO_PENDING, rv);
3366 spdy_data.RunFor(2);
3368 rv = callback.WaitForResult();
3369 EXPECT_EQ(OK, rv);
3371 LoadTimingInfo load_timing_info;
3372 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3373 TestLoadTimingNotReused(load_timing_info,
3374 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3376 const HttpResponseInfo* response = trans->GetResponseInfo();
3377 ASSERT_TRUE(response != NULL);
3378 ASSERT_TRUE(response->headers.get() != NULL);
3379 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3381 std::string response_data;
3382 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3383 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3384 spdy_data.RunFor(1);
3385 EXPECT_EQ(1, callback.WaitForResult());
3386 // Delete the first request, so the second one can reuse the socket.
3387 trans.reset();
3389 scoped_ptr<HttpTransaction> trans2(
3390 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3391 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3392 EXPECT_EQ(ERR_IO_PENDING, rv);
3394 spdy_data.RunFor(2);
3395 rv = callback.WaitForResult();
3396 EXPECT_EQ(OK, rv);
3398 LoadTimingInfo load_timing_info2;
3399 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3400 TestLoadTimingReused(load_timing_info2);
3402 // The requests should have the same ID.
3403 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3405 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3406 spdy_data.RunFor(1);
3407 EXPECT_EQ(2, callback.WaitForResult());
3410 // Test the challenge-response-retry sequence through an HTTPS Proxy
3411 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3412 HttpRequestInfo request;
3413 request.method = "GET";
3414 request.url = GURL("http://www.google.com/");
3415 // when the no authentication data flag is set.
3416 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3418 // Configure against https proxy server "myproxy:70".
3419 session_deps_.proxy_service.reset(
3420 ProxyService::CreateFixed("https://myproxy:70"));
3421 CapturingBoundNetLog log;
3422 session_deps_.net_log = log.bound().net_log();
3423 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3425 // Since we have proxy, should use full url
3426 MockWrite data_writes1[] = {
3427 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3428 "Host: www.google.com\r\n"
3429 "Proxy-Connection: keep-alive\r\n\r\n"),
3431 // After calling trans->RestartWithAuth(), this is the request we should
3432 // be issuing -- the final header line contains the credentials.
3433 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3434 "Host: www.google.com\r\n"
3435 "Proxy-Connection: keep-alive\r\n"
3436 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3439 // The proxy responds to the GET with a 407, using a persistent
3440 // connection.
3441 MockRead data_reads1[] = {
3442 // No credentials.
3443 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3444 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3445 MockRead("Proxy-Connection: keep-alive\r\n"),
3446 MockRead("Content-Length: 0\r\n\r\n"),
3448 MockRead("HTTP/1.1 200 OK\r\n"),
3449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3450 MockRead("Content-Length: 100\r\n\r\n"),
3451 MockRead(SYNCHRONOUS, OK),
3454 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3455 data_writes1, arraysize(data_writes1));
3456 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3457 SSLSocketDataProvider ssl(ASYNC, OK);
3458 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3460 TestCompletionCallback callback1;
3462 scoped_ptr<HttpTransaction> trans(
3463 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3465 int rv = trans->Start(&request, callback1.callback(), log.bound());
3466 EXPECT_EQ(ERR_IO_PENDING, rv);
3468 rv = callback1.WaitForResult();
3469 EXPECT_EQ(OK, rv);
3471 LoadTimingInfo load_timing_info;
3472 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3473 TestLoadTimingNotReused(load_timing_info,
3474 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3476 const HttpResponseInfo* response = trans->GetResponseInfo();
3477 ASSERT_TRUE(response != NULL);
3478 ASSERT_FALSE(response->headers.get() == NULL);
3479 EXPECT_EQ(407, response->headers->response_code());
3480 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3481 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3483 TestCompletionCallback callback2;
3485 rv = trans->RestartWithAuth(
3486 AuthCredentials(kFoo, kBar), callback2.callback());
3487 EXPECT_EQ(ERR_IO_PENDING, rv);
3489 rv = callback2.WaitForResult();
3490 EXPECT_EQ(OK, rv);
3492 load_timing_info = LoadTimingInfo();
3493 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3494 // Retrying with HTTP AUTH is considered to be reusing a socket.
3495 TestLoadTimingReused(load_timing_info);
3497 response = trans->GetResponseInfo();
3498 ASSERT_TRUE(response != NULL);
3500 EXPECT_TRUE(response->headers->IsKeepAlive());
3501 EXPECT_EQ(200, response->headers->response_code());
3502 EXPECT_EQ(100, response->headers->GetContentLength());
3503 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3505 // The password prompt info should not be set.
3506 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3509 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3510 const MockRead& status, int expected_status) {
3511 HttpRequestInfo request;
3512 request.method = "GET";
3513 request.url = GURL("https://www.google.com/");
3514 request.load_flags = 0;
3516 // Configure against proxy server "myproxy:70".
3517 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3519 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3521 // Since we have proxy, should try to establish tunnel.
3522 MockWrite data_writes[] = {
3523 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3524 "Host: www.google.com\r\n"
3525 "Proxy-Connection: keep-alive\r\n\r\n"),
3528 MockRead data_reads[] = {
3529 status,
3530 MockRead("Content-Length: 10\r\n\r\n"),
3531 // No response body because the test stops reading here.
3532 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3535 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3536 data_writes, arraysize(data_writes));
3537 session_deps_.socket_factory->AddSocketDataProvider(&data);
3539 TestCompletionCallback callback;
3541 scoped_ptr<HttpTransaction> trans(
3542 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3544 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3545 EXPECT_EQ(ERR_IO_PENDING, rv);
3547 rv = callback.WaitForResult();
3548 EXPECT_EQ(expected_status, rv);
3551 void HttpNetworkTransactionTest::ConnectStatusHelper(
3552 const MockRead& status) {
3553 ConnectStatusHelperWithExpectedStatus(
3554 status, ERR_TUNNEL_CONNECTION_FAILED);
3557 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3558 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3561 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3562 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3565 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3566 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3569 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3570 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3573 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
3574 ConnectStatusHelper(
3575 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3578 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
3579 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3582 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
3583 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3586 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
3587 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3590 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
3591 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3594 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
3595 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3598 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
3599 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3602 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
3603 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3606 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
3607 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3610 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
3611 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3614 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
3615 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3618 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
3619 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3622 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
3623 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3626 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
3627 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3630 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
3631 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3634 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
3635 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3638 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
3639 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3642 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
3643 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3646 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
3647 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3650 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
3651 ConnectStatusHelperWithExpectedStatus(
3652 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3653 ERR_PROXY_AUTH_UNSUPPORTED);
3656 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
3657 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3660 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
3661 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3664 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
3665 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
3668 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
3669 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
3672 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
3673 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
3676 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
3677 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
3680 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
3681 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
3684 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
3685 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
3688 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
3689 ConnectStatusHelper(
3690 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
3693 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
3694 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
3697 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
3698 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
3701 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
3702 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
3705 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
3706 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
3709 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
3710 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
3713 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
3714 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
3717 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
3718 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
3721 // Test the flow when both the proxy server AND origin server require
3722 // authentication. Again, this uses basic auth for both since that is
3723 // the simplest to mock.
3724 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
3725 HttpRequestInfo request;
3726 request.method = "GET";
3727 request.url = GURL("http://www.google.com/");
3728 request.load_flags = 0;
3730 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3732 // Configure against proxy server "myproxy:70".
3733 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY,
3734 CreateSession(&session_deps_)));
3736 MockWrite data_writes1[] = {
3737 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3738 "Host: www.google.com\r\n"
3739 "Proxy-Connection: keep-alive\r\n\r\n"),
3742 MockRead data_reads1[] = {
3743 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
3744 // Give a couple authenticate options (only the middle one is actually
3745 // supported).
3746 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
3747 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3748 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3749 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3750 // Large content-length -- won't matter, as connection will be reset.
3751 MockRead("Content-Length: 10000\r\n\r\n"),
3752 MockRead(SYNCHRONOUS, ERR_FAILED),
3755 // After calling trans->RestartWithAuth() the first time, this is the
3756 // request we should be issuing -- the final header line contains the
3757 // proxy's credentials.
3758 MockWrite data_writes2[] = {
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"
3762 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3765 // Now the proxy server lets the request pass through to origin server.
3766 // The origin server responds with a 401.
3767 MockRead data_reads2[] = {
3768 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3769 // Note: We are using the same realm-name as the proxy server. This is
3770 // completely valid, as realms are unique across hosts.
3771 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3772 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3773 MockRead("Content-Length: 2000\r\n\r\n"),
3774 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
3777 // After calling trans->RestartWithAuth() the second time, we should send
3778 // the credentials for both the proxy and origin server.
3779 MockWrite data_writes3[] = {
3780 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3781 "Host: www.google.com\r\n"
3782 "Proxy-Connection: keep-alive\r\n"
3783 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
3784 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3787 // Lastly we get the desired content.
3788 MockRead data_reads3[] = {
3789 MockRead("HTTP/1.0 200 OK\r\n"),
3790 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3791 MockRead("Content-Length: 100\r\n\r\n"),
3792 MockRead(SYNCHRONOUS, OK),
3795 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3796 data_writes1, arraysize(data_writes1));
3797 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3798 data_writes2, arraysize(data_writes2));
3799 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3800 data_writes3, arraysize(data_writes3));
3801 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3802 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3803 session_deps_.socket_factory->AddSocketDataProvider(&data3);
3805 TestCompletionCallback callback1;
3807 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3808 EXPECT_EQ(ERR_IO_PENDING, rv);
3810 rv = callback1.WaitForResult();
3811 EXPECT_EQ(OK, rv);
3813 const HttpResponseInfo* response = trans->GetResponseInfo();
3814 ASSERT_TRUE(response != NULL);
3815 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3817 TestCompletionCallback callback2;
3819 rv = trans->RestartWithAuth(
3820 AuthCredentials(kFoo, kBar), callback2.callback());
3821 EXPECT_EQ(ERR_IO_PENDING, rv);
3823 rv = callback2.WaitForResult();
3824 EXPECT_EQ(OK, rv);
3826 response = trans->GetResponseInfo();
3827 ASSERT_TRUE(response != NULL);
3828 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
3830 TestCompletionCallback callback3;
3832 rv = trans->RestartWithAuth(
3833 AuthCredentials(kFoo2, kBar2), callback3.callback());
3834 EXPECT_EQ(ERR_IO_PENDING, rv);
3836 rv = callback3.WaitForResult();
3837 EXPECT_EQ(OK, rv);
3839 response = trans->GetResponseInfo();
3840 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3841 EXPECT_EQ(100, response->headers->GetContentLength());
3844 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
3845 // can't hook into its internals to cause it to generate predictable NTLM
3846 // authorization headers.
3847 #if defined(NTLM_PORTABLE)
3848 // The NTLM authentication unit tests were generated by capturing the HTTP
3849 // requests and responses using Fiddler 2 and inspecting the generated random
3850 // bytes in the debugger.
3852 // Enter the correct password and authenticate successfully.
3853 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
3854 HttpRequestInfo request;
3855 request.method = "GET";
3856 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3857 request.load_flags = 0;
3859 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
3860 MockGetHostName);
3861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3863 MockWrite data_writes1[] = {
3864 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3865 "Host: 172.22.68.17\r\n"
3866 "Connection: keep-alive\r\n\r\n"),
3869 MockRead data_reads1[] = {
3870 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3871 // Negotiate and NTLM are often requested together. However, we only want
3872 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3873 // the header that requests Negotiate for this test.
3874 MockRead("WWW-Authenticate: NTLM\r\n"),
3875 MockRead("Connection: close\r\n"),
3876 MockRead("Content-Length: 42\r\n"),
3877 MockRead("Content-Type: text/html\r\n\r\n"),
3878 // Missing content -- won't matter, as connection will be reset.
3879 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
3882 MockWrite data_writes2[] = {
3883 // After restarting with a null identity, this is the
3884 // request we should be issuing -- the final header line contains a Type
3885 // 1 message.
3886 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3887 "Host: 172.22.68.17\r\n"
3888 "Connection: keep-alive\r\n"
3889 "Authorization: NTLM "
3890 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3892 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3893 // (the credentials for the origin server). The second request continues
3894 // on the same connection.
3895 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3896 "Host: 172.22.68.17\r\n"
3897 "Connection: keep-alive\r\n"
3898 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3899 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3900 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
3901 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
3902 "ahlhx5I=\r\n\r\n"),
3905 MockRead data_reads2[] = {
3906 // The origin server responds with a Type 2 message.
3907 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3908 MockRead("WWW-Authenticate: NTLM "
3909 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
3910 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3911 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3912 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3913 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3914 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3915 "BtAAAAAAA=\r\n"),
3916 MockRead("Content-Length: 42\r\n"),
3917 MockRead("Content-Type: text/html\r\n\r\n"),
3918 MockRead("You are not authorized to view this page\r\n"),
3920 // Lastly we get the desired content.
3921 MockRead("HTTP/1.1 200 OK\r\n"),
3922 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3923 MockRead("Content-Length: 13\r\n\r\n"),
3924 MockRead("Please Login\r\n"),
3925 MockRead(SYNCHRONOUS, OK),
3928 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3929 data_writes1, arraysize(data_writes1));
3930 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3931 data_writes2, arraysize(data_writes2));
3932 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3933 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3935 TestCompletionCallback callback1;
3937 scoped_ptr<HttpTransaction> trans(
3938 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3940 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3941 EXPECT_EQ(ERR_IO_PENDING, rv);
3943 rv = callback1.WaitForResult();
3944 EXPECT_EQ(OK, rv);
3946 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3948 const HttpResponseInfo* response = trans->GetResponseInfo();
3949 ASSERT_FALSE(response == NULL);
3950 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
3952 TestCompletionCallback callback2;
3954 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
3955 callback2.callback());
3956 EXPECT_EQ(ERR_IO_PENDING, rv);
3958 rv = callback2.WaitForResult();
3959 EXPECT_EQ(OK, rv);
3961 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3963 response = trans->GetResponseInfo();
3964 ASSERT_TRUE(response != NULL);
3965 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3967 TestCompletionCallback callback3;
3969 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
3970 EXPECT_EQ(ERR_IO_PENDING, rv);
3972 rv = callback3.WaitForResult();
3973 EXPECT_EQ(OK, rv);
3975 response = trans->GetResponseInfo();
3976 ASSERT_TRUE(response != NULL);
3977 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3978 EXPECT_EQ(13, response->headers->GetContentLength());
3981 // Enter a wrong password, and then the correct one.
3982 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
3983 HttpRequestInfo request;
3984 request.method = "GET";
3985 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3986 request.load_flags = 0;
3988 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3989 MockGetHostName);
3990 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3992 MockWrite data_writes1[] = {
3993 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3994 "Host: 172.22.68.17\r\n"
3995 "Connection: keep-alive\r\n\r\n"),
3998 MockRead data_reads1[] = {
3999 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4000 // Negotiate and NTLM are often requested together. However, we only want
4001 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4002 // the header that requests Negotiate for this test.
4003 MockRead("WWW-Authenticate: NTLM\r\n"),
4004 MockRead("Connection: close\r\n"),
4005 MockRead("Content-Length: 42\r\n"),
4006 MockRead("Content-Type: text/html\r\n\r\n"),
4007 // Missing content -- won't matter, as connection will be reset.
4008 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4011 MockWrite data_writes2[] = {
4012 // After restarting with a null identity, this is the
4013 // request we should be issuing -- the final header line contains a Type
4014 // 1 message.
4015 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4016 "Host: 172.22.68.17\r\n"
4017 "Connection: keep-alive\r\n"
4018 "Authorization: NTLM "
4019 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4021 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4022 // (the credentials for the origin server). The second request continues
4023 // on the same connection.
4024 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4025 "Host: 172.22.68.17\r\n"
4026 "Connection: keep-alive\r\n"
4027 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4028 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4029 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4030 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4031 "4Ww7b7E=\r\n\r\n"),
4034 MockRead data_reads2[] = {
4035 // The origin server responds with a Type 2 message.
4036 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4037 MockRead("WWW-Authenticate: NTLM "
4038 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4039 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4040 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4041 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4042 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4043 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4044 "BtAAAAAAA=\r\n"),
4045 MockRead("Content-Length: 42\r\n"),
4046 MockRead("Content-Type: text/html\r\n\r\n"),
4047 MockRead("You are not authorized to view this page\r\n"),
4049 // Wrong password.
4050 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4051 MockRead("WWW-Authenticate: NTLM\r\n"),
4052 MockRead("Connection: close\r\n"),
4053 MockRead("Content-Length: 42\r\n"),
4054 MockRead("Content-Type: text/html\r\n\r\n"),
4055 // Missing content -- won't matter, as connection will be reset.
4056 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4059 MockWrite data_writes3[] = {
4060 // After restarting with a null identity, this is the
4061 // request we should be issuing -- the final header line contains a Type
4062 // 1 message.
4063 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4064 "Host: 172.22.68.17\r\n"
4065 "Connection: keep-alive\r\n"
4066 "Authorization: NTLM "
4067 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4069 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4070 // (the credentials for the origin server). The second request continues
4071 // on the same connection.
4072 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4073 "Host: 172.22.68.17\r\n"
4074 "Connection: keep-alive\r\n"
4075 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4076 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4077 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4078 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4079 "+4MUm7c=\r\n\r\n"),
4082 MockRead data_reads3[] = {
4083 // The origin server responds with a Type 2 message.
4084 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4085 MockRead("WWW-Authenticate: NTLM "
4086 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4087 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4088 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4089 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4090 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4091 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4092 "BtAAAAAAA=\r\n"),
4093 MockRead("Content-Length: 42\r\n"),
4094 MockRead("Content-Type: text/html\r\n\r\n"),
4095 MockRead("You are not authorized to view this page\r\n"),
4097 // Lastly we get the desired content.
4098 MockRead("HTTP/1.1 200 OK\r\n"),
4099 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4100 MockRead("Content-Length: 13\r\n\r\n"),
4101 MockRead("Please Login\r\n"),
4102 MockRead(SYNCHRONOUS, OK),
4105 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4106 data_writes1, arraysize(data_writes1));
4107 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4108 data_writes2, arraysize(data_writes2));
4109 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4110 data_writes3, arraysize(data_writes3));
4111 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4112 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4113 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4115 TestCompletionCallback callback1;
4117 scoped_ptr<HttpTransaction> trans(
4118 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4120 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4121 EXPECT_EQ(ERR_IO_PENDING, rv);
4123 rv = callback1.WaitForResult();
4124 EXPECT_EQ(OK, rv);
4126 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4128 const HttpResponseInfo* response = trans->GetResponseInfo();
4129 ASSERT_TRUE(response != NULL);
4130 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4132 TestCompletionCallback callback2;
4134 // Enter the wrong password.
4135 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4136 callback2.callback());
4137 EXPECT_EQ(ERR_IO_PENDING, rv);
4139 rv = callback2.WaitForResult();
4140 EXPECT_EQ(OK, rv);
4142 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4143 TestCompletionCallback callback3;
4144 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4145 EXPECT_EQ(ERR_IO_PENDING, rv);
4146 rv = callback3.WaitForResult();
4147 EXPECT_EQ(OK, rv);
4148 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4150 response = trans->GetResponseInfo();
4151 ASSERT_FALSE(response == NULL);
4152 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4154 TestCompletionCallback callback4;
4156 // Now enter the right password.
4157 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4158 callback4.callback());
4159 EXPECT_EQ(ERR_IO_PENDING, rv);
4161 rv = callback4.WaitForResult();
4162 EXPECT_EQ(OK, rv);
4164 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4166 TestCompletionCallback callback5;
4168 // One more roundtrip
4169 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4170 EXPECT_EQ(ERR_IO_PENDING, rv);
4172 rv = callback5.WaitForResult();
4173 EXPECT_EQ(OK, rv);
4175 response = trans->GetResponseInfo();
4176 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4177 EXPECT_EQ(13, response->headers->GetContentLength());
4179 #endif // NTLM_PORTABLE
4181 // Test reading a server response which has only headers, and no body.
4182 // After some maximum number of bytes is consumed, the transaction should
4183 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4184 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4185 HttpRequestInfo request;
4186 request.method = "GET";
4187 request.url = GURL("http://www.google.com/");
4188 request.load_flags = 0;
4190 scoped_ptr<HttpTransaction> trans(
4191 new HttpNetworkTransaction(DEFAULT_PRIORITY,
4192 CreateSession(&session_deps_)));
4194 // Respond with 300 kb of headers (we should fail after 256 kb).
4195 std::string large_headers_string;
4196 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4198 MockRead data_reads[] = {
4199 MockRead("HTTP/1.0 200 OK\r\n"),
4200 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4201 MockRead("\r\nBODY"),
4202 MockRead(SYNCHRONOUS, OK),
4204 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4205 session_deps_.socket_factory->AddSocketDataProvider(&data);
4207 TestCompletionCallback callback;
4209 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4210 EXPECT_EQ(ERR_IO_PENDING, rv);
4212 rv = callback.WaitForResult();
4213 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4215 const HttpResponseInfo* response = trans->GetResponseInfo();
4216 EXPECT_TRUE(response == NULL);
4219 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4220 // establish tunnel.
4221 // http://code.google.com/p/chromium/issues/detail?id=3772
4222 TEST_P(HttpNetworkTransactionTest,
4223 DontRecycleTransportSocketForSSLTunnel) {
4224 HttpRequestInfo request;
4225 request.method = "GET";
4226 request.url = GURL("https://www.google.com/");
4227 request.load_flags = 0;
4229 // Configure against proxy server "myproxy:70".
4230 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4232 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4234 scoped_ptr<HttpTransaction> trans(
4235 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4237 // Since we have proxy, should try to establish tunnel.
4238 MockWrite data_writes1[] = {
4239 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4240 "Host: www.google.com\r\n"
4241 "Proxy-Connection: keep-alive\r\n\r\n"),
4244 // The proxy responds to the connect with a 404, using a persistent
4245 // connection. Usually a proxy would return 501 (not implemented),
4246 // or 200 (tunnel established).
4247 MockRead data_reads1[] = {
4248 MockRead("HTTP/1.1 404 Not Found\r\n"),
4249 MockRead("Content-Length: 10\r\n\r\n"),
4250 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4253 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4254 data_writes1, arraysize(data_writes1));
4255 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4257 TestCompletionCallback callback1;
4259 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4260 EXPECT_EQ(ERR_IO_PENDING, rv);
4262 rv = callback1.WaitForResult();
4263 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4265 const HttpResponseInfo* response = trans->GetResponseInfo();
4266 EXPECT_TRUE(response == NULL);
4268 // Empty the current queue. This is necessary because idle sockets are
4269 // added to the connection pool asynchronously with a PostTask.
4270 base::MessageLoop::current()->RunUntilIdle();
4272 // We now check to make sure the TCPClientSocket was not added back to
4273 // the pool.
4274 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4275 trans.reset();
4276 base::MessageLoop::current()->RunUntilIdle();
4277 // Make sure that the socket didn't get recycled after calling the destructor.
4278 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4281 // Make sure that we recycle a socket after reading all of the response body.
4282 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4283 HttpRequestInfo request;
4284 request.method = "GET";
4285 request.url = GURL("http://www.google.com/");
4286 request.load_flags = 0;
4288 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4290 scoped_ptr<HttpTransaction> trans(
4291 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4293 MockRead data_reads[] = {
4294 // A part of the response body is received with the response headers.
4295 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4296 // The rest of the response body is received in two parts.
4297 MockRead("lo"),
4298 MockRead(" world"),
4299 MockRead("junk"), // Should not be read!!
4300 MockRead(SYNCHRONOUS, OK),
4303 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4304 session_deps_.socket_factory->AddSocketDataProvider(&data);
4306 TestCompletionCallback callback;
4308 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4309 EXPECT_EQ(ERR_IO_PENDING, rv);
4311 rv = callback.WaitForResult();
4312 EXPECT_EQ(OK, rv);
4314 const HttpResponseInfo* response = trans->GetResponseInfo();
4315 ASSERT_TRUE(response != NULL);
4317 EXPECT_TRUE(response->headers.get() != NULL);
4318 std::string status_line = response->headers->GetStatusLine();
4319 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4321 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4323 std::string response_data;
4324 rv = ReadTransaction(trans.get(), &response_data);
4325 EXPECT_EQ(OK, rv);
4326 EXPECT_EQ("hello world", response_data);
4328 // Empty the current queue. This is necessary because idle sockets are
4329 // added to the connection pool asynchronously with a PostTask.
4330 base::MessageLoop::current()->RunUntilIdle();
4332 // We now check to make sure the socket was added back to the pool.
4333 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4336 // Make sure that we recycle a SSL socket after reading all of the response
4337 // body.
4338 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4339 HttpRequestInfo request;
4340 request.method = "GET";
4341 request.url = GURL("https://www.google.com/");
4342 request.load_flags = 0;
4344 MockWrite data_writes[] = {
4345 MockWrite("GET / HTTP/1.1\r\n"
4346 "Host: www.google.com\r\n"
4347 "Connection: keep-alive\r\n\r\n"),
4350 MockRead data_reads[] = {
4351 MockRead("HTTP/1.1 200 OK\r\n"),
4352 MockRead("Content-Length: 11\r\n\r\n"),
4353 MockRead("hello world"),
4354 MockRead(SYNCHRONOUS, OK),
4357 SSLSocketDataProvider ssl(ASYNC, OK);
4358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4360 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4361 data_writes, arraysize(data_writes));
4362 session_deps_.socket_factory->AddSocketDataProvider(&data);
4364 TestCompletionCallback callback;
4366 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4367 scoped_ptr<HttpTransaction> trans(
4368 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4370 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4372 EXPECT_EQ(ERR_IO_PENDING, rv);
4373 EXPECT_EQ(OK, callback.WaitForResult());
4375 const HttpResponseInfo* response = trans->GetResponseInfo();
4376 ASSERT_TRUE(response != NULL);
4377 ASSERT_TRUE(response->headers.get() != NULL);
4378 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4380 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4382 std::string response_data;
4383 rv = ReadTransaction(trans.get(), &response_data);
4384 EXPECT_EQ(OK, rv);
4385 EXPECT_EQ("hello world", response_data);
4387 // Empty the current queue. This is necessary because idle sockets are
4388 // added to the connection pool asynchronously with a PostTask.
4389 base::MessageLoop::current()->RunUntilIdle();
4391 // We now check to make sure the socket was added back to the pool.
4392 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4395 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4396 // from the pool and make sure that we recover okay.
4397 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4398 HttpRequestInfo request;
4399 request.method = "GET";
4400 request.url = GURL("https://www.google.com/");
4401 request.load_flags = 0;
4403 MockWrite data_writes[] = {
4404 MockWrite("GET / HTTP/1.1\r\n"
4405 "Host: www.google.com\r\n"
4406 "Connection: keep-alive\r\n\r\n"),
4407 MockWrite("GET / HTTP/1.1\r\n"
4408 "Host: www.google.com\r\n"
4409 "Connection: keep-alive\r\n\r\n"),
4412 MockRead data_reads[] = {
4413 MockRead("HTTP/1.1 200 OK\r\n"),
4414 MockRead("Content-Length: 11\r\n\r\n"),
4415 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4416 MockRead("hello world"),
4417 MockRead(ASYNC, 0, 0) // EOF
4420 SSLSocketDataProvider ssl(ASYNC, OK);
4421 SSLSocketDataProvider ssl2(ASYNC, OK);
4422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4425 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4426 data_writes, arraysize(data_writes));
4427 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4428 data_writes, arraysize(data_writes));
4429 session_deps_.socket_factory->AddSocketDataProvider(&data);
4430 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4432 TestCompletionCallback callback;
4434 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4435 scoped_ptr<HttpTransaction> trans(
4436 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4438 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4440 EXPECT_EQ(ERR_IO_PENDING, rv);
4441 EXPECT_EQ(OK, callback.WaitForResult());
4443 const HttpResponseInfo* response = trans->GetResponseInfo();
4444 ASSERT_TRUE(response != NULL);
4445 ASSERT_TRUE(response->headers.get() != NULL);
4446 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4448 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4450 std::string response_data;
4451 rv = ReadTransaction(trans.get(), &response_data);
4452 EXPECT_EQ(OK, rv);
4453 EXPECT_EQ("hello world", response_data);
4455 // Empty the current queue. This is necessary because idle sockets are
4456 // added to the connection pool asynchronously with a PostTask.
4457 base::MessageLoop::current()->RunUntilIdle();
4459 // We now check to make sure the socket was added back to the pool.
4460 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4462 // Now start the second transaction, which should reuse the previous socket.
4464 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4466 rv = trans->Start(&request, callback.callback(), BoundNetLog());
4468 EXPECT_EQ(ERR_IO_PENDING, rv);
4469 EXPECT_EQ(OK, callback.WaitForResult());
4471 response = trans->GetResponseInfo();
4472 ASSERT_TRUE(response != NULL);
4473 ASSERT_TRUE(response->headers.get() != NULL);
4474 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4476 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4478 rv = ReadTransaction(trans.get(), &response_data);
4479 EXPECT_EQ(OK, rv);
4480 EXPECT_EQ("hello world", response_data);
4482 // Empty the current queue. This is necessary because idle sockets are
4483 // added to the connection pool asynchronously with a PostTask.
4484 base::MessageLoop::current()->RunUntilIdle();
4486 // We now check to make sure the socket was added back to the pool.
4487 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4490 // Make sure that we recycle a socket after a zero-length response.
4491 // http://crbug.com/9880
4492 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4493 HttpRequestInfo request;
4494 request.method = "GET";
4495 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4496 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4497 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4498 "rt=prt.2642,ol.2649,xjs.2951");
4499 request.load_flags = 0;
4501 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4503 scoped_ptr<HttpTransaction> trans(
4504 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4506 MockRead data_reads[] = {
4507 MockRead("HTTP/1.1 204 No Content\r\n"
4508 "Content-Length: 0\r\n"
4509 "Content-Type: text/html\r\n\r\n"),
4510 MockRead("junk"), // Should not be read!!
4511 MockRead(SYNCHRONOUS, OK),
4514 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4515 session_deps_.socket_factory->AddSocketDataProvider(&data);
4517 TestCompletionCallback callback;
4519 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4520 EXPECT_EQ(ERR_IO_PENDING, rv);
4522 rv = callback.WaitForResult();
4523 EXPECT_EQ(OK, rv);
4525 const HttpResponseInfo* response = trans->GetResponseInfo();
4526 ASSERT_TRUE(response != NULL);
4528 EXPECT_TRUE(response->headers.get() != NULL);
4529 std::string status_line = response->headers->GetStatusLine();
4530 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4532 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4534 std::string response_data;
4535 rv = ReadTransaction(trans.get(), &response_data);
4536 EXPECT_EQ(OK, rv);
4537 EXPECT_EQ("", response_data);
4539 // Empty the current queue. This is necessary because idle sockets are
4540 // added to the connection pool asynchronously with a PostTask.
4541 base::MessageLoop::current()->RunUntilIdle();
4543 // We now check to make sure the socket was added back to the pool.
4544 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4547 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
4548 ScopedVector<UploadElementReader> element_readers;
4549 element_readers.push_back(new UploadBytesElementReader("foo", 3));
4550 UploadDataStream upload_data_stream(&element_readers, 0);
4552 HttpRequestInfo request[2];
4553 // Transaction 1: a GET request that succeeds. The socket is recycled
4554 // after use.
4555 request[0].method = "GET";
4556 request[0].url = GURL("http://www.google.com/");
4557 request[0].load_flags = 0;
4558 // Transaction 2: a POST request. Reuses the socket kept alive from
4559 // transaction 1. The first attempts fails when writing the POST data.
4560 // This causes the transaction to retry with a new socket. The second
4561 // attempt succeeds.
4562 request[1].method = "POST";
4563 request[1].url = GURL("http://www.google.com/login.cgi");
4564 request[1].upload_data_stream = &upload_data_stream;
4565 request[1].load_flags = 0;
4567 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4569 // The first socket is used for transaction 1 and the first attempt of
4570 // transaction 2.
4572 // The response of transaction 1.
4573 MockRead data_reads1[] = {
4574 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4575 MockRead("hello world"),
4576 MockRead(SYNCHRONOUS, OK),
4578 // The mock write results of transaction 1 and the first attempt of
4579 // transaction 2.
4580 MockWrite data_writes1[] = {
4581 MockWrite(SYNCHRONOUS, 64), // GET
4582 MockWrite(SYNCHRONOUS, 93), // POST
4583 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
4585 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4586 data_writes1, arraysize(data_writes1));
4588 // The second socket is used for the second attempt of transaction 2.
4590 // The response of transaction 2.
4591 MockRead data_reads2[] = {
4592 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4593 MockRead("welcome"),
4594 MockRead(SYNCHRONOUS, OK),
4596 // The mock write results of the second attempt of transaction 2.
4597 MockWrite data_writes2[] = {
4598 MockWrite(SYNCHRONOUS, 93), // POST
4599 MockWrite(SYNCHRONOUS, 3), // POST data
4601 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4602 data_writes2, arraysize(data_writes2));
4604 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4605 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4607 const char* kExpectedResponseData[] = {
4608 "hello world", "welcome"
4611 for (int i = 0; i < 2; ++i) {
4612 scoped_ptr<HttpTransaction> trans(
4613 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4615 TestCompletionCallback callback;
4617 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
4618 EXPECT_EQ(ERR_IO_PENDING, rv);
4620 rv = callback.WaitForResult();
4621 EXPECT_EQ(OK, rv);
4623 const HttpResponseInfo* response = trans->GetResponseInfo();
4624 ASSERT_TRUE(response != NULL);
4626 EXPECT_TRUE(response->headers.get() != NULL);
4627 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4629 std::string response_data;
4630 rv = ReadTransaction(trans.get(), &response_data);
4631 EXPECT_EQ(OK, rv);
4632 EXPECT_EQ(kExpectedResponseData[i], response_data);
4636 // Test the request-challenge-retry sequence for basic auth when there is
4637 // an identity in the URL. The request should be sent as normal, but when
4638 // it fails the identity from the URL is used to answer the challenge.
4639 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
4640 HttpRequestInfo request;
4641 request.method = "GET";
4642 request.url = GURL("http://foo:b@r@www.google.com/");
4643 request.load_flags = LOAD_NORMAL;
4645 scoped_ptr<HttpTransaction> trans(
4646 new HttpNetworkTransaction(DEFAULT_PRIORITY,
4647 CreateSession(&session_deps_)));
4649 // The password contains an escaped character -- for this test to pass it
4650 // will need to be unescaped by HttpNetworkTransaction.
4651 EXPECT_EQ("b%40r", request.url.password());
4653 MockWrite data_writes1[] = {
4654 MockWrite("GET / HTTP/1.1\r\n"
4655 "Host: www.google.com\r\n"
4656 "Connection: keep-alive\r\n\r\n"),
4659 MockRead data_reads1[] = {
4660 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4661 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4662 MockRead("Content-Length: 10\r\n\r\n"),
4663 MockRead(SYNCHRONOUS, ERR_FAILED),
4666 // After the challenge above, the transaction will be restarted using the
4667 // identity from the url (foo, b@r) to answer the challenge.
4668 MockWrite data_writes2[] = {
4669 MockWrite("GET / HTTP/1.1\r\n"
4670 "Host: www.google.com\r\n"
4671 "Connection: keep-alive\r\n"
4672 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
4675 MockRead data_reads2[] = {
4676 MockRead("HTTP/1.0 200 OK\r\n"),
4677 MockRead("Content-Length: 100\r\n\r\n"),
4678 MockRead(SYNCHRONOUS, OK),
4681 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4682 data_writes1, arraysize(data_writes1));
4683 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4684 data_writes2, arraysize(data_writes2));
4685 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4686 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4688 TestCompletionCallback callback1;
4689 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4690 EXPECT_EQ(ERR_IO_PENDING, rv);
4691 rv = callback1.WaitForResult();
4692 EXPECT_EQ(OK, rv);
4693 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4695 TestCompletionCallback callback2;
4696 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4697 EXPECT_EQ(ERR_IO_PENDING, rv);
4698 rv = callback2.WaitForResult();
4699 EXPECT_EQ(OK, rv);
4700 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4702 const HttpResponseInfo* response = trans->GetResponseInfo();
4703 ASSERT_TRUE(response != NULL);
4705 // There is no challenge info, since the identity in URL worked.
4706 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4708 EXPECT_EQ(100, response->headers->GetContentLength());
4710 // Empty the current queue.
4711 base::MessageLoop::current()->RunUntilIdle();
4714 // Test the request-challenge-retry sequence for basic auth when there is an
4715 // incorrect identity in the URL. The identity from the URL should be used only
4716 // once.
4717 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
4718 HttpRequestInfo request;
4719 request.method = "GET";
4720 // Note: the URL has a username:password in it. The password "baz" is
4721 // wrong (should be "bar").
4722 request.url = GURL("http://foo:baz@www.google.com/");
4724 request.load_flags = LOAD_NORMAL;
4726 scoped_ptr<HttpTransaction> trans(
4727 new HttpNetworkTransaction(DEFAULT_PRIORITY,
4728 CreateSession(&session_deps_)));
4730 MockWrite data_writes1[] = {
4731 MockWrite("GET / HTTP/1.1\r\n"
4732 "Host: www.google.com\r\n"
4733 "Connection: keep-alive\r\n\r\n"),
4736 MockRead data_reads1[] = {
4737 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4738 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4739 MockRead("Content-Length: 10\r\n\r\n"),
4740 MockRead(SYNCHRONOUS, ERR_FAILED),
4743 // After the challenge above, the transaction will be restarted using the
4744 // identity from the url (foo, baz) to answer the challenge.
4745 MockWrite data_writes2[] = {
4746 MockWrite("GET / HTTP/1.1\r\n"
4747 "Host: www.google.com\r\n"
4748 "Connection: keep-alive\r\n"
4749 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
4752 MockRead data_reads2[] = {
4753 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4754 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4755 MockRead("Content-Length: 10\r\n\r\n"),
4756 MockRead(SYNCHRONOUS, ERR_FAILED),
4759 // After the challenge above, the transaction will be restarted using the
4760 // identity supplied by the user (foo, bar) to answer the challenge.
4761 MockWrite data_writes3[] = {
4762 MockWrite("GET / HTTP/1.1\r\n"
4763 "Host: www.google.com\r\n"
4764 "Connection: keep-alive\r\n"
4765 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4768 MockRead data_reads3[] = {
4769 MockRead("HTTP/1.0 200 OK\r\n"),
4770 MockRead("Content-Length: 100\r\n\r\n"),
4771 MockRead(SYNCHRONOUS, OK),
4774 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4775 data_writes1, arraysize(data_writes1));
4776 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4777 data_writes2, arraysize(data_writes2));
4778 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4779 data_writes3, arraysize(data_writes3));
4780 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4781 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4782 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4784 TestCompletionCallback callback1;
4786 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4787 EXPECT_EQ(ERR_IO_PENDING, rv);
4789 rv = callback1.WaitForResult();
4790 EXPECT_EQ(OK, rv);
4792 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4793 TestCompletionCallback callback2;
4794 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4795 EXPECT_EQ(ERR_IO_PENDING, rv);
4796 rv = callback2.WaitForResult();
4797 EXPECT_EQ(OK, rv);
4798 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4800 const HttpResponseInfo* response = trans->GetResponseInfo();
4801 ASSERT_TRUE(response != NULL);
4802 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4804 TestCompletionCallback callback3;
4805 rv = trans->RestartWithAuth(
4806 AuthCredentials(kFoo, kBar), callback3.callback());
4807 EXPECT_EQ(ERR_IO_PENDING, rv);
4808 rv = callback3.WaitForResult();
4809 EXPECT_EQ(OK, rv);
4810 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4812 response = trans->GetResponseInfo();
4813 ASSERT_TRUE(response != NULL);
4815 // There is no challenge info, since the identity worked.
4816 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4818 EXPECT_EQ(100, response->headers->GetContentLength());
4820 // Empty the current queue.
4821 base::MessageLoop::current()->RunUntilIdle();
4824 // Test that previously tried username/passwords for a realm get re-used.
4825 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
4826 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4828 // Transaction 1: authenticate (foo, bar) on MyRealm1
4830 HttpRequestInfo request;
4831 request.method = "GET";
4832 request.url = GURL("http://www.google.com/x/y/z");
4833 request.load_flags = 0;
4835 scoped_ptr<HttpTransaction> trans(
4836 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4838 MockWrite data_writes1[] = {
4839 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4840 "Host: www.google.com\r\n"
4841 "Connection: keep-alive\r\n\r\n"),
4844 MockRead data_reads1[] = {
4845 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4846 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4847 MockRead("Content-Length: 10000\r\n\r\n"),
4848 MockRead(SYNCHRONOUS, ERR_FAILED),
4851 // Resend with authorization (username=foo, password=bar)
4852 MockWrite data_writes2[] = {
4853 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4854 "Host: www.google.com\r\n"
4855 "Connection: keep-alive\r\n"
4856 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4859 // Sever accepts the authorization.
4860 MockRead data_reads2[] = {
4861 MockRead("HTTP/1.0 200 OK\r\n"),
4862 MockRead("Content-Length: 100\r\n\r\n"),
4863 MockRead(SYNCHRONOUS, OK),
4866 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4867 data_writes1, arraysize(data_writes1));
4868 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4869 data_writes2, arraysize(data_writes2));
4870 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4871 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4873 TestCompletionCallback callback1;
4875 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4876 EXPECT_EQ(ERR_IO_PENDING, rv);
4878 rv = callback1.WaitForResult();
4879 EXPECT_EQ(OK, rv);
4881 const HttpResponseInfo* response = trans->GetResponseInfo();
4882 ASSERT_TRUE(response != NULL);
4883 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4885 TestCompletionCallback callback2;
4887 rv = trans->RestartWithAuth(
4888 AuthCredentials(kFoo, kBar), callback2.callback());
4889 EXPECT_EQ(ERR_IO_PENDING, rv);
4891 rv = callback2.WaitForResult();
4892 EXPECT_EQ(OK, rv);
4894 response = trans->GetResponseInfo();
4895 ASSERT_TRUE(response != NULL);
4896 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4897 EXPECT_EQ(100, response->headers->GetContentLength());
4900 // ------------------------------------------------------------------------
4902 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
4904 HttpRequestInfo request;
4905 request.method = "GET";
4906 // Note that Transaction 1 was at /x/y/z, so this is in the same
4907 // protection space as MyRealm1.
4908 request.url = GURL("http://www.google.com/x/y/a/b");
4909 request.load_flags = 0;
4911 scoped_ptr<HttpTransaction> trans(
4912 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4914 MockWrite data_writes1[] = {
4915 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4916 "Host: www.google.com\r\n"
4917 "Connection: keep-alive\r\n"
4918 // Send preemptive authorization for MyRealm1
4919 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4922 // The server didn't like the preemptive authorization, and
4923 // challenges us for a different realm (MyRealm2).
4924 MockRead data_reads1[] = {
4925 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4926 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
4927 MockRead("Content-Length: 10000\r\n\r\n"),
4928 MockRead(SYNCHRONOUS, ERR_FAILED),
4931 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
4932 MockWrite data_writes2[] = {
4933 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4934 "Host: www.google.com\r\n"
4935 "Connection: keep-alive\r\n"
4936 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4939 // Sever accepts the authorization.
4940 MockRead data_reads2[] = {
4941 MockRead("HTTP/1.0 200 OK\r\n"),
4942 MockRead("Content-Length: 100\r\n\r\n"),
4943 MockRead(SYNCHRONOUS, OK),
4946 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4947 data_writes1, arraysize(data_writes1));
4948 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4949 data_writes2, arraysize(data_writes2));
4950 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4951 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4953 TestCompletionCallback callback1;
4955 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4956 EXPECT_EQ(ERR_IO_PENDING, rv);
4958 rv = callback1.WaitForResult();
4959 EXPECT_EQ(OK, rv);
4961 const HttpResponseInfo* response = trans->GetResponseInfo();
4962 ASSERT_TRUE(response != NULL);
4963 ASSERT_TRUE(response->auth_challenge.get());
4964 EXPECT_FALSE(response->auth_challenge->is_proxy);
4965 EXPECT_EQ("www.google.com:80",
4966 response->auth_challenge->challenger.ToString());
4967 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
4968 EXPECT_EQ("basic", response->auth_challenge->scheme);
4970 TestCompletionCallback callback2;
4972 rv = trans->RestartWithAuth(
4973 AuthCredentials(kFoo2, kBar2), callback2.callback());
4974 EXPECT_EQ(ERR_IO_PENDING, rv);
4976 rv = callback2.WaitForResult();
4977 EXPECT_EQ(OK, rv);
4979 response = trans->GetResponseInfo();
4980 ASSERT_TRUE(response != NULL);
4981 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4982 EXPECT_EQ(100, response->headers->GetContentLength());
4985 // ------------------------------------------------------------------------
4987 // Transaction 3: Resend a request in MyRealm's protection space --
4988 // succeed with preemptive authorization.
4990 HttpRequestInfo request;
4991 request.method = "GET";
4992 request.url = GURL("http://www.google.com/x/y/z2");
4993 request.load_flags = 0;
4995 scoped_ptr<HttpTransaction> trans(
4996 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4998 MockWrite data_writes1[] = {
4999 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5000 "Host: www.google.com\r\n"
5001 "Connection: keep-alive\r\n"
5002 // The authorization for MyRealm1 gets sent preemptively
5003 // (since the url is in the same protection space)
5004 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5007 // Sever accepts the preemptive authorization
5008 MockRead data_reads1[] = {
5009 MockRead("HTTP/1.0 200 OK\r\n"),
5010 MockRead("Content-Length: 100\r\n\r\n"),
5011 MockRead(SYNCHRONOUS, OK),
5014 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5015 data_writes1, arraysize(data_writes1));
5016 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5018 TestCompletionCallback callback1;
5020 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5021 EXPECT_EQ(ERR_IO_PENDING, rv);
5023 rv = callback1.WaitForResult();
5024 EXPECT_EQ(OK, rv);
5026 const HttpResponseInfo* response = trans->GetResponseInfo();
5027 ASSERT_TRUE(response != NULL);
5029 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5030 EXPECT_EQ(100, response->headers->GetContentLength());
5033 // ------------------------------------------------------------------------
5035 // Transaction 4: request another URL in MyRealm (however the
5036 // url is not known to belong to the protection space, so no pre-auth).
5038 HttpRequestInfo request;
5039 request.method = "GET";
5040 request.url = GURL("http://www.google.com/x/1");
5041 request.load_flags = 0;
5043 scoped_ptr<HttpTransaction> trans(
5044 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5046 MockWrite data_writes1[] = {
5047 MockWrite("GET /x/1 HTTP/1.1\r\n"
5048 "Host: www.google.com\r\n"
5049 "Connection: keep-alive\r\n\r\n"),
5052 MockRead data_reads1[] = {
5053 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5054 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5055 MockRead("Content-Length: 10000\r\n\r\n"),
5056 MockRead(SYNCHRONOUS, ERR_FAILED),
5059 // Resend with authorization from MyRealm's cache.
5060 MockWrite data_writes2[] = {
5061 MockWrite("GET /x/1 HTTP/1.1\r\n"
5062 "Host: www.google.com\r\n"
5063 "Connection: keep-alive\r\n"
5064 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5067 // Sever accepts the authorization.
5068 MockRead data_reads2[] = {
5069 MockRead("HTTP/1.0 200 OK\r\n"),
5070 MockRead("Content-Length: 100\r\n\r\n"),
5071 MockRead(SYNCHRONOUS, OK),
5074 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5075 data_writes1, arraysize(data_writes1));
5076 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5077 data_writes2, arraysize(data_writes2));
5078 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5079 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5081 TestCompletionCallback callback1;
5083 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5084 EXPECT_EQ(ERR_IO_PENDING, rv);
5086 rv = callback1.WaitForResult();
5087 EXPECT_EQ(OK, rv);
5089 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5090 TestCompletionCallback callback2;
5091 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5092 EXPECT_EQ(ERR_IO_PENDING, rv);
5093 rv = callback2.WaitForResult();
5094 EXPECT_EQ(OK, rv);
5095 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5097 const HttpResponseInfo* response = trans->GetResponseInfo();
5098 ASSERT_TRUE(response != NULL);
5099 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5100 EXPECT_EQ(100, response->headers->GetContentLength());
5103 // ------------------------------------------------------------------------
5105 // Transaction 5: request a URL in MyRealm, but the server rejects the
5106 // cached identity. Should invalidate and re-prompt.
5108 HttpRequestInfo request;
5109 request.method = "GET";
5110 request.url = GURL("http://www.google.com/p/q/t");
5111 request.load_flags = 0;
5113 scoped_ptr<HttpTransaction> trans(
5114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5116 MockWrite data_writes1[] = {
5117 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5118 "Host: www.google.com\r\n"
5119 "Connection: keep-alive\r\n\r\n"),
5122 MockRead data_reads1[] = {
5123 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5124 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5125 MockRead("Content-Length: 10000\r\n\r\n"),
5126 MockRead(SYNCHRONOUS, ERR_FAILED),
5129 // Resend with authorization from cache for MyRealm.
5130 MockWrite data_writes2[] = {
5131 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5132 "Host: www.google.com\r\n"
5133 "Connection: keep-alive\r\n"
5134 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5137 // Sever rejects the authorization.
5138 MockRead data_reads2[] = {
5139 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5140 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5141 MockRead("Content-Length: 10000\r\n\r\n"),
5142 MockRead(SYNCHRONOUS, ERR_FAILED),
5145 // At this point we should prompt for new credentials for MyRealm.
5146 // Restart with username=foo3, password=foo4.
5147 MockWrite data_writes3[] = {
5148 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5149 "Host: www.google.com\r\n"
5150 "Connection: keep-alive\r\n"
5151 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5154 // Sever accepts the authorization.
5155 MockRead data_reads3[] = {
5156 MockRead("HTTP/1.0 200 OK\r\n"),
5157 MockRead("Content-Length: 100\r\n\r\n"),
5158 MockRead(SYNCHRONOUS, OK),
5161 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5162 data_writes1, arraysize(data_writes1));
5163 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5164 data_writes2, arraysize(data_writes2));
5165 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5166 data_writes3, arraysize(data_writes3));
5167 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5168 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5169 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5171 TestCompletionCallback callback1;
5173 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5174 EXPECT_EQ(ERR_IO_PENDING, rv);
5176 rv = callback1.WaitForResult();
5177 EXPECT_EQ(OK, rv);
5179 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5180 TestCompletionCallback callback2;
5181 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5182 EXPECT_EQ(ERR_IO_PENDING, rv);
5183 rv = callback2.WaitForResult();
5184 EXPECT_EQ(OK, rv);
5185 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5187 const HttpResponseInfo* response = trans->GetResponseInfo();
5188 ASSERT_TRUE(response != NULL);
5189 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5191 TestCompletionCallback callback3;
5193 rv = trans->RestartWithAuth(
5194 AuthCredentials(kFoo3, kBar3), callback3.callback());
5195 EXPECT_EQ(ERR_IO_PENDING, rv);
5197 rv = callback3.WaitForResult();
5198 EXPECT_EQ(OK, rv);
5200 response = trans->GetResponseInfo();
5201 ASSERT_TRUE(response != NULL);
5202 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5203 EXPECT_EQ(100, response->headers->GetContentLength());
5207 // Tests that nonce count increments when multiple auth attempts
5208 // are started with the same nonce.
5209 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5210 HttpAuthHandlerDigest::Factory* digest_factory =
5211 new HttpAuthHandlerDigest::Factory();
5212 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5213 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5214 digest_factory->set_nonce_generator(nonce_generator);
5215 session_deps_.http_auth_handler_factory.reset(digest_factory);
5216 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5218 // Transaction 1: authenticate (foo, bar) on MyRealm1
5220 HttpRequestInfo request;
5221 request.method = "GET";
5222 request.url = GURL("http://www.google.com/x/y/z");
5223 request.load_flags = 0;
5225 scoped_ptr<HttpTransaction> trans(
5226 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5228 MockWrite data_writes1[] = {
5229 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5230 "Host: www.google.com\r\n"
5231 "Connection: keep-alive\r\n\r\n"),
5234 MockRead data_reads1[] = {
5235 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5236 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5237 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5238 MockRead(SYNCHRONOUS, OK),
5241 // Resend with authorization (username=foo, password=bar)
5242 MockWrite data_writes2[] = {
5243 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5244 "Host: www.google.com\r\n"
5245 "Connection: keep-alive\r\n"
5246 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5247 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5248 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5249 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5252 // Sever accepts the authorization.
5253 MockRead data_reads2[] = {
5254 MockRead("HTTP/1.0 200 OK\r\n"),
5255 MockRead(SYNCHRONOUS, OK),
5258 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5259 data_writes1, arraysize(data_writes1));
5260 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5261 data_writes2, arraysize(data_writes2));
5262 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5263 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5265 TestCompletionCallback callback1;
5267 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5268 EXPECT_EQ(ERR_IO_PENDING, rv);
5270 rv = callback1.WaitForResult();
5271 EXPECT_EQ(OK, rv);
5273 const HttpResponseInfo* response = trans->GetResponseInfo();
5274 ASSERT_TRUE(response != NULL);
5275 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5277 TestCompletionCallback callback2;
5279 rv = trans->RestartWithAuth(
5280 AuthCredentials(kFoo, kBar), callback2.callback());
5281 EXPECT_EQ(ERR_IO_PENDING, rv);
5283 rv = callback2.WaitForResult();
5284 EXPECT_EQ(OK, rv);
5286 response = trans->GetResponseInfo();
5287 ASSERT_TRUE(response != NULL);
5288 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5291 // ------------------------------------------------------------------------
5293 // Transaction 2: Request another resource in digestive's protection space.
5294 // This will preemptively add an Authorization header which should have an
5295 // "nc" value of 2 (as compared to 1 in the first use.
5297 HttpRequestInfo request;
5298 request.method = "GET";
5299 // Note that Transaction 1 was at /x/y/z, so this is in the same
5300 // protection space as digest.
5301 request.url = GURL("http://www.google.com/x/y/a/b");
5302 request.load_flags = 0;
5304 scoped_ptr<HttpTransaction> trans(
5305 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5307 MockWrite data_writes1[] = {
5308 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5309 "Host: www.google.com\r\n"
5310 "Connection: keep-alive\r\n"
5311 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5312 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5313 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5314 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5317 // Sever accepts the authorization.
5318 MockRead data_reads1[] = {
5319 MockRead("HTTP/1.0 200 OK\r\n"),
5320 MockRead("Content-Length: 100\r\n\r\n"),
5321 MockRead(SYNCHRONOUS, OK),
5324 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5325 data_writes1, arraysize(data_writes1));
5326 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5328 TestCompletionCallback callback1;
5330 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5331 EXPECT_EQ(ERR_IO_PENDING, rv);
5333 rv = callback1.WaitForResult();
5334 EXPECT_EQ(OK, rv);
5336 const HttpResponseInfo* response = trans->GetResponseInfo();
5337 ASSERT_TRUE(response != NULL);
5338 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5342 // Test the ResetStateForRestart() private method.
5343 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5344 // Create a transaction (the dependencies aren't important).
5345 scoped_ptr<HttpNetworkTransaction> trans(
5346 new HttpNetworkTransaction(DEFAULT_PRIORITY,
5347 CreateSession(&session_deps_)));
5349 // Setup some state (which we expect ResetStateForRestart() will clear).
5350 trans->read_buf_ = new IOBuffer(15);
5351 trans->read_buf_len_ = 15;
5352 trans->request_headers_.SetHeader("Authorization", "NTLM");
5354 // Setup state in response_
5355 HttpResponseInfo* response = &trans->response_;
5356 response->auth_challenge = new AuthChallengeInfo();
5357 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
5358 response->response_time = base::Time::Now();
5359 response->was_cached = true; // (Wouldn't ever actually be true...)
5361 { // Setup state for response_.vary_data
5362 HttpRequestInfo request;
5363 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5364 std::replace(temp.begin(), temp.end(), '\n', '\0');
5365 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5366 request.extra_headers.SetHeader("Foo", "1");
5367 request.extra_headers.SetHeader("bar", "23");
5368 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5371 // Cause the above state to be reset.
5372 trans->ResetStateForRestart();
5374 // Verify that the state that needed to be reset, has been reset.
5375 EXPECT_TRUE(trans->read_buf_.get() == NULL);
5376 EXPECT_EQ(0, trans->read_buf_len_);
5377 EXPECT_TRUE(trans->request_headers_.IsEmpty());
5378 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5379 EXPECT_TRUE(response->headers.get() == NULL);
5380 EXPECT_FALSE(response->was_cached);
5381 EXPECT_EQ(0U, response->ssl_info.cert_status);
5382 EXPECT_FALSE(response->vary_data.is_valid());
5385 // Test HTTPS connections to a site with a bad certificate
5386 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5387 HttpRequestInfo request;
5388 request.method = "GET";
5389 request.url = GURL("https://www.google.com/");
5390 request.load_flags = 0;
5392 scoped_ptr<HttpTransaction> trans(
5393 new HttpNetworkTransaction(DEFAULT_PRIORITY,
5394 CreateSession(&session_deps_)));
5396 MockWrite data_writes[] = {
5397 MockWrite("GET / HTTP/1.1\r\n"
5398 "Host: www.google.com\r\n"
5399 "Connection: keep-alive\r\n\r\n"),
5402 MockRead data_reads[] = {
5403 MockRead("HTTP/1.0 200 OK\r\n"),
5404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5405 MockRead("Content-Length: 100\r\n\r\n"),
5406 MockRead(SYNCHRONOUS, OK),
5409 StaticSocketDataProvider ssl_bad_certificate;
5410 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5411 data_writes, arraysize(data_writes));
5412 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5413 SSLSocketDataProvider ssl(ASYNC, OK);
5415 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5416 session_deps_.socket_factory->AddSocketDataProvider(&data);
5417 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5418 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5420 TestCompletionCallback callback;
5422 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5423 EXPECT_EQ(ERR_IO_PENDING, rv);
5425 rv = callback.WaitForResult();
5426 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5428 rv = trans->RestartIgnoringLastError(callback.callback());
5429 EXPECT_EQ(ERR_IO_PENDING, rv);
5431 rv = callback.WaitForResult();
5432 EXPECT_EQ(OK, rv);
5434 const HttpResponseInfo* response = trans->GetResponseInfo();
5436 ASSERT_TRUE(response != NULL);
5437 EXPECT_EQ(100, response->headers->GetContentLength());
5440 // Test HTTPS connections to a site with a bad certificate, going through a
5441 // proxy
5442 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5443 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5445 HttpRequestInfo request;
5446 request.method = "GET";
5447 request.url = GURL("https://www.google.com/");
5448 request.load_flags = 0;
5450 MockWrite proxy_writes[] = {
5451 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5452 "Host: www.google.com\r\n"
5453 "Proxy-Connection: keep-alive\r\n\r\n"),
5456 MockRead proxy_reads[] = {
5457 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5458 MockRead(SYNCHRONOUS, OK)
5461 MockWrite data_writes[] = {
5462 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5463 "Host: www.google.com\r\n"
5464 "Proxy-Connection: keep-alive\r\n\r\n"),
5465 MockWrite("GET / HTTP/1.1\r\n"
5466 "Host: www.google.com\r\n"
5467 "Connection: keep-alive\r\n\r\n"),
5470 MockRead data_reads[] = {
5471 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5472 MockRead("HTTP/1.0 200 OK\r\n"),
5473 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5474 MockRead("Content-Length: 100\r\n\r\n"),
5475 MockRead(SYNCHRONOUS, OK),
5478 StaticSocketDataProvider ssl_bad_certificate(
5479 proxy_reads, arraysize(proxy_reads),
5480 proxy_writes, arraysize(proxy_writes));
5481 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5482 data_writes, arraysize(data_writes));
5483 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5484 SSLSocketDataProvider ssl(ASYNC, OK);
5486 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5487 session_deps_.socket_factory->AddSocketDataProvider(&data);
5488 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5491 TestCompletionCallback callback;
5493 for (int i = 0; i < 2; i++) {
5494 session_deps_.socket_factory->ResetNextMockIndexes();
5496 scoped_ptr<HttpTransaction> trans(
5497 new HttpNetworkTransaction(DEFAULT_PRIORITY,
5498 CreateSession(&session_deps_)));
5500 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5501 EXPECT_EQ(ERR_IO_PENDING, rv);
5503 rv = callback.WaitForResult();
5504 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5506 rv = trans->RestartIgnoringLastError(callback.callback());
5507 EXPECT_EQ(ERR_IO_PENDING, rv);
5509 rv = callback.WaitForResult();
5510 EXPECT_EQ(OK, rv);
5512 const HttpResponseInfo* response = trans->GetResponseInfo();
5514 ASSERT_TRUE(response != NULL);
5515 EXPECT_EQ(100, response->headers->GetContentLength());
5520 // Test HTTPS connections to a site, going through an HTTPS proxy
5521 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
5522 session_deps_.proxy_service.reset(
5523 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5524 CapturingNetLog net_log;
5525 session_deps_.net_log = &net_log;
5527 HttpRequestInfo request;
5528 request.method = "GET";
5529 request.url = GURL("https://www.google.com/");
5530 request.load_flags = 0;
5532 MockWrite data_writes[] = {
5533 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5534 "Host: www.google.com\r\n"
5535 "Proxy-Connection: keep-alive\r\n\r\n"),
5536 MockWrite("GET / HTTP/1.1\r\n"
5537 "Host: www.google.com\r\n"
5538 "Connection: keep-alive\r\n\r\n"),
5541 MockRead data_reads[] = {
5542 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5543 MockRead("HTTP/1.1 200 OK\r\n"),
5544 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5545 MockRead("Content-Length: 100\r\n\r\n"),
5546 MockRead(SYNCHRONOUS, OK),
5549 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5550 data_writes, arraysize(data_writes));
5551 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5552 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
5554 session_deps_.socket_factory->AddSocketDataProvider(&data);
5555 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5556 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
5558 TestCompletionCallback callback;
5560 scoped_ptr<HttpTransaction> trans(
5561 new HttpNetworkTransaction(DEFAULT_PRIORITY,
5562 CreateSession(&session_deps_)));
5564 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5565 EXPECT_EQ(ERR_IO_PENDING, rv);
5567 rv = callback.WaitForResult();
5568 EXPECT_EQ(OK, rv);
5569 const HttpResponseInfo* response = trans->GetResponseInfo();
5571 ASSERT_TRUE(response != NULL);
5573 EXPECT_TRUE(response->headers->IsKeepAlive());
5574 EXPECT_EQ(200, response->headers->response_code());
5575 EXPECT_EQ(100, response->headers->GetContentLength());
5576 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5578 LoadTimingInfo load_timing_info;
5579 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5580 TestLoadTimingNotReusedWithPac(load_timing_info,
5581 CONNECT_TIMING_HAS_SSL_TIMES);
5584 // Test an HTTPS Proxy's ability to redirect a CONNECT request
5585 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
5586 session_deps_.proxy_service.reset(
5587 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5588 CapturingNetLog net_log;
5589 session_deps_.net_log = &net_log;
5591 HttpRequestInfo request;
5592 request.method = "GET";
5593 request.url = GURL("https://www.google.com/");
5594 request.load_flags = 0;
5596 MockWrite data_writes[] = {
5597 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5598 "Host: www.google.com\r\n"
5599 "Proxy-Connection: keep-alive\r\n\r\n"),
5602 MockRead data_reads[] = {
5603 MockRead("HTTP/1.1 302 Redirect\r\n"),
5604 MockRead("Location: http://login.example.com/\r\n"),
5605 MockRead("Content-Length: 0\r\n\r\n"),
5606 MockRead(SYNCHRONOUS, OK),
5609 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5610 data_writes, arraysize(data_writes));
5611 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5613 session_deps_.socket_factory->AddSocketDataProvider(&data);
5614 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5616 TestCompletionCallback callback;
5618 scoped_ptr<HttpTransaction> trans(
5619 new HttpNetworkTransaction(DEFAULT_PRIORITY,
5620 CreateSession(&session_deps_)));
5622 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5623 EXPECT_EQ(ERR_IO_PENDING, rv);
5625 rv = callback.WaitForResult();
5626 EXPECT_EQ(OK, rv);
5627 const HttpResponseInfo* response = trans->GetResponseInfo();
5629 ASSERT_TRUE(response != NULL);
5631 EXPECT_EQ(302, response->headers->response_code());
5632 std::string url;
5633 EXPECT_TRUE(response->headers->IsRedirect(&url));
5634 EXPECT_EQ("http://login.example.com/", url);
5636 // In the case of redirects from proxies, HttpNetworkTransaction returns
5637 // timing for the proxy connection instead of the connection to the host,
5638 // and no send / receive times.
5639 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
5640 LoadTimingInfo load_timing_info;
5641 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5643 EXPECT_FALSE(load_timing_info.socket_reused);
5644 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
5646 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
5647 EXPECT_LE(load_timing_info.proxy_resolve_start,
5648 load_timing_info.proxy_resolve_end);
5649 EXPECT_LE(load_timing_info.proxy_resolve_end,
5650 load_timing_info.connect_timing.connect_start);
5651 ExpectConnectTimingHasTimes(
5652 load_timing_info.connect_timing,
5653 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
5655 EXPECT_TRUE(load_timing_info.send_start.is_null());
5656 EXPECT_TRUE(load_timing_info.send_end.is_null());
5657 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
5660 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
5661 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
5662 session_deps_.proxy_service.reset(
5663 ProxyService::CreateFixed("https://proxy:70"));
5665 HttpRequestInfo request;
5666 request.method = "GET";
5667 request.url = GURL("https://www.google.com/");
5668 request.load_flags = 0;
5670 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
5671 scoped_ptr<SpdyFrame> goaway(
5672 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5673 MockWrite data_writes[] = {
5674 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
5675 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
5678 static const char* const kExtraHeaders[] = {
5679 "location",
5680 "http://login.example.com/",
5682 scoped_ptr<SpdyFrame> resp(
5683 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
5684 arraysize(kExtraHeaders)/2, 1));
5685 MockRead data_reads[] = {
5686 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
5687 MockRead(ASYNC, 0, 2), // EOF
5690 DelayedSocketData data(
5691 1, // wait for one write to finish before reading.
5692 data_reads, arraysize(data_reads),
5693 data_writes, arraysize(data_writes));
5694 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5695 proxy_ssl.SetNextProto(GetParam());
5697 session_deps_.socket_factory->AddSocketDataProvider(&data);
5698 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5700 TestCompletionCallback callback;
5702 scoped_ptr<HttpTransaction> trans(
5703 new HttpNetworkTransaction(DEFAULT_PRIORITY,
5704 CreateSession(&session_deps_)));
5706 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5707 EXPECT_EQ(ERR_IO_PENDING, rv);
5709 rv = callback.WaitForResult();
5710 EXPECT_EQ(OK, rv);
5711 const HttpResponseInfo* response = trans->GetResponseInfo();
5713 ASSERT_TRUE(response != NULL);
5715 EXPECT_EQ(302, response->headers->response_code());
5716 std::string url;
5717 EXPECT_TRUE(response->headers->IsRedirect(&url));
5718 EXPECT_EQ("http://login.example.com/", url);
5721 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
5722 TEST_P(HttpNetworkTransactionTest,
5723 ErrorResponseToHttpsConnectViaHttpsProxy) {
5724 session_deps_.proxy_service.reset(
5725 ProxyService::CreateFixed("https://proxy:70"));
5727 HttpRequestInfo request;
5728 request.method = "GET";
5729 request.url = GURL("https://www.google.com/");
5730 request.load_flags = 0;
5732 MockWrite data_writes[] = {
5733 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5734 "Host: www.google.com\r\n"
5735 "Proxy-Connection: keep-alive\r\n\r\n"),
5738 MockRead data_reads[] = {
5739 MockRead("HTTP/1.1 404 Not Found\r\n"),
5740 MockRead("Content-Length: 23\r\n\r\n"),
5741 MockRead("The host does not exist"),
5742 MockRead(SYNCHRONOUS, OK),
5745 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5746 data_writes, arraysize(data_writes));
5747 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5749 session_deps_.socket_factory->AddSocketDataProvider(&data);
5750 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5752 TestCompletionCallback callback;
5754 scoped_ptr<HttpTransaction> trans(
5755 new HttpNetworkTransaction(DEFAULT_PRIORITY,
5756 CreateSession(&session_deps_)));
5758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5759 EXPECT_EQ(ERR_IO_PENDING, rv);
5761 rv = callback.WaitForResult();
5762 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5764 // TODO(ttuttle): Anything else to check here?
5767 // Test that a SPDY proxy's response to a CONNECT request is filtered.
5768 TEST_P(HttpNetworkTransactionTest,
5769 ErrorResponseToHttpsConnectViaSpdyProxy) {
5770 session_deps_.proxy_service.reset(
5771 ProxyService::CreateFixed("https://proxy:70"));
5773 HttpRequestInfo request;
5774 request.method = "GET";
5775 request.url = GURL("https://www.google.com/");
5776 request.load_flags = 0;
5778 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
5779 scoped_ptr<SpdyFrame> rst(
5780 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5781 MockWrite data_writes[] = {
5782 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
5783 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
5786 static const char* const kExtraHeaders[] = {
5787 "location",
5788 "http://login.example.com/",
5790 scoped_ptr<SpdyFrame> resp(
5791 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
5792 arraysize(kExtraHeaders)/2, 1));
5793 scoped_ptr<SpdyFrame> body(
5794 spdy_util_.ConstructSpdyBodyFrame(
5795 1, "The host does not exist", 23, true));
5796 MockRead data_reads[] = {
5797 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
5798 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
5799 MockRead(ASYNC, 0, 4), // EOF
5802 DelayedSocketData data(
5803 1, // wait for one write to finish before reading.
5804 data_reads, arraysize(data_reads),
5805 data_writes, arraysize(data_writes));
5806 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5807 proxy_ssl.SetNextProto(GetParam());
5809 session_deps_.socket_factory->AddSocketDataProvider(&data);
5810 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5812 TestCompletionCallback callback;
5814 scoped_ptr<HttpTransaction> trans(
5815 new HttpNetworkTransaction(DEFAULT_PRIORITY,
5816 CreateSession(&session_deps_)));
5818 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5819 EXPECT_EQ(ERR_IO_PENDING, rv);
5821 rv = callback.WaitForResult();
5822 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5824 // TODO(ttuttle): Anything else to check here?
5827 // Test the request-challenge-retry sequence for basic auth, through
5828 // a SPDY proxy over a single SPDY session.
5829 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
5830 HttpRequestInfo request;
5831 request.method = "GET";
5832 request.url = GURL("https://www.google.com/");
5833 // when the no authentication data flag is set.
5834 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
5836 // Configure against https proxy server "myproxy:70".
5837 session_deps_.proxy_service.reset(
5838 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
5839 CapturingBoundNetLog log;
5840 session_deps_.net_log = log.bound().net_log();
5841 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5843 // Since we have proxy, should try to establish tunnel.
5844 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
5845 scoped_ptr<SpdyFrame> rst(
5846 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5848 // After calling trans->RestartWithAuth(), this is the request we should
5849 // be issuing -- the final header line contains the credentials.
5850 const char* const kAuthCredentials[] = {
5851 "proxy-authorization", "Basic Zm9vOmJhcg==",
5853 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
5854 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3));
5855 // fetch https://www.google.com/ via HTTP
5856 const char get[] = "GET / HTTP/1.1\r\n"
5857 "Host: www.google.com\r\n"
5858 "Connection: keep-alive\r\n\r\n";
5859 scoped_ptr<SpdyFrame> wrapped_get(
5860 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
5862 MockWrite spdy_writes[] = {
5863 CreateMockWrite(*req, 1, ASYNC),
5864 CreateMockWrite(*rst, 4, ASYNC),
5865 CreateMockWrite(*connect2, 5),
5866 CreateMockWrite(*wrapped_get, 8),
5869 // The proxy responds to the connect with a 407, using a persistent
5870 // connection.
5871 const char* const kAuthChallenge[] = {
5872 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
5873 spdy_util_.GetVersionKey(), "HTTP/1.1",
5874 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
5877 scoped_ptr<SpdyFrame> conn_auth_resp(
5878 spdy_util_.ConstructSpdyControlFrame(NULL,
5880 false,
5882 LOWEST,
5883 SYN_REPLY,
5884 CONTROL_FLAG_NONE,
5885 kAuthChallenge,
5886 arraysize(kAuthChallenge),
5887 0));
5889 scoped_ptr<SpdyFrame> conn_resp(
5890 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5891 const char resp[] = "HTTP/1.1 200 OK\r\n"
5892 "Content-Length: 5\r\n\r\n";
5894 scoped_ptr<SpdyFrame> wrapped_get_resp(
5895 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
5896 scoped_ptr<SpdyFrame> wrapped_body(
5897 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
5898 MockRead spdy_reads[] = {
5899 CreateMockRead(*conn_auth_resp, 2, ASYNC),
5900 CreateMockRead(*conn_resp, 6, ASYNC),
5901 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
5902 CreateMockRead(*wrapped_body, 10, ASYNC),
5903 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
5906 OrderedSocketData spdy_data(
5907 spdy_reads, arraysize(spdy_reads),
5908 spdy_writes, arraysize(spdy_writes));
5909 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5910 // Negotiate SPDY to the proxy
5911 SSLSocketDataProvider proxy(ASYNC, OK);
5912 proxy.SetNextProto(GetParam());
5913 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
5914 // Vanilla SSL to the server
5915 SSLSocketDataProvider server(ASYNC, OK);
5916 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
5918 TestCompletionCallback callback1;
5920 scoped_ptr<HttpTransaction> trans(
5921 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5923 int rv = trans->Start(&request, callback1.callback(), log.bound());
5924 EXPECT_EQ(ERR_IO_PENDING, rv);
5926 rv = callback1.WaitForResult();
5927 EXPECT_EQ(OK, rv);
5928 net::CapturingNetLog::CapturedEntryList entries;
5929 log.GetEntries(&entries);
5930 size_t pos = ExpectLogContainsSomewhere(
5931 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
5932 NetLog::PHASE_NONE);
5933 ExpectLogContainsSomewhere(
5934 entries, pos,
5935 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
5936 NetLog::PHASE_NONE);
5938 const HttpResponseInfo* response = trans->GetResponseInfo();
5939 ASSERT_TRUE(response != NULL);
5940 ASSERT_FALSE(response->headers.get() == NULL);
5941 EXPECT_EQ(407, response->headers->response_code());
5942 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5943 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5944 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
5946 TestCompletionCallback callback2;
5948 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
5949 callback2.callback());
5950 EXPECT_EQ(ERR_IO_PENDING, rv);
5952 rv = callback2.WaitForResult();
5953 EXPECT_EQ(OK, rv);
5955 response = trans->GetResponseInfo();
5956 ASSERT_TRUE(response != NULL);
5958 EXPECT_TRUE(response->headers->IsKeepAlive());
5959 EXPECT_EQ(200, response->headers->response_code());
5960 EXPECT_EQ(5, response->headers->GetContentLength());
5961 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5963 // The password prompt info should not be set.
5964 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5966 LoadTimingInfo load_timing_info;
5967 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5968 TestLoadTimingNotReusedWithPac(load_timing_info,
5969 CONNECT_TIMING_HAS_SSL_TIMES);
5971 trans.reset();
5972 session->CloseAllConnections();
5975 // Test that an explicitly trusted SPDY proxy can push a resource from an
5976 // origin that is different from that of its associated resource.
5977 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
5978 HttpRequestInfo request;
5979 HttpRequestInfo push_request;
5981 request.method = "GET";
5982 request.url = GURL("http://www.google.com/");
5983 push_request.method = "GET";
5984 push_request.url = GURL("http://www.another-origin.com/foo.dat");
5986 // Configure against https proxy server "myproxy:70".
5987 session_deps_.proxy_service.reset(
5988 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
5989 CapturingBoundNetLog log;
5990 session_deps_.net_log = log.bound().net_log();
5992 // Enable cross-origin push.
5993 session_deps_.trusted_spdy_proxy = "myproxy:70";
5995 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5997 scoped_ptr<SpdyFrame> stream1_syn(
5998 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6000 MockWrite spdy_writes[] = {
6001 CreateMockWrite(*stream1_syn, 1, ASYNC),
6004 scoped_ptr<SpdyFrame>
6005 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6007 scoped_ptr<SpdyFrame>
6008 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6010 scoped_ptr<SpdyFrame>
6011 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6015 "http://www.another-origin.com/foo.dat"));
6016 const char kPushedData[] = "pushed";
6017 scoped_ptr<SpdyFrame> stream2_body(
6018 spdy_util_.ConstructSpdyBodyFrame(
6019 2, kPushedData, strlen(kPushedData), true));
6021 MockRead spdy_reads[] = {
6022 CreateMockRead(*stream1_reply, 2, ASYNC),
6023 CreateMockRead(*stream2_syn, 3, ASYNC),
6024 CreateMockRead(*stream1_body, 4, ASYNC),
6025 CreateMockRead(*stream2_body, 5, ASYNC),
6026 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6029 OrderedSocketData spdy_data(
6030 spdy_reads, arraysize(spdy_reads),
6031 spdy_writes, arraysize(spdy_writes));
6032 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6033 // Negotiate SPDY to the proxy
6034 SSLSocketDataProvider proxy(ASYNC, OK);
6035 proxy.SetNextProto(GetParam());
6036 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6038 scoped_ptr<HttpTransaction> trans(
6039 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6040 TestCompletionCallback callback;
6041 int rv = trans->Start(&request, callback.callback(), log.bound());
6042 EXPECT_EQ(ERR_IO_PENDING, rv);
6044 rv = callback.WaitForResult();
6045 EXPECT_EQ(OK, rv);
6046 const HttpResponseInfo* response = trans->GetResponseInfo();
6048 scoped_ptr<HttpTransaction> push_trans(
6049 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6050 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6051 EXPECT_EQ(ERR_IO_PENDING, rv);
6053 rv = callback.WaitForResult();
6054 EXPECT_EQ(OK, rv);
6055 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6057 ASSERT_TRUE(response != NULL);
6058 EXPECT_TRUE(response->headers->IsKeepAlive());
6060 EXPECT_EQ(200, response->headers->response_code());
6061 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6063 std::string response_data;
6064 rv = ReadTransaction(trans.get(), &response_data);
6065 EXPECT_EQ(OK, rv);
6066 EXPECT_EQ("hello!", response_data);
6068 LoadTimingInfo load_timing_info;
6069 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6070 TestLoadTimingNotReusedWithPac(load_timing_info,
6071 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6073 // Verify the pushed stream.
6074 EXPECT_TRUE(push_response->headers.get() != NULL);
6075 EXPECT_EQ(200, push_response->headers->response_code());
6077 rv = ReadTransaction(push_trans.get(), &response_data);
6078 EXPECT_EQ(OK, rv);
6079 EXPECT_EQ("pushed", response_data);
6081 LoadTimingInfo push_load_timing_info;
6082 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6083 TestLoadTimingReusedWithPac(push_load_timing_info);
6084 // The transactions should share a socket ID, despite being for different
6085 // origins.
6086 EXPECT_EQ(load_timing_info.socket_log_id,
6087 push_load_timing_info.socket_log_id);
6089 trans.reset();
6090 push_trans.reset();
6091 session->CloseAllConnections();
6094 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6095 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6096 HttpRequestInfo request;
6098 request.method = "GET";
6099 request.url = GURL("http://www.google.com/");
6101 // Configure against https proxy server "myproxy:70".
6102 session_deps_.proxy_service.reset(
6103 ProxyService::CreateFixed("https://myproxy:70"));
6104 CapturingBoundNetLog log;
6105 session_deps_.net_log = log.bound().net_log();
6107 // Enable cross-origin push.
6108 session_deps_.trusted_spdy_proxy = "myproxy:70";
6110 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6112 scoped_ptr<SpdyFrame> stream1_syn(
6113 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6115 scoped_ptr<SpdyFrame> push_rst(
6116 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6118 MockWrite spdy_writes[] = {
6119 CreateMockWrite(*stream1_syn, 1, ASYNC),
6120 CreateMockWrite(*push_rst, 4),
6123 scoped_ptr<SpdyFrame>
6124 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6126 scoped_ptr<SpdyFrame>
6127 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6129 scoped_ptr<SpdyFrame>
6130 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6134 "https://www.another-origin.com/foo.dat"));
6136 MockRead spdy_reads[] = {
6137 CreateMockRead(*stream1_reply, 2, ASYNC),
6138 CreateMockRead(*stream2_syn, 3, ASYNC),
6139 CreateMockRead(*stream1_body, 5, ASYNC),
6140 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6143 OrderedSocketData spdy_data(
6144 spdy_reads, arraysize(spdy_reads),
6145 spdy_writes, arraysize(spdy_writes));
6146 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6147 // Negotiate SPDY to the proxy
6148 SSLSocketDataProvider proxy(ASYNC, OK);
6149 proxy.SetNextProto(GetParam());
6150 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6152 scoped_ptr<HttpTransaction> trans(
6153 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6154 TestCompletionCallback callback;
6155 int rv = trans->Start(&request, callback.callback(), log.bound());
6156 EXPECT_EQ(ERR_IO_PENDING, rv);
6158 rv = callback.WaitForResult();
6159 EXPECT_EQ(OK, rv);
6160 const HttpResponseInfo* response = trans->GetResponseInfo();
6162 ASSERT_TRUE(response != NULL);
6163 EXPECT_TRUE(response->headers->IsKeepAlive());
6165 EXPECT_EQ(200, response->headers->response_code());
6166 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6168 std::string response_data;
6169 rv = ReadTransaction(trans.get(), &response_data);
6170 EXPECT_EQ(OK, rv);
6171 EXPECT_EQ("hello!", response_data);
6173 trans.reset();
6174 session->CloseAllConnections();
6177 // Test HTTPS connections to a site with a bad certificate, going through an
6178 // HTTPS proxy
6179 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6180 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6181 "https://proxy:70"));
6183 HttpRequestInfo request;
6184 request.method = "GET";
6185 request.url = GURL("https://www.google.com/");
6186 request.load_flags = 0;
6188 // Attempt to fetch the URL from a server with a bad cert
6189 MockWrite bad_cert_writes[] = {
6190 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6191 "Host: www.google.com\r\n"
6192 "Proxy-Connection: keep-alive\r\n\r\n"),
6195 MockRead bad_cert_reads[] = {
6196 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6197 MockRead(SYNCHRONOUS, OK)
6200 // Attempt to fetch the URL with a good cert
6201 MockWrite good_data_writes[] = {
6202 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6203 "Host: www.google.com\r\n"
6204 "Proxy-Connection: keep-alive\r\n\r\n"),
6205 MockWrite("GET / HTTP/1.1\r\n"
6206 "Host: www.google.com\r\n"
6207 "Connection: keep-alive\r\n\r\n"),
6210 MockRead good_cert_reads[] = {
6211 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6212 MockRead("HTTP/1.0 200 OK\r\n"),
6213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6214 MockRead("Content-Length: 100\r\n\r\n"),
6215 MockRead(SYNCHRONOUS, OK),
6218 StaticSocketDataProvider ssl_bad_certificate(
6219 bad_cert_reads, arraysize(bad_cert_reads),
6220 bad_cert_writes, arraysize(bad_cert_writes));
6221 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6222 good_data_writes, arraysize(good_data_writes));
6223 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6224 SSLSocketDataProvider ssl(ASYNC, OK);
6226 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6227 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6228 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6229 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6231 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6233 session_deps_.socket_factory->AddSocketDataProvider(&data);
6234 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6236 TestCompletionCallback callback;
6238 scoped_ptr<HttpTransaction> trans(
6239 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6240 CreateSession(&session_deps_)));
6242 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6243 EXPECT_EQ(ERR_IO_PENDING, rv);
6245 rv = callback.WaitForResult();
6246 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6248 rv = trans->RestartIgnoringLastError(callback.callback());
6249 EXPECT_EQ(ERR_IO_PENDING, rv);
6251 rv = callback.WaitForResult();
6252 EXPECT_EQ(OK, rv);
6254 const HttpResponseInfo* response = trans->GetResponseInfo();
6256 ASSERT_TRUE(response != NULL);
6257 EXPECT_EQ(100, response->headers->GetContentLength());
6260 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6261 HttpRequestInfo request;
6262 request.method = "GET";
6263 request.url = GURL("http://www.google.com/");
6264 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6265 "Chromium Ultra Awesome X Edition");
6267 scoped_ptr<HttpTransaction> trans(
6268 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6269 CreateSession(&session_deps_)));
6271 MockWrite data_writes[] = {
6272 MockWrite("GET / HTTP/1.1\r\n"
6273 "Host: www.google.com\r\n"
6274 "Connection: keep-alive\r\n"
6275 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6278 // Lastly, the server responds with the actual content.
6279 MockRead data_reads[] = {
6280 MockRead("HTTP/1.0 200 OK\r\n"),
6281 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6282 MockRead("Content-Length: 100\r\n\r\n"),
6283 MockRead(SYNCHRONOUS, OK),
6286 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6287 data_writes, arraysize(data_writes));
6288 session_deps_.socket_factory->AddSocketDataProvider(&data);
6290 TestCompletionCallback callback;
6292 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6293 EXPECT_EQ(ERR_IO_PENDING, rv);
6295 rv = callback.WaitForResult();
6296 EXPECT_EQ(OK, rv);
6299 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6300 HttpRequestInfo request;
6301 request.method = "GET";
6302 request.url = GURL("https://www.google.com/");
6303 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6304 "Chromium Ultra Awesome X Edition");
6306 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6307 scoped_ptr<HttpTransaction> trans(
6308 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6309 CreateSession(&session_deps_)));
6311 MockWrite data_writes[] = {
6312 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6313 "Host: www.google.com\r\n"
6314 "Proxy-Connection: keep-alive\r\n"
6315 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6317 MockRead data_reads[] = {
6318 // Return an error, so the transaction stops here (this test isn't
6319 // interested in the rest).
6320 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6321 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6322 MockRead("Proxy-Connection: close\r\n\r\n"),
6325 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6326 data_writes, arraysize(data_writes));
6327 session_deps_.socket_factory->AddSocketDataProvider(&data);
6329 TestCompletionCallback callback;
6331 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6332 EXPECT_EQ(ERR_IO_PENDING, rv);
6334 rv = callback.WaitForResult();
6335 EXPECT_EQ(OK, rv);
6338 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6339 HttpRequestInfo request;
6340 request.method = "GET";
6341 request.url = GURL("http://www.google.com/");
6342 request.load_flags = 0;
6343 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6344 "http://the.previous.site.com/");
6346 scoped_ptr<HttpTransaction> trans(
6347 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6348 CreateSession(&session_deps_)));
6350 MockWrite data_writes[] = {
6351 MockWrite("GET / HTTP/1.1\r\n"
6352 "Host: www.google.com\r\n"
6353 "Connection: keep-alive\r\n"
6354 "Referer: http://the.previous.site.com/\r\n\r\n"),
6357 // Lastly, the server responds with the actual content.
6358 MockRead data_reads[] = {
6359 MockRead("HTTP/1.0 200 OK\r\n"),
6360 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6361 MockRead("Content-Length: 100\r\n\r\n"),
6362 MockRead(SYNCHRONOUS, OK),
6365 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6366 data_writes, arraysize(data_writes));
6367 session_deps_.socket_factory->AddSocketDataProvider(&data);
6369 TestCompletionCallback callback;
6371 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6372 EXPECT_EQ(ERR_IO_PENDING, rv);
6374 rv = callback.WaitForResult();
6375 EXPECT_EQ(OK, rv);
6378 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6379 HttpRequestInfo request;
6380 request.method = "POST";
6381 request.url = GURL("http://www.google.com/");
6383 scoped_ptr<HttpTransaction> trans(
6384 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6385 CreateSession(&session_deps_)));
6387 MockWrite data_writes[] = {
6388 MockWrite("POST / HTTP/1.1\r\n"
6389 "Host: www.google.com\r\n"
6390 "Connection: keep-alive\r\n"
6391 "Content-Length: 0\r\n\r\n"),
6394 // Lastly, the server responds with the actual content.
6395 MockRead data_reads[] = {
6396 MockRead("HTTP/1.0 200 OK\r\n"),
6397 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6398 MockRead("Content-Length: 100\r\n\r\n"),
6399 MockRead(SYNCHRONOUS, OK),
6402 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6403 data_writes, arraysize(data_writes));
6404 session_deps_.socket_factory->AddSocketDataProvider(&data);
6406 TestCompletionCallback callback;
6408 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6409 EXPECT_EQ(ERR_IO_PENDING, rv);
6411 rv = callback.WaitForResult();
6412 EXPECT_EQ(OK, rv);
6415 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6416 HttpRequestInfo request;
6417 request.method = "PUT";
6418 request.url = GURL("http://www.google.com/");
6420 scoped_ptr<HttpTransaction> trans(
6421 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6422 CreateSession(&session_deps_)));
6424 MockWrite data_writes[] = {
6425 MockWrite("PUT / HTTP/1.1\r\n"
6426 "Host: www.google.com\r\n"
6427 "Connection: keep-alive\r\n"
6428 "Content-Length: 0\r\n\r\n"),
6431 // Lastly, the server responds with the actual content.
6432 MockRead data_reads[] = {
6433 MockRead("HTTP/1.0 200 OK\r\n"),
6434 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6435 MockRead("Content-Length: 100\r\n\r\n"),
6436 MockRead(SYNCHRONOUS, OK),
6439 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6440 data_writes, arraysize(data_writes));
6441 session_deps_.socket_factory->AddSocketDataProvider(&data);
6443 TestCompletionCallback callback;
6445 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6446 EXPECT_EQ(ERR_IO_PENDING, rv);
6448 rv = callback.WaitForResult();
6449 EXPECT_EQ(OK, rv);
6452 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6453 HttpRequestInfo request;
6454 request.method = "HEAD";
6455 request.url = GURL("http://www.google.com/");
6457 scoped_ptr<HttpTransaction> trans(
6458 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6459 CreateSession(&session_deps_)));
6461 MockWrite data_writes[] = {
6462 MockWrite("HEAD / HTTP/1.1\r\n"
6463 "Host: www.google.com\r\n"
6464 "Connection: keep-alive\r\n"
6465 "Content-Length: 0\r\n\r\n"),
6468 // Lastly, the server responds with the actual content.
6469 MockRead data_reads[] = {
6470 MockRead("HTTP/1.0 200 OK\r\n"),
6471 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6472 MockRead("Content-Length: 100\r\n\r\n"),
6473 MockRead(SYNCHRONOUS, OK),
6476 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6477 data_writes, arraysize(data_writes));
6478 session_deps_.socket_factory->AddSocketDataProvider(&data);
6480 TestCompletionCallback callback;
6482 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6483 EXPECT_EQ(ERR_IO_PENDING, rv);
6485 rv = callback.WaitForResult();
6486 EXPECT_EQ(OK, rv);
6489 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
6490 HttpRequestInfo request;
6491 request.method = "GET";
6492 request.url = GURL("http://www.google.com/");
6493 request.load_flags = LOAD_BYPASS_CACHE;
6495 scoped_ptr<HttpTransaction> trans(
6496 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6497 CreateSession(&session_deps_)));
6499 MockWrite data_writes[] = {
6500 MockWrite("GET / HTTP/1.1\r\n"
6501 "Host: www.google.com\r\n"
6502 "Connection: keep-alive\r\n"
6503 "Pragma: no-cache\r\n"
6504 "Cache-Control: no-cache\r\n\r\n"),
6507 // Lastly, the server responds with the actual content.
6508 MockRead data_reads[] = {
6509 MockRead("HTTP/1.0 200 OK\r\n"),
6510 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6511 MockRead("Content-Length: 100\r\n\r\n"),
6512 MockRead(SYNCHRONOUS, OK),
6515 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6516 data_writes, arraysize(data_writes));
6517 session_deps_.socket_factory->AddSocketDataProvider(&data);
6519 TestCompletionCallback callback;
6521 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6522 EXPECT_EQ(ERR_IO_PENDING, rv);
6524 rv = callback.WaitForResult();
6525 EXPECT_EQ(OK, rv);
6528 TEST_P(HttpNetworkTransactionTest,
6529 BuildRequest_CacheControlValidateCache) {
6530 HttpRequestInfo request;
6531 request.method = "GET";
6532 request.url = GURL("http://www.google.com/");
6533 request.load_flags = LOAD_VALIDATE_CACHE;
6535 scoped_ptr<HttpTransaction> trans(
6536 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6537 CreateSession(&session_deps_)));
6539 MockWrite data_writes[] = {
6540 MockWrite("GET / HTTP/1.1\r\n"
6541 "Host: www.google.com\r\n"
6542 "Connection: keep-alive\r\n"
6543 "Cache-Control: max-age=0\r\n\r\n"),
6546 // Lastly, the server responds with the actual content.
6547 MockRead data_reads[] = {
6548 MockRead("HTTP/1.0 200 OK\r\n"),
6549 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6550 MockRead("Content-Length: 100\r\n\r\n"),
6551 MockRead(SYNCHRONOUS, OK),
6554 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6555 data_writes, arraysize(data_writes));
6556 session_deps_.socket_factory->AddSocketDataProvider(&data);
6558 TestCompletionCallback callback;
6560 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6561 EXPECT_EQ(ERR_IO_PENDING, rv);
6563 rv = callback.WaitForResult();
6564 EXPECT_EQ(OK, rv);
6567 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
6568 HttpRequestInfo request;
6569 request.method = "GET";
6570 request.url = GURL("http://www.google.com/");
6571 request.extra_headers.SetHeader("FooHeader", "Bar");
6573 scoped_ptr<HttpTransaction> trans(
6574 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6575 CreateSession(&session_deps_)));
6577 MockWrite data_writes[] = {
6578 MockWrite("GET / HTTP/1.1\r\n"
6579 "Host: www.google.com\r\n"
6580 "Connection: keep-alive\r\n"
6581 "FooHeader: Bar\r\n\r\n"),
6584 // Lastly, the server responds with the actual content.
6585 MockRead data_reads[] = {
6586 MockRead("HTTP/1.0 200 OK\r\n"),
6587 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6588 MockRead("Content-Length: 100\r\n\r\n"),
6589 MockRead(SYNCHRONOUS, OK),
6592 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6593 data_writes, arraysize(data_writes));
6594 session_deps_.socket_factory->AddSocketDataProvider(&data);
6596 TestCompletionCallback callback;
6598 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6599 EXPECT_EQ(ERR_IO_PENDING, rv);
6601 rv = callback.WaitForResult();
6602 EXPECT_EQ(OK, rv);
6605 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
6606 HttpRequestInfo request;
6607 request.method = "GET";
6608 request.url = GURL("http://www.google.com/");
6609 request.extra_headers.SetHeader("referer", "www.foo.com");
6610 request.extra_headers.SetHeader("hEllo", "Kitty");
6611 request.extra_headers.SetHeader("FoO", "bar");
6613 scoped_ptr<HttpTransaction> trans(
6614 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6615 CreateSession(&session_deps_)));
6617 MockWrite data_writes[] = {
6618 MockWrite("GET / HTTP/1.1\r\n"
6619 "Host: www.google.com\r\n"
6620 "Connection: keep-alive\r\n"
6621 "referer: www.foo.com\r\n"
6622 "hEllo: Kitty\r\n"
6623 "FoO: bar\r\n\r\n"),
6626 // Lastly, the server responds with the actual content.
6627 MockRead data_reads[] = {
6628 MockRead("HTTP/1.0 200 OK\r\n"),
6629 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6630 MockRead("Content-Length: 100\r\n\r\n"),
6631 MockRead(SYNCHRONOUS, OK),
6634 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6635 data_writes, arraysize(data_writes));
6636 session_deps_.socket_factory->AddSocketDataProvider(&data);
6638 TestCompletionCallback callback;
6640 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6641 EXPECT_EQ(ERR_IO_PENDING, rv);
6643 rv = callback.WaitForResult();
6644 EXPECT_EQ(OK, rv);
6647 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
6648 HttpRequestInfo request;
6649 request.method = "GET";
6650 request.url = GURL("http://www.google.com/");
6651 request.load_flags = 0;
6653 session_deps_.proxy_service.reset(
6654 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6655 CapturingNetLog net_log;
6656 session_deps_.net_log = &net_log;
6658 scoped_ptr<HttpTransaction> trans(
6659 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6660 CreateSession(&session_deps_)));
6662 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6663 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6665 MockWrite data_writes[] = {
6666 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
6667 MockWrite("GET / HTTP/1.1\r\n"
6668 "Host: www.google.com\r\n"
6669 "Connection: keep-alive\r\n\r\n")
6672 MockRead data_reads[] = {
6673 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
6674 MockRead("HTTP/1.0 200 OK\r\n"),
6675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6676 MockRead("Payload"),
6677 MockRead(SYNCHRONOUS, OK)
6680 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6681 data_writes, arraysize(data_writes));
6682 session_deps_.socket_factory->AddSocketDataProvider(&data);
6684 TestCompletionCallback callback;
6686 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6687 EXPECT_EQ(ERR_IO_PENDING, rv);
6689 rv = callback.WaitForResult();
6690 EXPECT_EQ(OK, rv);
6692 const HttpResponseInfo* response = trans->GetResponseInfo();
6693 ASSERT_TRUE(response != NULL);
6695 LoadTimingInfo load_timing_info;
6696 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6697 TestLoadTimingNotReusedWithPac(load_timing_info,
6698 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6700 std::string response_text;
6701 rv = ReadTransaction(trans.get(), &response_text);
6702 EXPECT_EQ(OK, rv);
6703 EXPECT_EQ("Payload", response_text);
6706 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
6707 HttpRequestInfo request;
6708 request.method = "GET";
6709 request.url = GURL("https://www.google.com/");
6710 request.load_flags = 0;
6712 session_deps_.proxy_service.reset(
6713 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6714 CapturingNetLog net_log;
6715 session_deps_.net_log = &net_log;
6717 scoped_ptr<HttpTransaction> trans(
6718 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6719 CreateSession(&session_deps_)));
6721 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
6722 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6724 MockWrite data_writes[] = {
6725 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
6726 arraysize(write_buffer)),
6727 MockWrite("GET / HTTP/1.1\r\n"
6728 "Host: www.google.com\r\n"
6729 "Connection: keep-alive\r\n\r\n")
6732 MockRead data_reads[] = {
6733 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
6734 arraysize(read_buffer)),
6735 MockRead("HTTP/1.0 200 OK\r\n"),
6736 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6737 MockRead("Payload"),
6738 MockRead(SYNCHRONOUS, OK)
6741 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6742 data_writes, arraysize(data_writes));
6743 session_deps_.socket_factory->AddSocketDataProvider(&data);
6745 SSLSocketDataProvider ssl(ASYNC, OK);
6746 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6748 TestCompletionCallback callback;
6750 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6751 EXPECT_EQ(ERR_IO_PENDING, rv);
6753 rv = callback.WaitForResult();
6754 EXPECT_EQ(OK, rv);
6756 LoadTimingInfo load_timing_info;
6757 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6758 TestLoadTimingNotReusedWithPac(load_timing_info,
6759 CONNECT_TIMING_HAS_SSL_TIMES);
6761 const HttpResponseInfo* response = trans->GetResponseInfo();
6762 ASSERT_TRUE(response != NULL);
6764 std::string response_text;
6765 rv = ReadTransaction(trans.get(), &response_text);
6766 EXPECT_EQ(OK, rv);
6767 EXPECT_EQ("Payload", response_text);
6770 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
6771 HttpRequestInfo request;
6772 request.method = "GET";
6773 request.url = GURL("http://www.google.com/");
6774 request.load_flags = 0;
6776 session_deps_.proxy_service.reset(
6777 ProxyService::CreateFixed("socks4://myproxy:1080"));
6778 CapturingNetLog net_log;
6779 session_deps_.net_log = &net_log;
6781 scoped_ptr<HttpTransaction> trans(
6782 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6783 CreateSession(&session_deps_)));
6785 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6786 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6788 MockWrite data_writes[] = {
6789 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
6790 MockWrite("GET / HTTP/1.1\r\n"
6791 "Host: www.google.com\r\n"
6792 "Connection: keep-alive\r\n\r\n")
6795 MockRead data_reads[] = {
6796 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
6797 MockRead("HTTP/1.0 200 OK\r\n"),
6798 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6799 MockRead("Payload"),
6800 MockRead(SYNCHRONOUS, OK)
6803 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6804 data_writes, arraysize(data_writes));
6805 session_deps_.socket_factory->AddSocketDataProvider(&data);
6807 TestCompletionCallback callback;
6809 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6810 EXPECT_EQ(ERR_IO_PENDING, rv);
6812 rv = callback.WaitForResult();
6813 EXPECT_EQ(OK, rv);
6815 const HttpResponseInfo* response = trans->GetResponseInfo();
6816 ASSERT_TRUE(response != NULL);
6818 LoadTimingInfo load_timing_info;
6819 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6820 TestLoadTimingNotReused(load_timing_info,
6821 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6823 std::string response_text;
6824 rv = ReadTransaction(trans.get(), &response_text);
6825 EXPECT_EQ(OK, rv);
6826 EXPECT_EQ("Payload", response_text);
6829 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
6830 HttpRequestInfo request;
6831 request.method = "GET";
6832 request.url = GURL("http://www.google.com/");
6833 request.load_flags = 0;
6835 session_deps_.proxy_service.reset(
6836 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
6837 CapturingNetLog net_log;
6838 session_deps_.net_log = &net_log;
6840 scoped_ptr<HttpTransaction> trans(
6841 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6842 CreateSession(&session_deps_)));
6844 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
6845 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
6846 const char kSOCKS5OkRequest[] = {
6847 0x05, // Version
6848 0x01, // Command (CONNECT)
6849 0x00, // Reserved.
6850 0x03, // Address type (DOMAINNAME).
6851 0x0E, // Length of domain (14)
6852 // Domain string:
6853 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
6854 0x00, 0x50, // 16-bit port (80)
6856 const char kSOCKS5OkResponse[] =
6857 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
6859 MockWrite data_writes[] = {
6860 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
6861 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
6862 MockWrite("GET / HTTP/1.1\r\n"
6863 "Host: www.google.com\r\n"
6864 "Connection: keep-alive\r\n\r\n")
6867 MockRead data_reads[] = {
6868 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
6869 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
6870 MockRead("HTTP/1.0 200 OK\r\n"),
6871 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6872 MockRead("Payload"),
6873 MockRead(SYNCHRONOUS, OK)
6876 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6877 data_writes, arraysize(data_writes));
6878 session_deps_.socket_factory->AddSocketDataProvider(&data);
6880 TestCompletionCallback callback;
6882 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6883 EXPECT_EQ(ERR_IO_PENDING, rv);
6885 rv = callback.WaitForResult();
6886 EXPECT_EQ(OK, rv);
6888 const HttpResponseInfo* response = trans->GetResponseInfo();
6889 ASSERT_TRUE(response != NULL);
6891 LoadTimingInfo load_timing_info;
6892 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6893 TestLoadTimingNotReusedWithPac(load_timing_info,
6894 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6896 std::string response_text;
6897 rv = ReadTransaction(trans.get(), &response_text);
6898 EXPECT_EQ(OK, rv);
6899 EXPECT_EQ("Payload", response_text);
6902 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
6903 HttpRequestInfo request;
6904 request.method = "GET";
6905 request.url = GURL("https://www.google.com/");
6906 request.load_flags = 0;
6908 session_deps_.proxy_service.reset(
6909 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
6910 CapturingNetLog net_log;
6911 session_deps_.net_log = &net_log;
6913 scoped_ptr<HttpTransaction> trans(
6914 new HttpNetworkTransaction(DEFAULT_PRIORITY,
6915 CreateSession(&session_deps_)));
6917 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
6918 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
6919 const unsigned char kSOCKS5OkRequest[] = {
6920 0x05, // Version
6921 0x01, // Command (CONNECT)
6922 0x00, // Reserved.
6923 0x03, // Address type (DOMAINNAME).
6924 0x0E, // Length of domain (14)
6925 // Domain string:
6926 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
6927 0x01, 0xBB, // 16-bit port (443)
6930 const char kSOCKS5OkResponse[] =
6931 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
6933 MockWrite data_writes[] = {
6934 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
6935 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
6936 arraysize(kSOCKS5OkRequest)),
6937 MockWrite("GET / HTTP/1.1\r\n"
6938 "Host: www.google.com\r\n"
6939 "Connection: keep-alive\r\n\r\n")
6942 MockRead data_reads[] = {
6943 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
6944 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
6945 MockRead("HTTP/1.0 200 OK\r\n"),
6946 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6947 MockRead("Payload"),
6948 MockRead(SYNCHRONOUS, OK)
6951 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6952 data_writes, arraysize(data_writes));
6953 session_deps_.socket_factory->AddSocketDataProvider(&data);
6955 SSLSocketDataProvider ssl(ASYNC, OK);
6956 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6958 TestCompletionCallback callback;
6960 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6961 EXPECT_EQ(ERR_IO_PENDING, rv);
6963 rv = callback.WaitForResult();
6964 EXPECT_EQ(OK, rv);
6966 const HttpResponseInfo* response = trans->GetResponseInfo();
6967 ASSERT_TRUE(response != NULL);
6969 LoadTimingInfo load_timing_info;
6970 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6971 TestLoadTimingNotReusedWithPac(load_timing_info,
6972 CONNECT_TIMING_HAS_SSL_TIMES);
6974 std::string response_text;
6975 rv = ReadTransaction(trans.get(), &response_text);
6976 EXPECT_EQ(OK, rv);
6977 EXPECT_EQ("Payload", response_text);
6980 namespace {
6982 // Tests that for connection endpoints the group names are correctly set.
6984 struct GroupNameTest {
6985 std::string proxy_server;
6986 std::string url;
6987 std::string expected_group_name;
6988 bool ssl;
6991 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
6992 NextProto next_proto,
6993 SpdySessionDependencies* session_deps_) {
6994 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
6996 base::WeakPtr<HttpServerProperties> http_server_properties =
6997 session->http_server_properties();
6998 http_server_properties->SetAlternateProtocol(
6999 HostPortPair("host.with.alternate", 80), 443,
7000 AlternateProtocolFromNextProto(next_proto));
7002 return session;
7005 int GroupNameTransactionHelper(
7006 const std::string& url,
7007 const scoped_refptr<HttpNetworkSession>& session) {
7008 HttpRequestInfo request;
7009 request.method = "GET";
7010 request.url = GURL(url);
7011 request.load_flags = 0;
7013 scoped_ptr<HttpTransaction> trans(
7014 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7016 TestCompletionCallback callback;
7018 // We do not complete this request, the dtor will clean the transaction up.
7019 return trans->Start(&request, callback.callback(), BoundNetLog());
7022 } // namespace
7024 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7025 const GroupNameTest tests[] = {
7027 "", // unused
7028 "http://www.google.com/direct",
7029 "www.google.com:80",
7030 false,
7033 "", // unused
7034 "http://[2001:1418:13:1::25]/direct",
7035 "[2001:1418:13:1::25]:80",
7036 false,
7039 // SSL Tests
7041 "", // unused
7042 "https://www.google.com/direct_ssl",
7043 "ssl/www.google.com:443",
7044 true,
7047 "", // unused
7048 "https://[2001:1418:13:1::25]/direct",
7049 "ssl/[2001:1418:13:1::25]:443",
7050 true,
7053 "", // unused
7054 "http://host.with.alternate/direct",
7055 "ssl/host.with.alternate:443",
7056 true,
7060 HttpStreamFactory::set_use_alternate_protocols(true);
7062 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7063 session_deps_.proxy_service.reset(
7064 ProxyService::CreateFixed(tests[i].proxy_server));
7065 scoped_refptr<HttpNetworkSession> session(
7066 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7068 HttpNetworkSessionPeer peer(session);
7069 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7070 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7071 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7072 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7073 MockClientSocketPoolManager* mock_pool_manager =
7074 new MockClientSocketPoolManager;
7075 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7076 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7077 peer.SetClientSocketPoolManager(mock_pool_manager);
7079 EXPECT_EQ(ERR_IO_PENDING,
7080 GroupNameTransactionHelper(tests[i].url, session));
7081 if (tests[i].ssl)
7082 EXPECT_EQ(tests[i].expected_group_name,
7083 ssl_conn_pool->last_group_name_received());
7084 else
7085 EXPECT_EQ(tests[i].expected_group_name,
7086 transport_conn_pool->last_group_name_received());
7091 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7092 const GroupNameTest tests[] = {
7094 "http_proxy",
7095 "http://www.google.com/http_proxy_normal",
7096 "www.google.com:80",
7097 false,
7100 // SSL Tests
7102 "http_proxy",
7103 "https://www.google.com/http_connect_ssl",
7104 "ssl/www.google.com:443",
7105 true,
7109 "http_proxy",
7110 "http://host.with.alternate/direct",
7111 "ssl/host.with.alternate:443",
7112 true,
7116 "http_proxy",
7117 "ftp://ftp.google.com/http_proxy_normal",
7118 "ftp/ftp.google.com:21",
7119 false,
7123 HttpStreamFactory::set_use_alternate_protocols(true);
7125 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7126 session_deps_.proxy_service.reset(
7127 ProxyService::CreateFixed(tests[i].proxy_server));
7128 scoped_refptr<HttpNetworkSession> session(
7129 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7131 HttpNetworkSessionPeer peer(session);
7133 HostPortPair proxy_host("http_proxy", 80);
7134 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7135 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7136 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7137 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7139 MockClientSocketPoolManager* mock_pool_manager =
7140 new MockClientSocketPoolManager;
7141 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7142 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7143 peer.SetClientSocketPoolManager(mock_pool_manager);
7145 EXPECT_EQ(ERR_IO_PENDING,
7146 GroupNameTransactionHelper(tests[i].url, session));
7147 if (tests[i].ssl)
7148 EXPECT_EQ(tests[i].expected_group_name,
7149 ssl_conn_pool->last_group_name_received());
7150 else
7151 EXPECT_EQ(tests[i].expected_group_name,
7152 http_proxy_pool->last_group_name_received());
7156 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7157 const GroupNameTest tests[] = {
7159 "socks4://socks_proxy:1080",
7160 "http://www.google.com/socks4_direct",
7161 "socks4/www.google.com:80",
7162 false,
7165 "socks5://socks_proxy:1080",
7166 "http://www.google.com/socks5_direct",
7167 "socks5/www.google.com:80",
7168 false,
7171 // SSL Tests
7173 "socks4://socks_proxy:1080",
7174 "https://www.google.com/socks4_ssl",
7175 "socks4/ssl/www.google.com:443",
7176 true,
7179 "socks5://socks_proxy:1080",
7180 "https://www.google.com/socks5_ssl",
7181 "socks5/ssl/www.google.com:443",
7182 true,
7186 "socks4://socks_proxy:1080",
7187 "http://host.with.alternate/direct",
7188 "socks4/ssl/host.with.alternate:443",
7189 true,
7193 HttpStreamFactory::set_use_alternate_protocols(true);
7195 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7196 session_deps_.proxy_service.reset(
7197 ProxyService::CreateFixed(tests[i].proxy_server));
7198 scoped_refptr<HttpNetworkSession> session(
7199 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7201 HttpNetworkSessionPeer peer(session);
7203 HostPortPair proxy_host("socks_proxy", 1080);
7204 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7205 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7206 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7207 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7209 MockClientSocketPoolManager* mock_pool_manager =
7210 new MockClientSocketPoolManager;
7211 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7212 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7213 peer.SetClientSocketPoolManager(mock_pool_manager);
7215 scoped_ptr<HttpTransaction> trans(
7216 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7218 EXPECT_EQ(ERR_IO_PENDING,
7219 GroupNameTransactionHelper(tests[i].url, session));
7220 if (tests[i].ssl)
7221 EXPECT_EQ(tests[i].expected_group_name,
7222 ssl_conn_pool->last_group_name_received());
7223 else
7224 EXPECT_EQ(tests[i].expected_group_name,
7225 socks_conn_pool->last_group_name_received());
7229 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7230 HttpRequestInfo request;
7231 request.method = "GET";
7232 request.url = GURL("http://www.google.com/");
7234 session_deps_.proxy_service.reset(
7235 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7237 // This simulates failure resolving all hostnames; that means we will fail
7238 // connecting to both proxies (myproxy:70 and foobar:80).
7239 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7241 scoped_ptr<HttpTransaction> trans(
7242 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7243 CreateSession(&session_deps_)));
7245 TestCompletionCallback callback;
7247 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7248 EXPECT_EQ(ERR_IO_PENDING, rv);
7250 rv = callback.WaitForResult();
7251 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7254 // Base test to make sure that when the load flags for a request specify to
7255 // bypass the cache, the DNS cache is not used.
7256 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7257 int load_flags) {
7258 // Issue a request, asking to bypass the cache(s).
7259 HttpRequestInfo request;
7260 request.method = "GET";
7261 request.load_flags = load_flags;
7262 request.url = GURL("http://www.google.com/");
7264 // Select a host resolver that does caching.
7265 session_deps_.host_resolver.reset(new MockCachingHostResolver);
7267 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY,
7268 CreateSession(&session_deps_)));
7270 // Warm up the host cache so it has an entry for "www.google.com".
7271 AddressList addrlist;
7272 TestCompletionCallback callback;
7273 int rv = session_deps_.host_resolver->Resolve(
7274 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
7275 callback.callback(), NULL, BoundNetLog());
7276 EXPECT_EQ(ERR_IO_PENDING, rv);
7277 rv = callback.WaitForResult();
7278 EXPECT_EQ(OK, rv);
7280 // Verify that it was added to host cache, by doing a subsequent async lookup
7281 // and confirming it completes synchronously.
7282 rv = session_deps_.host_resolver->Resolve(
7283 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
7284 callback.callback(), NULL, BoundNetLog());
7285 ASSERT_EQ(OK, rv);
7287 // Inject a failure the next time that "www.google.com" is resolved. This way
7288 // we can tell if the next lookup hit the cache, or the "network".
7289 // (cache --> success, "network" --> failure).
7290 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7292 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7293 // first read -- this won't be reached as the host resolution will fail first.
7294 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7295 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7296 session_deps_.socket_factory->AddSocketDataProvider(&data);
7298 // Run the request.
7299 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7300 ASSERT_EQ(ERR_IO_PENDING, rv);
7301 rv = callback.WaitForResult();
7303 // If we bypassed the cache, we would have gotten a failure while resolving
7304 // "www.google.com".
7305 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7308 // There are multiple load flags that should trigger the host cache bypass.
7309 // Test each in isolation:
7310 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7311 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7314 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7315 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7318 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7319 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7322 // Make sure we can handle an error when writing the request.
7323 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7324 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7326 HttpRequestInfo request;
7327 request.method = "GET";
7328 request.url = GURL("http://www.foo.com/");
7329 request.load_flags = 0;
7331 MockWrite write_failure[] = {
7332 MockWrite(ASYNC, ERR_CONNECTION_RESET),
7334 StaticSocketDataProvider data(NULL, 0,
7335 write_failure, arraysize(write_failure));
7336 session_deps_.socket_factory->AddSocketDataProvider(&data);
7338 TestCompletionCallback callback;
7340 scoped_ptr<HttpTransaction> trans(
7341 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7342 CreateSession(&session_deps_)));
7344 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7345 EXPECT_EQ(ERR_IO_PENDING, rv);
7347 rv = callback.WaitForResult();
7348 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7351 // Check that a connection closed after the start of the headers finishes ok.
7352 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7353 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7355 HttpRequestInfo request;
7356 request.method = "GET";
7357 request.url = GURL("http://www.foo.com/");
7358 request.load_flags = 0;
7360 MockRead data_reads[] = {
7361 MockRead("HTTP/1."),
7362 MockRead(SYNCHRONOUS, OK),
7365 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7366 session_deps_.socket_factory->AddSocketDataProvider(&data);
7368 TestCompletionCallback callback;
7370 scoped_ptr<HttpTransaction> trans(
7371 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7372 CreateSession(&session_deps_)));
7374 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7375 EXPECT_EQ(ERR_IO_PENDING, rv);
7377 rv = callback.WaitForResult();
7378 EXPECT_EQ(OK, rv);
7380 const HttpResponseInfo* response = trans->GetResponseInfo();
7381 ASSERT_TRUE(response != NULL);
7383 EXPECT_TRUE(response->headers.get() != NULL);
7384 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7386 std::string response_data;
7387 rv = ReadTransaction(trans.get(), &response_data);
7388 EXPECT_EQ(OK, rv);
7389 EXPECT_EQ("", response_data);
7392 // Make sure that a dropped connection while draining the body for auth
7393 // restart does the right thing.
7394 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7395 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7397 HttpRequestInfo request;
7398 request.method = "GET";
7399 request.url = GURL("http://www.google.com/");
7400 request.load_flags = 0;
7402 MockWrite data_writes1[] = {
7403 MockWrite("GET / HTTP/1.1\r\n"
7404 "Host: www.google.com\r\n"
7405 "Connection: keep-alive\r\n\r\n"),
7408 MockRead data_reads1[] = {
7409 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7410 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7412 MockRead("Content-Length: 14\r\n\r\n"),
7413 MockRead("Unauth"),
7414 MockRead(ASYNC, ERR_CONNECTION_RESET),
7417 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7418 data_writes1, arraysize(data_writes1));
7419 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7421 // After calling trans->RestartWithAuth(), this is the request we should
7422 // be issuing -- the final header line contains the credentials.
7423 MockWrite data_writes2[] = {
7424 MockWrite("GET / HTTP/1.1\r\n"
7425 "Host: www.google.com\r\n"
7426 "Connection: keep-alive\r\n"
7427 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7430 // Lastly, the server responds with the actual content.
7431 MockRead data_reads2[] = {
7432 MockRead("HTTP/1.1 200 OK\r\n"),
7433 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7434 MockRead("Content-Length: 100\r\n\r\n"),
7435 MockRead(SYNCHRONOUS, OK),
7438 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7439 data_writes2, arraysize(data_writes2));
7440 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7442 TestCompletionCallback callback1;
7444 scoped_ptr<HttpTransaction> trans(
7445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7447 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7448 EXPECT_EQ(ERR_IO_PENDING, rv);
7450 rv = callback1.WaitForResult();
7451 EXPECT_EQ(OK, rv);
7453 const HttpResponseInfo* response = trans->GetResponseInfo();
7454 ASSERT_TRUE(response != NULL);
7455 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7457 TestCompletionCallback callback2;
7459 rv = trans->RestartWithAuth(
7460 AuthCredentials(kFoo, kBar), callback2.callback());
7461 EXPECT_EQ(ERR_IO_PENDING, rv);
7463 rv = callback2.WaitForResult();
7464 EXPECT_EQ(OK, rv);
7466 response = trans->GetResponseInfo();
7467 ASSERT_TRUE(response != NULL);
7468 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7469 EXPECT_EQ(100, response->headers->GetContentLength());
7472 // Test HTTPS connections going through a proxy that sends extra data.
7473 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
7474 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7476 HttpRequestInfo request;
7477 request.method = "GET";
7478 request.url = GURL("https://www.google.com/");
7479 request.load_flags = 0;
7481 MockRead proxy_reads[] = {
7482 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7483 MockRead(SYNCHRONOUS, OK)
7486 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
7487 SSLSocketDataProvider ssl(ASYNC, OK);
7489 session_deps_.socket_factory->AddSocketDataProvider(&data);
7490 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7492 TestCompletionCallback callback;
7494 session_deps_.socket_factory->ResetNextMockIndexes();
7496 scoped_ptr<HttpTransaction> trans(
7497 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7498 CreateSession(&session_deps_)));
7500 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7501 EXPECT_EQ(ERR_IO_PENDING, rv);
7503 rv = callback.WaitForResult();
7504 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
7507 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
7508 HttpRequestInfo request;
7509 request.method = "GET";
7510 request.url = GURL("http://www.google.com/");
7511 request.load_flags = 0;
7513 scoped_ptr<HttpTransaction> trans(
7514 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7515 CreateSession(&session_deps_)));
7517 MockRead data_reads[] = {
7518 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7519 MockRead(SYNCHRONOUS, OK),
7522 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7523 session_deps_.socket_factory->AddSocketDataProvider(&data);
7525 TestCompletionCallback callback;
7527 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7528 EXPECT_EQ(ERR_IO_PENDING, rv);
7530 EXPECT_EQ(OK, callback.WaitForResult());
7532 const HttpResponseInfo* response = trans->GetResponseInfo();
7533 ASSERT_TRUE(response != NULL);
7535 EXPECT_TRUE(response->headers.get() != NULL);
7536 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7538 std::string response_data;
7539 rv = ReadTransaction(trans.get(), &response_data);
7540 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
7543 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
7544 base::FilePath temp_file_path;
7545 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
7546 const uint64 kFakeSize = 100000; // file is actually blank
7547 UploadFileElementReader::ScopedOverridingContentLengthForTests
7548 overriding_content_length(kFakeSize);
7550 ScopedVector<UploadElementReader> element_readers;
7551 element_readers.push_back(
7552 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7553 temp_file_path,
7555 kuint64max,
7556 base::Time()));
7557 UploadDataStream upload_data_stream(&element_readers, 0);
7559 HttpRequestInfo request;
7560 request.method = "POST";
7561 request.url = GURL("http://www.google.com/upload");
7562 request.upload_data_stream = &upload_data_stream;
7563 request.load_flags = 0;
7565 scoped_ptr<HttpTransaction> trans(
7566 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7567 CreateSession(&session_deps_)));
7569 MockRead data_reads[] = {
7570 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7571 MockRead("hello world"),
7572 MockRead(SYNCHRONOUS, OK),
7574 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7575 session_deps_.socket_factory->AddSocketDataProvider(&data);
7577 TestCompletionCallback callback;
7579 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7580 EXPECT_EQ(ERR_IO_PENDING, rv);
7582 rv = callback.WaitForResult();
7583 EXPECT_EQ(OK, rv);
7585 const HttpResponseInfo* response = trans->GetResponseInfo();
7586 ASSERT_TRUE(response != NULL);
7588 EXPECT_TRUE(response->headers.get() != NULL);
7589 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7591 std::string response_data;
7592 rv = ReadTransaction(trans.get(), &response_data);
7593 EXPECT_EQ(OK, rv);
7594 EXPECT_EQ("hello world", response_data);
7596 base::DeleteFile(temp_file_path, false);
7599 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
7600 base::FilePath temp_file;
7601 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
7602 std::string temp_file_content("Unreadable file.");
7603 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
7604 temp_file_content.length()));
7605 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
7607 ScopedVector<UploadElementReader> element_readers;
7608 element_readers.push_back(
7609 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7610 temp_file,
7612 kuint64max,
7613 base::Time()));
7614 UploadDataStream upload_data_stream(&element_readers, 0);
7616 HttpRequestInfo request;
7617 request.method = "POST";
7618 request.url = GURL("http://www.google.com/upload");
7619 request.upload_data_stream = &upload_data_stream;
7620 request.load_flags = 0;
7622 // If we try to upload an unreadable file, the network stack should report
7623 // the file size as zero and upload zero bytes for that file.
7624 scoped_ptr<HttpTransaction> trans(
7625 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7626 CreateSession(&session_deps_)));
7628 MockRead data_reads[] = {
7629 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7630 MockRead(SYNCHRONOUS, OK),
7632 MockWrite data_writes[] = {
7633 MockWrite("POST /upload HTTP/1.1\r\n"
7634 "Host: www.google.com\r\n"
7635 "Connection: keep-alive\r\n"
7636 "Content-Length: 0\r\n\r\n"),
7637 MockWrite(SYNCHRONOUS, OK),
7639 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
7640 arraysize(data_writes));
7641 session_deps_.socket_factory->AddSocketDataProvider(&data);
7643 TestCompletionCallback callback;
7645 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7646 EXPECT_EQ(ERR_IO_PENDING, rv);
7648 rv = callback.WaitForResult();
7649 EXPECT_EQ(OK, rv);
7651 const HttpResponseInfo* response = trans->GetResponseInfo();
7652 ASSERT_TRUE(response != NULL);
7653 EXPECT_TRUE(response->headers.get() != NULL);
7654 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7656 base::DeleteFile(temp_file, false);
7659 TEST_P(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
7660 base::FilePath temp_file;
7661 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
7662 std::string temp_file_contents("Unreadable file.");
7663 std::string unreadable_contents(temp_file_contents.length(), '\0');
7664 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
7665 temp_file_contents.length()));
7667 ScopedVector<UploadElementReader> element_readers;
7668 element_readers.push_back(
7669 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7670 temp_file,
7672 kuint64max,
7673 base::Time()));
7674 UploadDataStream upload_data_stream(&element_readers, 0);
7676 HttpRequestInfo request;
7677 request.method = "POST";
7678 request.url = GURL("http://www.google.com/upload");
7679 request.upload_data_stream = &upload_data_stream;
7680 request.load_flags = 0;
7682 scoped_ptr<HttpTransaction> trans(
7683 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7684 CreateSession(&session_deps_)));
7686 MockRead data_reads[] = {
7687 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7688 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7689 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
7691 MockRead("HTTP/1.1 200 OK\r\n"),
7692 MockRead("Content-Length: 0\r\n\r\n"),
7693 MockRead(SYNCHRONOUS, OK),
7695 MockWrite data_writes[] = {
7696 MockWrite("POST /upload HTTP/1.1\r\n"
7697 "Host: www.google.com\r\n"
7698 "Connection: keep-alive\r\n"
7699 "Content-Length: 16\r\n\r\n"),
7700 MockWrite(SYNCHRONOUS, temp_file_contents.c_str()),
7702 MockWrite("POST /upload HTTP/1.1\r\n"
7703 "Host: www.google.com\r\n"
7704 "Connection: keep-alive\r\n"
7705 "Content-Length: 0\r\n"
7706 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7707 MockWrite(SYNCHRONOUS, unreadable_contents.c_str(),
7708 temp_file_contents.length()),
7709 MockWrite(SYNCHRONOUS, OK),
7711 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
7712 arraysize(data_writes));
7713 session_deps_.socket_factory->AddSocketDataProvider(&data);
7715 TestCompletionCallback callback1;
7717 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7718 EXPECT_EQ(ERR_IO_PENDING, rv);
7720 rv = callback1.WaitForResult();
7721 EXPECT_EQ(OK, rv);
7723 const HttpResponseInfo* response = trans->GetResponseInfo();
7724 ASSERT_TRUE(response != NULL);
7725 ASSERT_TRUE(response->headers.get() != NULL);
7726 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
7727 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7729 // Now make the file unreadable and try again.
7730 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
7732 TestCompletionCallback callback2;
7734 rv = trans->RestartWithAuth(
7735 AuthCredentials(kFoo, kBar), callback2.callback());
7736 EXPECT_EQ(ERR_IO_PENDING, rv);
7738 rv = callback2.WaitForResult();
7739 EXPECT_EQ(OK, rv);
7741 response = trans->GetResponseInfo();
7742 ASSERT_TRUE(response != NULL);
7743 EXPECT_TRUE(response->headers.get() != NULL);
7744 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7745 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7747 base::DeleteFile(temp_file, false);
7750 // Tests that changes to Auth realms are treated like auth rejections.
7751 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
7753 HttpRequestInfo request;
7754 request.method = "GET";
7755 request.url = GURL("http://www.google.com/");
7756 request.load_flags = 0;
7758 // First transaction will request a resource and receive a Basic challenge
7759 // with realm="first_realm".
7760 MockWrite data_writes1[] = {
7761 MockWrite("GET / HTTP/1.1\r\n"
7762 "Host: www.google.com\r\n"
7763 "Connection: keep-alive\r\n"
7764 "\r\n"),
7766 MockRead data_reads1[] = {
7767 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7768 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7769 "\r\n"),
7772 // After calling trans->RestartWithAuth(), provide an Authentication header
7773 // for first_realm. The server will reject and provide a challenge with
7774 // second_realm.
7775 MockWrite data_writes2[] = {
7776 MockWrite("GET / HTTP/1.1\r\n"
7777 "Host: www.google.com\r\n"
7778 "Connection: keep-alive\r\n"
7779 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
7780 "\r\n"),
7782 MockRead data_reads2[] = {
7783 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7784 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
7785 "\r\n"),
7788 // This again fails, and goes back to first_realm. Make sure that the
7789 // entry is removed from cache.
7790 MockWrite data_writes3[] = {
7791 MockWrite("GET / HTTP/1.1\r\n"
7792 "Host: www.google.com\r\n"
7793 "Connection: keep-alive\r\n"
7794 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
7795 "\r\n"),
7797 MockRead data_reads3[] = {
7798 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7799 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7800 "\r\n"),
7803 // Try one last time (with the correct password) and get the resource.
7804 MockWrite data_writes4[] = {
7805 MockWrite("GET / HTTP/1.1\r\n"
7806 "Host: www.google.com\r\n"
7807 "Connection: keep-alive\r\n"
7808 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
7809 "\r\n"),
7811 MockRead data_reads4[] = {
7812 MockRead("HTTP/1.1 200 OK\r\n"
7813 "Content-Type: text/html; charset=iso-8859-1\r\n"
7814 "Content-Length: 5\r\n"
7815 "\r\n"
7816 "hello"),
7819 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7820 data_writes1, arraysize(data_writes1));
7821 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7822 data_writes2, arraysize(data_writes2));
7823 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
7824 data_writes3, arraysize(data_writes3));
7825 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
7826 data_writes4, arraysize(data_writes4));
7827 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7828 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7829 session_deps_.socket_factory->AddSocketDataProvider(&data3);
7830 session_deps_.socket_factory->AddSocketDataProvider(&data4);
7832 TestCompletionCallback callback1;
7834 scoped_ptr<HttpTransaction> trans(
7835 new HttpNetworkTransaction(DEFAULT_PRIORITY,
7836 CreateSession(&session_deps_)));
7838 // Issue the first request with Authorize headers. There should be a
7839 // password prompt for first_realm waiting to be filled in after the
7840 // transaction completes.
7841 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7842 EXPECT_EQ(ERR_IO_PENDING, rv);
7843 rv = callback1.WaitForResult();
7844 EXPECT_EQ(OK, rv);
7845 const HttpResponseInfo* response = trans->GetResponseInfo();
7846 ASSERT_TRUE(response != NULL);
7847 const AuthChallengeInfo* challenge = response->auth_challenge.get();
7848 ASSERT_FALSE(challenge == NULL);
7849 EXPECT_FALSE(challenge->is_proxy);
7850 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
7851 EXPECT_EQ("first_realm", challenge->realm);
7852 EXPECT_EQ("basic", challenge->scheme);
7854 // Issue the second request with an incorrect password. There should be a
7855 // password prompt for second_realm waiting to be filled in after the
7856 // transaction completes.
7857 TestCompletionCallback callback2;
7858 rv = trans->RestartWithAuth(
7859 AuthCredentials(kFirst, kBaz), callback2.callback());
7860 EXPECT_EQ(ERR_IO_PENDING, rv);
7861 rv = callback2.WaitForResult();
7862 EXPECT_EQ(OK, rv);
7863 response = trans->GetResponseInfo();
7864 ASSERT_TRUE(response != NULL);
7865 challenge = response->auth_challenge.get();
7866 ASSERT_FALSE(challenge == NULL);
7867 EXPECT_FALSE(challenge->is_proxy);
7868 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
7869 EXPECT_EQ("second_realm", challenge->realm);
7870 EXPECT_EQ("basic", challenge->scheme);
7872 // Issue the third request with another incorrect password. There should be
7873 // a password prompt for first_realm waiting to be filled in. If the password
7874 // prompt is not present, it indicates that the HttpAuthCacheEntry for
7875 // first_realm was not correctly removed.
7876 TestCompletionCallback callback3;
7877 rv = trans->RestartWithAuth(
7878 AuthCredentials(kSecond, kFou), callback3.callback());
7879 EXPECT_EQ(ERR_IO_PENDING, rv);
7880 rv = callback3.WaitForResult();
7881 EXPECT_EQ(OK, rv);
7882 response = trans->GetResponseInfo();
7883 ASSERT_TRUE(response != NULL);
7884 challenge = response->auth_challenge.get();
7885 ASSERT_FALSE(challenge == NULL);
7886 EXPECT_FALSE(challenge->is_proxy);
7887 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
7888 EXPECT_EQ("first_realm", challenge->realm);
7889 EXPECT_EQ("basic", challenge->scheme);
7891 // Issue the fourth request with the correct password and username.
7892 TestCompletionCallback callback4;
7893 rv = trans->RestartWithAuth(
7894 AuthCredentials(kFirst, kBar), callback4.callback());
7895 EXPECT_EQ(ERR_IO_PENDING, rv);
7896 rv = callback4.WaitForResult();
7897 EXPECT_EQ(OK, rv);
7898 response = trans->GetResponseInfo();
7899 ASSERT_TRUE(response != NULL);
7900 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7903 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
7904 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
7905 HttpStreamFactory::set_use_alternate_protocols(true);
7907 std::string alternate_protocol_http_header =
7908 GetAlternateProtocolHttpHeader();
7910 MockRead data_reads[] = {
7911 MockRead("HTTP/1.1 200 OK\r\n"),
7912 MockRead(alternate_protocol_http_header.c_str()),
7913 MockRead("hello world"),
7914 MockRead(SYNCHRONOUS, OK),
7917 HttpRequestInfo request;
7918 request.method = "GET";
7919 request.url = GURL("http://www.google.com/");
7920 request.load_flags = 0;
7922 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7924 session_deps_.socket_factory->AddSocketDataProvider(&data);
7926 TestCompletionCallback callback;
7928 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7929 scoped_ptr<HttpTransaction> trans(
7930 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7932 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7933 EXPECT_EQ(ERR_IO_PENDING, rv);
7935 HostPortPair http_host_port_pair("www.google.com", 80);
7936 const HttpServerProperties& http_server_properties =
7937 *session->http_server_properties();
7938 EXPECT_FALSE(
7939 http_server_properties.HasAlternateProtocol(http_host_port_pair));
7941 EXPECT_EQ(OK, callback.WaitForResult());
7943 const HttpResponseInfo* response = trans->GetResponseInfo();
7944 ASSERT_TRUE(response != NULL);
7945 ASSERT_TRUE(response->headers.get() != NULL);
7946 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7947 EXPECT_FALSE(response->was_fetched_via_spdy);
7948 EXPECT_FALSE(response->was_npn_negotiated);
7950 std::string response_data;
7951 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7952 EXPECT_EQ("hello world", response_data);
7954 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
7955 const PortAlternateProtocolPair alternate =
7956 http_server_properties.GetAlternateProtocol(http_host_port_pair);
7957 PortAlternateProtocolPair expected_alternate;
7958 expected_alternate.port = 443;
7959 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
7960 EXPECT_TRUE(expected_alternate.Equals(alternate));
7963 TEST_P(HttpNetworkTransactionTest,
7964 MarkBrokenAlternateProtocolAndFallback) {
7965 HttpStreamFactory::set_use_alternate_protocols(true);
7967 HttpRequestInfo request;
7968 request.method = "GET";
7969 request.url = GURL("http://www.google.com/");
7970 request.load_flags = 0;
7972 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
7973 StaticSocketDataProvider first_data;
7974 first_data.set_connect_data(mock_connect);
7975 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
7977 MockRead data_reads[] = {
7978 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
7979 MockRead("hello world"),
7980 MockRead(ASYNC, OK),
7982 StaticSocketDataProvider second_data(
7983 data_reads, arraysize(data_reads), NULL, 0);
7984 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
7986 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7988 base::WeakPtr<HttpServerProperties> http_server_properties =
7989 session->http_server_properties();
7990 // Port must be < 1024, or the header will be ignored (since initial port was
7991 // port 80 (another restricted port).
7992 http_server_properties->SetAlternateProtocol(
7993 HostPortPair::FromURL(request.url),
7994 666 /* port is ignored by MockConnect anyway */,
7995 AlternateProtocolFromNextProto(GetParam()));
7997 scoped_ptr<HttpTransaction> trans(
7998 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7999 TestCompletionCallback callback;
8001 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8002 EXPECT_EQ(ERR_IO_PENDING, rv);
8003 EXPECT_EQ(OK, callback.WaitForResult());
8005 const HttpResponseInfo* response = trans->GetResponseInfo();
8006 ASSERT_TRUE(response != NULL);
8007 ASSERT_TRUE(response->headers.get() != NULL);
8008 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8010 std::string response_data;
8011 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8012 EXPECT_EQ("hello world", response_data);
8014 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8015 HostPortPair::FromURL(request.url)));
8016 const PortAlternateProtocolPair alternate =
8017 http_server_properties->GetAlternateProtocol(
8018 HostPortPair::FromURL(request.url));
8019 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8022 TEST_P(HttpNetworkTransactionTest,
8023 AlternateProtocolPortRestrictedBlocked) {
8024 // Ensure that we're not allowed to redirect traffic via an alternate
8025 // protocol to an unrestricted (port >= 1024) when the original traffic was
8026 // on a restricted port (port < 1024). Ensure that we can redirect in all
8027 // other cases.
8028 HttpStreamFactory::set_use_alternate_protocols(true);
8030 HttpRequestInfo restricted_port_request;
8031 restricted_port_request.method = "GET";
8032 restricted_port_request.url = GURL("http://www.google.com:1023/");
8033 restricted_port_request.load_flags = 0;
8035 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8036 StaticSocketDataProvider first_data;
8037 first_data.set_connect_data(mock_connect);
8038 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8040 MockRead data_reads[] = {
8041 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8042 MockRead("hello world"),
8043 MockRead(ASYNC, OK),
8045 StaticSocketDataProvider second_data(
8046 data_reads, arraysize(data_reads), NULL, 0);
8047 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8049 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8051 base::WeakPtr<HttpServerProperties> http_server_properties =
8052 session->http_server_properties();
8053 const int kUnrestrictedAlternatePort = 1024;
8054 http_server_properties->SetAlternateProtocol(
8055 HostPortPair::FromURL(restricted_port_request.url),
8056 kUnrestrictedAlternatePort,
8057 AlternateProtocolFromNextProto(GetParam()));
8059 scoped_ptr<HttpTransaction> trans(
8060 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8061 TestCompletionCallback callback;
8063 int rv = trans->Start(
8064 &restricted_port_request,
8065 callback.callback(), BoundNetLog());
8066 EXPECT_EQ(ERR_IO_PENDING, rv);
8067 // Invalid change to unrestricted port should fail.
8068 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8071 TEST_P(HttpNetworkTransactionTest,
8072 AlternateProtocolPortRestrictedPermitted) {
8073 // Ensure that we're allowed to redirect traffic via an alternate
8074 // protocol to an unrestricted (port >= 1024) when the original traffic was
8075 // on a restricted port (port < 1024) if we set
8076 // enable_user_alternate_protocol_ports.
8078 HttpStreamFactory::set_use_alternate_protocols(true);
8079 session_deps_.enable_user_alternate_protocol_ports = true;
8081 HttpRequestInfo restricted_port_request;
8082 restricted_port_request.method = "GET";
8083 restricted_port_request.url = GURL("http://www.google.com:1023/");
8084 restricted_port_request.load_flags = 0;
8086 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8087 StaticSocketDataProvider first_data;
8088 first_data.set_connect_data(mock_connect);
8089 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8091 MockRead data_reads[] = {
8092 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8093 MockRead("hello world"),
8094 MockRead(ASYNC, OK),
8096 StaticSocketDataProvider second_data(
8097 data_reads, arraysize(data_reads), NULL, 0);
8098 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8100 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8102 base::WeakPtr<HttpServerProperties> http_server_properties =
8103 session->http_server_properties();
8104 const int kUnrestrictedAlternatePort = 1024;
8105 http_server_properties->SetAlternateProtocol(
8106 HostPortPair::FromURL(restricted_port_request.url),
8107 kUnrestrictedAlternatePort,
8108 AlternateProtocolFromNextProto(GetParam()));
8110 scoped_ptr<HttpTransaction> trans(
8111 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8112 TestCompletionCallback callback;
8114 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8115 &restricted_port_request,
8116 callback.callback(), BoundNetLog()));
8117 // Change to unrestricted port should succeed.
8118 EXPECT_EQ(OK, callback.WaitForResult());
8121 TEST_P(HttpNetworkTransactionTest,
8122 AlternateProtocolPortRestrictedAllowed) {
8123 // Ensure that we're not allowed to redirect traffic via an alternate
8124 // protocol to an unrestricted (port >= 1024) when the original traffic was
8125 // on a restricted port (port < 1024). Ensure that we can redirect in all
8126 // other cases.
8127 HttpStreamFactory::set_use_alternate_protocols(true);
8129 HttpRequestInfo restricted_port_request;
8130 restricted_port_request.method = "GET";
8131 restricted_port_request.url = GURL("http://www.google.com:1023/");
8132 restricted_port_request.load_flags = 0;
8134 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8135 StaticSocketDataProvider first_data;
8136 first_data.set_connect_data(mock_connect);
8137 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8139 MockRead data_reads[] = {
8140 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8141 MockRead("hello world"),
8142 MockRead(ASYNC, OK),
8144 StaticSocketDataProvider second_data(
8145 data_reads, arraysize(data_reads), NULL, 0);
8146 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8148 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8150 base::WeakPtr<HttpServerProperties> http_server_properties =
8151 session->http_server_properties();
8152 const int kRestrictedAlternatePort = 80;
8153 http_server_properties->SetAlternateProtocol(
8154 HostPortPair::FromURL(restricted_port_request.url),
8155 kRestrictedAlternatePort,
8156 AlternateProtocolFromNextProto(GetParam()));
8158 scoped_ptr<HttpTransaction> trans(
8159 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8160 TestCompletionCallback callback;
8162 int rv = trans->Start(
8163 &restricted_port_request,
8164 callback.callback(), BoundNetLog());
8165 EXPECT_EQ(ERR_IO_PENDING, rv);
8166 // Valid change to restricted port should pass.
8167 EXPECT_EQ(OK, callback.WaitForResult());
8170 TEST_P(HttpNetworkTransactionTest,
8171 AlternateProtocolPortUnrestrictedAllowed1) {
8172 // Ensure that we're not allowed to redirect traffic via an alternate
8173 // protocol to an unrestricted (port >= 1024) when the original traffic was
8174 // on a restricted port (port < 1024). Ensure that we can redirect in all
8175 // other cases.
8176 HttpStreamFactory::set_use_alternate_protocols(true);
8178 HttpRequestInfo unrestricted_port_request;
8179 unrestricted_port_request.method = "GET";
8180 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8181 unrestricted_port_request.load_flags = 0;
8183 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8184 StaticSocketDataProvider first_data;
8185 first_data.set_connect_data(mock_connect);
8186 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8188 MockRead data_reads[] = {
8189 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8190 MockRead("hello world"),
8191 MockRead(ASYNC, OK),
8193 StaticSocketDataProvider second_data(
8194 data_reads, arraysize(data_reads), NULL, 0);
8195 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8199 base::WeakPtr<HttpServerProperties> http_server_properties =
8200 session->http_server_properties();
8201 const int kRestrictedAlternatePort = 80;
8202 http_server_properties->SetAlternateProtocol(
8203 HostPortPair::FromURL(unrestricted_port_request.url),
8204 kRestrictedAlternatePort,
8205 AlternateProtocolFromNextProto(GetParam()));
8207 scoped_ptr<HttpTransaction> trans(
8208 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8209 TestCompletionCallback callback;
8211 int rv = trans->Start(
8212 &unrestricted_port_request, callback.callback(), BoundNetLog());
8213 EXPECT_EQ(ERR_IO_PENDING, rv);
8214 // Valid change to restricted port should pass.
8215 EXPECT_EQ(OK, callback.WaitForResult());
8218 TEST_P(HttpNetworkTransactionTest,
8219 AlternateProtocolPortUnrestrictedAllowed2) {
8220 // Ensure that we're not allowed to redirect traffic via an alternate
8221 // protocol to an unrestricted (port >= 1024) when the original traffic was
8222 // on a restricted port (port < 1024). Ensure that we can redirect in all
8223 // other cases.
8224 HttpStreamFactory::set_use_alternate_protocols(true);
8226 HttpRequestInfo unrestricted_port_request;
8227 unrestricted_port_request.method = "GET";
8228 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8229 unrestricted_port_request.load_flags = 0;
8231 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8232 StaticSocketDataProvider first_data;
8233 first_data.set_connect_data(mock_connect);
8234 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8236 MockRead data_reads[] = {
8237 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8238 MockRead("hello world"),
8239 MockRead(ASYNC, OK),
8241 StaticSocketDataProvider second_data(
8242 data_reads, arraysize(data_reads), NULL, 0);
8243 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8245 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8247 base::WeakPtr<HttpServerProperties> http_server_properties =
8248 session->http_server_properties();
8249 const int kUnrestrictedAlternatePort = 1024;
8250 http_server_properties->SetAlternateProtocol(
8251 HostPortPair::FromURL(unrestricted_port_request.url),
8252 kUnrestrictedAlternatePort,
8253 AlternateProtocolFromNextProto(GetParam()));
8255 scoped_ptr<HttpTransaction> trans(
8256 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8257 TestCompletionCallback callback;
8259 int rv = trans->Start(
8260 &unrestricted_port_request, callback.callback(), BoundNetLog());
8261 EXPECT_EQ(ERR_IO_PENDING, rv);
8262 // Valid change to an unrestricted port should pass.
8263 EXPECT_EQ(OK, callback.WaitForResult());
8266 TEST_P(HttpNetworkTransactionTest,
8267 AlternateProtocolUnsafeBlocked) {
8268 // Ensure that we're not allowed to redirect traffic via an alternate
8269 // protocol to an unsafe port, and that we resume the second
8270 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8271 HttpStreamFactory::set_use_alternate_protocols(true);
8273 HttpRequestInfo request;
8274 request.method = "GET";
8275 request.url = GURL("http://www.google.com/");
8276 request.load_flags = 0;
8278 // The alternate protocol request will error out before we attempt to connect,
8279 // so only the standard HTTP request will try to connect.
8280 MockRead data_reads[] = {
8281 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8282 MockRead("hello world"),
8283 MockRead(ASYNC, OK),
8285 StaticSocketDataProvider data(
8286 data_reads, arraysize(data_reads), NULL, 0);
8287 session_deps_.socket_factory->AddSocketDataProvider(&data);
8289 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8291 base::WeakPtr<HttpServerProperties> http_server_properties =
8292 session->http_server_properties();
8293 const int kUnsafePort = 7;
8294 http_server_properties->SetAlternateProtocol(
8295 HostPortPair::FromURL(request.url),
8296 kUnsafePort,
8297 AlternateProtocolFromNextProto(GetParam()));
8299 scoped_ptr<HttpTransaction> trans(
8300 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8301 TestCompletionCallback callback;
8303 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8304 EXPECT_EQ(ERR_IO_PENDING, rv);
8305 // The HTTP request should succeed.
8306 EXPECT_EQ(OK, callback.WaitForResult());
8308 // Disable alternate protocol before the asserts.
8309 HttpStreamFactory::set_use_alternate_protocols(false);
8311 const HttpResponseInfo* response = trans->GetResponseInfo();
8312 ASSERT_TRUE(response != NULL);
8313 ASSERT_TRUE(response->headers.get() != NULL);
8314 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8316 std::string response_data;
8317 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8318 EXPECT_EQ("hello world", response_data);
8321 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8322 HttpStreamFactory::set_use_alternate_protocols(true);
8323 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8325 HttpRequestInfo request;
8326 request.method = "GET";
8327 request.url = GURL("http://www.google.com/");
8328 request.load_flags = 0;
8330 std::string alternate_protocol_http_header =
8331 GetAlternateProtocolHttpHeader();
8333 MockRead data_reads[] = {
8334 MockRead("HTTP/1.1 200 OK\r\n"),
8335 MockRead(alternate_protocol_http_header.c_str()),
8336 MockRead("hello world"),
8337 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8338 MockRead(ASYNC, OK)
8341 StaticSocketDataProvider first_transaction(
8342 data_reads, arraysize(data_reads), NULL, 0);
8343 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8345 SSLSocketDataProvider ssl(ASYNC, OK);
8346 ssl.SetNextProto(GetParam());
8347 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8349 scoped_ptr<SpdyFrame> req(
8350 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8351 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8353 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8354 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8355 MockRead spdy_reads[] = {
8356 CreateMockRead(*resp),
8357 CreateMockRead(*data),
8358 MockRead(ASYNC, 0, 0),
8361 DelayedSocketData spdy_data(
8362 1, // wait for one write to finish before reading.
8363 spdy_reads, arraysize(spdy_reads),
8364 spdy_writes, arraysize(spdy_writes));
8365 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8367 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8368 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8369 NULL, 0, NULL, 0);
8370 hanging_non_alternate_protocol_socket.set_connect_data(
8371 never_finishing_connect);
8372 session_deps_.socket_factory->AddSocketDataProvider(
8373 &hanging_non_alternate_protocol_socket);
8375 TestCompletionCallback callback;
8377 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8378 scoped_ptr<HttpTransaction> trans(
8379 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8381 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8382 EXPECT_EQ(ERR_IO_PENDING, rv);
8383 EXPECT_EQ(OK, callback.WaitForResult());
8385 const HttpResponseInfo* response = trans->GetResponseInfo();
8386 ASSERT_TRUE(response != NULL);
8387 ASSERT_TRUE(response->headers.get() != NULL);
8388 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8390 std::string response_data;
8391 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8392 EXPECT_EQ("hello world", response_data);
8394 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8396 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8397 EXPECT_EQ(ERR_IO_PENDING, rv);
8398 EXPECT_EQ(OK, callback.WaitForResult());
8400 response = trans->GetResponseInfo();
8401 ASSERT_TRUE(response != NULL);
8402 ASSERT_TRUE(response->headers.get() != NULL);
8403 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8404 EXPECT_TRUE(response->was_fetched_via_spdy);
8405 EXPECT_TRUE(response->was_npn_negotiated);
8407 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8408 EXPECT_EQ("hello!", response_data);
8411 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8412 HttpStreamFactory::set_use_alternate_protocols(true);
8413 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8415 HttpRequestInfo request;
8416 request.method = "GET";
8417 request.url = GURL("http://www.google.com/");
8418 request.load_flags = 0;
8420 std::string alternate_protocol_http_header =
8421 GetAlternateProtocolHttpHeader();
8423 MockRead data_reads[] = {
8424 MockRead("HTTP/1.1 200 OK\r\n"),
8425 MockRead(alternate_protocol_http_header.c_str()),
8426 MockRead("hello world"),
8427 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8428 MockRead(ASYNC, OK),
8431 StaticSocketDataProvider first_transaction(
8432 data_reads, arraysize(data_reads), NULL, 0);
8433 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8434 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8436 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8437 StaticSocketDataProvider hanging_socket(
8438 NULL, 0, NULL, 0);
8439 hanging_socket.set_connect_data(never_finishing_connect);
8440 // Socket 2 and 3 are the hanging Alternate-Protocol and
8441 // non-Alternate-Protocol jobs from the 2nd transaction.
8442 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8443 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8445 SSLSocketDataProvider ssl(ASYNC, OK);
8446 ssl.SetNextProto(GetParam());
8447 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8449 scoped_ptr<SpdyFrame> req1(
8450 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8451 scoped_ptr<SpdyFrame> req2(
8452 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8453 MockWrite spdy_writes[] = {
8454 CreateMockWrite(*req1),
8455 CreateMockWrite(*req2),
8457 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8458 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8459 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8460 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8461 MockRead spdy_reads[] = {
8462 CreateMockRead(*resp1),
8463 CreateMockRead(*data1),
8464 CreateMockRead(*resp2),
8465 CreateMockRead(*data2),
8466 MockRead(ASYNC, 0, 0),
8469 DelayedSocketData spdy_data(
8470 2, // wait for writes to finish before reading.
8471 spdy_reads, arraysize(spdy_reads),
8472 spdy_writes, arraysize(spdy_writes));
8473 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8474 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8476 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8477 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8479 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8480 TestCompletionCallback callback1;
8481 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8483 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8484 EXPECT_EQ(ERR_IO_PENDING, rv);
8485 EXPECT_EQ(OK, callback1.WaitForResult());
8487 const HttpResponseInfo* response = trans1.GetResponseInfo();
8488 ASSERT_TRUE(response != NULL);
8489 ASSERT_TRUE(response->headers.get() != NULL);
8490 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8492 std::string response_data;
8493 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8494 EXPECT_EQ("hello world", response_data);
8496 TestCompletionCallback callback2;
8497 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8498 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8499 EXPECT_EQ(ERR_IO_PENDING, rv);
8501 TestCompletionCallback callback3;
8502 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8503 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8504 EXPECT_EQ(ERR_IO_PENDING, rv);
8506 EXPECT_EQ(OK, callback2.WaitForResult());
8507 EXPECT_EQ(OK, callback3.WaitForResult());
8509 response = trans2.GetResponseInfo();
8510 ASSERT_TRUE(response != NULL);
8511 ASSERT_TRUE(response->headers.get() != NULL);
8512 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8513 EXPECT_TRUE(response->was_fetched_via_spdy);
8514 EXPECT_TRUE(response->was_npn_negotiated);
8515 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8516 EXPECT_EQ("hello!", response_data);
8518 response = trans3.GetResponseInfo();
8519 ASSERT_TRUE(response != NULL);
8520 ASSERT_TRUE(response->headers.get() != NULL);
8521 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8522 EXPECT_TRUE(response->was_fetched_via_spdy);
8523 EXPECT_TRUE(response->was_npn_negotiated);
8524 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
8525 EXPECT_EQ("hello!", response_data);
8528 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
8529 HttpStreamFactory::set_use_alternate_protocols(true);
8530 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8532 HttpRequestInfo request;
8533 request.method = "GET";
8534 request.url = GURL("http://www.google.com/");
8535 request.load_flags = 0;
8537 std::string alternate_protocol_http_header =
8538 GetAlternateProtocolHttpHeader();
8540 MockRead data_reads[] = {
8541 MockRead("HTTP/1.1 200 OK\r\n"),
8542 MockRead(alternate_protocol_http_header.c_str()),
8543 MockRead("hello world"),
8544 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8545 MockRead(ASYNC, OK),
8548 StaticSocketDataProvider first_transaction(
8549 data_reads, arraysize(data_reads), NULL, 0);
8550 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8552 SSLSocketDataProvider ssl(ASYNC, OK);
8553 ssl.SetNextProto(GetParam());
8554 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8556 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8557 StaticSocketDataProvider hanging_alternate_protocol_socket(
8558 NULL, 0, NULL, 0);
8559 hanging_alternate_protocol_socket.set_connect_data(
8560 never_finishing_connect);
8561 session_deps_.socket_factory->AddSocketDataProvider(
8562 &hanging_alternate_protocol_socket);
8564 // 2nd request is just a copy of the first one, over HTTP again.
8565 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8567 TestCompletionCallback callback;
8569 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8570 scoped_ptr<HttpTransaction> trans(
8571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8573 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8574 EXPECT_EQ(ERR_IO_PENDING, rv);
8575 EXPECT_EQ(OK, callback.WaitForResult());
8577 const HttpResponseInfo* response = trans->GetResponseInfo();
8578 ASSERT_TRUE(response != NULL);
8579 ASSERT_TRUE(response->headers.get() != NULL);
8580 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8582 std::string response_data;
8583 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8584 EXPECT_EQ("hello world", response_data);
8586 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8588 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8589 EXPECT_EQ(ERR_IO_PENDING, rv);
8590 EXPECT_EQ(OK, callback.WaitForResult());
8592 response = trans->GetResponseInfo();
8593 ASSERT_TRUE(response != NULL);
8594 ASSERT_TRUE(response->headers.get() != NULL);
8595 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8596 EXPECT_FALSE(response->was_fetched_via_spdy);
8597 EXPECT_FALSE(response->was_npn_negotiated);
8599 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8600 EXPECT_EQ("hello world", response_data);
8603 class CapturingProxyResolver : public ProxyResolver {
8604 public:
8605 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8606 virtual ~CapturingProxyResolver() {}
8608 virtual int GetProxyForURL(const GURL& url,
8609 ProxyInfo* results,
8610 const CompletionCallback& callback,
8611 RequestHandle* request,
8612 const BoundNetLog& net_log) OVERRIDE {
8613 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
8614 HostPortPair("myproxy", 80));
8615 results->UseProxyServer(proxy_server);
8616 resolved_.push_back(url);
8617 return OK;
8620 virtual void CancelRequest(RequestHandle request) OVERRIDE {
8621 NOTREACHED();
8624 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
8625 NOTREACHED();
8626 return LOAD_STATE_IDLE;
8629 virtual void CancelSetPacScript() OVERRIDE {
8630 NOTREACHED();
8633 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
8634 const CompletionCallback& /*callback*/) OVERRIDE {
8635 return OK;
8638 const std::vector<GURL>& resolved() const { return resolved_; }
8640 private:
8641 std::vector<GURL> resolved_;
8643 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
8646 TEST_P(HttpNetworkTransactionTest,
8647 UseAlternateProtocolForTunneledNpnSpdy) {
8648 HttpStreamFactory::set_use_alternate_protocols(true);
8649 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8651 ProxyConfig proxy_config;
8652 proxy_config.set_auto_detect(true);
8653 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
8655 CapturingProxyResolver* capturing_proxy_resolver =
8656 new CapturingProxyResolver();
8657 session_deps_.proxy_service.reset(new ProxyService(
8658 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
8659 NULL));
8660 CapturingNetLog net_log;
8661 session_deps_.net_log = &net_log;
8663 HttpRequestInfo request;
8664 request.method = "GET";
8665 request.url = GURL("http://www.google.com/");
8666 request.load_flags = 0;
8668 std::string alternate_protocol_http_header =
8669 GetAlternateProtocolHttpHeader();
8671 MockRead data_reads[] = {
8672 MockRead("HTTP/1.1 200 OK\r\n"),
8673 MockRead(alternate_protocol_http_header.c_str()),
8674 MockRead("hello world"),
8675 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8676 MockRead(ASYNC, OK),
8679 StaticSocketDataProvider first_transaction(
8680 data_reads, arraysize(data_reads), NULL, 0);
8681 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8683 SSLSocketDataProvider ssl(ASYNC, OK);
8684 ssl.SetNextProto(GetParam());
8685 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8687 scoped_ptr<SpdyFrame> req(
8688 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8689 MockWrite spdy_writes[] = {
8690 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8691 "Host: www.google.com\r\n"
8692 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
8693 CreateMockWrite(*req), // 3
8696 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8698 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8699 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8700 MockRead spdy_reads[] = {
8701 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
8702 CreateMockRead(*resp.get(), 4), // 2, 4
8703 CreateMockRead(*data.get(), 4), // 5
8704 MockRead(ASYNC, 0, 0, 4), // 6
8707 OrderedSocketData spdy_data(
8708 spdy_reads, arraysize(spdy_reads),
8709 spdy_writes, arraysize(spdy_writes));
8710 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8712 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8713 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8714 NULL, 0, NULL, 0);
8715 hanging_non_alternate_protocol_socket.set_connect_data(
8716 never_finishing_connect);
8717 session_deps_.socket_factory->AddSocketDataProvider(
8718 &hanging_non_alternate_protocol_socket);
8720 TestCompletionCallback callback;
8722 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8723 scoped_ptr<HttpTransaction> trans(
8724 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8726 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8727 EXPECT_EQ(ERR_IO_PENDING, rv);
8728 EXPECT_EQ(OK, callback.WaitForResult());
8730 const HttpResponseInfo* response = trans->GetResponseInfo();
8731 ASSERT_TRUE(response != NULL);
8732 ASSERT_TRUE(response->headers.get() != NULL);
8733 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8734 EXPECT_FALSE(response->was_fetched_via_spdy);
8735 EXPECT_FALSE(response->was_npn_negotiated);
8737 std::string response_data;
8738 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8739 EXPECT_EQ("hello world", response_data);
8741 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8743 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8744 EXPECT_EQ(ERR_IO_PENDING, rv);
8745 EXPECT_EQ(OK, callback.WaitForResult());
8747 response = trans->GetResponseInfo();
8748 ASSERT_TRUE(response != NULL);
8749 ASSERT_TRUE(response->headers.get() != NULL);
8750 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8751 EXPECT_TRUE(response->was_fetched_via_spdy);
8752 EXPECT_TRUE(response->was_npn_negotiated);
8754 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8755 EXPECT_EQ("hello!", response_data);
8756 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
8757 EXPECT_EQ("http://www.google.com/",
8758 capturing_proxy_resolver->resolved()[0].spec());
8759 EXPECT_EQ("https://www.google.com/",
8760 capturing_proxy_resolver->resolved()[1].spec());
8762 LoadTimingInfo load_timing_info;
8763 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8764 TestLoadTimingNotReusedWithPac(load_timing_info,
8765 CONNECT_TIMING_HAS_SSL_TIMES);
8768 TEST_P(HttpNetworkTransactionTest,
8769 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
8770 HttpStreamFactory::set_use_alternate_protocols(true);
8771 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8773 HttpRequestInfo request;
8774 request.method = "GET";
8775 request.url = GURL("http://www.google.com/");
8776 request.load_flags = 0;
8778 std::string alternate_protocol_http_header =
8779 GetAlternateProtocolHttpHeader();
8781 MockRead data_reads[] = {
8782 MockRead("HTTP/1.1 200 OK\r\n"),
8783 MockRead(alternate_protocol_http_header.c_str()),
8784 MockRead("hello world"),
8785 MockRead(ASYNC, OK),
8788 StaticSocketDataProvider first_transaction(
8789 data_reads, arraysize(data_reads), NULL, 0);
8790 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8792 SSLSocketDataProvider ssl(ASYNC, OK);
8793 ssl.SetNextProto(GetParam());
8794 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8796 scoped_ptr<SpdyFrame> req(
8797 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8798 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8800 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8801 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8802 MockRead spdy_reads[] = {
8803 CreateMockRead(*resp),
8804 CreateMockRead(*data),
8805 MockRead(ASYNC, 0, 0),
8808 DelayedSocketData spdy_data(
8809 1, // wait for one write to finish before reading.
8810 spdy_reads, arraysize(spdy_reads),
8811 spdy_writes, arraysize(spdy_writes));
8812 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8814 TestCompletionCallback callback;
8816 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8818 scoped_ptr<HttpTransaction> trans(
8819 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8821 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8822 EXPECT_EQ(ERR_IO_PENDING, rv);
8823 EXPECT_EQ(OK, callback.WaitForResult());
8825 const HttpResponseInfo* response = trans->GetResponseInfo();
8826 ASSERT_TRUE(response != NULL);
8827 ASSERT_TRUE(response->headers.get() != NULL);
8828 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8830 std::string response_data;
8831 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8832 EXPECT_EQ("hello world", response_data);
8834 // Set up an initial SpdySession in the pool to reuse.
8835 HostPortPair host_port_pair("www.google.com", 443);
8836 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
8837 kPrivacyModeDisabled);
8838 base::WeakPtr<SpdySession> spdy_session =
8839 CreateSecureSpdySession(session, key, BoundNetLog());
8841 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8843 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8844 EXPECT_EQ(ERR_IO_PENDING, rv);
8845 EXPECT_EQ(OK, callback.WaitForResult());
8847 response = trans->GetResponseInfo();
8848 ASSERT_TRUE(response != NULL);
8849 ASSERT_TRUE(response->headers.get() != NULL);
8850 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8851 EXPECT_TRUE(response->was_fetched_via_spdy);
8852 EXPECT_TRUE(response->was_npn_negotiated);
8854 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8855 EXPECT_EQ("hello!", response_data);
8858 // GenerateAuthToken is a mighty big test.
8859 // It tests all permutation of GenerateAuthToken behavior:
8860 // - Synchronous and Asynchronous completion.
8861 // - OK or error on completion.
8862 // - Direct connection, non-authenticating proxy, and authenticating proxy.
8863 // - HTTP or HTTPS backend (to include proxy tunneling).
8864 // - Non-authenticating and authenticating backend.
8866 // In all, there are 44 reasonable permuations (for example, if there are
8867 // problems generating an auth token for an authenticating proxy, we don't
8868 // need to test all permutations of the backend server).
8870 // The test proceeds by going over each of the configuration cases, and
8871 // potentially running up to three rounds in each of the tests. The TestConfig
8872 // specifies both the configuration for the test as well as the expectations
8873 // for the results.
8874 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
8875 static const char kServer[] = "http://www.example.com";
8876 static const char kSecureServer[] = "https://www.example.com";
8877 static const char kProxy[] = "myproxy:70";
8878 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
8880 enum AuthTiming {
8881 AUTH_NONE,
8882 AUTH_SYNC,
8883 AUTH_ASYNC,
8886 const MockWrite kGet(
8887 "GET / HTTP/1.1\r\n"
8888 "Host: www.example.com\r\n"
8889 "Connection: keep-alive\r\n\r\n");
8890 const MockWrite kGetProxy(
8891 "GET http://www.example.com/ HTTP/1.1\r\n"
8892 "Host: www.example.com\r\n"
8893 "Proxy-Connection: keep-alive\r\n\r\n");
8894 const MockWrite kGetAuth(
8895 "GET / HTTP/1.1\r\n"
8896 "Host: www.example.com\r\n"
8897 "Connection: keep-alive\r\n"
8898 "Authorization: auth_token\r\n\r\n");
8899 const MockWrite kGetProxyAuth(
8900 "GET http://www.example.com/ HTTP/1.1\r\n"
8901 "Host: www.example.com\r\n"
8902 "Proxy-Connection: keep-alive\r\n"
8903 "Proxy-Authorization: auth_token\r\n\r\n");
8904 const MockWrite kGetAuthThroughProxy(
8905 "GET http://www.example.com/ HTTP/1.1\r\n"
8906 "Host: www.example.com\r\n"
8907 "Proxy-Connection: keep-alive\r\n"
8908 "Authorization: auth_token\r\n\r\n");
8909 const MockWrite kGetAuthWithProxyAuth(
8910 "GET http://www.example.com/ HTTP/1.1\r\n"
8911 "Host: www.example.com\r\n"
8912 "Proxy-Connection: keep-alive\r\n"
8913 "Proxy-Authorization: auth_token\r\n"
8914 "Authorization: auth_token\r\n\r\n");
8915 const MockWrite kConnect(
8916 "CONNECT www.example.com:443 HTTP/1.1\r\n"
8917 "Host: www.example.com\r\n"
8918 "Proxy-Connection: keep-alive\r\n\r\n");
8919 const MockWrite kConnectProxyAuth(
8920 "CONNECT www.example.com:443 HTTP/1.1\r\n"
8921 "Host: www.example.com\r\n"
8922 "Proxy-Connection: keep-alive\r\n"
8923 "Proxy-Authorization: auth_token\r\n\r\n");
8925 const MockRead kSuccess(
8926 "HTTP/1.1 200 OK\r\n"
8927 "Content-Type: text/html; charset=iso-8859-1\r\n"
8928 "Content-Length: 3\r\n\r\n"
8929 "Yes");
8930 const MockRead kFailure(
8931 "Should not be called.");
8932 const MockRead kServerChallenge(
8933 "HTTP/1.1 401 Unauthorized\r\n"
8934 "WWW-Authenticate: Mock realm=server\r\n"
8935 "Content-Type: text/html; charset=iso-8859-1\r\n"
8936 "Content-Length: 14\r\n\r\n"
8937 "Unauthorized\r\n");
8938 const MockRead kProxyChallenge(
8939 "HTTP/1.1 407 Unauthorized\r\n"
8940 "Proxy-Authenticate: Mock realm=proxy\r\n"
8941 "Proxy-Connection: close\r\n"
8942 "Content-Type: text/html; charset=iso-8859-1\r\n"
8943 "Content-Length: 14\r\n\r\n"
8944 "Unauthorized\r\n");
8945 const MockRead kProxyConnected(
8946 "HTTP/1.1 200 Connection Established\r\n\r\n");
8948 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
8949 // no constructors, but the C++ compiler on Windows warns about
8950 // unspecified data in compound literals. So, moved to using constructors,
8951 // and TestRound's created with the default constructor should not be used.
8952 struct TestRound {
8953 TestRound()
8954 : expected_rv(ERR_UNEXPECTED),
8955 extra_write(NULL),
8956 extra_read(NULL) {
8958 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
8959 int expected_rv_arg)
8960 : write(write_arg),
8961 read(read_arg),
8962 expected_rv(expected_rv_arg),
8963 extra_write(NULL),
8964 extra_read(NULL) {
8966 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
8967 int expected_rv_arg, const MockWrite* extra_write_arg,
8968 const MockRead* extra_read_arg)
8969 : write(write_arg),
8970 read(read_arg),
8971 expected_rv(expected_rv_arg),
8972 extra_write(extra_write_arg),
8973 extra_read(extra_read_arg) {
8975 MockWrite write;
8976 MockRead read;
8977 int expected_rv;
8978 const MockWrite* extra_write;
8979 const MockRead* extra_read;
8982 static const int kNoSSL = 500;
8984 struct TestConfig {
8985 const char* proxy_url;
8986 AuthTiming proxy_auth_timing;
8987 int proxy_auth_rv;
8988 const char* server_url;
8989 AuthTiming server_auth_timing;
8990 int server_auth_rv;
8991 int num_auth_rounds;
8992 int first_ssl_round;
8993 TestRound rounds[3];
8994 } test_configs[] = {
8995 // Non-authenticating HTTP server with a direct connection.
8996 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
8997 { TestRound(kGet, kSuccess, OK)}},
8998 // Authenticating HTTP server with a direct connection.
8999 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9000 { TestRound(kGet, kServerChallenge, OK),
9001 TestRound(kGetAuth, kSuccess, OK)}},
9002 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9003 { TestRound(kGet, kServerChallenge, OK),
9004 TestRound(kGetAuth, kFailure, kAuthErr)}},
9005 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9006 { TestRound(kGet, kServerChallenge, OK),
9007 TestRound(kGetAuth, kSuccess, OK)}},
9008 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9009 { TestRound(kGet, kServerChallenge, OK),
9010 TestRound(kGetAuth, kFailure, kAuthErr)}},
9011 // Non-authenticating HTTP server through a non-authenticating proxy.
9012 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9013 { TestRound(kGetProxy, kSuccess, OK)}},
9014 // Authenticating HTTP server through a non-authenticating proxy.
9015 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9016 { TestRound(kGetProxy, kServerChallenge, OK),
9017 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9018 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9019 { TestRound(kGetProxy, kServerChallenge, OK),
9020 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9021 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9022 { TestRound(kGetProxy, kServerChallenge, OK),
9023 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9024 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9025 { TestRound(kGetProxy, kServerChallenge, OK),
9026 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9027 // Non-authenticating HTTP server through an authenticating proxy.
9028 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9029 { TestRound(kGetProxy, kProxyChallenge, OK),
9030 TestRound(kGetProxyAuth, kSuccess, OK)}},
9031 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9032 { TestRound(kGetProxy, kProxyChallenge, OK),
9033 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9034 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9035 { TestRound(kGetProxy, kProxyChallenge, OK),
9036 TestRound(kGetProxyAuth, kSuccess, OK)}},
9037 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9038 { TestRound(kGetProxy, kProxyChallenge, OK),
9039 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9040 // Authenticating HTTP server through an authenticating proxy.
9041 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9042 { TestRound(kGetProxy, kProxyChallenge, OK),
9043 TestRound(kGetProxyAuth, kServerChallenge, OK),
9044 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9045 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9046 { TestRound(kGetProxy, kProxyChallenge, OK),
9047 TestRound(kGetProxyAuth, kServerChallenge, OK),
9048 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9049 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9050 { TestRound(kGetProxy, kProxyChallenge, OK),
9051 TestRound(kGetProxyAuth, kServerChallenge, OK),
9052 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9053 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9054 { TestRound(kGetProxy, kProxyChallenge, OK),
9055 TestRound(kGetProxyAuth, kServerChallenge, OK),
9056 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9057 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9058 { TestRound(kGetProxy, kProxyChallenge, OK),
9059 TestRound(kGetProxyAuth, kServerChallenge, OK),
9060 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9061 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9062 { TestRound(kGetProxy, kProxyChallenge, OK),
9063 TestRound(kGetProxyAuth, kServerChallenge, OK),
9064 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9065 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9066 { TestRound(kGetProxy, kProxyChallenge, OK),
9067 TestRound(kGetProxyAuth, kServerChallenge, OK),
9068 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9069 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9070 { TestRound(kGetProxy, kProxyChallenge, OK),
9071 TestRound(kGetProxyAuth, kServerChallenge, OK),
9072 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9073 // Non-authenticating HTTPS server with a direct connection.
9074 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9075 { TestRound(kGet, kSuccess, OK)}},
9076 // Authenticating HTTPS server with a direct connection.
9077 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9078 { TestRound(kGet, kServerChallenge, OK),
9079 TestRound(kGetAuth, kSuccess, OK)}},
9080 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9081 { TestRound(kGet, kServerChallenge, OK),
9082 TestRound(kGetAuth, kFailure, kAuthErr)}},
9083 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9084 { TestRound(kGet, kServerChallenge, OK),
9085 TestRound(kGetAuth, kSuccess, OK)}},
9086 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9087 { TestRound(kGet, kServerChallenge, OK),
9088 TestRound(kGetAuth, kFailure, kAuthErr)}},
9089 // Non-authenticating HTTPS server with a non-authenticating proxy.
9090 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9091 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9092 // Authenticating HTTPS server through a non-authenticating proxy.
9093 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9094 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9095 TestRound(kGetAuth, kSuccess, OK)}},
9096 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9097 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9098 TestRound(kGetAuth, kFailure, kAuthErr)}},
9099 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9100 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9101 TestRound(kGetAuth, kSuccess, OK)}},
9102 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9103 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9104 TestRound(kGetAuth, kFailure, kAuthErr)}},
9105 // Non-Authenticating HTTPS server through an authenticating proxy.
9106 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9107 { TestRound(kConnect, kProxyChallenge, OK),
9108 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9109 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9110 { TestRound(kConnect, kProxyChallenge, OK),
9111 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9112 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9113 { TestRound(kConnect, kProxyChallenge, OK),
9114 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9115 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9116 { TestRound(kConnect, kProxyChallenge, OK),
9117 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9118 // Authenticating HTTPS server through an authenticating proxy.
9119 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9120 { TestRound(kConnect, kProxyChallenge, OK),
9121 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9122 &kGet, &kServerChallenge),
9123 TestRound(kGetAuth, kSuccess, OK)}},
9124 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9125 { TestRound(kConnect, kProxyChallenge, OK),
9126 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9127 &kGet, &kServerChallenge),
9128 TestRound(kGetAuth, kFailure, kAuthErr)}},
9129 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9130 { TestRound(kConnect, kProxyChallenge, OK),
9131 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9132 &kGet, &kServerChallenge),
9133 TestRound(kGetAuth, kSuccess, OK)}},
9134 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9135 { TestRound(kConnect, kProxyChallenge, OK),
9136 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9137 &kGet, &kServerChallenge),
9138 TestRound(kGetAuth, kFailure, kAuthErr)}},
9139 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9140 { TestRound(kConnect, kProxyChallenge, OK),
9141 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9142 &kGet, &kServerChallenge),
9143 TestRound(kGetAuth, kSuccess, OK)}},
9144 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9145 { TestRound(kConnect, kProxyChallenge, OK),
9146 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9147 &kGet, &kServerChallenge),
9148 TestRound(kGetAuth, kFailure, kAuthErr)}},
9149 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9150 { TestRound(kConnect, kProxyChallenge, OK),
9151 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9152 &kGet, &kServerChallenge),
9153 TestRound(kGetAuth, kSuccess, OK)}},
9154 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9155 { TestRound(kConnect, kProxyChallenge, OK),
9156 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9157 &kGet, &kServerChallenge),
9158 TestRound(kGetAuth, kFailure, kAuthErr)}},
9161 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9162 HttpAuthHandlerMock::Factory* auth_factory(
9163 new HttpAuthHandlerMock::Factory());
9164 session_deps_.http_auth_handler_factory.reset(auth_factory);
9165 const TestConfig& test_config = test_configs[i];
9167 // Set up authentication handlers as necessary.
9168 if (test_config.proxy_auth_timing != AUTH_NONE) {
9169 for (int n = 0; n < 2; n++) {
9170 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9171 std::string auth_challenge = "Mock realm=proxy";
9172 GURL origin(test_config.proxy_url);
9173 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9174 auth_challenge.end());
9175 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9176 origin, BoundNetLog());
9177 auth_handler->SetGenerateExpectation(
9178 test_config.proxy_auth_timing == AUTH_ASYNC,
9179 test_config.proxy_auth_rv);
9180 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9183 if (test_config.server_auth_timing != AUTH_NONE) {
9184 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9185 std::string auth_challenge = "Mock realm=server";
9186 GURL origin(test_config.server_url);
9187 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9188 auth_challenge.end());
9189 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9190 origin, BoundNetLog());
9191 auth_handler->SetGenerateExpectation(
9192 test_config.server_auth_timing == AUTH_ASYNC,
9193 test_config.server_auth_rv);
9194 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9196 if (test_config.proxy_url) {
9197 session_deps_.proxy_service.reset(
9198 ProxyService::CreateFixed(test_config.proxy_url));
9199 } else {
9200 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9203 HttpRequestInfo request;
9204 request.method = "GET";
9205 request.url = GURL(test_config.server_url);
9206 request.load_flags = 0;
9208 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9209 HttpNetworkTransaction trans(
9210 DEFAULT_PRIORITY, CreateSession(&session_deps_));
9212 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9213 const TestRound& read_write_round = test_config.rounds[round];
9215 // Set up expected reads and writes.
9216 MockRead reads[2];
9217 reads[0] = read_write_round.read;
9218 size_t length_reads = 1;
9219 if (read_write_round.extra_read) {
9220 reads[1] = *read_write_round.extra_read;
9221 length_reads = 2;
9224 MockWrite writes[2];
9225 writes[0] = read_write_round.write;
9226 size_t length_writes = 1;
9227 if (read_write_round.extra_write) {
9228 writes[1] = *read_write_round.extra_write;
9229 length_writes = 2;
9231 StaticSocketDataProvider data_provider(
9232 reads, length_reads, writes, length_writes);
9233 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9235 // Add an SSL sequence if necessary.
9236 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9237 if (round >= test_config.first_ssl_round)
9238 session_deps_.socket_factory->AddSSLSocketDataProvider(
9239 &ssl_socket_data_provider);
9241 // Start or restart the transaction.
9242 TestCompletionCallback callback;
9243 int rv;
9244 if (round == 0) {
9245 rv = trans.Start(&request, callback.callback(), BoundNetLog());
9246 } else {
9247 rv = trans.RestartWithAuth(
9248 AuthCredentials(kFoo, kBar), callback.callback());
9250 if (rv == ERR_IO_PENDING)
9251 rv = callback.WaitForResult();
9253 // Compare results with expected data.
9254 EXPECT_EQ(read_write_round.expected_rv, rv);
9255 const HttpResponseInfo* response = trans.GetResponseInfo();
9256 if (read_write_round.expected_rv == OK) {
9257 ASSERT_TRUE(response != NULL);
9258 } else {
9259 EXPECT_TRUE(response == NULL);
9260 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9261 continue;
9263 if (round + 1 < test_config.num_auth_rounds) {
9264 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9265 } else {
9266 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9272 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9273 // Do multi-round authentication and make sure it works correctly.
9274 HttpAuthHandlerMock::Factory* auth_factory(
9275 new HttpAuthHandlerMock::Factory());
9276 session_deps_.http_auth_handler_factory.reset(auth_factory);
9277 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9278 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9279 session_deps_.host_resolver->set_synchronous_mode(true);
9281 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9282 auth_handler->set_connection_based(true);
9283 std::string auth_challenge = "Mock realm=server";
9284 GURL origin("http://www.example.com");
9285 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9286 auth_challenge.end());
9287 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9288 origin, BoundNetLog());
9289 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9291 int rv = OK;
9292 const HttpResponseInfo* response = NULL;
9293 HttpRequestInfo request;
9294 request.method = "GET";
9295 request.url = origin;
9296 request.load_flags = 0;
9298 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9300 // Use a TCP Socket Pool with only one connection per group. This is used
9301 // to validate that the TCP socket is not released to the pool between
9302 // each round of multi-round authentication.
9303 HttpNetworkSessionPeer session_peer(session);
9304 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9305 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9306 50, // Max sockets for pool
9307 1, // Max sockets per group
9308 &transport_pool_histograms,
9309 session_deps_.host_resolver.get(),
9310 session_deps_.socket_factory.get(),
9311 session_deps_.net_log);
9312 MockClientSocketPoolManager* mock_pool_manager =
9313 new MockClientSocketPoolManager;
9314 mock_pool_manager->SetTransportSocketPool(transport_pool);
9315 session_peer.SetClientSocketPoolManager(mock_pool_manager);
9317 scoped_ptr<HttpTransaction> trans(
9318 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9319 TestCompletionCallback callback;
9321 const MockWrite kGet(
9322 "GET / HTTP/1.1\r\n"
9323 "Host: www.example.com\r\n"
9324 "Connection: keep-alive\r\n\r\n");
9325 const MockWrite kGetAuth(
9326 "GET / HTTP/1.1\r\n"
9327 "Host: www.example.com\r\n"
9328 "Connection: keep-alive\r\n"
9329 "Authorization: auth_token\r\n\r\n");
9331 const MockRead kServerChallenge(
9332 "HTTP/1.1 401 Unauthorized\r\n"
9333 "WWW-Authenticate: Mock realm=server\r\n"
9334 "Content-Type: text/html; charset=iso-8859-1\r\n"
9335 "Content-Length: 14\r\n\r\n"
9336 "Unauthorized\r\n");
9337 const MockRead kSuccess(
9338 "HTTP/1.1 200 OK\r\n"
9339 "Content-Type: text/html; charset=iso-8859-1\r\n"
9340 "Content-Length: 3\r\n\r\n"
9341 "Yes");
9343 MockWrite writes[] = {
9344 // First round
9345 kGet,
9346 // Second round
9347 kGetAuth,
9348 // Third round
9349 kGetAuth,
9350 // Fourth round
9351 kGetAuth,
9352 // Competing request
9353 kGet,
9355 MockRead reads[] = {
9356 // First round
9357 kServerChallenge,
9358 // Second round
9359 kServerChallenge,
9360 // Third round
9361 kServerChallenge,
9362 // Fourth round
9363 kSuccess,
9364 // Competing response
9365 kSuccess,
9367 StaticSocketDataProvider data_provider(reads, arraysize(reads),
9368 writes, arraysize(writes));
9369 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9371 const char* const kSocketGroup = "www.example.com:80";
9373 // First round of authentication.
9374 auth_handler->SetGenerateExpectation(false, OK);
9375 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9376 if (rv == ERR_IO_PENDING)
9377 rv = callback.WaitForResult();
9378 EXPECT_EQ(OK, rv);
9379 response = trans->GetResponseInfo();
9380 ASSERT_TRUE(response != NULL);
9381 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9382 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9384 // In between rounds, another request comes in for the same domain.
9385 // It should not be able to grab the TCP socket that trans has already
9386 // claimed.
9387 scoped_ptr<HttpTransaction> trans_compete(
9388 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9389 TestCompletionCallback callback_compete;
9390 rv = trans_compete->Start(
9391 &request, callback_compete.callback(), BoundNetLog());
9392 EXPECT_EQ(ERR_IO_PENDING, rv);
9393 // callback_compete.WaitForResult at this point would stall forever,
9394 // since the HttpNetworkTransaction does not release the request back to
9395 // the pool until after authentication completes.
9397 // Second round of authentication.
9398 auth_handler->SetGenerateExpectation(false, OK);
9399 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9400 if (rv == ERR_IO_PENDING)
9401 rv = callback.WaitForResult();
9402 EXPECT_EQ(OK, rv);
9403 response = trans->GetResponseInfo();
9404 ASSERT_TRUE(response != NULL);
9405 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9406 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9408 // Third round of authentication.
9409 auth_handler->SetGenerateExpectation(false, OK);
9410 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9411 if (rv == ERR_IO_PENDING)
9412 rv = callback.WaitForResult();
9413 EXPECT_EQ(OK, rv);
9414 response = trans->GetResponseInfo();
9415 ASSERT_TRUE(response != NULL);
9416 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9417 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9419 // Fourth round of authentication, which completes successfully.
9420 auth_handler->SetGenerateExpectation(false, OK);
9421 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9422 if (rv == ERR_IO_PENDING)
9423 rv = callback.WaitForResult();
9424 EXPECT_EQ(OK, rv);
9425 response = trans->GetResponseInfo();
9426 ASSERT_TRUE(response != NULL);
9427 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9428 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9430 // Read the body since the fourth round was successful. This will also
9431 // release the socket back to the pool.
9432 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9433 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9434 if (rv == ERR_IO_PENDING)
9435 rv = callback.WaitForResult();
9436 EXPECT_EQ(3, rv);
9437 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9438 EXPECT_EQ(0, rv);
9439 // There are still 0 idle sockets, since the trans_compete transaction
9440 // will be handed it immediately after trans releases it to the group.
9441 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9443 // The competing request can now finish. Wait for the headers and then
9444 // read the body.
9445 rv = callback_compete.WaitForResult();
9446 EXPECT_EQ(OK, rv);
9447 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9448 if (rv == ERR_IO_PENDING)
9449 rv = callback.WaitForResult();
9450 EXPECT_EQ(3, rv);
9451 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9452 EXPECT_EQ(0, rv);
9454 // Finally, the socket is released to the group.
9455 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9458 // This tests the case that a request is issued via http instead of spdy after
9459 // npn is negotiated.
9460 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9461 HttpStreamFactory::set_use_alternate_protocols(true);
9462 std::vector<NextProto> next_protos;
9463 next_protos.push_back(kProtoHTTP11);
9464 HttpStreamFactory::SetNextProtos(next_protos);
9465 HttpRequestInfo request;
9466 request.method = "GET";
9467 request.url = GURL("https://www.google.com/");
9468 request.load_flags = 0;
9470 MockWrite data_writes[] = {
9471 MockWrite("GET / HTTP/1.1\r\n"
9472 "Host: www.google.com\r\n"
9473 "Connection: keep-alive\r\n\r\n"),
9476 std::string alternate_protocol_http_header =
9477 GetAlternateProtocolHttpHeader();
9479 MockRead data_reads[] = {
9480 MockRead("HTTP/1.1 200 OK\r\n"),
9481 MockRead(alternate_protocol_http_header.c_str()),
9482 MockRead("hello world"),
9483 MockRead(SYNCHRONOUS, OK),
9486 SSLSocketDataProvider ssl(ASYNC, OK);
9487 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9488 ssl.next_proto = "http/1.1";
9489 ssl.protocol_negotiated = kProtoHTTP11;
9491 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9493 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9494 data_writes, arraysize(data_writes));
9495 session_deps_.socket_factory->AddSocketDataProvider(&data);
9497 TestCompletionCallback callback;
9499 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9500 scoped_ptr<HttpTransaction> trans(
9501 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9503 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9505 EXPECT_EQ(ERR_IO_PENDING, rv);
9506 EXPECT_EQ(OK, callback.WaitForResult());
9508 const HttpResponseInfo* response = trans->GetResponseInfo();
9509 ASSERT_TRUE(response != NULL);
9510 ASSERT_TRUE(response->headers.get() != NULL);
9511 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9513 std::string response_data;
9514 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9515 EXPECT_EQ("hello world", response_data);
9517 EXPECT_FALSE(response->was_fetched_via_spdy);
9518 EXPECT_TRUE(response->was_npn_negotiated);
9521 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
9522 // Simulate the SSL handshake completing with an NPN negotiation
9523 // followed by an immediate server closing of the socket.
9524 // Fix crash: http://crbug.com/46369
9525 HttpStreamFactory::set_use_alternate_protocols(true);
9526 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9528 HttpRequestInfo request;
9529 request.method = "GET";
9530 request.url = GURL("https://www.google.com/");
9531 request.load_flags = 0;
9533 SSLSocketDataProvider ssl(ASYNC, OK);
9534 ssl.SetNextProto(GetParam());
9535 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9537 scoped_ptr<SpdyFrame> req(
9538 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9539 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9541 MockRead spdy_reads[] = {
9542 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
9545 DelayedSocketData spdy_data(
9546 0, // don't wait in this case, immediate hangup.
9547 spdy_reads, arraysize(spdy_reads),
9548 spdy_writes, arraysize(spdy_writes));
9549 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9551 TestCompletionCallback callback;
9553 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9554 scoped_ptr<HttpTransaction> trans(
9555 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9557 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9558 EXPECT_EQ(ERR_IO_PENDING, rv);
9559 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
9562 // A subclass of HttpAuthHandlerMock that records the request URL when
9563 // it gets it. This is needed since the auth handler may get destroyed
9564 // before we get a chance to query it.
9565 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
9566 public:
9567 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
9569 virtual ~UrlRecordingHttpAuthHandlerMock() {}
9571 protected:
9572 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
9573 const HttpRequestInfo* request,
9574 const CompletionCallback& callback,
9575 std::string* auth_token) OVERRIDE {
9576 *url_ = request->url;
9577 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9578 credentials, request, callback, auth_token);
9581 private:
9582 GURL* url_;
9585 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
9586 // This test ensures that the URL passed into the proxy is upgraded
9587 // to https when doing an Alternate Protocol upgrade.
9588 HttpStreamFactory::set_use_alternate_protocols(true);
9589 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9591 session_deps_.proxy_service.reset(
9592 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9593 CapturingNetLog net_log;
9594 session_deps_.net_log = &net_log;
9595 GURL request_url;
9597 HttpAuthHandlerMock::Factory* auth_factory =
9598 new HttpAuthHandlerMock::Factory();
9599 UrlRecordingHttpAuthHandlerMock* auth_handler =
9600 new UrlRecordingHttpAuthHandlerMock(&request_url);
9601 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9602 auth_factory->set_do_init_from_challenge(true);
9603 session_deps_.http_auth_handler_factory.reset(auth_factory);
9606 HttpRequestInfo request;
9607 request.method = "GET";
9608 request.url = GURL("http://www.google.com");
9609 request.load_flags = 0;
9611 // First round goes unauthenticated through the proxy.
9612 MockWrite data_writes_1[] = {
9613 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9614 "Host: www.google.com\r\n"
9615 "Proxy-Connection: keep-alive\r\n"
9616 "\r\n"),
9618 MockRead data_reads_1[] = {
9619 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9620 MockRead("HTTP/1.1 200 OK\r\n"
9621 "Alternate-Protocol: 443:npn-spdy/2\r\n"
9622 "Proxy-Connection: close\r\n"
9623 "\r\n"),
9625 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
9626 data_writes_1, arraysize(data_writes_1));
9628 // Second round tries to tunnel to www.google.com due to the
9629 // Alternate-Protocol announcement in the first round. It fails due
9630 // to a proxy authentication challenge.
9631 // After the failure, a tunnel is established to www.google.com using
9632 // Proxy-Authorization headers. There is then a SPDY request round.
9634 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
9635 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
9636 // does a Disconnect and Connect on the same socket, rather than trying
9637 // to obtain a new one.
9639 // NOTE: Originally, the proxy response to the second CONNECT request
9640 // simply returned another 407 so the unit test could skip the SSL connection
9641 // establishment and SPDY framing issues. Alas, the
9642 // retry-http-when-alternate-protocol fails logic kicks in, which was more
9643 // complicated to set up expectations for than the SPDY session.
9645 scoped_ptr<SpdyFrame> req(
9646 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9647 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9648 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9650 MockWrite data_writes_2[] = {
9651 // First connection attempt without Proxy-Authorization.
9652 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9653 "Host: www.google.com\r\n"
9654 "Proxy-Connection: keep-alive\r\n"
9655 "\r\n"),
9657 // Second connection attempt with Proxy-Authorization.
9658 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9659 "Host: www.google.com\r\n"
9660 "Proxy-Connection: keep-alive\r\n"
9661 "Proxy-Authorization: auth_token\r\n"
9662 "\r\n"),
9664 // SPDY request
9665 CreateMockWrite(*req),
9667 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
9668 "Proxy-Authenticate: Mock\r\n"
9669 "Proxy-Connection: close\r\n"
9670 "\r\n");
9671 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9672 MockRead data_reads_2[] = {
9673 // First connection attempt fails
9674 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
9675 MockRead(ASYNC, kRejectConnectResponse,
9676 arraysize(kRejectConnectResponse) - 1, 1),
9678 // Second connection attempt passes
9679 MockRead(ASYNC, kAcceptConnectResponse,
9680 arraysize(kAcceptConnectResponse) -1, 4),
9682 // SPDY response
9683 CreateMockRead(*resp.get(), 6),
9684 CreateMockRead(*data.get(), 6),
9685 MockRead(ASYNC, 0, 0, 6),
9687 OrderedSocketData data_2(
9688 data_reads_2, arraysize(data_reads_2),
9689 data_writes_2, arraysize(data_writes_2));
9691 SSLSocketDataProvider ssl(ASYNC, OK);
9692 ssl.SetNextProto(GetParam());
9694 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9695 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9696 NULL, 0, NULL, 0);
9697 hanging_non_alternate_protocol_socket.set_connect_data(
9698 never_finishing_connect);
9700 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
9701 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
9702 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9703 session_deps_.socket_factory->AddSocketDataProvider(
9704 &hanging_non_alternate_protocol_socket);
9705 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9707 // First round should work and provide the Alternate-Protocol state.
9708 TestCompletionCallback callback_1;
9709 scoped_ptr<HttpTransaction> trans_1(
9710 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9711 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
9712 EXPECT_EQ(ERR_IO_PENDING, rv);
9713 EXPECT_EQ(OK, callback_1.WaitForResult());
9715 // Second round should attempt a tunnel connect and get an auth challenge.
9716 TestCompletionCallback callback_2;
9717 scoped_ptr<HttpTransaction> trans_2(
9718 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9719 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
9720 EXPECT_EQ(ERR_IO_PENDING, rv);
9721 EXPECT_EQ(OK, callback_2.WaitForResult());
9722 const HttpResponseInfo* response = trans_2->GetResponseInfo();
9723 ASSERT_TRUE(response != NULL);
9724 ASSERT_FALSE(response->auth_challenge.get() == NULL);
9726 // Restart with auth. Tunnel should work and response received.
9727 TestCompletionCallback callback_3;
9728 rv = trans_2->RestartWithAuth(
9729 AuthCredentials(kFoo, kBar), callback_3.callback());
9730 EXPECT_EQ(ERR_IO_PENDING, rv);
9731 EXPECT_EQ(OK, callback_3.WaitForResult());
9733 // After all that work, these two lines (or actually, just the scheme) are
9734 // what this test is all about. Make sure it happens correctly.
9735 EXPECT_EQ("https", request_url.scheme());
9736 EXPECT_EQ("www.google.com", request_url.host());
9738 LoadTimingInfo load_timing_info;
9739 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
9740 TestLoadTimingNotReusedWithPac(load_timing_info,
9741 CONNECT_TIMING_HAS_SSL_TIMES);
9744 // Test that if we cancel the transaction as the connection is completing, that
9745 // everything tears down correctly.
9746 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
9747 // Setup everything about the connection to complete synchronously, so that
9748 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
9749 // for is the callback from the HttpStreamRequest.
9750 // Then cancel the transaction.
9751 // Verify that we don't crash.
9752 MockConnect mock_connect(SYNCHRONOUS, OK);
9753 MockRead data_reads[] = {
9754 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
9755 MockRead(SYNCHRONOUS, "hello world"),
9756 MockRead(SYNCHRONOUS, OK),
9759 HttpRequestInfo request;
9760 request.method = "GET";
9761 request.url = GURL("http://www.google.com/");
9762 request.load_flags = 0;
9764 session_deps_.host_resolver->set_synchronous_mode(true);
9765 scoped_ptr<HttpTransaction> trans(
9766 new HttpNetworkTransaction(DEFAULT_PRIORITY,
9767 CreateSession(&session_deps_)));
9769 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9770 data.set_connect_data(mock_connect);
9771 session_deps_.socket_factory->AddSocketDataProvider(&data);
9773 TestCompletionCallback callback;
9775 CapturingBoundNetLog log;
9776 int rv = trans->Start(&request, callback.callback(), log.bound());
9777 EXPECT_EQ(ERR_IO_PENDING, rv);
9778 trans.reset(); // Cancel the transaction here.
9780 base::MessageLoop::current()->RunUntilIdle();
9783 // Test a basic GET request through a proxy.
9784 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
9785 session_deps_.proxy_service.reset(
9786 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9787 CapturingBoundNetLog log;
9788 session_deps_.net_log = log.bound().net_log();
9789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9791 HttpRequestInfo request;
9792 request.method = "GET";
9793 request.url = GURL("http://www.google.com/");
9795 MockWrite data_writes1[] = {
9796 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9797 "Host: www.google.com\r\n"
9798 "Proxy-Connection: keep-alive\r\n\r\n"),
9801 MockRead data_reads1[] = {
9802 MockRead("HTTP/1.1 200 OK\r\n"),
9803 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9804 MockRead("Content-Length: 100\r\n\r\n"),
9805 MockRead(SYNCHRONOUS, OK),
9808 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9809 data_writes1, arraysize(data_writes1));
9810 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9812 TestCompletionCallback callback1;
9814 scoped_ptr<HttpTransaction> trans(
9815 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9817 int rv = trans->Start(&request, callback1.callback(), log.bound());
9818 EXPECT_EQ(ERR_IO_PENDING, rv);
9820 rv = callback1.WaitForResult();
9821 EXPECT_EQ(OK, rv);
9823 const HttpResponseInfo* response = trans->GetResponseInfo();
9824 ASSERT_TRUE(response != NULL);
9826 EXPECT_TRUE(response->headers->IsKeepAlive());
9827 EXPECT_EQ(200, response->headers->response_code());
9828 EXPECT_EQ(100, response->headers->GetContentLength());
9829 EXPECT_TRUE(response->was_fetched_via_proxy);
9830 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9832 LoadTimingInfo load_timing_info;
9833 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9834 TestLoadTimingNotReusedWithPac(load_timing_info,
9835 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
9838 // Test a basic HTTPS GET request through a proxy.
9839 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
9840 session_deps_.proxy_service.reset(
9841 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9842 CapturingBoundNetLog log;
9843 session_deps_.net_log = log.bound().net_log();
9844 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9846 HttpRequestInfo request;
9847 request.method = "GET";
9848 request.url = GURL("https://www.google.com/");
9850 // Since we have proxy, should try to establish tunnel.
9851 MockWrite data_writes1[] = {
9852 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9853 "Host: www.google.com\r\n"
9854 "Proxy-Connection: keep-alive\r\n\r\n"),
9856 MockWrite("GET / HTTP/1.1\r\n"
9857 "Host: www.google.com\r\n"
9858 "Connection: keep-alive\r\n\r\n"),
9861 MockRead data_reads1[] = {
9862 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
9864 MockRead("HTTP/1.1 200 OK\r\n"),
9865 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9866 MockRead("Content-Length: 100\r\n\r\n"),
9867 MockRead(SYNCHRONOUS, OK),
9870 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9871 data_writes1, arraysize(data_writes1));
9872 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9873 SSLSocketDataProvider ssl(ASYNC, OK);
9874 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9876 TestCompletionCallback callback1;
9878 scoped_ptr<HttpTransaction> trans(
9879 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9881 int rv = trans->Start(&request, callback1.callback(), log.bound());
9882 EXPECT_EQ(ERR_IO_PENDING, rv);
9884 rv = callback1.WaitForResult();
9885 EXPECT_EQ(OK, rv);
9886 net::CapturingNetLog::CapturedEntryList entries;
9887 log.GetEntries(&entries);
9888 size_t pos = ExpectLogContainsSomewhere(
9889 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
9890 NetLog::PHASE_NONE);
9891 ExpectLogContainsSomewhere(
9892 entries, pos,
9893 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
9894 NetLog::PHASE_NONE);
9896 const HttpResponseInfo* response = trans->GetResponseInfo();
9897 ASSERT_TRUE(response != NULL);
9899 EXPECT_TRUE(response->headers->IsKeepAlive());
9900 EXPECT_EQ(200, response->headers->response_code());
9901 EXPECT_EQ(100, response->headers->GetContentLength());
9902 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9903 EXPECT_TRUE(response->was_fetched_via_proxy);
9905 LoadTimingInfo load_timing_info;
9906 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9907 TestLoadTimingNotReusedWithPac(load_timing_info,
9908 CONNECT_TIMING_HAS_SSL_TIMES);
9911 // Test a basic HTTPS GET request through a proxy, but the server hangs up
9912 // while establishing the tunnel.
9913 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
9914 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
9915 CapturingBoundNetLog log;
9916 session_deps_.net_log = log.bound().net_log();
9917 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9919 HttpRequestInfo request;
9920 request.method = "GET";
9921 request.url = GURL("https://www.google.com/");
9923 // Since we have proxy, should try to establish tunnel.
9924 MockWrite data_writes1[] = {
9925 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9926 "Host: www.google.com\r\n"
9927 "Proxy-Connection: keep-alive\r\n\r\n"),
9929 MockWrite("GET / HTTP/1.1\r\n"
9930 "Host: www.google.com\r\n"
9931 "Connection: keep-alive\r\n\r\n"),
9934 MockRead data_reads1[] = {
9935 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9936 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
9937 MockRead(ASYNC, 0, 0), // EOF
9940 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9941 data_writes1, arraysize(data_writes1));
9942 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9943 SSLSocketDataProvider ssl(ASYNC, OK);
9944 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9946 TestCompletionCallback callback1;
9948 scoped_ptr<HttpTransaction> trans(
9949 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9951 int rv = trans->Start(&request, callback1.callback(), log.bound());
9952 EXPECT_EQ(ERR_IO_PENDING, rv);
9954 rv = callback1.WaitForResult();
9955 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
9956 net::CapturingNetLog::CapturedEntryList entries;
9957 log.GetEntries(&entries);
9958 size_t pos = ExpectLogContainsSomewhere(
9959 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
9960 NetLog::PHASE_NONE);
9961 ExpectLogContainsSomewhere(
9962 entries, pos,
9963 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
9964 NetLog::PHASE_NONE);
9967 // Test for crbug.com/55424.
9968 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
9969 scoped_ptr<SpdyFrame> req(
9970 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
9971 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9973 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9974 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9975 MockRead spdy_reads[] = {
9976 CreateMockRead(*resp),
9977 CreateMockRead(*data),
9978 MockRead(ASYNC, 0, 0),
9981 DelayedSocketData spdy_data(
9982 1, // wait for one write to finish before reading.
9983 spdy_reads, arraysize(spdy_reads),
9984 spdy_writes, arraysize(spdy_writes));
9985 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9987 SSLSocketDataProvider ssl(ASYNC, OK);
9988 ssl.SetNextProto(GetParam());
9989 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9991 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9993 // Set up an initial SpdySession in the pool to reuse.
9994 HostPortPair host_port_pair("www.google.com", 443);
9995 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9996 kPrivacyModeDisabled);
9997 base::WeakPtr<SpdySession> spdy_session =
9998 CreateInsecureSpdySession(session, key, BoundNetLog());
10000 HttpRequestInfo request;
10001 request.method = "GET";
10002 request.url = GURL("https://www.google.com/");
10003 request.load_flags = 0;
10005 // This is the important line that marks this as a preconnect.
10006 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10008 scoped_ptr<HttpTransaction> trans(
10009 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10011 TestCompletionCallback callback;
10012 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10013 EXPECT_EQ(ERR_IO_PENDING, rv);
10014 EXPECT_EQ(OK, callback.WaitForResult());
10017 // Given a net error, cause that error to be returned from the first Write()
10018 // call and verify that the HttpTransaction fails with that error.
10019 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10020 int error, IoMode mode) {
10021 net::HttpRequestInfo request_info;
10022 request_info.url = GURL("https://www.example.com/");
10023 request_info.method = "GET";
10024 request_info.load_flags = net::LOAD_NORMAL;
10026 SSLSocketDataProvider ssl_data(mode, OK);
10027 net::MockWrite data_writes[] = {
10028 net::MockWrite(mode, error),
10030 net::StaticSocketDataProvider data(NULL, 0,
10031 data_writes, arraysize(data_writes));
10032 session_deps_.socket_factory->AddSocketDataProvider(&data);
10033 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10035 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10036 scoped_ptr<HttpTransaction> trans(
10037 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10039 TestCompletionCallback callback;
10040 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10041 if (rv == net::ERR_IO_PENDING)
10042 rv = callback.WaitForResult();
10043 ASSERT_EQ(error, rv);
10046 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10047 // Just check a grab bag of cert errors.
10048 static const int kErrors[] = {
10049 ERR_CERT_COMMON_NAME_INVALID,
10050 ERR_CERT_AUTHORITY_INVALID,
10051 ERR_CERT_DATE_INVALID,
10053 for (size_t i = 0; i < arraysize(kErrors); i++) {
10054 CheckErrorIsPassedBack(kErrors[i], ASYNC);
10055 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10059 // Ensure that a client certificate is removed from the SSL client auth
10060 // cache when:
10061 // 1) No proxy is involved.
10062 // 2) TLS False Start is disabled.
10063 // 3) The initial TLS handshake requests a client certificate.
10064 // 4) The client supplies an invalid/unacceptable certificate.
10065 TEST_P(HttpNetworkTransactionTest,
10066 ClientAuthCertCache_Direct_NoFalseStart) {
10067 net::HttpRequestInfo request_info;
10068 request_info.url = GURL("https://www.example.com/");
10069 request_info.method = "GET";
10070 request_info.load_flags = net::LOAD_NORMAL;
10072 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10073 cert_request->host_and_port = "www.example.com:443";
10075 // [ssl_]data1 contains the data for the first SSL handshake. When a
10076 // CertificateRequest is received for the first time, the handshake will
10077 // be aborted to allow the caller to provide a certificate.
10078 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10079 ssl_data1.cert_request_info = cert_request.get();
10080 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10081 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10082 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10084 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10085 // False Start is not being used, the result of the SSL handshake will be
10086 // returned as part of the SSLClientSocket::Connect() call. This test
10087 // matches the result of a server sending a handshake_failure alert,
10088 // rather than a Finished message, because it requires a client
10089 // certificate and none was supplied.
10090 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10091 ssl_data2.cert_request_info = cert_request.get();
10092 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10093 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10094 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10096 // [ssl_]data3 contains the data for the third SSL handshake. When a
10097 // connection to a server fails during an SSL handshake,
10098 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10099 // connection was attempted with TLSv1.1. This is transparent to the caller
10100 // of the HttpNetworkTransaction. Because this test failure is due to
10101 // requiring a client certificate, this fallback handshake should also
10102 // fail.
10103 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10104 ssl_data3.cert_request_info = cert_request.get();
10105 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10106 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10107 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10109 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10110 // connection to a server fails during an SSL handshake,
10111 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10112 // connection was attempted with TLSv1. This is transparent to the caller
10113 // of the HttpNetworkTransaction. Because this test failure is due to
10114 // requiring a client certificate, this fallback handshake should also
10115 // fail.
10116 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10117 ssl_data4.cert_request_info = cert_request.get();
10118 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10119 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10120 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10122 // Need one more if TLSv1.2 is enabled.
10123 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10124 ssl_data5.cert_request_info = cert_request.get();
10125 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10126 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10127 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10129 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10130 scoped_ptr<HttpTransaction> trans(
10131 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10133 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10134 TestCompletionCallback callback;
10135 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10136 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10138 // Complete the SSL handshake, which should abort due to requiring a
10139 // client certificate.
10140 rv = callback.WaitForResult();
10141 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10143 // Indicate that no certificate should be supplied. From the perspective
10144 // of SSLClientCertCache, NULL is just as meaningful as a real
10145 // certificate, so this is the same as supply a
10146 // legitimate-but-unacceptable certificate.
10147 rv = trans->RestartWithCertificate(NULL, callback.callback());
10148 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10150 // Ensure the certificate was added to the client auth cache before
10151 // allowing the connection to continue restarting.
10152 scoped_refptr<X509Certificate> client_cert;
10153 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10154 &client_cert));
10155 ASSERT_EQ(NULL, client_cert.get());
10157 // Restart the handshake. This will consume ssl_data2, which fails, and
10158 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10159 // The result code is checked against what ssl_data4 should return.
10160 rv = callback.WaitForResult();
10161 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10163 // Ensure that the client certificate is removed from the cache on a
10164 // handshake failure.
10165 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10166 &client_cert));
10169 // Ensure that a client certificate is removed from the SSL client auth
10170 // cache when:
10171 // 1) No proxy is involved.
10172 // 2) TLS False Start is enabled.
10173 // 3) The initial TLS handshake requests a client certificate.
10174 // 4) The client supplies an invalid/unacceptable certificate.
10175 TEST_P(HttpNetworkTransactionTest,
10176 ClientAuthCertCache_Direct_FalseStart) {
10177 net::HttpRequestInfo request_info;
10178 request_info.url = GURL("https://www.example.com/");
10179 request_info.method = "GET";
10180 request_info.load_flags = net::LOAD_NORMAL;
10182 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10183 cert_request->host_and_port = "www.example.com:443";
10185 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10186 // return successfully after reading up to the peer's Certificate message.
10187 // This is to allow the caller to call SSLClientSocket::Write(), which can
10188 // enqueue application data to be sent in the same packet as the
10189 // ChangeCipherSpec and Finished messages.
10190 // The actual handshake will be finished when SSLClientSocket::Read() is
10191 // called, which expects to process the peer's ChangeCipherSpec and
10192 // Finished messages. If there was an error negotiating with the peer,
10193 // such as due to the peer requiring a client certificate when none was
10194 // supplied, the alert sent by the peer won't be processed until Read() is
10195 // called.
10197 // Like the non-False Start case, when a client certificate is requested by
10198 // the peer, the handshake is aborted during the Connect() call.
10199 // [ssl_]data1 represents the initial SSL handshake with the peer.
10200 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10201 ssl_data1.cert_request_info = cert_request.get();
10202 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10203 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10204 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10206 // When a client certificate is supplied, Connect() will not be aborted
10207 // when the peer requests the certificate. Instead, the handshake will
10208 // artificially succeed, allowing the caller to write the HTTP request to
10209 // the socket. The handshake messages are not processed until Read() is
10210 // called, which then detects that the handshake was aborted, due to the
10211 // peer sending a handshake_failure because it requires a client
10212 // certificate.
10213 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10214 ssl_data2.cert_request_info = cert_request.get();
10215 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10216 net::MockRead data2_reads[] = {
10217 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10219 net::StaticSocketDataProvider data2(
10220 data2_reads, arraysize(data2_reads), NULL, 0);
10221 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10223 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10224 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10225 // TLSv1. It has the same behaviour as [ssl_]data2.
10226 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10227 ssl_data3.cert_request_info = cert_request.get();
10228 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10229 net::StaticSocketDataProvider data3(
10230 data2_reads, arraysize(data2_reads), NULL, 0);
10231 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10233 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10234 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10235 SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10236 ssl_data4.cert_request_info = cert_request.get();
10237 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10238 net::StaticSocketDataProvider data4(
10239 data2_reads, arraysize(data2_reads), NULL, 0);
10240 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10242 // Need one more if TLSv1.2 is enabled.
10243 SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10244 ssl_data5.cert_request_info = cert_request.get();
10245 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10246 net::StaticSocketDataProvider data5(
10247 data2_reads, arraysize(data2_reads), NULL, 0);
10248 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10250 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10251 scoped_ptr<HttpTransaction> trans(
10252 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10254 // Begin the initial SSL handshake.
10255 TestCompletionCallback callback;
10256 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10257 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10259 // Complete the SSL handshake, which should abort due to requiring a
10260 // client certificate.
10261 rv = callback.WaitForResult();
10262 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10264 // Indicate that no certificate should be supplied. From the perspective
10265 // of SSLClientCertCache, NULL is just as meaningful as a real
10266 // certificate, so this is the same as supply a
10267 // legitimate-but-unacceptable certificate.
10268 rv = trans->RestartWithCertificate(NULL, callback.callback());
10269 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10271 // Ensure the certificate was added to the client auth cache before
10272 // allowing the connection to continue restarting.
10273 scoped_refptr<X509Certificate> client_cert;
10274 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10275 &client_cert));
10276 ASSERT_EQ(NULL, client_cert.get());
10278 // Restart the handshake. This will consume ssl_data2, which fails, and
10279 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10280 // The result code is checked against what ssl_data4 should return.
10281 rv = callback.WaitForResult();
10282 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10284 // Ensure that the client certificate is removed from the cache on a
10285 // handshake failure.
10286 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10287 &client_cert));
10290 // Ensure that a client certificate is removed from the SSL client auth
10291 // cache when:
10292 // 1) An HTTPS proxy is involved.
10293 // 3) The HTTPS proxy requests a client certificate.
10294 // 4) The client supplies an invalid/unacceptable certificate for the
10295 // proxy.
10296 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10297 // then for connecting to an HTTP endpoint.
10298 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10299 session_deps_.proxy_service.reset(
10300 ProxyService::CreateFixed("https://proxy:70"));
10301 CapturingBoundNetLog log;
10302 session_deps_.net_log = log.bound().net_log();
10304 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10305 cert_request->host_and_port = "proxy:70";
10307 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10308 // [ssl_]data[1-3]. Rather than represending the endpoint
10309 // (www.example.com:443), they represent failures with the HTTPS proxy
10310 // (proxy:70).
10311 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10312 ssl_data1.cert_request_info = cert_request.get();
10313 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10314 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10315 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10317 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10318 ssl_data2.cert_request_info = cert_request.get();
10319 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10320 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10321 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10323 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10324 #if 0
10325 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10326 ssl_data3.cert_request_info = cert_request.get();
10327 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10328 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10329 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10330 #endif
10332 net::HttpRequestInfo requests[2];
10333 requests[0].url = GURL("https://www.example.com/");
10334 requests[0].method = "GET";
10335 requests[0].load_flags = net::LOAD_NORMAL;
10337 requests[1].url = GURL("http://www.example.com/");
10338 requests[1].method = "GET";
10339 requests[1].load_flags = net::LOAD_NORMAL;
10341 for (size_t i = 0; i < arraysize(requests); ++i) {
10342 session_deps_.socket_factory->ResetNextMockIndexes();
10343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10344 scoped_ptr<HttpNetworkTransaction> trans(
10345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10347 // Begin the SSL handshake with the proxy.
10348 TestCompletionCallback callback;
10349 int rv = trans->Start(
10350 &requests[i], callback.callback(), net::BoundNetLog());
10351 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10353 // Complete the SSL handshake, which should abort due to requiring a
10354 // client certificate.
10355 rv = callback.WaitForResult();
10356 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10358 // Indicate that no certificate should be supplied. From the perspective
10359 // of SSLClientCertCache, NULL is just as meaningful as a real
10360 // certificate, so this is the same as supply a
10361 // legitimate-but-unacceptable certificate.
10362 rv = trans->RestartWithCertificate(NULL, callback.callback());
10363 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10365 // Ensure the certificate was added to the client auth cache before
10366 // allowing the connection to continue restarting.
10367 scoped_refptr<X509Certificate> client_cert;
10368 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
10369 &client_cert));
10370 ASSERT_EQ(NULL, client_cert.get());
10371 // Ensure the certificate was NOT cached for the endpoint. This only
10372 // applies to HTTPS requests, but is fine to check for HTTP requests.
10373 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10374 &client_cert));
10376 // Restart the handshake. This will consume ssl_data2, which fails, and
10377 // then consume ssl_data3, which should also fail. The result code is
10378 // checked against what ssl_data3 should return.
10379 rv = callback.WaitForResult();
10380 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10382 // Now that the new handshake has failed, ensure that the client
10383 // certificate was removed from the client auth cache.
10384 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
10385 &client_cert));
10386 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10387 &client_cert));
10391 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10392 // TEST_P is a macro that expands directly to code that stringizes the
10393 // arguments. As a result, macros passed as parameters (such as prefix
10394 // or test_case_name) will not be expanded by the preprocessor. To
10395 // work around this, indirect the macro for TEST_P, so that the
10396 // pre-processor will expand macros such as MAYBE_test_name before
10397 // instantiating the test.
10398 #define WRAPPED_TEST_P(test_case_name, test_name) \
10399 TEST_P(test_case_name, test_name)
10401 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10402 #if defined(OS_WIN)
10403 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10404 #else
10405 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10406 #endif
10407 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10408 HttpStreamFactory::set_use_alternate_protocols(true);
10409 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10411 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10412 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10414 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10415 pool_peer.DisableDomainAuthenticationVerification();
10417 SSLSocketDataProvider ssl(ASYNC, OK);
10418 ssl.SetNextProto(GetParam());
10419 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10421 scoped_ptr<SpdyFrame> host1_req(
10422 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10423 scoped_ptr<SpdyFrame> host2_req(
10424 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10425 MockWrite spdy_writes[] = {
10426 CreateMockWrite(*host1_req, 1),
10427 CreateMockWrite(*host2_req, 4),
10429 scoped_ptr<SpdyFrame> host1_resp(
10430 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10431 scoped_ptr<SpdyFrame> host1_resp_body(
10432 spdy_util_.ConstructSpdyBodyFrame(1, true));
10433 scoped_ptr<SpdyFrame> host2_resp(
10434 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10435 scoped_ptr<SpdyFrame> host2_resp_body(
10436 spdy_util_.ConstructSpdyBodyFrame(3, true));
10437 MockRead spdy_reads[] = {
10438 CreateMockRead(*host1_resp, 2),
10439 CreateMockRead(*host1_resp_body, 3),
10440 CreateMockRead(*host2_resp, 5),
10441 CreateMockRead(*host2_resp_body, 6),
10442 MockRead(ASYNC, 0, 7),
10445 IPAddressNumber ip;
10446 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10447 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10448 MockConnect connect(ASYNC, OK, peer_addr);
10449 OrderedSocketData spdy_data(
10450 connect,
10451 spdy_reads, arraysize(spdy_reads),
10452 spdy_writes, arraysize(spdy_writes));
10453 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10455 TestCompletionCallback callback;
10456 HttpRequestInfo request1;
10457 request1.method = "GET";
10458 request1.url = GURL("https://www.google.com/");
10459 request1.load_flags = 0;
10460 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10462 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10463 EXPECT_EQ(ERR_IO_PENDING, rv);
10464 EXPECT_EQ(OK, callback.WaitForResult());
10466 const HttpResponseInfo* response = trans1.GetResponseInfo();
10467 ASSERT_TRUE(response != NULL);
10468 ASSERT_TRUE(response->headers.get() != NULL);
10469 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10471 std::string response_data;
10472 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10473 EXPECT_EQ("hello!", response_data);
10475 // Preload www.gmail.com into HostCache.
10476 HostPortPair host_port("www.gmail.com", 443);
10477 HostResolver::RequestInfo resolve_info(host_port);
10478 AddressList ignored;
10479 rv = session_deps_.host_resolver->Resolve(resolve_info, &ignored,
10480 callback.callback(), NULL,
10481 BoundNetLog());
10482 EXPECT_EQ(ERR_IO_PENDING, rv);
10483 rv = callback.WaitForResult();
10484 EXPECT_EQ(OK, rv);
10486 HttpRequestInfo request2;
10487 request2.method = "GET";
10488 request2.url = GURL("https://www.gmail.com/");
10489 request2.load_flags = 0;
10490 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10492 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10493 EXPECT_EQ(ERR_IO_PENDING, rv);
10494 EXPECT_EQ(OK, callback.WaitForResult());
10496 response = trans2.GetResponseInfo();
10497 ASSERT_TRUE(response != NULL);
10498 ASSERT_TRUE(response->headers.get() != NULL);
10499 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10500 EXPECT_TRUE(response->was_fetched_via_spdy);
10501 EXPECT_TRUE(response->was_npn_negotiated);
10502 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10503 EXPECT_EQ("hello!", response_data);
10505 #undef MAYBE_UseIPConnectionPooling
10507 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
10508 HttpStreamFactory::set_use_alternate_protocols(true);
10509 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10511 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10512 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10514 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10515 pool_peer.DisableDomainAuthenticationVerification();
10517 SSLSocketDataProvider ssl(ASYNC, OK);
10518 ssl.SetNextProto(GetParam());
10519 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10521 scoped_ptr<SpdyFrame> host1_req(
10522 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10523 scoped_ptr<SpdyFrame> host2_req(
10524 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10525 MockWrite spdy_writes[] = {
10526 CreateMockWrite(*host1_req, 1),
10527 CreateMockWrite(*host2_req, 4),
10529 scoped_ptr<SpdyFrame> host1_resp(
10530 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10531 scoped_ptr<SpdyFrame> host1_resp_body(
10532 spdy_util_.ConstructSpdyBodyFrame(1, true));
10533 scoped_ptr<SpdyFrame> host2_resp(
10534 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10535 scoped_ptr<SpdyFrame> host2_resp_body(
10536 spdy_util_.ConstructSpdyBodyFrame(3, true));
10537 MockRead spdy_reads[] = {
10538 CreateMockRead(*host1_resp, 2),
10539 CreateMockRead(*host1_resp_body, 3),
10540 CreateMockRead(*host2_resp, 5),
10541 CreateMockRead(*host2_resp_body, 6),
10542 MockRead(ASYNC, 0, 7),
10545 IPAddressNumber ip;
10546 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10547 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10548 MockConnect connect(ASYNC, OK, peer_addr);
10549 OrderedSocketData spdy_data(
10550 connect,
10551 spdy_reads, arraysize(spdy_reads),
10552 spdy_writes, arraysize(spdy_writes));
10553 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10555 TestCompletionCallback callback;
10556 HttpRequestInfo request1;
10557 request1.method = "GET";
10558 request1.url = GURL("https://www.google.com/");
10559 request1.load_flags = 0;
10560 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10562 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10563 EXPECT_EQ(ERR_IO_PENDING, rv);
10564 EXPECT_EQ(OK, callback.WaitForResult());
10566 const HttpResponseInfo* response = trans1.GetResponseInfo();
10567 ASSERT_TRUE(response != NULL);
10568 ASSERT_TRUE(response->headers.get() != NULL);
10569 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10571 std::string response_data;
10572 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10573 EXPECT_EQ("hello!", response_data);
10575 HttpRequestInfo request2;
10576 request2.method = "GET";
10577 request2.url = GURL("https://www.gmail.com/");
10578 request2.load_flags = 0;
10579 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10581 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10582 EXPECT_EQ(ERR_IO_PENDING, rv);
10583 EXPECT_EQ(OK, callback.WaitForResult());
10585 response = trans2.GetResponseInfo();
10586 ASSERT_TRUE(response != NULL);
10587 ASSERT_TRUE(response->headers.get() != NULL);
10588 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10589 EXPECT_TRUE(response->was_fetched_via_spdy);
10590 EXPECT_TRUE(response->was_npn_negotiated);
10591 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10592 EXPECT_EQ("hello!", response_data);
10595 class OneTimeCachingHostResolver : public net::HostResolver {
10596 public:
10597 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
10598 : host_port_(host_port) {}
10599 virtual ~OneTimeCachingHostResolver() {}
10601 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
10603 // HostResolver methods:
10604 virtual int Resolve(const RequestInfo& info,
10605 AddressList* addresses,
10606 const CompletionCallback& callback,
10607 RequestHandle* out_req,
10608 const BoundNetLog& net_log) OVERRIDE {
10609 return host_resolver_.Resolve(
10610 info, addresses, callback, out_req, net_log);
10613 virtual int ResolveFromCache(const RequestInfo& info,
10614 AddressList* addresses,
10615 const BoundNetLog& net_log) OVERRIDE {
10616 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
10617 if (rv == OK && info.host_port_pair().Equals(host_port_))
10618 host_resolver_.GetHostCache()->clear();
10619 return rv;
10622 virtual void CancelRequest(RequestHandle req) OVERRIDE {
10623 host_resolver_.CancelRequest(req);
10626 MockCachingHostResolver* GetMockHostResolver() {
10627 return &host_resolver_;
10630 private:
10631 MockCachingHostResolver host_resolver_;
10632 const HostPortPair host_port_;
10635 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10636 #if defined(OS_WIN)
10637 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10638 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
10639 #else
10640 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10641 UseIPConnectionPoolingWithHostCacheExpiration
10642 #endif
10643 WRAPPED_TEST_P(HttpNetworkTransactionTest,
10644 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
10645 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
10646 // prefix doesn't work with parametrized tests).
10647 #if defined(OS_WIN)
10648 return;
10649 #endif
10651 HttpStreamFactory::set_use_alternate_protocols(true);
10652 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10654 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
10655 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
10656 HttpNetworkSession::Params params =
10657 SpdySessionDependencies::CreateSessionParams(&session_deps_);
10658 params.host_resolver = &host_resolver;
10659 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10660 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10661 pool_peer.DisableDomainAuthenticationVerification();
10663 SSLSocketDataProvider ssl(ASYNC, OK);
10664 ssl.SetNextProto(GetParam());
10665 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10667 scoped_ptr<SpdyFrame> host1_req(
10668 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10669 scoped_ptr<SpdyFrame> host2_req(
10670 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10671 MockWrite spdy_writes[] = {
10672 CreateMockWrite(*host1_req, 1),
10673 CreateMockWrite(*host2_req, 4),
10675 scoped_ptr<SpdyFrame> host1_resp(
10676 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10677 scoped_ptr<SpdyFrame> host1_resp_body(
10678 spdy_util_.ConstructSpdyBodyFrame(1, true));
10679 scoped_ptr<SpdyFrame> host2_resp(
10680 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10681 scoped_ptr<SpdyFrame> host2_resp_body(
10682 spdy_util_.ConstructSpdyBodyFrame(3, true));
10683 MockRead spdy_reads[] = {
10684 CreateMockRead(*host1_resp, 2),
10685 CreateMockRead(*host1_resp_body, 3),
10686 CreateMockRead(*host2_resp, 5),
10687 CreateMockRead(*host2_resp_body, 6),
10688 MockRead(ASYNC, 0, 7),
10691 IPAddressNumber ip;
10692 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10693 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10694 MockConnect connect(ASYNC, OK, peer_addr);
10695 OrderedSocketData spdy_data(
10696 connect,
10697 spdy_reads, arraysize(spdy_reads),
10698 spdy_writes, arraysize(spdy_writes));
10699 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10701 TestCompletionCallback callback;
10702 HttpRequestInfo request1;
10703 request1.method = "GET";
10704 request1.url = GURL("https://www.google.com/");
10705 request1.load_flags = 0;
10706 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10708 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10709 EXPECT_EQ(ERR_IO_PENDING, rv);
10710 EXPECT_EQ(OK, callback.WaitForResult());
10712 const HttpResponseInfo* response = trans1.GetResponseInfo();
10713 ASSERT_TRUE(response != NULL);
10714 ASSERT_TRUE(response->headers.get() != NULL);
10715 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10717 std::string response_data;
10718 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10719 EXPECT_EQ("hello!", response_data);
10721 // Preload cache entries into HostCache.
10722 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
10723 AddressList ignored;
10724 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(),
10725 NULL, BoundNetLog());
10726 EXPECT_EQ(ERR_IO_PENDING, rv);
10727 rv = callback.WaitForResult();
10728 EXPECT_EQ(OK, rv);
10730 HttpRequestInfo request2;
10731 request2.method = "GET";
10732 request2.url = GURL("https://www.gmail.com/");
10733 request2.load_flags = 0;
10734 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10736 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10737 EXPECT_EQ(ERR_IO_PENDING, rv);
10738 EXPECT_EQ(OK, callback.WaitForResult());
10740 response = trans2.GetResponseInfo();
10741 ASSERT_TRUE(response != NULL);
10742 ASSERT_TRUE(response->headers.get() != NULL);
10743 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10744 EXPECT_TRUE(response->was_fetched_via_spdy);
10745 EXPECT_TRUE(response->was_npn_negotiated);
10746 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10747 EXPECT_EQ("hello!", response_data);
10749 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
10751 TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
10752 MockRead data_reads1[] = {
10753 MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
10755 MockRead data_reads2[] = {
10756 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10757 MockRead("hello world"),
10758 MockRead(SYNCHRONOUS, OK),
10760 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
10761 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
10762 StaticSocketDataProvider* data[] = { &data1, &data2 };
10764 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
10766 EXPECT_EQ(OK, out.rv);
10767 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
10768 EXPECT_EQ("hello world", out.response_data);
10771 TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
10772 MockWrite data_writes1[] = {
10773 MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
10775 MockWrite data_writes2[] = {
10776 MockWrite("GET / HTTP/1.1\r\n"
10777 "Host: www.google.com\r\n"
10778 "Connection: keep-alive\r\n\r\n"),
10780 MockRead data_reads2[] = {
10781 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10782 MockRead("hello world"),
10783 MockRead(SYNCHRONOUS, OK),
10785 StaticSocketDataProvider data1(NULL, 0,
10786 data_writes1, arraysize(data_writes1));
10787 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
10788 data_writes2, arraysize(data_writes2));
10789 StaticSocketDataProvider* data[] = { &data1, &data2 };
10791 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
10793 EXPECT_EQ(OK, out.rv);
10794 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
10795 EXPECT_EQ("hello world", out.response_data);
10798 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
10799 const std::string https_url = "https://www.google.com/";
10800 const std::string http_url = "http://www.google.com:443/";
10802 // SPDY GET for HTTPS URL
10803 scoped_ptr<SpdyFrame> req1(
10804 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
10806 MockWrite writes1[] = {
10807 CreateMockWrite(*req1, 0),
10810 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10811 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10812 MockRead reads1[] = {
10813 CreateMockRead(*resp1, 1),
10814 CreateMockRead(*body1, 2),
10815 MockRead(ASYNC, ERR_IO_PENDING, 3)
10818 DelayedSocketData data1(
10819 1, reads1, arraysize(reads1),
10820 writes1, arraysize(writes1));
10821 MockConnect connect_data1(ASYNC, OK);
10822 data1.set_connect_data(connect_data1);
10824 // HTTP GET for the HTTP URL
10825 MockWrite writes2[] = {
10826 MockWrite(ASYNC, 4,
10827 "GET / HTTP/1.1\r\n"
10828 "Host: www.google.com:443\r\n"
10829 "Connection: keep-alive\r\n\r\n"),
10832 MockRead reads2[] = {
10833 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
10834 MockRead(ASYNC, 6, "hello"),
10835 MockRead(ASYNC, 7, OK),
10838 DelayedSocketData data2(
10839 1, reads2, arraysize(reads2),
10840 writes2, arraysize(writes2));
10842 SSLSocketDataProvider ssl(ASYNC, OK);
10843 ssl.SetNextProto(GetParam());
10844 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10845 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10846 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10848 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10850 // Start the first transaction to set up the SpdySession
10851 HttpRequestInfo request1;
10852 request1.method = "GET";
10853 request1.url = GURL(https_url);
10854 request1.load_flags = 0;
10855 HttpNetworkTransaction trans1(LOWEST, session.get());
10856 TestCompletionCallback callback1;
10857 EXPECT_EQ(ERR_IO_PENDING,
10858 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
10859 base::MessageLoop::current()->RunUntilIdle();
10861 EXPECT_EQ(OK, callback1.WaitForResult());
10862 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
10864 // Now, start the HTTP request
10865 HttpRequestInfo request2;
10866 request2.method = "GET";
10867 request2.url = GURL(http_url);
10868 request2.load_flags = 0;
10869 HttpNetworkTransaction trans2(MEDIUM, session.get());
10870 TestCompletionCallback callback2;
10871 EXPECT_EQ(ERR_IO_PENDING,
10872 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
10873 base::MessageLoop::current()->RunUntilIdle();
10875 EXPECT_EQ(OK, callback2.WaitForResult());
10876 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
10879 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
10880 const std::string https_url = "https://www.google.com/";
10881 const std::string http_url = "http://www.google.com:443/";
10883 // SPDY GET for HTTPS URL (through CONNECT tunnel)
10884 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
10885 scoped_ptr<SpdyFrame> req1(
10886 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
10888 // SPDY GET for HTTP URL (through the proxy, but not the tunnel)
10889 scoped_ptr<SpdyFrame> wrapped_req1(
10890 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
10891 const char* const headers[] = {
10892 spdy_util_.GetMethodKey(), "GET",
10893 spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/",
10894 spdy_util_.GetHostKey(), "www.google.com:443",
10895 spdy_util_.GetSchemeKey(), "http",
10896 spdy_util_.GetVersionKey(), "HTTP/1.1"
10898 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame(
10899 NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN,
10900 headers, arraysize(headers), 0));
10902 MockWrite writes1[] = {
10903 CreateMockWrite(*connect, 0),
10904 CreateMockWrite(*wrapped_req1, 2),
10905 CreateMockWrite(*req2, 5),
10908 scoped_ptr<SpdyFrame> conn_resp(
10909 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10910 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10911 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10912 scoped_ptr<SpdyFrame> wrapped_resp1(
10913 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
10914 scoped_ptr<SpdyFrame> wrapped_body1(
10915 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
10916 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10917 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
10918 MockRead reads1[] = {
10919 CreateMockRead(*conn_resp, 1),
10920 CreateMockRead(*wrapped_resp1, 3),
10921 CreateMockRead(*wrapped_body1, 4),
10922 CreateMockRead(*resp2, 6),
10923 CreateMockRead(*body2, 7),
10924 MockRead(ASYNC, ERR_IO_PENDING, 8)
10927 DeterministicSocketData data1(reads1, arraysize(reads1),
10928 writes1, arraysize(writes1));
10929 MockConnect connect_data1(ASYNC, OK);
10930 data1.set_connect_data(connect_data1);
10932 session_deps_.proxy_service.reset(
10933 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
10934 CapturingNetLog log;
10935 session_deps_.net_log = &log;
10936 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
10937 ssl1.SetNextProto(GetParam());
10938 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
10939 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
10940 ssl2.SetNextProto(GetParam());
10941 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
10942 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
10944 scoped_refptr<HttpNetworkSession> session(
10945 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
10947 // Start the first transaction to set up the SpdySession
10948 HttpRequestInfo request1;
10949 request1.method = "GET";
10950 request1.url = GURL(https_url);
10951 request1.load_flags = 0;
10952 HttpNetworkTransaction trans1(LOWEST, session.get());
10953 TestCompletionCallback callback1;
10954 EXPECT_EQ(ERR_IO_PENDING,
10955 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
10956 base::MessageLoop::current()->RunUntilIdle();
10957 data1.RunFor(4);
10959 EXPECT_EQ(OK, callback1.WaitForResult());
10960 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
10962 LoadTimingInfo load_timing_info1;
10963 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
10964 TestLoadTimingNotReusedWithPac(load_timing_info1,
10965 CONNECT_TIMING_HAS_SSL_TIMES);
10967 // Now, start the HTTP request
10968 HttpRequestInfo request2;
10969 request2.method = "GET";
10970 request2.url = GURL(http_url);
10971 request2.load_flags = 0;
10972 HttpNetworkTransaction trans2(MEDIUM, session.get());
10973 TestCompletionCallback callback2;
10974 EXPECT_EQ(ERR_IO_PENDING,
10975 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
10976 base::MessageLoop::current()->RunUntilIdle();
10977 data1.RunFor(3);
10979 EXPECT_EQ(OK, callback2.WaitForResult());
10980 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
10982 LoadTimingInfo load_timing_info2;
10983 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
10984 // The established SPDY sessions is considered reused by the HTTP request.
10985 TestLoadTimingReusedWithPac(load_timing_info2);
10986 // HTTP requests over a SPDY session should have a different connection
10987 // socket_log_id than requests over a tunnel.
10988 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
10991 TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
10992 HttpStreamFactory::set_force_spdy_always(true);
10993 const std::string https_url = "https://www.google.com/";
10994 const std::string http_url = "http://www.google.com:443/";
10996 // SPDY GET for HTTPS URL
10997 scoped_ptr<SpdyFrame> req1(
10998 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
10999 // SPDY GET for the HTTP URL
11000 scoped_ptr<SpdyFrame> req2(
11001 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11003 MockWrite writes[] = {
11004 CreateMockWrite(*req1, 1),
11005 CreateMockWrite(*req2, 4),
11008 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11009 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11010 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11011 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11012 MockRead reads[] = {
11013 CreateMockRead(*resp1, 2),
11014 CreateMockRead(*body1, 3),
11015 CreateMockRead(*resp2, 5),
11016 CreateMockRead(*body2, 6),
11017 MockRead(ASYNC, ERR_IO_PENDING, 7)
11020 OrderedSocketData data(reads, arraysize(reads),
11021 writes, arraysize(writes));
11023 SSLSocketDataProvider ssl(ASYNC, OK);
11024 ssl.SetNextProto(GetParam());
11025 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11026 session_deps_.socket_factory->AddSocketDataProvider(&data);
11028 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11030 // Start the first transaction to set up the SpdySession
11031 HttpRequestInfo request1;
11032 request1.method = "GET";
11033 request1.url = GURL(https_url);
11034 request1.load_flags = 0;
11035 HttpNetworkTransaction trans1(LOWEST, session.get());
11036 TestCompletionCallback callback1;
11037 EXPECT_EQ(ERR_IO_PENDING,
11038 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11039 base::MessageLoop::current()->RunUntilIdle();
11041 EXPECT_EQ(OK, callback1.WaitForResult());
11042 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11044 // Now, start the HTTP request
11045 HttpRequestInfo request2;
11046 request2.method = "GET";
11047 request2.url = GURL(http_url);
11048 request2.load_flags = 0;
11049 HttpNetworkTransaction trans2(MEDIUM, session.get());
11050 TestCompletionCallback callback2;
11051 EXPECT_EQ(ERR_IO_PENDING,
11052 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11053 base::MessageLoop::current()->RunUntilIdle();
11055 EXPECT_EQ(OK, callback2.WaitForResult());
11056 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11059 // Test that in the case where we have a SPDY session to a SPDY proxy
11060 // that we do not pool other origins that resolve to the same IP when
11061 // the certificate does not match the new origin.
11062 // http://crbug.com/134690
11063 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11064 const std::string url1 = "http://www.google.com/";
11065 const std::string url2 = "https://mail.google.com/";
11066 const std::string ip_addr = "1.2.3.4";
11068 // SPDY GET for HTTP URL (through SPDY proxy)
11069 scoped_ptr<SpdyHeaderBlock> headers(
11070 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11071 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
11072 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
11074 MockWrite writes1[] = {
11075 CreateMockWrite(*req1, 0),
11078 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11079 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11080 MockRead reads1[] = {
11081 CreateMockRead(*resp1, 1),
11082 CreateMockRead(*body1, 2),
11083 MockRead(ASYNC, OK, 3) // EOF
11086 scoped_ptr<DeterministicSocketData> data1(
11087 new DeterministicSocketData(reads1, arraysize(reads1),
11088 writes1, arraysize(writes1)));
11089 IPAddressNumber ip;
11090 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11091 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11092 MockConnect connect_data1(ASYNC, OK, peer_addr);
11093 data1->set_connect_data(connect_data1);
11095 // SPDY GET for HTTPS URL (direct)
11096 scoped_ptr<SpdyFrame> req2(
11097 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11099 MockWrite writes2[] = {
11100 CreateMockWrite(*req2, 0),
11103 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11104 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11105 MockRead reads2[] = {
11106 CreateMockRead(*resp2, 1),
11107 CreateMockRead(*body2, 2),
11108 MockRead(ASYNC, OK, 3) // EOF
11111 scoped_ptr<DeterministicSocketData> data2(
11112 new DeterministicSocketData(reads2, arraysize(reads2),
11113 writes2, arraysize(writes2)));
11114 MockConnect connect_data2(ASYNC, OK);
11115 data2->set_connect_data(connect_data2);
11117 // Set up a proxy config that sends HTTP requests to a proxy, and
11118 // all others direct.
11119 ProxyConfig proxy_config;
11120 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11121 CapturingProxyResolver* capturing_proxy_resolver =
11122 new CapturingProxyResolver();
11123 session_deps_.proxy_service.reset(new ProxyService(
11124 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11125 NULL));
11127 // Load a valid cert. Note, that this does not need to
11128 // be valid for proxy because the MockSSLClientSocket does
11129 // not actually verify it. But SpdySession will use this
11130 // to see if it is valid for the new origin
11131 base::FilePath certs_dir = GetTestCertsDirectory();
11132 scoped_refptr<X509Certificate> server_cert(
11133 ImportCertFromFile(certs_dir, "ok_cert.pem"));
11134 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11136 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11137 ssl1.SetNextProto(GetParam());
11138 ssl1.cert = server_cert;
11139 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11140 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11141 data1.get());
11143 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11144 ssl2.SetNextProto(GetParam());
11145 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11146 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11147 data2.get());
11149 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11150 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11151 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11153 scoped_refptr<HttpNetworkSession> session(
11154 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11156 // Start the first transaction to set up the SpdySession
11157 HttpRequestInfo request1;
11158 request1.method = "GET";
11159 request1.url = GURL(url1);
11160 request1.load_flags = 0;
11161 HttpNetworkTransaction trans1(LOWEST, session.get());
11162 TestCompletionCallback callback1;
11163 ASSERT_EQ(ERR_IO_PENDING,
11164 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11165 data1->RunFor(3);
11167 ASSERT_TRUE(callback1.have_result());
11168 EXPECT_EQ(OK, callback1.WaitForResult());
11169 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11171 // Now, start the HTTP request
11172 HttpRequestInfo request2;
11173 request2.method = "GET";
11174 request2.url = GURL(url2);
11175 request2.load_flags = 0;
11176 HttpNetworkTransaction trans2(MEDIUM, session.get());
11177 TestCompletionCallback callback2;
11178 EXPECT_EQ(ERR_IO_PENDING,
11179 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11180 base::MessageLoop::current()->RunUntilIdle();
11181 data2->RunFor(3);
11183 ASSERT_TRUE(callback2.have_result());
11184 EXPECT_EQ(OK, callback2.WaitForResult());
11185 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11188 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11189 // error) in SPDY session, removes the socket from pool and closes the SPDY
11190 // session. Verify that new url's from the same HttpNetworkSession (and a new
11191 // SpdySession) do work. http://crbug.com/224701
11192 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11193 const std::string https_url = "https://www.google.com/";
11195 MockRead reads1[] = {
11196 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11199 scoped_ptr<DeterministicSocketData> data1(
11200 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11201 data1->SetStop(1);
11203 scoped_ptr<SpdyFrame> req2(
11204 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11205 MockWrite writes2[] = {
11206 CreateMockWrite(*req2, 0),
11209 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11210 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11211 MockRead reads2[] = {
11212 CreateMockRead(*resp2, 1),
11213 CreateMockRead(*body2, 2),
11214 MockRead(ASYNC, OK, 3) // EOF
11217 scoped_ptr<DeterministicSocketData> data2(
11218 new DeterministicSocketData(reads2, arraysize(reads2),
11219 writes2, arraysize(writes2)));
11221 SSLSocketDataProvider ssl1(ASYNC, OK);
11222 ssl1.SetNextProto(GetParam());
11223 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11224 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11225 data1.get());
11227 SSLSocketDataProvider ssl2(ASYNC, OK);
11228 ssl2.SetNextProto(GetParam());
11229 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11230 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11231 data2.get());
11233 scoped_refptr<HttpNetworkSession> session(
11234 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11236 // Start the first transaction to set up the SpdySession and verify that
11237 // connection was closed.
11238 HttpRequestInfo request1;
11239 request1.method = "GET";
11240 request1.url = GURL(https_url);
11241 request1.load_flags = 0;
11242 HttpNetworkTransaction trans1(MEDIUM, session.get());
11243 TestCompletionCallback callback1;
11244 EXPECT_EQ(ERR_IO_PENDING,
11245 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11246 base::MessageLoop::current()->RunUntilIdle();
11247 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11249 // Now, start the second request and make sure it succeeds.
11250 HttpRequestInfo request2;
11251 request2.method = "GET";
11252 request2.url = GURL(https_url);
11253 request2.load_flags = 0;
11254 HttpNetworkTransaction trans2(MEDIUM, session.get());
11255 TestCompletionCallback callback2;
11256 EXPECT_EQ(ERR_IO_PENDING,
11257 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11258 base::MessageLoop::current()->RunUntilIdle();
11259 data2->RunFor(3);
11261 ASSERT_TRUE(callback2.have_result());
11262 EXPECT_EQ(OK, callback2.WaitForResult());
11263 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11266 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11267 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11268 ClientSocketPoolManager::set_max_sockets_per_group(
11269 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11270 ClientSocketPoolManager::set_max_sockets_per_pool(
11271 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11273 // Use two different hosts with different IPs so they don't get pooled.
11274 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11275 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11276 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11278 SSLSocketDataProvider ssl1(ASYNC, OK);
11279 ssl1.SetNextProto(GetParam());
11280 SSLSocketDataProvider ssl2(ASYNC, OK);
11281 ssl2.SetNextProto(GetParam());
11282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11283 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11285 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11286 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11287 MockWrite spdy1_writes[] = {
11288 CreateMockWrite(*host1_req, 1),
11290 scoped_ptr<SpdyFrame> host1_resp(
11291 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11292 scoped_ptr<SpdyFrame> host1_resp_body(
11293 spdy_util_.ConstructSpdyBodyFrame(1, true));
11294 MockRead spdy1_reads[] = {
11295 CreateMockRead(*host1_resp, 2),
11296 CreateMockRead(*host1_resp_body, 3),
11297 MockRead(ASYNC, ERR_IO_PENDING, 4),
11300 scoped_ptr<OrderedSocketData> spdy1_data(
11301 new OrderedSocketData(
11302 spdy1_reads, arraysize(spdy1_reads),
11303 spdy1_writes, arraysize(spdy1_writes)));
11304 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11306 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11307 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11308 MockWrite spdy2_writes[] = {
11309 CreateMockWrite(*host2_req, 1),
11311 scoped_ptr<SpdyFrame> host2_resp(
11312 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11313 scoped_ptr<SpdyFrame> host2_resp_body(
11314 spdy_util_.ConstructSpdyBodyFrame(1, true));
11315 MockRead spdy2_reads[] = {
11316 CreateMockRead(*host2_resp, 2),
11317 CreateMockRead(*host2_resp_body, 3),
11318 MockRead(ASYNC, ERR_IO_PENDING, 4),
11321 scoped_ptr<OrderedSocketData> spdy2_data(
11322 new OrderedSocketData(
11323 spdy2_reads, arraysize(spdy2_reads),
11324 spdy2_writes, arraysize(spdy2_writes)));
11325 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11327 MockWrite http_write[] = {
11328 MockWrite("GET / HTTP/1.1\r\n"
11329 "Host: www.a.com\r\n"
11330 "Connection: keep-alive\r\n\r\n"),
11333 MockRead http_read[] = {
11334 MockRead("HTTP/1.1 200 OK\r\n"),
11335 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11336 MockRead("Content-Length: 6\r\n\r\n"),
11337 MockRead("hello!"),
11339 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11340 http_write, arraysize(http_write));
11341 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11343 HostPortPair host_port_pair_a("www.a.com", 443);
11344 SpdySessionKey spdy_session_key_a(
11345 host_port_pair_a, ProxyServer::Direct(), kPrivacyModeDisabled);
11346 EXPECT_FALSE(
11347 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11349 TestCompletionCallback callback;
11350 HttpRequestInfo request1;
11351 request1.method = "GET";
11352 request1.url = GURL("https://www.a.com/");
11353 request1.load_flags = 0;
11354 scoped_ptr<HttpNetworkTransaction> trans(
11355 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11357 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11358 EXPECT_EQ(ERR_IO_PENDING, rv);
11359 EXPECT_EQ(OK, callback.WaitForResult());
11361 const HttpResponseInfo* response = trans->GetResponseInfo();
11362 ASSERT_TRUE(response != NULL);
11363 ASSERT_TRUE(response->headers.get() != NULL);
11364 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11365 EXPECT_TRUE(response->was_fetched_via_spdy);
11366 EXPECT_TRUE(response->was_npn_negotiated);
11368 std::string response_data;
11369 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11370 EXPECT_EQ("hello!", response_data);
11371 trans.reset();
11372 EXPECT_TRUE(
11373 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11375 HostPortPair host_port_pair_b("www.b.com", 443);
11376 SpdySessionKey spdy_session_key_b(
11377 host_port_pair_b, ProxyServer::Direct(), kPrivacyModeDisabled);
11378 EXPECT_FALSE(
11379 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11380 HttpRequestInfo request2;
11381 request2.method = "GET";
11382 request2.url = GURL("https://www.b.com/");
11383 request2.load_flags = 0;
11384 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11386 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11387 EXPECT_EQ(ERR_IO_PENDING, rv);
11388 EXPECT_EQ(OK, callback.WaitForResult());
11390 response = trans->GetResponseInfo();
11391 ASSERT_TRUE(response != NULL);
11392 ASSERT_TRUE(response->headers.get() != NULL);
11393 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11394 EXPECT_TRUE(response->was_fetched_via_spdy);
11395 EXPECT_TRUE(response->was_npn_negotiated);
11396 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11397 EXPECT_EQ("hello!", response_data);
11398 EXPECT_FALSE(
11399 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11400 EXPECT_TRUE(
11401 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11403 HostPortPair host_port_pair_a1("www.a.com", 80);
11404 SpdySessionKey spdy_session_key_a1(
11405 host_port_pair_a1, ProxyServer::Direct(), kPrivacyModeDisabled);
11406 EXPECT_FALSE(
11407 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11408 HttpRequestInfo request3;
11409 request3.method = "GET";
11410 request3.url = GURL("http://www.a.com/");
11411 request3.load_flags = 0;
11412 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11414 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11415 EXPECT_EQ(ERR_IO_PENDING, rv);
11416 EXPECT_EQ(OK, callback.WaitForResult());
11418 response = trans->GetResponseInfo();
11419 ASSERT_TRUE(response != NULL);
11420 ASSERT_TRUE(response->headers.get() != NULL);
11421 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11422 EXPECT_FALSE(response->was_fetched_via_spdy);
11423 EXPECT_FALSE(response->was_npn_negotiated);
11424 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11425 EXPECT_EQ("hello!", response_data);
11426 EXPECT_FALSE(
11427 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11428 EXPECT_FALSE(
11429 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11432 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11433 HttpRequestInfo request;
11434 request.method = "GET";
11435 request.url = GURL("http://www.google.com/");
11436 request.load_flags = 0;
11438 scoped_ptr<HttpTransaction> trans(
11439 new HttpNetworkTransaction(DEFAULT_PRIORITY,
11440 CreateSession(&session_deps_)));
11442 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11443 StaticSocketDataProvider data;
11444 data.set_connect_data(mock_connect);
11445 session_deps_.socket_factory->AddSocketDataProvider(&data);
11447 TestCompletionCallback callback;
11449 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11450 EXPECT_EQ(ERR_IO_PENDING, rv);
11452 rv = callback.WaitForResult();
11453 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11455 EXPECT_EQ(NULL, trans->GetResponseInfo());
11457 // We don't care whether this succeeds or fails, but it shouldn't crash.
11458 HttpRequestHeaders request_headers;
11459 trans->GetFullRequestHeaders(&request_headers);
11462 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11463 HttpRequestInfo request;
11464 request.method = "GET";
11465 request.url = GURL("http://www.google.com/");
11466 request.load_flags = 0;
11468 scoped_ptr<HttpTransaction> trans(
11469 new HttpNetworkTransaction(DEFAULT_PRIORITY,
11470 CreateSession(&session_deps_)));
11472 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11473 StaticSocketDataProvider data;
11474 data.set_connect_data(mock_connect);
11475 session_deps_.socket_factory->AddSocketDataProvider(&data);
11477 TestCompletionCallback callback;
11479 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11480 EXPECT_EQ(ERR_IO_PENDING, rv);
11482 rv = callback.WaitForResult();
11483 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11485 EXPECT_EQ(NULL, trans->GetResponseInfo());
11487 // We don't care whether this succeeds or fails, but it shouldn't crash.
11488 HttpRequestHeaders request_headers;
11489 trans->GetFullRequestHeaders(&request_headers);
11492 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
11493 HttpRequestInfo request;
11494 request.method = "GET";
11495 request.url = GURL("http://www.google.com/");
11496 request.load_flags = 0;
11498 scoped_ptr<HttpTransaction> trans(
11499 new HttpNetworkTransaction(DEFAULT_PRIORITY,
11500 CreateSession(&session_deps_)));
11502 MockWrite data_writes[] = {
11503 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
11505 MockRead data_reads[] = {
11506 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11509 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11510 data_writes, arraysize(data_writes));
11511 session_deps_.socket_factory->AddSocketDataProvider(&data);
11513 TestCompletionCallback callback;
11515 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11516 EXPECT_EQ(ERR_IO_PENDING, rv);
11518 rv = callback.WaitForResult();
11519 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11521 EXPECT_EQ(NULL, trans->GetResponseInfo());
11523 HttpRequestHeaders request_headers;
11524 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11525 EXPECT_TRUE(request_headers.HasHeader("Host"));
11528 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
11529 HttpRequestInfo request;
11530 request.method = "GET";
11531 request.url = GURL("http://www.google.com/");
11532 request.load_flags = 0;
11534 scoped_ptr<HttpTransaction> trans(
11535 new HttpNetworkTransaction(DEFAULT_PRIORITY,
11536 CreateSession(&session_deps_)));
11538 MockWrite data_writes[] = {
11539 MockWrite(ASYNC, ERR_CONNECTION_RESET),
11541 MockRead data_reads[] = {
11542 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11545 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11546 data_writes, arraysize(data_writes));
11547 session_deps_.socket_factory->AddSocketDataProvider(&data);
11549 TestCompletionCallback callback;
11551 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11552 EXPECT_EQ(ERR_IO_PENDING, rv);
11554 rv = callback.WaitForResult();
11555 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11557 EXPECT_EQ(NULL, trans->GetResponseInfo());
11559 HttpRequestHeaders request_headers;
11560 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11561 EXPECT_TRUE(request_headers.HasHeader("Host"));
11564 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
11565 HttpRequestInfo request;
11566 request.method = "GET";
11567 request.url = GURL("http://www.google.com/");
11568 request.load_flags = 0;
11570 scoped_ptr<HttpTransaction> trans(
11571 new HttpNetworkTransaction(DEFAULT_PRIORITY,
11572 CreateSession(&session_deps_)));
11574 MockWrite data_writes[] = {
11575 MockWrite("GET / HTTP/1.1\r\n"
11576 "Host: www.google.com\r\n"
11577 "Connection: keep-alive\r\n\r\n"),
11579 MockRead data_reads[] = {
11580 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
11583 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11584 data_writes, arraysize(data_writes));
11585 session_deps_.socket_factory->AddSocketDataProvider(&data);
11587 TestCompletionCallback callback;
11589 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11590 EXPECT_EQ(ERR_IO_PENDING, rv);
11592 rv = callback.WaitForResult();
11593 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11595 EXPECT_EQ(NULL, trans->GetResponseInfo());
11597 HttpRequestHeaders request_headers;
11598 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11599 EXPECT_TRUE(request_headers.HasHeader("Host"));
11602 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
11603 HttpRequestInfo request;
11604 request.method = "GET";
11605 request.url = GURL("http://www.google.com/");
11606 request.load_flags = 0;
11608 scoped_ptr<HttpTransaction> trans(
11609 new HttpNetworkTransaction(DEFAULT_PRIORITY,
11610 CreateSession(&session_deps_)));
11612 MockWrite data_writes[] = {
11613 MockWrite("GET / HTTP/1.1\r\n"
11614 "Host: www.google.com\r\n"
11615 "Connection: keep-alive\r\n\r\n"),
11617 MockRead data_reads[] = {
11618 MockRead(ASYNC, ERR_CONNECTION_RESET),
11621 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11622 data_writes, arraysize(data_writes));
11623 session_deps_.socket_factory->AddSocketDataProvider(&data);
11625 TestCompletionCallback callback;
11627 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11628 EXPECT_EQ(ERR_IO_PENDING, rv);
11630 rv = callback.WaitForResult();
11631 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11633 EXPECT_EQ(NULL, trans->GetResponseInfo());
11635 HttpRequestHeaders request_headers;
11636 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11637 EXPECT_TRUE(request_headers.HasHeader("Host"));
11640 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
11641 HttpRequestInfo request;
11642 request.method = "GET";
11643 request.url = GURL("http://www.google.com/");
11644 request.load_flags = 0;
11645 request.extra_headers.SetHeader("X-Foo", "bar");
11647 scoped_ptr<HttpTransaction> trans(
11648 new HttpNetworkTransaction(DEFAULT_PRIORITY,
11649 CreateSession(&session_deps_)));
11651 MockWrite data_writes[] = {
11652 MockWrite("GET / HTTP/1.1\r\n"
11653 "Host: www.google.com\r\n"
11654 "Connection: keep-alive\r\n"
11655 "X-Foo: bar\r\n\r\n"),
11657 MockRead data_reads[] = {
11658 MockRead("HTTP/1.1 200 OK\r\n"
11659 "Content-Length: 5\r\n\r\n"
11660 "hello"),
11661 MockRead(ASYNC, ERR_UNEXPECTED),
11664 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11665 data_writes, arraysize(data_writes));
11666 session_deps_.socket_factory->AddSocketDataProvider(&data);
11668 TestCompletionCallback callback;
11670 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11671 EXPECT_EQ(ERR_IO_PENDING, rv);
11673 rv = callback.WaitForResult();
11674 EXPECT_EQ(OK, rv);
11676 HttpRequestHeaders request_headers;
11677 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11678 std::string foo;
11679 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
11680 EXPECT_EQ("bar", foo);
11683 } // namespace net