Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / net / http / http_network_transaction_unittest.cc
blob44e200ce6ce3b5317785a293eed85804b1db97e0
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
8 #include <stdarg.h>
9 #include <string>
10 #include <vector>
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/json/json_writer.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/test/test_file_util.h"
24 #include "net/base/auth.h"
25 #include "net/base/chunked_upload_data_stream.h"
26 #include "net/base/completion_callback.h"
27 #include "net/base/elements_upload_data_stream.h"
28 #include "net/base/load_timing_info.h"
29 #include "net/base/load_timing_info_test_util.h"
30 #include "net/base/net_errors.h"
31 #include "net/base/request_priority.h"
32 #include "net/base/test_completion_callback.h"
33 #include "net/base/test_data_directory.h"
34 #include "net/base/upload_bytes_element_reader.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_state.h"
44 #include "net/http/http_basic_stream.h"
45 #include "net/http/http_network_session.h"
46 #include "net/http/http_network_session_peer.h"
47 #include "net/http/http_request_headers.h"
48 #include "net/http/http_server_properties_impl.h"
49 #include "net/http/http_stream.h"
50 #include "net/http/http_stream_factory.h"
51 #include "net/http/http_stream_parser.h"
52 #include "net/http/http_transaction_test_util.h"
53 #include "net/log/net_log.h"
54 #include "net/log/net_log_unittest.h"
55 #include "net/log/test_net_log.h"
56 #include "net/proxy/mock_proxy_resolver.h"
57 #include "net/proxy/proxy_config_service_fixed.h"
58 #include "net/proxy/proxy_info.h"
59 #include "net/proxy/proxy_resolver.h"
60 #include "net/proxy/proxy_service.h"
61 #include "net/socket/client_socket_factory.h"
62 #include "net/socket/client_socket_pool_manager.h"
63 #include "net/socket/mock_client_socket_pool_manager.h"
64 #include "net/socket/next_proto.h"
65 #include "net/socket/socket_test_util.h"
66 #include "net/socket/ssl_client_socket.h"
67 #include "net/spdy/spdy_framer.h"
68 #include "net/spdy/spdy_session.h"
69 #include "net/spdy/spdy_session_pool.h"
70 #include "net/spdy/spdy_test_util_common.h"
71 #include "net/ssl/ssl_cert_request_info.h"
72 #include "net/ssl/ssl_config_service.h"
73 #include "net/ssl/ssl_config_service_defaults.h"
74 #include "net/ssl/ssl_info.h"
75 #include "net/test/cert_test_util.h"
76 #include "net/websockets/websocket_handshake_stream_base.h"
77 #include "testing/gtest/include/gtest/gtest.h"
78 #include "testing/platform_test.h"
79 #include "url/gurl.h"
81 using base::ASCIIToUTF16;
83 //-----------------------------------------------------------------------------
85 namespace net {
87 namespace {
89 const base::string16 kBar(ASCIIToUTF16("bar"));
90 const base::string16 kBar2(ASCIIToUTF16("bar2"));
91 const base::string16 kBar3(ASCIIToUTF16("bar3"));
92 const base::string16 kBaz(ASCIIToUTF16("baz"));
93 const base::string16 kFirst(ASCIIToUTF16("first"));
94 const base::string16 kFoo(ASCIIToUTF16("foo"));
95 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
96 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
97 const base::string16 kFou(ASCIIToUTF16("fou"));
98 const base::string16 kSecond(ASCIIToUTF16("second"));
99 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
100 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
102 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
103 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
104 ->IdleSocketCount();
107 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
108 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
109 ->IdleSocketCount();
112 bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
113 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
114 ->IsStalled();
117 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
118 // a JSONified list of headers as a single string. Uses single quotes instead
119 // of double quotes for easier comparison. Returns false on failure.
120 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
121 if (!params)
122 return false;
123 base::ListValue* header_list;
124 if (!params->GetList("headers", &header_list))
125 return false;
126 std::string double_quote_headers;
127 base::JSONWriter::Write(header_list, &double_quote_headers);
128 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
129 return true;
132 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
133 // used.
134 void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
135 EXPECT_TRUE(load_timing_info.socket_reused);
136 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
138 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
139 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
141 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
142 EXPECT_FALSE(load_timing_info.send_start.is_null());
144 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
146 // Set at a higher level.
147 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
148 EXPECT_TRUE(load_timing_info.request_start.is_null());
149 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
152 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
153 // used.
154 void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
155 int connect_timing_flags) {
156 EXPECT_FALSE(load_timing_info.socket_reused);
157 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
159 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
160 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
162 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
163 connect_timing_flags);
164 EXPECT_LE(load_timing_info.connect_timing.connect_end,
165 load_timing_info.send_start);
167 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
169 // Set at a higher level.
170 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
171 EXPECT_TRUE(load_timing_info.request_start.is_null());
172 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
175 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
176 // used.
177 void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
178 EXPECT_TRUE(load_timing_info.socket_reused);
179 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
181 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
183 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
184 EXPECT_LE(load_timing_info.proxy_resolve_start,
185 load_timing_info.proxy_resolve_end);
186 EXPECT_LE(load_timing_info.proxy_resolve_end,
187 load_timing_info.send_start);
188 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
190 // Set at a higher level.
191 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
192 EXPECT_TRUE(load_timing_info.request_start.is_null());
193 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
196 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
197 // used.
198 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
199 int connect_timing_flags) {
200 EXPECT_FALSE(load_timing_info.socket_reused);
201 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
203 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
204 EXPECT_LE(load_timing_info.proxy_resolve_start,
205 load_timing_info.proxy_resolve_end);
206 EXPECT_LE(load_timing_info.proxy_resolve_end,
207 load_timing_info.connect_timing.connect_start);
208 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
209 connect_timing_flags);
210 EXPECT_LE(load_timing_info.connect_timing.connect_end,
211 load_timing_info.send_start);
213 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
215 // Set at a higher level.
216 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
217 EXPECT_TRUE(load_timing_info.request_start.is_null());
218 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
221 void AddWebSocketHeaders(HttpRequestHeaders* headers) {
222 headers->SetHeader("Connection", "Upgrade");
223 headers->SetHeader("Upgrade", "websocket");
224 headers->SetHeader("Origin", "http://www.example.org");
225 headers->SetHeader("Sec-WebSocket-Version", "13");
226 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
229 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
230 return SpdySessionDependencies::SpdyCreateSession(session_deps);
233 } // namespace
235 class HttpNetworkTransactionTest
236 : public PlatformTest,
237 public ::testing::WithParamInterface<NextProto> {
238 public:
239 virtual ~HttpNetworkTransactionTest() {
240 // Important to restore the per-pool limit first, since the pool limit must
241 // always be greater than group limit, and the tests reduce both limits.
242 ClientSocketPoolManager::set_max_sockets_per_pool(
243 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
244 ClientSocketPoolManager::set_max_sockets_per_group(
245 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
248 protected:
249 HttpNetworkTransactionTest()
250 : spdy_util_(GetParam()),
251 session_deps_(GetParam()),
252 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
253 HttpNetworkSession::NORMAL_SOCKET_POOL)),
254 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
255 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
258 struct SimpleGetHelperResult {
259 int rv;
260 std::string status_line;
261 std::string response_data;
262 int64 totalReceivedBytes;
263 LoadTimingInfo load_timing_info;
266 void SetUp() override {
267 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
268 base::MessageLoop::current()->RunUntilIdle();
271 void TearDown() override {
272 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
273 base::MessageLoop::current()->RunUntilIdle();
274 // Empty the current queue.
275 base::MessageLoop::current()->RunUntilIdle();
276 PlatformTest::TearDown();
277 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
278 base::MessageLoop::current()->RunUntilIdle();
281 const char* GetAlternateProtocolFromParam() {
282 return
283 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
286 // This is the expected return from a current server advertising SPDY.
287 std::string GetAlternateProtocolHttpHeader() {
288 return std::string("Alternate-Protocol: 443:") +
289 GetAlternateProtocolFromParam() + "\r\n\r\n";
292 // Either |write_failure| specifies a write failure or |read_failure|
293 // specifies a read failure when using a reused socket. In either case, the
294 // failure should cause the network transaction to resend the request, and the
295 // other argument should be NULL.
296 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
297 const MockRead* read_failure);
299 // Either |write_failure| specifies a write failure or |read_failure|
300 // specifies a read failure when using a reused socket. In either case, the
301 // failure should cause the network transaction to resend the request, and the
302 // other argument should be NULL.
303 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
304 const MockRead* read_failure,
305 bool use_spdy);
307 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
308 size_t data_count) {
309 SimpleGetHelperResult out;
311 HttpRequestInfo request;
312 request.method = "GET";
313 request.url = GURL("http://www.example.org/");
314 request.load_flags = 0;
316 BoundTestNetLog log;
317 session_deps_.net_log = log.bound().net_log();
318 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
319 scoped_ptr<HttpTransaction> trans(
320 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
322 for (size_t i = 0; i < data_count; ++i) {
323 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
326 TestCompletionCallback callback;
328 EXPECT_TRUE(log.bound().GetCaptureMode().enabled());
329 int rv = trans->Start(&request, callback.callback(), log.bound());
330 EXPECT_EQ(ERR_IO_PENDING, rv);
332 out.rv = callback.WaitForResult();
334 // Even in the failure cases that use this function, connections are always
335 // successfully established before the error.
336 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
337 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
339 if (out.rv != OK)
340 return out;
342 const HttpResponseInfo* response = trans->GetResponseInfo();
343 // Can't use ASSERT_* inside helper functions like this, so
344 // return an error.
345 if (response == NULL || response->headers.get() == NULL) {
346 out.rv = ERR_UNEXPECTED;
347 return out;
349 out.status_line = response->headers->GetStatusLine();
351 EXPECT_EQ("127.0.0.1", response->socket_address.host());
352 EXPECT_EQ(80, response->socket_address.port());
354 rv = ReadTransaction(trans.get(), &out.response_data);
355 EXPECT_EQ(OK, rv);
357 TestNetLog::CapturedEntryList entries;
358 log.GetEntries(&entries);
359 size_t pos = ExpectLogContainsSomewhere(
360 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
361 NetLog::PHASE_NONE);
362 ExpectLogContainsSomewhere(
363 entries, pos,
364 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
365 NetLog::PHASE_NONE);
367 std::string line;
368 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
369 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
371 HttpRequestHeaders request_headers;
372 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
373 std::string value;
374 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
375 EXPECT_EQ("www.example.org", value);
376 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
377 EXPECT_EQ("keep-alive", value);
379 std::string response_headers;
380 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
381 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
382 response_headers);
384 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
385 return out;
388 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
389 size_t reads_count) {
390 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
391 StaticSocketDataProvider* data[] = { &reads };
392 return SimpleGetHelperForData(data, 1);
395 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
396 int64 size = 0;
397 for (size_t i = 0; i < reads_count; ++i)
398 size += data_reads[i].data_len;
399 return size;
402 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
403 int expected_status);
405 void ConnectStatusHelper(const MockRead& status);
407 void BypassHostCacheOnRefreshHelper(int load_flags);
409 void CheckErrorIsPassedBack(int error, IoMode mode);
411 SpdyTestUtil spdy_util_;
412 SpdySessionDependencies session_deps_;
414 // Original socket limits. Some tests set these. Safest to always restore
415 // them once each test has been run.
416 int old_max_group_sockets_;
417 int old_max_pool_sockets_;
420 INSTANTIATE_TEST_CASE_P(NextProto,
421 HttpNetworkTransactionTest,
422 testing::Values(kProtoSPDY31,
423 kProtoSPDY4_14,
424 kProtoSPDY4));
426 namespace {
428 class BeforeNetworkStartHandler {
429 public:
430 explicit BeforeNetworkStartHandler(bool defer)
431 : defer_on_before_network_start_(defer),
432 observed_before_network_start_(false) {}
434 void OnBeforeNetworkStart(bool* defer) {
435 *defer = defer_on_before_network_start_;
436 observed_before_network_start_ = true;
439 bool observed_before_network_start() const {
440 return observed_before_network_start_;
443 private:
444 const bool defer_on_before_network_start_;
445 bool observed_before_network_start_;
447 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
450 class BeforeProxyHeadersSentHandler {
451 public:
452 BeforeProxyHeadersSentHandler()
453 : observed_before_proxy_headers_sent_(false) {}
455 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
456 HttpRequestHeaders* request_headers) {
457 observed_before_proxy_headers_sent_ = true;
458 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
461 bool observed_before_proxy_headers_sent() const {
462 return observed_before_proxy_headers_sent_;
465 std::string observed_proxy_server_uri() const {
466 return observed_proxy_server_uri_;
469 private:
470 bool observed_before_proxy_headers_sent_;
471 std::string observed_proxy_server_uri_;
473 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
476 // Fill |str| with a long header list that consumes >= |size| bytes.
477 void FillLargeHeadersString(std::string* str, int size) {
478 const char row[] =
479 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
480 const int sizeof_row = strlen(row);
481 const int num_rows = static_cast<int>(
482 ceil(static_cast<float>(size) / sizeof_row));
483 const int sizeof_data = num_rows * sizeof_row;
484 DCHECK(sizeof_data >= size);
485 str->reserve(sizeof_data);
487 for (int i = 0; i < num_rows; ++i)
488 str->append(row, sizeof_row);
491 // Alternative functions that eliminate randomness and dependency on the local
492 // host name so that the generated NTLM messages are reproducible.
493 void MockGenerateRandom1(uint8* output, size_t n) {
494 static const uint8 bytes[] = {
495 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
497 static size_t current_byte = 0;
498 for (size_t i = 0; i < n; ++i) {
499 output[i] = bytes[current_byte++];
500 current_byte %= arraysize(bytes);
504 void MockGenerateRandom2(uint8* output, size_t n) {
505 static const uint8 bytes[] = {
506 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
507 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
509 static size_t current_byte = 0;
510 for (size_t i = 0; i < n; ++i) {
511 output[i] = bytes[current_byte++];
512 current_byte %= arraysize(bytes);
516 std::string MockGetHostName() {
517 return "WTC-WIN7";
520 template<typename ParentPool>
521 class CaptureGroupNameSocketPool : public ParentPool {
522 public:
523 CaptureGroupNameSocketPool(HostResolver* host_resolver,
524 CertVerifier* cert_verifier);
526 const std::string last_group_name_received() const {
527 return last_group_name_;
530 int RequestSocket(const std::string& group_name,
531 const void* socket_params,
532 RequestPriority priority,
533 ClientSocketHandle* handle,
534 const CompletionCallback& callback,
535 const BoundNetLog& net_log) override {
536 last_group_name_ = group_name;
537 return ERR_IO_PENDING;
539 void CancelRequest(const std::string& group_name,
540 ClientSocketHandle* handle) override {}
541 void ReleaseSocket(const std::string& group_name,
542 scoped_ptr<StreamSocket> socket,
543 int id) override {}
544 void CloseIdleSockets() override {}
545 int IdleSocketCount() const override { return 0; }
546 int IdleSocketCountInGroup(const std::string& group_name) const override {
547 return 0;
549 LoadState GetLoadState(const std::string& group_name,
550 const ClientSocketHandle* handle) const override {
551 return LOAD_STATE_IDLE;
553 base::TimeDelta ConnectionTimeout() const override {
554 return base::TimeDelta();
557 private:
558 std::string last_group_name_;
561 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
562 CaptureGroupNameTransportSocketPool;
563 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
564 CaptureGroupNameHttpProxySocketPool;
565 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
566 CaptureGroupNameSOCKSSocketPool;
567 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
568 CaptureGroupNameSSLSocketPool;
570 template <typename ParentPool>
571 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
572 HostResolver* host_resolver,
573 CertVerifier* /* cert_verifier */)
574 : ParentPool(0, 0, host_resolver, NULL, NULL) {
577 template <>
578 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
579 HostResolver* /* host_resolver */,
580 CertVerifier* /* cert_verifier */)
581 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
584 template <>
585 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
586 HostResolver* /* host_resolver */,
587 CertVerifier* cert_verifier)
588 : SSLClientSocketPool(0,
590 cert_verifier,
591 NULL,
592 NULL,
593 NULL,
594 NULL,
595 std::string(),
596 NULL,
597 NULL,
598 NULL,
599 NULL,
600 NULL,
601 NULL) {
604 //-----------------------------------------------------------------------------
606 // Helper functions for validating that AuthChallengeInfo's are correctly
607 // configured for common cases.
608 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
609 if (!auth_challenge)
610 return false;
611 EXPECT_FALSE(auth_challenge->is_proxy);
612 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
613 EXPECT_EQ("MyRealm1", auth_challenge->realm);
614 EXPECT_EQ("basic", auth_challenge->scheme);
615 return true;
618 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
619 if (!auth_challenge)
620 return false;
621 EXPECT_TRUE(auth_challenge->is_proxy);
622 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
623 EXPECT_EQ("MyRealm1", auth_challenge->realm);
624 EXPECT_EQ("basic", auth_challenge->scheme);
625 return true;
628 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
629 if (!auth_challenge)
630 return false;
631 EXPECT_FALSE(auth_challenge->is_proxy);
632 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
633 EXPECT_EQ("digestive", auth_challenge->realm);
634 EXPECT_EQ("digest", auth_challenge->scheme);
635 return true;
638 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
639 if (!auth_challenge)
640 return false;
641 EXPECT_FALSE(auth_challenge->is_proxy);
642 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
643 EXPECT_EQ(std::string(), auth_challenge->realm);
644 EXPECT_EQ("ntlm", auth_challenge->scheme);
645 return true;
648 } // namespace
650 TEST_P(HttpNetworkTransactionTest, Basic) {
651 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
652 scoped_ptr<HttpTransaction> trans(
653 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
656 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
657 MockRead data_reads[] = {
658 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
659 MockRead("hello world"),
660 MockRead(SYNCHRONOUS, OK),
662 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
663 arraysize(data_reads));
664 EXPECT_EQ(OK, out.rv);
665 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
666 EXPECT_EQ("hello world", out.response_data);
667 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
668 EXPECT_EQ(reads_size, out.totalReceivedBytes);
671 // Response with no status line.
672 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
673 MockRead data_reads[] = {
674 MockRead("hello world"),
675 MockRead(SYNCHRONOUS, OK),
677 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
678 arraysize(data_reads));
679 EXPECT_EQ(OK, out.rv);
680 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
681 EXPECT_EQ("hello world", out.response_data);
682 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
683 EXPECT_EQ(reads_size, out.totalReceivedBytes);
686 // Allow up to 4 bytes of junk to precede status line.
687 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
688 MockRead data_reads[] = {
689 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
690 MockRead(SYNCHRONOUS, OK),
692 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
693 arraysize(data_reads));
694 EXPECT_EQ(OK, out.rv);
695 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
696 EXPECT_EQ("DATA", out.response_data);
697 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
698 EXPECT_EQ(reads_size, out.totalReceivedBytes);
701 // Allow up to 4 bytes of junk to precede status line.
702 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
703 MockRead data_reads[] = {
704 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
705 MockRead(SYNCHRONOUS, OK),
707 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
708 arraysize(data_reads));
709 EXPECT_EQ(OK, out.rv);
710 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
711 EXPECT_EQ("DATA", out.response_data);
712 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
713 EXPECT_EQ(reads_size, out.totalReceivedBytes);
716 // Beyond 4 bytes of slop and it should fail to find a status line.
717 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
718 MockRead data_reads[] = {
719 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
720 MockRead(SYNCHRONOUS, OK),
722 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
723 arraysize(data_reads));
724 EXPECT_EQ(OK, out.rv);
725 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
726 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
727 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
728 EXPECT_EQ(reads_size, out.totalReceivedBytes);
731 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
732 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
733 MockRead data_reads[] = {
734 MockRead("\n"),
735 MockRead("\n"),
736 MockRead("Q"),
737 MockRead("J"),
738 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
739 MockRead(SYNCHRONOUS, OK),
741 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
742 arraysize(data_reads));
743 EXPECT_EQ(OK, out.rv);
744 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
745 EXPECT_EQ("DATA", out.response_data);
746 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
747 EXPECT_EQ(reads_size, out.totalReceivedBytes);
750 // Close the connection before enough bytes to have a status line.
751 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
752 MockRead data_reads[] = {
753 MockRead("HTT"),
754 MockRead(SYNCHRONOUS, OK),
756 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
757 arraysize(data_reads));
758 EXPECT_EQ(OK, out.rv);
759 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
760 EXPECT_EQ("HTT", out.response_data);
761 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
762 EXPECT_EQ(reads_size, out.totalReceivedBytes);
765 // Simulate a 204 response, lacking a Content-Length header, sent over a
766 // persistent connection. The response should still terminate since a 204
767 // cannot have a response body.
768 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
769 char junk[] = "junk";
770 MockRead data_reads[] = {
771 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
772 MockRead(junk), // Should not be read!!
773 MockRead(SYNCHRONOUS, OK),
775 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
776 arraysize(data_reads));
777 EXPECT_EQ(OK, out.rv);
778 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
779 EXPECT_EQ("", out.response_data);
780 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
781 int64 response_size = reads_size - strlen(junk);
782 EXPECT_EQ(response_size, out.totalReceivedBytes);
785 // A simple request using chunked encoding with some extra data after.
786 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
787 std::string final_chunk = "0\r\n\r\n";
788 std::string extra_data = "HTTP/1.1 200 OK\r\n";
789 std::string last_read = final_chunk + extra_data;
790 MockRead data_reads[] = {
791 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
792 MockRead("5\r\nHello\r\n"),
793 MockRead("1\r\n"),
794 MockRead(" \r\n"),
795 MockRead("5\r\nworld\r\n"),
796 MockRead(last_read.data()),
797 MockRead(SYNCHRONOUS, OK),
799 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
800 arraysize(data_reads));
801 EXPECT_EQ(OK, out.rv);
802 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
803 EXPECT_EQ("Hello world", out.response_data);
804 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
805 int64 response_size = reads_size - extra_data.size();
806 EXPECT_EQ(response_size, out.totalReceivedBytes);
809 // Next tests deal with http://crbug.com/56344.
811 TEST_P(HttpNetworkTransactionTest,
812 MultipleContentLengthHeadersNoTransferEncoding) {
813 MockRead data_reads[] = {
814 MockRead("HTTP/1.1 200 OK\r\n"),
815 MockRead("Content-Length: 10\r\n"),
816 MockRead("Content-Length: 5\r\n\r\n"),
818 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
819 arraysize(data_reads));
820 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
823 TEST_P(HttpNetworkTransactionTest,
824 DuplicateContentLengthHeadersNoTransferEncoding) {
825 MockRead data_reads[] = {
826 MockRead("HTTP/1.1 200 OK\r\n"),
827 MockRead("Content-Length: 5\r\n"),
828 MockRead("Content-Length: 5\r\n\r\n"),
829 MockRead("Hello"),
831 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
832 arraysize(data_reads));
833 EXPECT_EQ(OK, out.rv);
834 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
835 EXPECT_EQ("Hello", out.response_data);
838 TEST_P(HttpNetworkTransactionTest,
839 ComplexContentLengthHeadersNoTransferEncoding) {
840 // More than 2 dupes.
842 MockRead data_reads[] = {
843 MockRead("HTTP/1.1 200 OK\r\n"),
844 MockRead("Content-Length: 5\r\n"),
845 MockRead("Content-Length: 5\r\n"),
846 MockRead("Content-Length: 5\r\n\r\n"),
847 MockRead("Hello"),
849 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
850 arraysize(data_reads));
851 EXPECT_EQ(OK, out.rv);
852 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
853 EXPECT_EQ("Hello", out.response_data);
855 // HTTP/1.0
857 MockRead data_reads[] = {
858 MockRead("HTTP/1.0 200 OK\r\n"),
859 MockRead("Content-Length: 5\r\n"),
860 MockRead("Content-Length: 5\r\n"),
861 MockRead("Content-Length: 5\r\n\r\n"),
862 MockRead("Hello"),
864 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
865 arraysize(data_reads));
866 EXPECT_EQ(OK, out.rv);
867 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
868 EXPECT_EQ("Hello", out.response_data);
870 // 2 dupes and one mismatched.
872 MockRead data_reads[] = {
873 MockRead("HTTP/1.1 200 OK\r\n"),
874 MockRead("Content-Length: 10\r\n"),
875 MockRead("Content-Length: 10\r\n"),
876 MockRead("Content-Length: 5\r\n\r\n"),
878 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
879 arraysize(data_reads));
880 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
884 TEST_P(HttpNetworkTransactionTest,
885 MultipleContentLengthHeadersTransferEncoding) {
886 MockRead data_reads[] = {
887 MockRead("HTTP/1.1 200 OK\r\n"),
888 MockRead("Content-Length: 666\r\n"),
889 MockRead("Content-Length: 1337\r\n"),
890 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
891 MockRead("5\r\nHello\r\n"),
892 MockRead("1\r\n"),
893 MockRead(" \r\n"),
894 MockRead("5\r\nworld\r\n"),
895 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
896 MockRead(SYNCHRONOUS, OK),
898 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
899 arraysize(data_reads));
900 EXPECT_EQ(OK, out.rv);
901 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
902 EXPECT_EQ("Hello world", out.response_data);
905 // Next tests deal with http://crbug.com/98895.
907 // Checks that a single Content-Disposition header results in no error.
908 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
909 MockRead data_reads[] = {
910 MockRead("HTTP/1.1 200 OK\r\n"),
911 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
912 MockRead("Content-Length: 5\r\n\r\n"),
913 MockRead("Hello"),
915 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
916 arraysize(data_reads));
917 EXPECT_EQ(OK, out.rv);
918 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
919 EXPECT_EQ("Hello", out.response_data);
922 // Checks that two identical Content-Disposition headers result in no error.
923 TEST_P(HttpNetworkTransactionTest,
924 TwoIdenticalContentDispositionHeaders) {
925 MockRead data_reads[] = {
926 MockRead("HTTP/1.1 200 OK\r\n"),
927 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
928 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
929 MockRead("Content-Length: 5\r\n\r\n"),
930 MockRead("Hello"),
932 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
933 arraysize(data_reads));
934 EXPECT_EQ(OK, out.rv);
935 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
936 EXPECT_EQ("Hello", out.response_data);
939 // Checks that two distinct Content-Disposition headers result in an error.
940 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
941 MockRead data_reads[] = {
942 MockRead("HTTP/1.1 200 OK\r\n"),
943 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
944 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
945 MockRead("Content-Length: 5\r\n\r\n"),
946 MockRead("Hello"),
948 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
949 arraysize(data_reads));
950 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
953 // Checks that two identical Location headers result in no error.
954 // Also tests Location header behavior.
955 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
956 MockRead data_reads[] = {
957 MockRead("HTTP/1.1 302 Redirect\r\n"),
958 MockRead("Location: http://good.com/\r\n"),
959 MockRead("Location: http://good.com/\r\n"),
960 MockRead("Content-Length: 0\r\n\r\n"),
961 MockRead(SYNCHRONOUS, OK),
964 HttpRequestInfo request;
965 request.method = "GET";
966 request.url = GURL("http://redirect.com/");
967 request.load_flags = 0;
969 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
970 scoped_ptr<HttpTransaction> trans(
971 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
973 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
974 session_deps_.socket_factory->AddSocketDataProvider(&data);
976 TestCompletionCallback callback;
978 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
979 EXPECT_EQ(ERR_IO_PENDING, rv);
981 EXPECT_EQ(OK, callback.WaitForResult());
983 const HttpResponseInfo* response = trans->GetResponseInfo();
984 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
985 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
986 std::string url;
987 EXPECT_TRUE(response->headers->IsRedirect(&url));
988 EXPECT_EQ("http://good.com/", url);
989 EXPECT_TRUE(response->proxy_server.IsEmpty());
992 // Checks that two distinct Location headers result in an error.
993 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
994 MockRead data_reads[] = {
995 MockRead("HTTP/1.1 302 Redirect\r\n"),
996 MockRead("Location: http://good.com/\r\n"),
997 MockRead("Location: http://evil.com/\r\n"),
998 MockRead("Content-Length: 0\r\n\r\n"),
999 MockRead(SYNCHRONOUS, OK),
1001 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1002 arraysize(data_reads));
1003 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1006 // Do a request using the HEAD method. Verify that we don't try to read the
1007 // message body (since HEAD has none).
1008 TEST_P(HttpNetworkTransactionTest, Head) {
1009 HttpRequestInfo request;
1010 request.method = "HEAD";
1011 request.url = GURL("http://www.example.org/");
1012 request.load_flags = 0;
1014 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1015 scoped_ptr<HttpTransaction> trans(
1016 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1017 BeforeProxyHeadersSentHandler proxy_headers_handler;
1018 trans->SetBeforeProxyHeadersSentCallback(
1019 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1020 base::Unretained(&proxy_headers_handler)));
1022 MockWrite data_writes1[] = {
1023 MockWrite(
1024 "HEAD / HTTP/1.1\r\n"
1025 "Host: www.example.org\r\n"
1026 "Connection: keep-alive\r\n"
1027 "Content-Length: 0\r\n\r\n"),
1029 MockRead data_reads1[] = {
1030 MockRead("HTTP/1.1 404 Not Found\r\n"),
1031 MockRead("Server: Blah\r\n"),
1032 MockRead("Content-Length: 1234\r\n\r\n"),
1034 // No response body because the test stops reading here.
1035 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1038 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1039 data_writes1, arraysize(data_writes1));
1040 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1042 TestCompletionCallback callback1;
1044 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1045 EXPECT_EQ(ERR_IO_PENDING, rv);
1047 rv = callback1.WaitForResult();
1048 EXPECT_EQ(OK, rv);
1050 const HttpResponseInfo* response = trans->GetResponseInfo();
1051 ASSERT_TRUE(response != NULL);
1053 // Check that the headers got parsed.
1054 EXPECT_TRUE(response->headers.get() != NULL);
1055 EXPECT_EQ(1234, response->headers->GetContentLength());
1056 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1057 EXPECT_TRUE(response->proxy_server.IsEmpty());
1058 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1060 std::string server_header;
1061 void* iter = NULL;
1062 bool has_server_header = response->headers->EnumerateHeader(
1063 &iter, "Server", &server_header);
1064 EXPECT_TRUE(has_server_header);
1065 EXPECT_EQ("Blah", server_header);
1067 // Reading should give EOF right away, since there is no message body
1068 // (despite non-zero content-length).
1069 std::string response_data;
1070 rv = ReadTransaction(trans.get(), &response_data);
1071 EXPECT_EQ(OK, rv);
1072 EXPECT_EQ("", response_data);
1075 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1076 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1078 MockRead data_reads[] = {
1079 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1080 MockRead("hello"),
1081 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1082 MockRead("world"),
1083 MockRead(SYNCHRONOUS, OK),
1085 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1086 session_deps_.socket_factory->AddSocketDataProvider(&data);
1088 const char* const kExpectedResponseData[] = {
1089 "hello", "world"
1092 for (int i = 0; i < 2; ++i) {
1093 HttpRequestInfo request;
1094 request.method = "GET";
1095 request.url = GURL("http://www.example.org/");
1096 request.load_flags = 0;
1098 scoped_ptr<HttpTransaction> trans(
1099 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1101 TestCompletionCallback callback;
1103 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1104 EXPECT_EQ(ERR_IO_PENDING, rv);
1106 rv = callback.WaitForResult();
1107 EXPECT_EQ(OK, rv);
1109 const HttpResponseInfo* response = trans->GetResponseInfo();
1110 ASSERT_TRUE(response != NULL);
1112 EXPECT_TRUE(response->headers.get() != NULL);
1113 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1114 EXPECT_TRUE(response->proxy_server.IsEmpty());
1116 std::string response_data;
1117 rv = ReadTransaction(trans.get(), &response_data);
1118 EXPECT_EQ(OK, rv);
1119 EXPECT_EQ(kExpectedResponseData[i], response_data);
1123 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1124 ScopedVector<UploadElementReader> element_readers;
1125 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1126 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
1128 HttpRequestInfo request;
1129 request.method = "POST";
1130 request.url = GURL("http://www.foo.com/");
1131 request.upload_data_stream = &upload_data_stream;
1132 request.load_flags = 0;
1134 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1135 scoped_ptr<HttpTransaction> trans(
1136 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1138 MockRead data_reads[] = {
1139 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1140 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1141 MockRead("hello world"),
1142 MockRead(SYNCHRONOUS, OK),
1144 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1145 session_deps_.socket_factory->AddSocketDataProvider(&data);
1147 TestCompletionCallback callback;
1149 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1150 EXPECT_EQ(ERR_IO_PENDING, rv);
1152 rv = callback.WaitForResult();
1153 EXPECT_EQ(OK, rv);
1155 const HttpResponseInfo* response = trans->GetResponseInfo();
1156 ASSERT_TRUE(response != NULL);
1158 EXPECT_TRUE(response->headers.get() != NULL);
1159 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1161 std::string response_data;
1162 rv = ReadTransaction(trans.get(), &response_data);
1163 EXPECT_EQ(OK, rv);
1164 EXPECT_EQ("hello world", response_data);
1167 // This test is almost the same as Ignores100 above, but the response contains
1168 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1169 // HTTP/1.1 and the two status headers are read in one read.
1170 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1171 HttpRequestInfo request;
1172 request.method = "GET";
1173 request.url = GURL("http://www.foo.com/");
1174 request.load_flags = 0;
1176 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1177 scoped_ptr<HttpTransaction> trans(
1178 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1180 MockRead data_reads[] = {
1181 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1182 "HTTP/1.1 200 OK\r\n\r\n"),
1183 MockRead("hello world"),
1184 MockRead(SYNCHRONOUS, OK),
1186 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1187 session_deps_.socket_factory->AddSocketDataProvider(&data);
1189 TestCompletionCallback callback;
1191 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1192 EXPECT_EQ(ERR_IO_PENDING, rv);
1194 rv = callback.WaitForResult();
1195 EXPECT_EQ(OK, rv);
1197 const HttpResponseInfo* response = trans->GetResponseInfo();
1198 ASSERT_TRUE(response != NULL);
1200 EXPECT_TRUE(response->headers.get() != NULL);
1201 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1203 std::string response_data;
1204 rv = ReadTransaction(trans.get(), &response_data);
1205 EXPECT_EQ(OK, rv);
1206 EXPECT_EQ("hello world", response_data);
1209 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1210 HttpRequestInfo request;
1211 request.method = "POST";
1212 request.url = GURL("http://www.foo.com/");
1213 request.load_flags = 0;
1215 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1216 scoped_ptr<HttpTransaction> trans(
1217 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1219 MockRead data_reads[] = {
1220 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1221 MockRead(ASYNC, 0),
1223 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1224 session_deps_.socket_factory->AddSocketDataProvider(&data);
1226 TestCompletionCallback callback;
1228 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1229 EXPECT_EQ(ERR_IO_PENDING, rv);
1231 rv = callback.WaitForResult();
1232 EXPECT_EQ(OK, rv);
1234 std::string response_data;
1235 rv = ReadTransaction(trans.get(), &response_data);
1236 EXPECT_EQ(OK, rv);
1237 EXPECT_EQ("", response_data);
1240 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1241 HttpRequestInfo request;
1242 request.method = "POST";
1243 request.url = GURL("http://www.foo.com/");
1244 request.load_flags = 0;
1246 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1247 scoped_ptr<HttpTransaction> trans(
1248 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1250 MockRead data_reads[] = {
1251 MockRead(ASYNC, 0),
1253 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1254 session_deps_.socket_factory->AddSocketDataProvider(&data);
1256 TestCompletionCallback callback;
1258 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1259 EXPECT_EQ(ERR_IO_PENDING, rv);
1261 rv = callback.WaitForResult();
1262 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1265 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1266 const MockWrite* write_failure,
1267 const MockRead* read_failure) {
1268 HttpRequestInfo request;
1269 request.method = "GET";
1270 request.url = GURL("http://www.foo.com/");
1271 request.load_flags = 0;
1273 TestNetLog net_log;
1274 session_deps_.net_log = &net_log;
1275 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1277 // Written data for successfully sending both requests.
1278 MockWrite data1_writes[] = {
1279 MockWrite("GET / HTTP/1.1\r\n"
1280 "Host: www.foo.com\r\n"
1281 "Connection: keep-alive\r\n\r\n"),
1282 MockWrite("GET / HTTP/1.1\r\n"
1283 "Host: www.foo.com\r\n"
1284 "Connection: keep-alive\r\n\r\n")
1287 // Read results for the first request.
1288 MockRead data1_reads[] = {
1289 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1290 MockRead("hello"),
1291 MockRead(ASYNC, OK),
1294 if (write_failure) {
1295 ASSERT_FALSE(read_failure);
1296 data1_writes[1] = *write_failure;
1297 } else {
1298 ASSERT_TRUE(read_failure);
1299 data1_reads[2] = *read_failure;
1302 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1303 data1_writes, arraysize(data1_writes));
1304 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1306 MockRead data2_reads[] = {
1307 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1308 MockRead("world"),
1309 MockRead(ASYNC, OK),
1311 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1312 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1314 const char* const kExpectedResponseData[] = {
1315 "hello", "world"
1318 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1319 for (int i = 0; i < 2; ++i) {
1320 TestCompletionCallback callback;
1322 scoped_ptr<HttpTransaction> trans(
1323 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
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 LoadTimingInfo load_timing_info;
1332 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1333 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1334 if (i == 0) {
1335 first_socket_log_id = load_timing_info.socket_log_id;
1336 } else {
1337 // The second request should be using a new socket.
1338 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1341 const HttpResponseInfo* response = trans->GetResponseInfo();
1342 ASSERT_TRUE(response != NULL);
1344 EXPECT_TRUE(response->headers.get() != NULL);
1345 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1347 std::string response_data;
1348 rv = ReadTransaction(trans.get(), &response_data);
1349 EXPECT_EQ(OK, rv);
1350 EXPECT_EQ(kExpectedResponseData[i], response_data);
1354 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1355 const MockWrite* write_failure,
1356 const MockRead* read_failure,
1357 bool use_spdy) {
1358 HttpRequestInfo request;
1359 request.method = "GET";
1360 request.url = GURL("https://www.foo.com/");
1361 request.load_flags = 0;
1363 TestNetLog net_log;
1364 session_deps_.net_log = &net_log;
1365 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1367 SSLSocketDataProvider ssl1(ASYNC, OK);
1368 SSLSocketDataProvider ssl2(ASYNC, OK);
1369 if (use_spdy) {
1370 ssl1.SetNextProto(GetParam());
1371 ssl2.SetNextProto(GetParam());
1373 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1374 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1376 // SPDY versions of the request and response.
1377 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1378 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1379 scoped_ptr<SpdyFrame> spdy_response(
1380 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1381 scoped_ptr<SpdyFrame> spdy_data(
1382 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1384 // HTTP/1.1 versions of the request and response.
1385 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1386 "Host: www.foo.com\r\n"
1387 "Connection: keep-alive\r\n\r\n";
1388 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1389 const char kHttpData[] = "hello";
1391 std::vector<MockRead> data1_reads;
1392 std::vector<MockWrite> data1_writes;
1393 if (write_failure) {
1394 ASSERT_FALSE(read_failure);
1395 data1_writes.push_back(*write_failure);
1396 data1_reads.push_back(MockRead(ASYNC, OK));
1397 } else {
1398 ASSERT_TRUE(read_failure);
1399 if (use_spdy) {
1400 data1_writes.push_back(CreateMockWrite(*spdy_request));
1401 } else {
1402 data1_writes.push_back(MockWrite(kHttpRequest));
1404 data1_reads.push_back(*read_failure);
1407 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1408 &data1_writes[0], data1_writes.size());
1409 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1411 std::vector<MockRead> data2_reads;
1412 std::vector<MockWrite> data2_writes;
1414 if (use_spdy) {
1415 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1417 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1418 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1419 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1420 } else {
1421 data2_writes.push_back(
1422 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1424 data2_reads.push_back(
1425 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1426 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1427 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1429 OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
1430 &data2_writes[0], data2_writes.size());
1431 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1433 // Preconnect a socket.
1434 SSLConfig ssl_config;
1435 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1436 session->GetNextProtos(&ssl_config.next_protos);
1437 session->http_stream_factory()->PreconnectStreams(
1438 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1439 // Wait for the preconnect to complete.
1440 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1441 base::RunLoop().RunUntilIdle();
1442 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1444 // Make the request.
1445 TestCompletionCallback callback;
1447 scoped_ptr<HttpTransaction> trans(
1448 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1450 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1451 EXPECT_EQ(ERR_IO_PENDING, rv);
1453 rv = callback.WaitForResult();
1454 EXPECT_EQ(OK, rv);
1456 LoadTimingInfo load_timing_info;
1457 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1458 TestLoadTimingNotReused(
1459 load_timing_info,
1460 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1462 const HttpResponseInfo* response = trans->GetResponseInfo();
1463 ASSERT_TRUE(response != NULL);
1465 EXPECT_TRUE(response->headers.get() != NULL);
1466 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1468 std::string response_data;
1469 rv = ReadTransaction(trans.get(), &response_data);
1470 EXPECT_EQ(OK, rv);
1471 EXPECT_EQ(kHttpData, response_data);
1474 TEST_P(HttpNetworkTransactionTest,
1475 KeepAliveConnectionNotConnectedOnWrite) {
1476 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1477 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1480 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1481 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1482 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1485 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1486 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1487 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1490 // Make sure that on a 408 response (Request Timeout), the request is retried,
1491 // if the socket was a reused keep alive socket.
1492 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1493 MockRead read_failure(SYNCHRONOUS,
1494 "HTTP/1.1 408 Request Timeout\r\n"
1495 "Connection: Keep-Alive\r\n"
1496 "Content-Length: 6\r\n\r\n"
1497 "Pickle");
1498 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1501 TEST_P(HttpNetworkTransactionTest,
1502 PreconnectErrorNotConnectedOnWrite) {
1503 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1504 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1507 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1508 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1509 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1512 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1513 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1514 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1517 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1518 MockRead read_failure(ASYNC, OK); // EOF
1519 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1522 // Make sure that on a 408 response (Request Timeout), the request is retried,
1523 // if the socket was a preconnected (UNUSED_IDLE) socket.
1524 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1525 MockRead read_failure(SYNCHRONOUS,
1526 "HTTP/1.1 408 Request Timeout\r\n"
1527 "Connection: Keep-Alive\r\n"
1528 "Content-Length: 6\r\n\r\n"
1529 "Pickle");
1530 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1531 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1534 TEST_P(HttpNetworkTransactionTest,
1535 SpdyPreconnectErrorNotConnectedOnWrite) {
1536 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1537 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1540 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1541 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1542 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1545 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1546 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1547 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1550 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1551 MockRead read_failure(ASYNC, OK); // EOF
1552 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1555 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1556 HttpRequestInfo request;
1557 request.method = "GET";
1558 request.url = GURL("http://www.example.org/");
1559 request.load_flags = 0;
1561 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1562 scoped_ptr<HttpTransaction> trans(
1563 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1565 MockRead data_reads[] = {
1566 MockRead(ASYNC, ERR_CONNECTION_RESET),
1567 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1568 MockRead("hello world"),
1569 MockRead(SYNCHRONOUS, OK),
1571 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1572 session_deps_.socket_factory->AddSocketDataProvider(&data);
1574 TestCompletionCallback callback;
1576 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1577 EXPECT_EQ(ERR_IO_PENDING, rv);
1579 rv = callback.WaitForResult();
1580 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1582 const HttpResponseInfo* response = trans->GetResponseInfo();
1583 EXPECT_TRUE(response == NULL);
1586 // What do various browsers do when the server closes a non-keepalive
1587 // connection without sending any response header or body?
1589 // IE7: error page
1590 // Safari 3.1.2 (Windows): error page
1591 // Firefox 3.0.1: blank page
1592 // Opera 9.52: after five attempts, blank page
1593 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1594 // Us: error page (EMPTY_RESPONSE)
1595 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1596 MockRead data_reads[] = {
1597 MockRead(SYNCHRONOUS, OK), // EOF
1598 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1599 MockRead("hello world"),
1600 MockRead(SYNCHRONOUS, OK),
1602 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1603 arraysize(data_reads));
1604 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1607 // Test that network access can be deferred and resumed.
1608 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1609 HttpRequestInfo request;
1610 request.method = "GET";
1611 request.url = GURL("http://www.example.org/");
1612 request.load_flags = 0;
1614 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1615 scoped_ptr<HttpTransaction> trans(
1616 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1618 // Defer on OnBeforeNetworkStart.
1619 BeforeNetworkStartHandler net_start_handler(true); // defer
1620 trans->SetBeforeNetworkStartCallback(
1621 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1622 base::Unretained(&net_start_handler)));
1624 MockRead data_reads[] = {
1625 MockRead("HTTP/1.0 200 OK\r\n"),
1626 MockRead("Content-Length: 5\r\n\r\n"),
1627 MockRead("hello"),
1628 MockRead(SYNCHRONOUS, 0),
1630 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1631 session_deps_.socket_factory->AddSocketDataProvider(&data);
1633 TestCompletionCallback callback;
1635 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1636 EXPECT_EQ(ERR_IO_PENDING, rv);
1637 base::MessageLoop::current()->RunUntilIdle();
1639 // Should have deferred for network start.
1640 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1641 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1642 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1644 trans->ResumeNetworkStart();
1645 rv = callback.WaitForResult();
1646 EXPECT_EQ(OK, rv);
1647 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1649 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1650 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1651 if (rv == ERR_IO_PENDING)
1652 rv = callback.WaitForResult();
1653 EXPECT_EQ(5, rv);
1654 trans.reset();
1657 // Test that network use can be deferred and canceled.
1658 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1659 HttpRequestInfo request;
1660 request.method = "GET";
1661 request.url = GURL("http://www.example.org/");
1662 request.load_flags = 0;
1664 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1665 scoped_ptr<HttpTransaction> trans(
1666 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1668 // Defer on OnBeforeNetworkStart.
1669 BeforeNetworkStartHandler net_start_handler(true); // defer
1670 trans->SetBeforeNetworkStartCallback(
1671 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1672 base::Unretained(&net_start_handler)));
1674 TestCompletionCallback callback;
1676 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1677 EXPECT_EQ(ERR_IO_PENDING, rv);
1678 base::MessageLoop::current()->RunUntilIdle();
1680 // Should have deferred for network start.
1681 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1682 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1683 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1686 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1687 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1688 // destructor in such situations.
1689 // See http://crbug.com/154712 and http://crbug.com/156609.
1690 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1691 HttpRequestInfo request;
1692 request.method = "GET";
1693 request.url = GURL("http://www.example.org/");
1694 request.load_flags = 0;
1696 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1697 scoped_ptr<HttpTransaction> trans(
1698 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1700 MockRead data_reads[] = {
1701 MockRead("HTTP/1.0 200 OK\r\n"),
1702 MockRead("Connection: keep-alive\r\n"),
1703 MockRead("Content-Length: 100\r\n\r\n"),
1704 MockRead("hello"),
1705 MockRead(SYNCHRONOUS, 0),
1707 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1708 session_deps_.socket_factory->AddSocketDataProvider(&data);
1710 TestCompletionCallback callback;
1712 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1713 EXPECT_EQ(ERR_IO_PENDING, rv);
1715 rv = callback.WaitForResult();
1716 EXPECT_EQ(OK, rv);
1718 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1719 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1720 if (rv == ERR_IO_PENDING)
1721 rv = callback.WaitForResult();
1722 EXPECT_EQ(5, rv);
1723 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1724 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1726 trans.reset();
1727 base::MessageLoop::current()->RunUntilIdle();
1728 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1731 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1732 HttpRequestInfo request;
1733 request.method = "GET";
1734 request.url = GURL("http://www.example.org/");
1735 request.load_flags = 0;
1737 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1738 scoped_ptr<HttpTransaction> trans(
1739 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1741 MockRead data_reads[] = {
1742 MockRead("HTTP/1.0 200 OK\r\n"),
1743 MockRead("Connection: keep-alive\r\n"),
1744 MockRead("Content-Length: 100\r\n\r\n"),
1745 MockRead(SYNCHRONOUS, 0),
1747 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1748 session_deps_.socket_factory->AddSocketDataProvider(&data);
1750 TestCompletionCallback callback;
1752 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1753 EXPECT_EQ(ERR_IO_PENDING, rv);
1755 rv = callback.WaitForResult();
1756 EXPECT_EQ(OK, rv);
1758 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1759 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1760 if (rv == ERR_IO_PENDING)
1761 rv = callback.WaitForResult();
1762 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1764 trans.reset();
1765 base::MessageLoop::current()->RunUntilIdle();
1766 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1769 // Test that we correctly reuse a keep-alive connection after not explicitly
1770 // reading the body.
1771 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1772 HttpRequestInfo request;
1773 request.method = "GET";
1774 request.url = GURL("http://www.foo.com/");
1775 request.load_flags = 0;
1777 TestNetLog net_log;
1778 session_deps_.net_log = &net_log;
1779 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1781 // Note that because all these reads happen in the same
1782 // StaticSocketDataProvider, it shows that the same socket is being reused for
1783 // all transactions.
1784 MockRead data1_reads[] = {
1785 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1786 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1787 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1788 MockRead("HTTP/1.1 302 Found\r\n"
1789 "Content-Length: 0\r\n\r\n"),
1790 MockRead("HTTP/1.1 302 Found\r\n"
1791 "Content-Length: 5\r\n\r\n"
1792 "hello"),
1793 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1794 "Content-Length: 0\r\n\r\n"),
1795 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1796 "Content-Length: 5\r\n\r\n"
1797 "hello"),
1798 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1799 MockRead("hello"),
1801 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1802 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1804 MockRead data2_reads[] = {
1805 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1807 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1808 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1810 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1811 std::string response_lines[kNumUnreadBodies];
1813 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1814 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1815 TestCompletionCallback callback;
1817 scoped_ptr<HttpTransaction> trans(
1818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1820 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1821 EXPECT_EQ(ERR_IO_PENDING, rv);
1823 rv = callback.WaitForResult();
1824 EXPECT_EQ(OK, rv);
1826 LoadTimingInfo load_timing_info;
1827 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1828 if (i == 0) {
1829 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1830 first_socket_log_id = load_timing_info.socket_log_id;
1831 } else {
1832 TestLoadTimingReused(load_timing_info);
1833 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1836 const HttpResponseInfo* response = trans->GetResponseInfo();
1837 ASSERT_TRUE(response != NULL);
1839 ASSERT_TRUE(response->headers.get() != NULL);
1840 response_lines[i] = response->headers->GetStatusLine();
1842 // We intentionally don't read the response bodies.
1845 const char* const kStatusLines[] = {
1846 "HTTP/1.1 204 No Content",
1847 "HTTP/1.1 205 Reset Content",
1848 "HTTP/1.1 304 Not Modified",
1849 "HTTP/1.1 302 Found",
1850 "HTTP/1.1 302 Found",
1851 "HTTP/1.1 301 Moved Permanently",
1852 "HTTP/1.1 301 Moved Permanently",
1855 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1856 "forgot to update kStatusLines");
1858 for (int i = 0; i < kNumUnreadBodies; ++i)
1859 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1861 TestCompletionCallback callback;
1862 scoped_ptr<HttpTransaction> trans(
1863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1864 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1865 EXPECT_EQ(ERR_IO_PENDING, rv);
1866 rv = callback.WaitForResult();
1867 EXPECT_EQ(OK, rv);
1868 const HttpResponseInfo* response = trans->GetResponseInfo();
1869 ASSERT_TRUE(response != NULL);
1870 ASSERT_TRUE(response->headers.get() != NULL);
1871 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1872 std::string response_data;
1873 rv = ReadTransaction(trans.get(), &response_data);
1874 EXPECT_EQ(OK, rv);
1875 EXPECT_EQ("hello", response_data);
1878 // Test the request-challenge-retry sequence for basic auth.
1879 // (basic auth is the easiest to mock, because it has no randomness).
1880 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1881 HttpRequestInfo request;
1882 request.method = "GET";
1883 request.url = GURL("http://www.example.org/");
1884 request.load_flags = 0;
1886 TestNetLog log;
1887 session_deps_.net_log = &log;
1888 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1889 scoped_ptr<HttpTransaction> trans(
1890 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1892 MockWrite data_writes1[] = {
1893 MockWrite(
1894 "GET / HTTP/1.1\r\n"
1895 "Host: www.example.org\r\n"
1896 "Connection: keep-alive\r\n\r\n"),
1899 MockRead data_reads1[] = {
1900 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1901 // Give a couple authenticate options (only the middle one is actually
1902 // supported).
1903 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1904 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1905 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1906 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1907 // Large content-length -- won't matter, as connection will be reset.
1908 MockRead("Content-Length: 10000\r\n\r\n"),
1909 MockRead(SYNCHRONOUS, ERR_FAILED),
1912 // After calling trans->RestartWithAuth(), this is the request we should
1913 // be issuing -- the final header line contains the credentials.
1914 MockWrite data_writes2[] = {
1915 MockWrite(
1916 "GET / HTTP/1.1\r\n"
1917 "Host: www.example.org\r\n"
1918 "Connection: keep-alive\r\n"
1919 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1922 // Lastly, the server responds with the actual content.
1923 MockRead data_reads2[] = {
1924 MockRead("HTTP/1.0 200 OK\r\n"),
1925 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1926 MockRead("Content-Length: 100\r\n\r\n"),
1927 MockRead(SYNCHRONOUS, OK),
1930 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1931 data_writes1, arraysize(data_writes1));
1932 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1933 data_writes2, arraysize(data_writes2));
1934 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1935 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1937 TestCompletionCallback callback1;
1939 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1940 EXPECT_EQ(ERR_IO_PENDING, rv);
1942 rv = callback1.WaitForResult();
1943 EXPECT_EQ(OK, rv);
1945 LoadTimingInfo load_timing_info1;
1946 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1947 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1949 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1950 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1952 const HttpResponseInfo* response = trans->GetResponseInfo();
1953 ASSERT_TRUE(response != NULL);
1954 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1956 TestCompletionCallback callback2;
1958 rv = trans->RestartWithAuth(
1959 AuthCredentials(kFoo, kBar), callback2.callback());
1960 EXPECT_EQ(ERR_IO_PENDING, rv);
1962 rv = callback2.WaitForResult();
1963 EXPECT_EQ(OK, rv);
1965 LoadTimingInfo load_timing_info2;
1966 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1967 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1968 // The load timing after restart should have a new socket ID, and times after
1969 // those of the first load timing.
1970 EXPECT_LE(load_timing_info1.receive_headers_end,
1971 load_timing_info2.connect_timing.connect_start);
1972 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1974 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1975 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1977 response = trans->GetResponseInfo();
1978 ASSERT_TRUE(response != NULL);
1979 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1980 EXPECT_EQ(100, response->headers->GetContentLength());
1983 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1984 HttpRequestInfo request;
1985 request.method = "GET";
1986 request.url = GURL("http://www.example.org/");
1987 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
1989 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1990 scoped_ptr<HttpTransaction> trans(
1991 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1993 MockWrite data_writes[] = {
1994 MockWrite(
1995 "GET / HTTP/1.1\r\n"
1996 "Host: www.example.org\r\n"
1997 "Connection: keep-alive\r\n\r\n"),
2000 MockRead data_reads[] = {
2001 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2002 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2003 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2004 // Large content-length -- won't matter, as connection will be reset.
2005 MockRead("Content-Length: 10000\r\n\r\n"),
2006 MockRead(SYNCHRONOUS, ERR_FAILED),
2009 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2010 data_writes, arraysize(data_writes));
2011 session_deps_.socket_factory->AddSocketDataProvider(&data);
2012 TestCompletionCallback callback;
2014 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2015 EXPECT_EQ(ERR_IO_PENDING, rv);
2017 rv = callback.WaitForResult();
2018 EXPECT_EQ(0, rv);
2020 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2021 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2023 const HttpResponseInfo* response = trans->GetResponseInfo();
2024 ASSERT_TRUE(response != NULL);
2025 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2028 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2029 // connection.
2030 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2031 HttpRequestInfo request;
2032 request.method = "GET";
2033 request.url = GURL("http://www.example.org/");
2034 request.load_flags = 0;
2036 TestNetLog log;
2037 session_deps_.net_log = &log;
2038 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2040 MockWrite data_writes1[] = {
2041 MockWrite(
2042 "GET / HTTP/1.1\r\n"
2043 "Host: www.example.org\r\n"
2044 "Connection: keep-alive\r\n\r\n"),
2046 // After calling trans->RestartWithAuth(), this is the request we should
2047 // be issuing -- the final header line contains the credentials.
2048 MockWrite(
2049 "GET / HTTP/1.1\r\n"
2050 "Host: www.example.org\r\n"
2051 "Connection: keep-alive\r\n"
2052 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2055 MockRead data_reads1[] = {
2056 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2057 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2058 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2059 MockRead("Content-Length: 14\r\n\r\n"),
2060 MockRead("Unauthorized\r\n"),
2062 // Lastly, the server responds with the actual content.
2063 MockRead("HTTP/1.1 200 OK\r\n"),
2064 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2065 MockRead("Content-Length: 5\r\n\r\n"),
2066 MockRead("Hello"),
2069 // If there is a regression where we disconnect a Keep-Alive
2070 // connection during an auth roundtrip, we'll end up reading this.
2071 MockRead data_reads2[] = {
2072 MockRead(SYNCHRONOUS, ERR_FAILED),
2075 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2076 data_writes1, arraysize(data_writes1));
2077 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2078 NULL, 0);
2079 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2080 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2082 TestCompletionCallback callback1;
2084 scoped_ptr<HttpTransaction> trans(
2085 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2086 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2087 EXPECT_EQ(ERR_IO_PENDING, rv);
2089 rv = callback1.WaitForResult();
2090 EXPECT_EQ(OK, rv);
2092 LoadTimingInfo load_timing_info1;
2093 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2094 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2096 const HttpResponseInfo* response = trans->GetResponseInfo();
2097 ASSERT_TRUE(response != NULL);
2098 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2100 TestCompletionCallback callback2;
2102 rv = trans->RestartWithAuth(
2103 AuthCredentials(kFoo, kBar), callback2.callback());
2104 EXPECT_EQ(ERR_IO_PENDING, rv);
2106 rv = callback2.WaitForResult();
2107 EXPECT_EQ(OK, rv);
2109 LoadTimingInfo load_timing_info2;
2110 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2111 TestLoadTimingReused(load_timing_info2);
2112 // The load timing after restart should have the same socket ID, and times
2113 // those of the first load timing.
2114 EXPECT_LE(load_timing_info1.receive_headers_end,
2115 load_timing_info2.send_start);
2116 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2118 response = trans->GetResponseInfo();
2119 ASSERT_TRUE(response != NULL);
2120 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2121 EXPECT_EQ(5, response->headers->GetContentLength());
2123 std::string response_data;
2124 rv = ReadTransaction(trans.get(), &response_data);
2125 EXPECT_EQ(OK, rv);
2126 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2127 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2130 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2131 // connection and with no response body to drain.
2132 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2133 HttpRequestInfo request;
2134 request.method = "GET";
2135 request.url = GURL("http://www.example.org/");
2136 request.load_flags = 0;
2138 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2140 MockWrite data_writes1[] = {
2141 MockWrite(
2142 "GET / HTTP/1.1\r\n"
2143 "Host: www.example.org\r\n"
2144 "Connection: keep-alive\r\n\r\n"),
2146 // After calling trans->RestartWithAuth(), this is the request we should
2147 // be issuing -- the final header line contains the credentials.
2148 MockWrite(
2149 "GET / HTTP/1.1\r\n"
2150 "Host: www.example.org\r\n"
2151 "Connection: keep-alive\r\n"
2152 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2155 MockRead data_reads1[] = {
2156 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2157 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2158 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2160 // Lastly, the server responds with the actual content.
2161 MockRead("HTTP/1.1 200 OK\r\n"),
2162 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2163 MockRead("Content-Length: 5\r\n\r\n"),
2164 MockRead("hello"),
2167 // An incorrect reconnect would cause this to be read.
2168 MockRead data_reads2[] = {
2169 MockRead(SYNCHRONOUS, ERR_FAILED),
2172 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2173 data_writes1, arraysize(data_writes1));
2174 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2175 NULL, 0);
2176 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2177 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2179 TestCompletionCallback callback1;
2181 scoped_ptr<HttpTransaction> trans(
2182 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2183 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2184 EXPECT_EQ(ERR_IO_PENDING, rv);
2186 rv = callback1.WaitForResult();
2187 EXPECT_EQ(OK, rv);
2189 const HttpResponseInfo* response = trans->GetResponseInfo();
2190 ASSERT_TRUE(response != NULL);
2191 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2193 TestCompletionCallback callback2;
2195 rv = trans->RestartWithAuth(
2196 AuthCredentials(kFoo, kBar), callback2.callback());
2197 EXPECT_EQ(ERR_IO_PENDING, rv);
2199 rv = callback2.WaitForResult();
2200 EXPECT_EQ(OK, rv);
2202 response = trans->GetResponseInfo();
2203 ASSERT_TRUE(response != NULL);
2204 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2205 EXPECT_EQ(5, response->headers->GetContentLength());
2208 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2209 // connection and with a large response body to drain.
2210 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2211 HttpRequestInfo request;
2212 request.method = "GET";
2213 request.url = GURL("http://www.example.org/");
2214 request.load_flags = 0;
2216 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2218 MockWrite data_writes1[] = {
2219 MockWrite(
2220 "GET / HTTP/1.1\r\n"
2221 "Host: www.example.org\r\n"
2222 "Connection: keep-alive\r\n\r\n"),
2224 // After calling trans->RestartWithAuth(), this is the request we should
2225 // be issuing -- the final header line contains the credentials.
2226 MockWrite(
2227 "GET / HTTP/1.1\r\n"
2228 "Host: www.example.org\r\n"
2229 "Connection: keep-alive\r\n"
2230 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2233 // Respond with 5 kb of response body.
2234 std::string large_body_string("Unauthorized");
2235 large_body_string.append(5 * 1024, ' ');
2236 large_body_string.append("\r\n");
2238 MockRead data_reads1[] = {
2239 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2240 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2241 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2242 // 5134 = 12 + 5 * 1024 + 2
2243 MockRead("Content-Length: 5134\r\n\r\n"),
2244 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2246 // Lastly, the server responds with the actual content.
2247 MockRead("HTTP/1.1 200 OK\r\n"),
2248 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2249 MockRead("Content-Length: 5\r\n\r\n"),
2250 MockRead("hello"),
2253 // An incorrect reconnect would cause this to be read.
2254 MockRead data_reads2[] = {
2255 MockRead(SYNCHRONOUS, ERR_FAILED),
2258 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2259 data_writes1, arraysize(data_writes1));
2260 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2261 NULL, 0);
2262 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2263 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2265 TestCompletionCallback callback1;
2267 scoped_ptr<HttpTransaction> trans(
2268 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2269 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2270 EXPECT_EQ(ERR_IO_PENDING, rv);
2272 rv = callback1.WaitForResult();
2273 EXPECT_EQ(OK, rv);
2275 const HttpResponseInfo* response = trans->GetResponseInfo();
2276 ASSERT_TRUE(response != NULL);
2277 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2279 TestCompletionCallback callback2;
2281 rv = trans->RestartWithAuth(
2282 AuthCredentials(kFoo, kBar), callback2.callback());
2283 EXPECT_EQ(ERR_IO_PENDING, rv);
2285 rv = callback2.WaitForResult();
2286 EXPECT_EQ(OK, rv);
2288 response = trans->GetResponseInfo();
2289 ASSERT_TRUE(response != NULL);
2290 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2291 EXPECT_EQ(5, response->headers->GetContentLength());
2294 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2295 // connection, but the server gets impatient and closes the connection.
2296 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2297 HttpRequestInfo request;
2298 request.method = "GET";
2299 request.url = GURL("http://www.example.org/");
2300 request.load_flags = 0;
2302 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2304 MockWrite data_writes1[] = {
2305 MockWrite(
2306 "GET / HTTP/1.1\r\n"
2307 "Host: www.example.org\r\n"
2308 "Connection: keep-alive\r\n\r\n"),
2309 // This simulates the seemingly successful write to a closed connection
2310 // if the bug is not fixed.
2311 MockWrite(
2312 "GET / HTTP/1.1\r\n"
2313 "Host: www.example.org\r\n"
2314 "Connection: keep-alive\r\n"
2315 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2318 MockRead data_reads1[] = {
2319 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2320 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2321 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2322 MockRead("Content-Length: 14\r\n\r\n"),
2323 // Tell MockTCPClientSocket to simulate the server closing the connection.
2324 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2325 MockRead("Unauthorized\r\n"),
2326 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2329 // After calling trans->RestartWithAuth(), this is the request we should
2330 // be issuing -- the final header line contains the credentials.
2331 MockWrite data_writes2[] = {
2332 MockWrite(
2333 "GET / HTTP/1.1\r\n"
2334 "Host: www.example.org\r\n"
2335 "Connection: keep-alive\r\n"
2336 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2339 // Lastly, the server responds with the actual content.
2340 MockRead data_reads2[] = {
2341 MockRead("HTTP/1.1 200 OK\r\n"),
2342 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2343 MockRead("Content-Length: 5\r\n\r\n"),
2344 MockRead("hello"),
2347 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2348 data_writes1, arraysize(data_writes1));
2349 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2350 data_writes2, arraysize(data_writes2));
2351 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2352 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2354 TestCompletionCallback callback1;
2356 scoped_ptr<HttpTransaction> trans(
2357 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2358 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2359 EXPECT_EQ(ERR_IO_PENDING, rv);
2361 rv = callback1.WaitForResult();
2362 EXPECT_EQ(OK, rv);
2364 const HttpResponseInfo* response = trans->GetResponseInfo();
2365 ASSERT_TRUE(response != NULL);
2366 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2368 TestCompletionCallback callback2;
2370 rv = trans->RestartWithAuth(
2371 AuthCredentials(kFoo, kBar), callback2.callback());
2372 EXPECT_EQ(ERR_IO_PENDING, rv);
2374 rv = callback2.WaitForResult();
2375 EXPECT_EQ(OK, rv);
2377 response = trans->GetResponseInfo();
2378 ASSERT_TRUE(response != NULL);
2379 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2380 EXPECT_EQ(5, response->headers->GetContentLength());
2383 // Test the request-challenge-retry sequence for basic auth, over a connection
2384 // that requires a restart when setting up an SSL tunnel.
2385 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2386 HttpRequestInfo request;
2387 request.method = "GET";
2388 request.url = GURL("https://www.example.org/");
2389 // when the no authentication data flag is set.
2390 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2392 // Configure against proxy server "myproxy:70".
2393 session_deps_.proxy_service.reset(
2394 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2395 BoundTestNetLog log;
2396 session_deps_.net_log = log.bound().net_log();
2397 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2399 // Since we have proxy, should try to establish tunnel.
2400 MockWrite data_writes1[] = {
2401 MockWrite(
2402 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2403 "Host: www.example.org\r\n"
2404 "Proxy-Connection: keep-alive\r\n\r\n"),
2406 // After calling trans->RestartWithAuth(), this is the request we should
2407 // be issuing -- the final header line contains the credentials.
2408 MockWrite(
2409 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2410 "Host: www.example.org\r\n"
2411 "Proxy-Connection: keep-alive\r\n"
2412 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2414 MockWrite(
2415 "GET / HTTP/1.1\r\n"
2416 "Host: www.example.org\r\n"
2417 "Connection: keep-alive\r\n\r\n"),
2420 // The proxy responds to the connect with a 407, using a persistent
2421 // connection.
2422 MockRead data_reads1[] = {
2423 // No credentials.
2424 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2425 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2427 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2429 MockRead("HTTP/1.1 200 OK\r\n"),
2430 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2431 MockRead("Content-Length: 5\r\n\r\n"),
2432 MockRead(SYNCHRONOUS, "hello"),
2435 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2436 data_writes1, arraysize(data_writes1));
2437 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2438 SSLSocketDataProvider ssl(ASYNC, OK);
2439 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2441 TestCompletionCallback callback1;
2443 scoped_ptr<HttpTransaction> trans(
2444 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2446 int rv = trans->Start(&request, callback1.callback(), log.bound());
2447 EXPECT_EQ(ERR_IO_PENDING, rv);
2449 rv = callback1.WaitForResult();
2450 EXPECT_EQ(OK, rv);
2451 TestNetLog::CapturedEntryList entries;
2452 log.GetEntries(&entries);
2453 size_t pos = ExpectLogContainsSomewhere(
2454 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2455 NetLog::PHASE_NONE);
2456 ExpectLogContainsSomewhere(
2457 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2458 NetLog::PHASE_NONE);
2460 const HttpResponseInfo* response = trans->GetResponseInfo();
2461 ASSERT_TRUE(response != NULL);
2462 EXPECT_FALSE(response->headers->IsKeepAlive());
2463 ASSERT_FALSE(response->headers.get() == NULL);
2464 EXPECT_EQ(407, response->headers->response_code());
2465 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2466 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2468 LoadTimingInfo load_timing_info;
2469 // CONNECT requests and responses are handled at the connect job level, so
2470 // the transaction does not yet have a connection.
2471 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2473 TestCompletionCallback callback2;
2475 rv =
2476 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2477 EXPECT_EQ(ERR_IO_PENDING, rv);
2479 rv = callback2.WaitForResult();
2480 EXPECT_EQ(OK, rv);
2482 response = trans->GetResponseInfo();
2483 ASSERT_TRUE(response != NULL);
2485 EXPECT_TRUE(response->headers->IsKeepAlive());
2486 EXPECT_EQ(200, response->headers->response_code());
2487 EXPECT_EQ(5, response->headers->GetContentLength());
2488 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2490 // The password prompt info should not be set.
2491 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2493 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2494 TestLoadTimingNotReusedWithPac(load_timing_info,
2495 CONNECT_TIMING_HAS_SSL_TIMES);
2497 trans.reset();
2498 session->CloseAllConnections();
2501 // Test the request-challenge-retry sequence for basic auth, over a connection
2502 // that requires a restart when setting up an SSL tunnel.
2503 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
2504 HttpRequestInfo request;
2505 request.method = "GET";
2506 request.url = GURL("https://www.example.org/");
2507 // when the no authentication data flag is set.
2508 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2510 // Configure against proxy server "myproxy:70".
2511 session_deps_.proxy_service.reset(
2512 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2513 BoundTestNetLog log;
2514 session_deps_.net_log = log.bound().net_log();
2515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2517 // Since we have proxy, should try to establish tunnel.
2518 MockWrite data_writes1[] = {
2519 MockWrite(
2520 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2521 "Host: www.example.org\r\n"
2522 "Proxy-Connection: keep-alive\r\n\r\n"),
2524 // After calling trans->RestartWithAuth(), this is the request we should
2525 // be issuing -- the final header line contains the credentials.
2526 MockWrite(
2527 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2528 "Host: www.example.org\r\n"
2529 "Proxy-Connection: keep-alive\r\n"
2530 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2532 MockWrite(
2533 "GET / HTTP/1.1\r\n"
2534 "Host: www.example.org\r\n"
2535 "Connection: keep-alive\r\n\r\n"),
2538 // The proxy responds to the connect with a 407, using a persistent
2539 // connection.
2540 MockRead data_reads1[] = {
2541 // No credentials.
2542 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2543 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2544 MockRead("Proxy-Connection: close\r\n\r\n"),
2546 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2548 MockRead("HTTP/1.1 200 OK\r\n"),
2549 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2550 MockRead("Content-Length: 5\r\n\r\n"),
2551 MockRead(SYNCHRONOUS, "hello"),
2554 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2555 data_writes1, arraysize(data_writes1));
2556 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2557 SSLSocketDataProvider ssl(ASYNC, OK);
2558 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2560 TestCompletionCallback callback1;
2562 scoped_ptr<HttpTransaction> trans(
2563 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2565 int rv = trans->Start(&request, callback1.callback(), log.bound());
2566 EXPECT_EQ(ERR_IO_PENDING, rv);
2568 rv = callback1.WaitForResult();
2569 EXPECT_EQ(OK, rv);
2570 TestNetLog::CapturedEntryList entries;
2571 log.GetEntries(&entries);
2572 size_t pos = ExpectLogContainsSomewhere(
2573 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2574 NetLog::PHASE_NONE);
2575 ExpectLogContainsSomewhere(
2576 entries, pos,
2577 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2578 NetLog::PHASE_NONE);
2580 const HttpResponseInfo* response = trans->GetResponseInfo();
2581 ASSERT_TRUE(response != NULL);
2582 EXPECT_FALSE(response->headers->IsKeepAlive());
2583 ASSERT_FALSE(response->headers.get() == NULL);
2584 EXPECT_EQ(407, response->headers->response_code());
2585 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2586 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2588 LoadTimingInfo load_timing_info;
2589 // CONNECT requests and responses are handled at the connect job level, so
2590 // the transaction does not yet have a connection.
2591 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2593 TestCompletionCallback callback2;
2595 rv = trans->RestartWithAuth(
2596 AuthCredentials(kFoo, kBar), callback2.callback());
2597 EXPECT_EQ(ERR_IO_PENDING, rv);
2599 rv = callback2.WaitForResult();
2600 EXPECT_EQ(OK, rv);
2602 response = trans->GetResponseInfo();
2603 ASSERT_TRUE(response != NULL);
2605 EXPECT_TRUE(response->headers->IsKeepAlive());
2606 EXPECT_EQ(200, response->headers->response_code());
2607 EXPECT_EQ(5, response->headers->GetContentLength());
2608 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2610 // The password prompt info should not be set.
2611 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2613 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2614 TestLoadTimingNotReusedWithPac(load_timing_info,
2615 CONNECT_TIMING_HAS_SSL_TIMES);
2617 trans.reset();
2618 session->CloseAllConnections();
2621 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2622 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2623 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2624 HttpRequestInfo request;
2625 request.method = "GET";
2626 request.url = GURL("https://www.example.org/");
2627 // Ensure that proxy authentication is attempted even
2628 // when the no authentication data flag is set.
2629 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2631 // Configure against proxy server "myproxy:70".
2632 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2633 BoundTestNetLog log;
2634 session_deps_.net_log = log.bound().net_log();
2635 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2637 scoped_ptr<HttpTransaction> trans(
2638 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2640 // Since we have proxy, should try to establish tunnel.
2641 MockWrite data_writes1[] = {
2642 MockWrite(
2643 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2644 "Host: www.example.org\r\n"
2645 "Proxy-Connection: keep-alive\r\n\r\n"),
2647 // After calling trans->RestartWithAuth(), this is the request we should
2648 // be issuing -- the final header line contains the credentials.
2649 MockWrite(
2650 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2651 "Host: www.example.org\r\n"
2652 "Proxy-Connection: keep-alive\r\n"
2653 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2656 // The proxy responds to the connect with a 407, using a persistent
2657 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2658 MockRead data_reads1[] = {
2659 // No credentials.
2660 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2661 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2662 MockRead("Proxy-Connection: keep-alive\r\n"),
2663 MockRead("Content-Length: 10\r\n\r\n"),
2664 MockRead("0123456789"),
2666 // Wrong credentials (wrong password).
2667 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2668 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2669 MockRead("Proxy-Connection: keep-alive\r\n"),
2670 MockRead("Content-Length: 10\r\n\r\n"),
2671 // No response body because the test stops reading here.
2672 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2675 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2676 data_writes1, arraysize(data_writes1));
2677 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2679 TestCompletionCallback callback1;
2681 int rv = trans->Start(&request, callback1.callback(), log.bound());
2682 EXPECT_EQ(ERR_IO_PENDING, rv);
2684 rv = callback1.WaitForResult();
2685 EXPECT_EQ(OK, rv);
2686 TestNetLog::CapturedEntryList entries;
2687 log.GetEntries(&entries);
2688 size_t pos = ExpectLogContainsSomewhere(
2689 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2690 NetLog::PHASE_NONE);
2691 ExpectLogContainsSomewhere(
2692 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2693 NetLog::PHASE_NONE);
2695 const HttpResponseInfo* response = trans->GetResponseInfo();
2696 ASSERT_TRUE(response);
2697 ASSERT_TRUE(response->headers);
2698 EXPECT_TRUE(response->headers->IsKeepAlive());
2699 EXPECT_EQ(407, response->headers->response_code());
2700 EXPECT_EQ(10, response->headers->GetContentLength());
2701 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2702 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2704 TestCompletionCallback callback2;
2706 // Wrong password (should be "bar").
2707 rv =
2708 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2709 EXPECT_EQ(ERR_IO_PENDING, rv);
2711 rv = callback2.WaitForResult();
2712 EXPECT_EQ(OK, rv);
2714 response = trans->GetResponseInfo();
2715 ASSERT_TRUE(response);
2716 ASSERT_TRUE(response->headers);
2717 EXPECT_TRUE(response->headers->IsKeepAlive());
2718 EXPECT_EQ(407, response->headers->response_code());
2719 EXPECT_EQ(10, response->headers->GetContentLength());
2720 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2721 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2723 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2724 // out of scope.
2725 session->CloseAllConnections();
2728 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2729 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2730 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
2731 HttpRequestInfo request;
2732 request.method = "GET";
2733 request.url = GURL("https://www.example.org/");
2734 // Ensure that proxy authentication is attempted even
2735 // when the no authentication data flag is set.
2736 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2738 // Configure against proxy server "myproxy:70".
2739 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2740 BoundTestNetLog log;
2741 session_deps_.net_log = log.bound().net_log();
2742 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2744 scoped_ptr<HttpTransaction> trans(
2745 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2747 // Since we have proxy, should try to establish tunnel.
2748 MockWrite data_writes1[] = {
2749 MockWrite(
2750 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2751 "Host: www.example.org\r\n"
2752 "Proxy-Connection: keep-alive\r\n\r\n"),
2754 // After calling trans->RestartWithAuth(), this is the request we should
2755 // be issuing -- the final header line contains the credentials.
2756 MockWrite(
2757 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2758 "Host: www.example.org\r\n"
2759 "Proxy-Connection: keep-alive\r\n"
2760 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2763 // The proxy responds to the connect with a 407, using a persistent
2764 // connection.
2765 MockRead data_reads1[] = {
2766 // No credentials.
2767 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2768 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2769 MockRead("Content-Length: 10\r\n\r\n"),
2770 MockRead("0123456789"),
2772 // Wrong credentials (wrong password).
2773 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2774 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2775 MockRead("Content-Length: 10\r\n\r\n"),
2776 // No response body because the test stops reading here.
2777 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2780 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2781 data_writes1, arraysize(data_writes1));
2782 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2784 TestCompletionCallback callback1;
2786 int rv = trans->Start(&request, callback1.callback(), log.bound());
2787 EXPECT_EQ(ERR_IO_PENDING, rv);
2789 rv = callback1.WaitForResult();
2790 EXPECT_EQ(OK, rv);
2791 TestNetLog::CapturedEntryList entries;
2792 log.GetEntries(&entries);
2793 size_t pos = ExpectLogContainsSomewhere(
2794 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2795 NetLog::PHASE_NONE);
2796 ExpectLogContainsSomewhere(
2797 entries, pos,
2798 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2799 NetLog::PHASE_NONE);
2801 const HttpResponseInfo* response = trans->GetResponseInfo();
2802 ASSERT_TRUE(response);
2803 ASSERT_TRUE(response->headers);
2804 EXPECT_TRUE(response->headers->IsKeepAlive());
2805 EXPECT_EQ(407, response->headers->response_code());
2806 EXPECT_EQ(10, response->headers->GetContentLength());
2807 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2808 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2810 TestCompletionCallback callback2;
2812 // Wrong password (should be "bar").
2813 rv = trans->RestartWithAuth(
2814 AuthCredentials(kFoo, kBaz), callback2.callback());
2815 EXPECT_EQ(ERR_IO_PENDING, rv);
2817 rv = callback2.WaitForResult();
2818 EXPECT_EQ(OK, rv);
2820 response = trans->GetResponseInfo();
2821 ASSERT_TRUE(response);
2822 ASSERT_TRUE(response->headers);
2823 EXPECT_TRUE(response->headers->IsKeepAlive());
2824 EXPECT_EQ(407, response->headers->response_code());
2825 EXPECT_EQ(10, response->headers->GetContentLength());
2826 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2827 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2829 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2830 // out of scope.
2831 session->CloseAllConnections();
2834 // Test that we don't read the response body when we fail to establish a tunnel,
2835 // even if the user cancels the proxy's auth attempt.
2836 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2837 HttpRequestInfo request;
2838 request.method = "GET";
2839 request.url = GURL("https://www.example.org/");
2840 request.load_flags = 0;
2842 // Configure against proxy server "myproxy:70".
2843 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2845 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2847 scoped_ptr<HttpTransaction> trans(
2848 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2850 // Since we have proxy, should try to establish tunnel.
2851 MockWrite data_writes[] = {
2852 MockWrite(
2853 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2854 "Host: www.example.org\r\n"
2855 "Proxy-Connection: keep-alive\r\n\r\n"),
2858 // The proxy responds to the connect with a 407.
2859 MockRead data_reads[] = {
2860 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2861 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2862 MockRead("Content-Length: 10\r\n\r\n"),
2863 MockRead("0123456789"), // Should not be reached.
2864 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
2867 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2868 data_writes, arraysize(data_writes));
2869 session_deps_.socket_factory->AddSocketDataProvider(&data);
2871 TestCompletionCallback callback;
2873 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2874 EXPECT_EQ(ERR_IO_PENDING, rv);
2876 rv = callback.WaitForResult();
2877 EXPECT_EQ(OK, rv);
2879 const HttpResponseInfo* response = trans->GetResponseInfo();
2880 ASSERT_TRUE(response);
2881 ASSERT_TRUE(response->headers);
2882 EXPECT_TRUE(response->headers->IsKeepAlive());
2883 EXPECT_EQ(407, response->headers->response_code());
2884 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2886 std::string response_data;
2887 rv = ReadTransaction(trans.get(), &response_data);
2888 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2890 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2891 session->CloseAllConnections();
2894 // Test that we don't pass extraneous headers from the proxy's response to the
2895 // caller when the proxy responds to CONNECT with 407.
2896 TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
2897 HttpRequestInfo request;
2898 request.method = "GET";
2899 request.url = GURL("https://www.example.org/");
2900 request.load_flags = 0;
2902 // Configure against proxy server "myproxy:70".
2903 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2905 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2907 scoped_ptr<HttpTransaction> trans(
2908 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2910 // Since we have proxy, should try to establish tunnel.
2911 MockWrite data_writes[] = {
2912 MockWrite(
2913 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2914 "Host: www.example.org\r\n"
2915 "Proxy-Connection: keep-alive\r\n\r\n"),
2918 // The proxy responds to the connect with a 407.
2919 MockRead data_reads[] = {
2920 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2921 MockRead("X-Foo: bar\r\n"),
2922 MockRead("Set-Cookie: foo=bar\r\n"),
2923 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2924 MockRead("Content-Length: 10\r\n\r\n"),
2925 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2928 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
2929 arraysize(data_writes));
2930 session_deps_.socket_factory->AddSocketDataProvider(&data);
2932 TestCompletionCallback callback;
2934 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2935 EXPECT_EQ(ERR_IO_PENDING, rv);
2937 rv = callback.WaitForResult();
2938 EXPECT_EQ(OK, rv);
2940 const HttpResponseInfo* response = trans->GetResponseInfo();
2941 ASSERT_TRUE(response);
2942 ASSERT_TRUE(response->headers);
2943 EXPECT_TRUE(response->headers->IsKeepAlive());
2944 EXPECT_EQ(407, response->headers->response_code());
2945 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2946 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
2947 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
2949 std::string response_data;
2950 rv = ReadTransaction(trans.get(), &response_data);
2951 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2953 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2954 session->CloseAllConnections();
2957 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2958 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2959 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2960 HttpRequestInfo request;
2961 request.method = "GET";
2962 request.url = GURL("http://www.example.org/");
2963 request.load_flags = 0;
2965 // We are using a DIRECT connection (i.e. no proxy) for this session.
2966 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2967 scoped_ptr<HttpTransaction> trans(
2968 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2970 MockWrite data_writes1[] = {
2971 MockWrite(
2972 "GET / HTTP/1.1\r\n"
2973 "Host: www.example.org\r\n"
2974 "Connection: keep-alive\r\n\r\n"),
2977 MockRead data_reads1[] = {
2978 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2979 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2980 // Large content-length -- won't matter, as connection will be reset.
2981 MockRead("Content-Length: 10000\r\n\r\n"),
2982 MockRead(SYNCHRONOUS, ERR_FAILED),
2985 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2986 data_writes1, arraysize(data_writes1));
2987 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2989 TestCompletionCallback callback;
2991 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2992 EXPECT_EQ(ERR_IO_PENDING, rv);
2994 rv = callback.WaitForResult();
2995 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2998 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2999 // through a non-authenticating proxy. The request should fail with
3000 // ERR_UNEXPECTED_PROXY_AUTH.
3001 // Note that it is impossible to detect if an HTTP server returns a 407 through
3002 // a non-authenticating proxy - there is nothing to indicate whether the
3003 // response came from the proxy or the server, so it is treated as if the proxy
3004 // issued the challenge.
3005 TEST_P(HttpNetworkTransactionTest,
3006 HttpsServerRequestsProxyAuthThroughProxy) {
3007 HttpRequestInfo request;
3008 request.method = "GET";
3009 request.url = GURL("https://www.example.org/");
3011 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3012 BoundTestNetLog log;
3013 session_deps_.net_log = log.bound().net_log();
3014 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3016 // Since we have proxy, should try to establish tunnel.
3017 MockWrite data_writes1[] = {
3018 MockWrite(
3019 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3020 "Host: www.example.org\r\n"
3021 "Proxy-Connection: keep-alive\r\n\r\n"),
3023 MockWrite(
3024 "GET / HTTP/1.1\r\n"
3025 "Host: www.example.org\r\n"
3026 "Connection: keep-alive\r\n\r\n"),
3029 MockRead data_reads1[] = {
3030 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3032 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3033 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3034 MockRead("\r\n"),
3035 MockRead(SYNCHRONOUS, OK),
3038 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3039 data_writes1, arraysize(data_writes1));
3040 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3041 SSLSocketDataProvider ssl(ASYNC, OK);
3042 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3044 TestCompletionCallback callback1;
3046 scoped_ptr<HttpTransaction> trans(
3047 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3049 int rv = trans->Start(&request, callback1.callback(), log.bound());
3050 EXPECT_EQ(ERR_IO_PENDING, rv);
3052 rv = callback1.WaitForResult();
3053 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3054 TestNetLog::CapturedEntryList entries;
3055 log.GetEntries(&entries);
3056 size_t pos = ExpectLogContainsSomewhere(
3057 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3058 NetLog::PHASE_NONE);
3059 ExpectLogContainsSomewhere(
3060 entries, pos,
3061 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3062 NetLog::PHASE_NONE);
3065 // Test the load timing for HTTPS requests with an HTTP proxy.
3066 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
3067 HttpRequestInfo request1;
3068 request1.method = "GET";
3069 request1.url = GURL("https://www.example.org/1");
3071 HttpRequestInfo request2;
3072 request2.method = "GET";
3073 request2.url = GURL("https://www.example.org/2");
3075 // Configure against proxy server "myproxy:70".
3076 session_deps_.proxy_service.reset(
3077 ProxyService::CreateFixed("PROXY myproxy:70"));
3078 BoundTestNetLog log;
3079 session_deps_.net_log = log.bound().net_log();
3080 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3082 // Since we have proxy, should try to establish tunnel.
3083 MockWrite data_writes1[] = {
3084 MockWrite(
3085 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3086 "Host: www.example.org\r\n"
3087 "Proxy-Connection: keep-alive\r\n\r\n"),
3089 MockWrite(
3090 "GET /1 HTTP/1.1\r\n"
3091 "Host: www.example.org\r\n"
3092 "Connection: keep-alive\r\n\r\n"),
3094 MockWrite(
3095 "GET /2 HTTP/1.1\r\n"
3096 "Host: www.example.org\r\n"
3097 "Connection: keep-alive\r\n\r\n"),
3100 // The proxy responds to the connect with a 407, using a persistent
3101 // connection.
3102 MockRead data_reads1[] = {
3103 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3105 MockRead("HTTP/1.1 200 OK\r\n"),
3106 MockRead("Content-Length: 1\r\n\r\n"),
3107 MockRead(SYNCHRONOUS, "1"),
3109 MockRead("HTTP/1.1 200 OK\r\n"),
3110 MockRead("Content-Length: 2\r\n\r\n"),
3111 MockRead(SYNCHRONOUS, "22"),
3114 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3115 data_writes1, arraysize(data_writes1));
3116 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3117 SSLSocketDataProvider ssl(ASYNC, OK);
3118 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3120 TestCompletionCallback callback1;
3121 scoped_ptr<HttpTransaction> trans1(
3122 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3124 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3125 EXPECT_EQ(ERR_IO_PENDING, rv);
3127 rv = callback1.WaitForResult();
3128 EXPECT_EQ(OK, rv);
3130 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3131 ASSERT_TRUE(response1 != NULL);
3132 ASSERT_TRUE(response1->headers.get() != NULL);
3133 EXPECT_EQ(1, response1->headers->GetContentLength());
3135 LoadTimingInfo load_timing_info1;
3136 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3137 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3139 trans1.reset();
3141 TestCompletionCallback callback2;
3142 scoped_ptr<HttpTransaction> trans2(
3143 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3145 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3146 EXPECT_EQ(ERR_IO_PENDING, rv);
3148 rv = callback2.WaitForResult();
3149 EXPECT_EQ(OK, rv);
3151 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3152 ASSERT_TRUE(response2 != NULL);
3153 ASSERT_TRUE(response2->headers.get() != NULL);
3154 EXPECT_EQ(2, response2->headers->GetContentLength());
3156 LoadTimingInfo load_timing_info2;
3157 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3158 TestLoadTimingReused(load_timing_info2);
3160 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3162 trans2.reset();
3163 session->CloseAllConnections();
3166 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3167 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
3168 HttpRequestInfo request1;
3169 request1.method = "GET";
3170 request1.url = GURL("https://www.example.org/1");
3172 HttpRequestInfo request2;
3173 request2.method = "GET";
3174 request2.url = GURL("https://www.example.org/2");
3176 // Configure against proxy server "myproxy:70".
3177 session_deps_.proxy_service.reset(
3178 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3179 BoundTestNetLog log;
3180 session_deps_.net_log = log.bound().net_log();
3181 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3183 // Since we have proxy, should try to establish tunnel.
3184 MockWrite data_writes1[] = {
3185 MockWrite(
3186 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3187 "Host: www.example.org\r\n"
3188 "Proxy-Connection: keep-alive\r\n\r\n"),
3190 MockWrite(
3191 "GET /1 HTTP/1.1\r\n"
3192 "Host: www.example.org\r\n"
3193 "Connection: keep-alive\r\n\r\n"),
3195 MockWrite(
3196 "GET /2 HTTP/1.1\r\n"
3197 "Host: www.example.org\r\n"
3198 "Connection: keep-alive\r\n\r\n"),
3201 // The proxy responds to the connect with a 407, using a persistent
3202 // connection.
3203 MockRead data_reads1[] = {
3204 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3206 MockRead("HTTP/1.1 200 OK\r\n"),
3207 MockRead("Content-Length: 1\r\n\r\n"),
3208 MockRead(SYNCHRONOUS, "1"),
3210 MockRead("HTTP/1.1 200 OK\r\n"),
3211 MockRead("Content-Length: 2\r\n\r\n"),
3212 MockRead(SYNCHRONOUS, "22"),
3215 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3216 data_writes1, arraysize(data_writes1));
3217 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3218 SSLSocketDataProvider ssl(ASYNC, OK);
3219 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3221 TestCompletionCallback callback1;
3222 scoped_ptr<HttpTransaction> trans1(
3223 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3225 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3226 EXPECT_EQ(ERR_IO_PENDING, rv);
3228 rv = callback1.WaitForResult();
3229 EXPECT_EQ(OK, rv);
3231 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3232 ASSERT_TRUE(response1 != NULL);
3233 ASSERT_TRUE(response1->headers.get() != NULL);
3234 EXPECT_EQ(1, response1->headers->GetContentLength());
3236 LoadTimingInfo load_timing_info1;
3237 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3238 TestLoadTimingNotReusedWithPac(load_timing_info1,
3239 CONNECT_TIMING_HAS_SSL_TIMES);
3241 trans1.reset();
3243 TestCompletionCallback callback2;
3244 scoped_ptr<HttpTransaction> trans2(
3245 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3247 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3248 EXPECT_EQ(ERR_IO_PENDING, rv);
3250 rv = callback2.WaitForResult();
3251 EXPECT_EQ(OK, rv);
3253 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3254 ASSERT_TRUE(response2 != NULL);
3255 ASSERT_TRUE(response2->headers.get() != NULL);
3256 EXPECT_EQ(2, response2->headers->GetContentLength());
3258 LoadTimingInfo load_timing_info2;
3259 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3260 TestLoadTimingReusedWithPac(load_timing_info2);
3262 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3264 trans2.reset();
3265 session->CloseAllConnections();
3268 // Test a simple get through an HTTPS Proxy.
3269 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
3270 HttpRequestInfo request;
3271 request.method = "GET";
3272 request.url = GURL("http://www.example.org/");
3274 // Configure against https proxy server "proxy:70".
3275 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3276 "https://proxy:70"));
3277 BoundTestNetLog log;
3278 session_deps_.net_log = log.bound().net_log();
3279 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3281 // Since we have proxy, should use full url
3282 MockWrite data_writes1[] = {
3283 MockWrite(
3284 "GET http://www.example.org/ HTTP/1.1\r\n"
3285 "Host: www.example.org\r\n"
3286 "Proxy-Connection: keep-alive\r\n\r\n"),
3289 MockRead data_reads1[] = {
3290 MockRead("HTTP/1.1 200 OK\r\n"),
3291 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3292 MockRead("Content-Length: 100\r\n\r\n"),
3293 MockRead(SYNCHRONOUS, OK),
3296 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3297 data_writes1, arraysize(data_writes1));
3298 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3299 SSLSocketDataProvider ssl(ASYNC, OK);
3300 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3302 TestCompletionCallback callback1;
3304 scoped_ptr<HttpTransaction> trans(
3305 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3307 int rv = trans->Start(&request, callback1.callback(), log.bound());
3308 EXPECT_EQ(ERR_IO_PENDING, rv);
3310 rv = callback1.WaitForResult();
3311 EXPECT_EQ(OK, rv);
3313 LoadTimingInfo load_timing_info;
3314 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3315 TestLoadTimingNotReused(load_timing_info,
3316 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3318 const HttpResponseInfo* response = trans->GetResponseInfo();
3319 ASSERT_TRUE(response != NULL);
3321 EXPECT_TRUE(response->headers->IsKeepAlive());
3322 EXPECT_EQ(200, response->headers->response_code());
3323 EXPECT_EQ(100, response->headers->GetContentLength());
3324 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3326 // The password prompt info should not be set.
3327 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3330 // Test a SPDY get through an HTTPS Proxy.
3331 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3332 HttpRequestInfo request;
3333 request.method = "GET";
3334 request.url = GURL("http://www.example.org/");
3335 request.load_flags = 0;
3337 // Configure against https proxy server "proxy:70".
3338 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3339 "https://proxy:70"));
3340 BoundTestNetLog log;
3341 session_deps_.net_log = log.bound().net_log();
3342 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3344 // fetch http://www.example.org/ via SPDY
3345 scoped_ptr<SpdyFrame> req(
3346 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3347 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
3349 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3350 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3351 MockRead spdy_reads[] = {
3352 CreateMockRead(*resp),
3353 CreateMockRead(*data),
3354 MockRead(ASYNC, 0, 0),
3357 DelayedSocketData spdy_data(
3358 1, // wait for one write to finish before reading.
3359 spdy_reads, arraysize(spdy_reads),
3360 spdy_writes, arraysize(spdy_writes));
3361 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3363 SSLSocketDataProvider ssl(ASYNC, OK);
3364 ssl.SetNextProto(GetParam());
3365 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3367 TestCompletionCallback callback1;
3369 scoped_ptr<HttpTransaction> trans(
3370 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3372 int rv = trans->Start(&request, callback1.callback(), log.bound());
3373 EXPECT_EQ(ERR_IO_PENDING, rv);
3375 rv = callback1.WaitForResult();
3376 EXPECT_EQ(OK, rv);
3378 LoadTimingInfo load_timing_info;
3379 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3380 TestLoadTimingNotReused(load_timing_info,
3381 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3383 const HttpResponseInfo* response = trans->GetResponseInfo();
3384 ASSERT_TRUE(response != NULL);
3385 ASSERT_TRUE(response->headers.get() != NULL);
3386 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3388 std::string response_data;
3389 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3390 EXPECT_EQ(kUploadData, response_data);
3393 // Verifies that a session which races and wins against the owning transaction
3394 // (completing prior to host resolution), doesn't fail the transaction.
3395 // Regression test for crbug.com/334413.
3396 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3397 HttpRequestInfo request;
3398 request.method = "GET";
3399 request.url = GURL("http://www.example.org/");
3400 request.load_flags = 0;
3402 // Configure SPDY proxy server "proxy:70".
3403 session_deps_.proxy_service.reset(
3404 ProxyService::CreateFixed("https://proxy:70"));
3405 BoundTestNetLog log;
3406 session_deps_.net_log = log.bound().net_log();
3407 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3409 // Fetch http://www.example.org/ through the SPDY proxy.
3410 scoped_ptr<SpdyFrame> req(
3411 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3412 MockWrite spdy_writes[] = {CreateMockWrite(*req)};
3414 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3415 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3416 MockRead spdy_reads[] = {
3417 CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0),
3420 DelayedSocketData spdy_data(
3421 1, // wait for one write to finish before reading.
3422 spdy_reads,
3423 arraysize(spdy_reads),
3424 spdy_writes,
3425 arraysize(spdy_writes));
3426 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3428 SSLSocketDataProvider ssl(ASYNC, OK);
3429 ssl.SetNextProto(GetParam());
3430 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3432 TestCompletionCallback callback1;
3434 scoped_ptr<HttpTransaction> trans(
3435 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3437 // Stall the hostname resolution begun by the transaction.
3438 session_deps_.host_resolver->set_synchronous_mode(false);
3439 session_deps_.host_resolver->set_ondemand_mode(true);
3441 int rv = trans->Start(&request, callback1.callback(), log.bound());
3442 EXPECT_EQ(ERR_IO_PENDING, rv);
3444 // Race a session to the proxy, which completes first.
3445 session_deps_.host_resolver->set_ondemand_mode(false);
3446 SpdySessionKey key(
3447 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3448 base::WeakPtr<SpdySession> spdy_session =
3449 CreateSecureSpdySession(session, key, log.bound());
3451 // Unstall the resolution begun by the transaction.
3452 session_deps_.host_resolver->set_ondemand_mode(true);
3453 session_deps_.host_resolver->ResolveAllPending();
3455 EXPECT_FALSE(callback1.have_result());
3456 rv = callback1.WaitForResult();
3457 EXPECT_EQ(OK, rv);
3459 const HttpResponseInfo* response = trans->GetResponseInfo();
3460 ASSERT_TRUE(response != NULL);
3461 ASSERT_TRUE(response->headers.get() != NULL);
3462 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3464 std::string response_data;
3465 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3466 EXPECT_EQ(kUploadData, response_data);
3469 // Test a SPDY get through an HTTPS Proxy.
3470 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3471 HttpRequestInfo request;
3472 request.method = "GET";
3473 request.url = GURL("http://www.example.org/");
3474 request.load_flags = 0;
3476 // Configure against https proxy server "myproxy:70".
3477 session_deps_.proxy_service.reset(
3478 ProxyService::CreateFixed("https://myproxy:70"));
3479 BoundTestNetLog log;
3480 session_deps_.net_log = log.bound().net_log();
3481 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3483 // The first request will be a bare GET, the second request will be a
3484 // GET with a Proxy-Authorization header.
3485 scoped_ptr<SpdyFrame> req_get(
3486 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3487 const char* const kExtraAuthorizationHeaders[] = {
3488 "proxy-authorization", "Basic Zm9vOmJhcg=="
3490 scoped_ptr<SpdyFrame> req_get_authorization(
3491 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3492 arraysize(kExtraAuthorizationHeaders) / 2,
3493 false,
3495 LOWEST,
3496 false));
3497 MockWrite spdy_writes[] = {
3498 CreateMockWrite(*req_get, 1),
3499 CreateMockWrite(*req_get_authorization, 4),
3502 // The first response is a 407 proxy authentication challenge, and the second
3503 // response will be a 200 response since the second request includes a valid
3504 // Authorization header.
3505 const char* const kExtraAuthenticationHeaders[] = {
3506 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3508 scoped_ptr<SpdyFrame> resp_authentication(
3509 spdy_util_.ConstructSpdySynReplyError(
3510 "407 Proxy Authentication Required",
3511 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3512 1));
3513 scoped_ptr<SpdyFrame> body_authentication(
3514 spdy_util_.ConstructSpdyBodyFrame(1, true));
3515 scoped_ptr<SpdyFrame> resp_data(
3516 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3517 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3518 MockRead spdy_reads[] = {
3519 CreateMockRead(*resp_authentication, 2),
3520 CreateMockRead(*body_authentication, 3),
3521 CreateMockRead(*resp_data, 5),
3522 CreateMockRead(*body_data, 6),
3523 MockRead(ASYNC, 0, 7),
3526 OrderedSocketData data(
3527 spdy_reads, arraysize(spdy_reads),
3528 spdy_writes, arraysize(spdy_writes));
3529 session_deps_.socket_factory->AddSocketDataProvider(&data);
3531 SSLSocketDataProvider ssl(ASYNC, OK);
3532 ssl.SetNextProto(GetParam());
3533 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3535 TestCompletionCallback callback1;
3537 scoped_ptr<HttpTransaction> trans(
3538 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3540 int rv = trans->Start(&request, callback1.callback(), log.bound());
3541 EXPECT_EQ(ERR_IO_PENDING, rv);
3543 rv = callback1.WaitForResult();
3544 EXPECT_EQ(OK, rv);
3546 const HttpResponseInfo* const response = trans->GetResponseInfo();
3548 ASSERT_TRUE(response != NULL);
3549 ASSERT_TRUE(response->headers.get() != NULL);
3550 EXPECT_EQ(407, response->headers->response_code());
3551 EXPECT_TRUE(response->was_fetched_via_spdy);
3552 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3554 TestCompletionCallback callback2;
3556 rv = trans->RestartWithAuth(
3557 AuthCredentials(kFoo, kBar), callback2.callback());
3558 EXPECT_EQ(ERR_IO_PENDING, rv);
3560 rv = callback2.WaitForResult();
3561 EXPECT_EQ(OK, rv);
3563 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3565 ASSERT_TRUE(response_restart != NULL);
3566 ASSERT_TRUE(response_restart->headers.get() != NULL);
3567 EXPECT_EQ(200, response_restart->headers->response_code());
3568 // The password prompt info should not be set.
3569 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3572 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3573 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3574 HttpRequestInfo request;
3575 request.method = "GET";
3576 request.url = GURL("https://www.example.org/");
3577 request.load_flags = 0;
3579 // Configure against https proxy server "proxy:70".
3580 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3581 "https://proxy:70"));
3582 BoundTestNetLog log;
3583 session_deps_.net_log = log.bound().net_log();
3584 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3586 scoped_ptr<HttpTransaction> trans(
3587 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3589 // CONNECT to www.example.org:443 via SPDY
3590 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3591 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3592 // fetch https://www.example.org/ via HTTP
3594 const char get[] =
3595 "GET / HTTP/1.1\r\n"
3596 "Host: www.example.org\r\n"
3597 "Connection: keep-alive\r\n\r\n";
3598 scoped_ptr<SpdyFrame> wrapped_get(
3599 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3600 scoped_ptr<SpdyFrame> conn_resp(
3601 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3602 const char resp[] = "HTTP/1.1 200 OK\r\n"
3603 "Content-Length: 10\r\n\r\n";
3604 scoped_ptr<SpdyFrame> wrapped_get_resp(
3605 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3606 scoped_ptr<SpdyFrame> wrapped_body(
3607 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3608 scoped_ptr<SpdyFrame> window_update(
3609 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3611 MockWrite spdy_writes[] = {
3612 CreateMockWrite(*connect, 1),
3613 CreateMockWrite(*wrapped_get, 3),
3614 CreateMockWrite(*window_update, 5),
3617 MockRead spdy_reads[] = {
3618 CreateMockRead(*conn_resp, 2, ASYNC),
3619 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3620 CreateMockRead(*wrapped_body, 6, ASYNC),
3621 CreateMockRead(*wrapped_body, 7, ASYNC),
3622 MockRead(ASYNC, 0, 8),
3625 OrderedSocketData spdy_data(
3626 spdy_reads, arraysize(spdy_reads),
3627 spdy_writes, arraysize(spdy_writes));
3628 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3630 SSLSocketDataProvider ssl(ASYNC, OK);
3631 ssl.SetNextProto(GetParam());
3632 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3633 SSLSocketDataProvider ssl2(ASYNC, OK);
3634 ssl2.was_npn_negotiated = false;
3635 ssl2.protocol_negotiated = kProtoUnknown;
3636 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3638 TestCompletionCallback callback1;
3640 int rv = trans->Start(&request, callback1.callback(), log.bound());
3641 EXPECT_EQ(ERR_IO_PENDING, rv);
3643 rv = callback1.WaitForResult();
3644 EXPECT_EQ(OK, rv);
3646 LoadTimingInfo load_timing_info;
3647 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3648 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3650 const HttpResponseInfo* response = trans->GetResponseInfo();
3651 ASSERT_TRUE(response != NULL);
3652 ASSERT_TRUE(response->headers.get() != NULL);
3653 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3655 std::string response_data;
3656 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3657 EXPECT_EQ("1234567890", response_data);
3660 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3661 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3662 HttpRequestInfo request;
3663 request.method = "GET";
3664 request.url = GURL("https://www.example.org/");
3665 request.load_flags = 0;
3667 // Configure against https proxy server "proxy:70".
3668 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3669 "https://proxy:70"));
3670 BoundTestNetLog log;
3671 session_deps_.net_log = log.bound().net_log();
3672 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3674 scoped_ptr<HttpTransaction> trans(
3675 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3677 // CONNECT to www.example.org:443 via SPDY
3678 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3679 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3680 // fetch https://www.example.org/ via SPDY
3681 const char kMyUrl[] = "https://www.example.org/";
3682 scoped_ptr<SpdyFrame> get(
3683 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3684 scoped_ptr<SpdyFrame> wrapped_get(
3685 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3686 scoped_ptr<SpdyFrame> conn_resp(
3687 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3688 scoped_ptr<SpdyFrame> get_resp(
3689 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3690 scoped_ptr<SpdyFrame> wrapped_get_resp(
3691 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3692 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3693 scoped_ptr<SpdyFrame> wrapped_body(
3694 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3695 scoped_ptr<SpdyFrame> window_update_get_resp(
3696 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3697 scoped_ptr<SpdyFrame> window_update_body(
3698 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3700 MockWrite spdy_writes[] = {
3701 CreateMockWrite(*connect, 1),
3702 CreateMockWrite(*wrapped_get, 3),
3703 CreateMockWrite(*window_update_get_resp, 5),
3704 CreateMockWrite(*window_update_body, 7),
3707 MockRead spdy_reads[] = {
3708 CreateMockRead(*conn_resp, 2, ASYNC),
3709 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3710 CreateMockRead(*wrapped_body, 6, ASYNC),
3711 MockRead(ASYNC, 0, 8),
3714 OrderedSocketData spdy_data(
3715 spdy_reads, arraysize(spdy_reads),
3716 spdy_writes, arraysize(spdy_writes));
3717 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3719 SSLSocketDataProvider ssl(ASYNC, OK);
3720 ssl.SetNextProto(GetParam());
3721 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3722 SSLSocketDataProvider ssl2(ASYNC, OK);
3723 ssl2.SetNextProto(GetParam());
3724 ssl2.protocol_negotiated = GetParam();
3725 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3727 TestCompletionCallback callback1;
3729 int rv = trans->Start(&request, callback1.callback(), log.bound());
3730 EXPECT_EQ(ERR_IO_PENDING, rv);
3732 rv = callback1.WaitForResult();
3733 EXPECT_EQ(OK, rv);
3735 LoadTimingInfo load_timing_info;
3736 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3737 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3739 const HttpResponseInfo* response = trans->GetResponseInfo();
3740 ASSERT_TRUE(response != NULL);
3741 ASSERT_TRUE(response->headers.get() != NULL);
3742 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3744 std::string response_data;
3745 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3746 EXPECT_EQ(kUploadData, response_data);
3749 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3750 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3751 HttpRequestInfo request;
3752 request.method = "GET";
3753 request.url = GURL("https://www.example.org/");
3754 request.load_flags = 0;
3756 // Configure against https proxy server "proxy:70".
3757 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3758 "https://proxy:70"));
3759 BoundTestNetLog log;
3760 session_deps_.net_log = log.bound().net_log();
3761 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3763 scoped_ptr<HttpTransaction> trans(
3764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3766 // CONNECT to www.example.org:443 via SPDY
3767 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
3768 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3769 scoped_ptr<SpdyFrame> get(
3770 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3772 MockWrite spdy_writes[] = {
3773 CreateMockWrite(*connect, 1),
3774 CreateMockWrite(*get, 3),
3777 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3778 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3779 MockRead spdy_reads[] = {
3780 CreateMockRead(*resp, 2, ASYNC),
3781 MockRead(ASYNC, 0, 4),
3784 OrderedSocketData spdy_data(
3785 spdy_reads, arraysize(spdy_reads),
3786 spdy_writes, arraysize(spdy_writes));
3787 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3789 SSLSocketDataProvider ssl(ASYNC, OK);
3790 ssl.SetNextProto(GetParam());
3791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3792 SSLSocketDataProvider ssl2(ASYNC, OK);
3793 ssl2.SetNextProto(GetParam());
3794 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3796 TestCompletionCallback callback1;
3798 int rv = trans->Start(&request, callback1.callback(), log.bound());
3799 EXPECT_EQ(ERR_IO_PENDING, rv);
3801 rv = callback1.WaitForResult();
3802 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3804 // TODO(ttuttle): Anything else to check here?
3807 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3808 // HTTPS Proxy to different servers.
3809 TEST_P(HttpNetworkTransactionTest,
3810 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3811 // Configure against https proxy server "proxy:70".
3812 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3813 "https://proxy:70"));
3814 BoundTestNetLog log;
3815 session_deps_.net_log = log.bound().net_log();
3816 scoped_refptr<HttpNetworkSession> session(
3817 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3819 HttpRequestInfo request1;
3820 request1.method = "GET";
3821 request1.url = GURL("https://www.example.org/");
3822 request1.load_flags = 0;
3824 HttpRequestInfo request2;
3825 request2.method = "GET";
3826 request2.url = GURL("https://mail.example.org/");
3827 request2.load_flags = 0;
3829 // CONNECT to www.example.org:443 via SPDY.
3830 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3831 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3832 scoped_ptr<SpdyFrame> conn_resp1(
3833 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3835 // Fetch https://www.example.org/ via HTTP.
3836 const char get1[] =
3837 "GET / HTTP/1.1\r\n"
3838 "Host: www.example.org\r\n"
3839 "Connection: keep-alive\r\n\r\n";
3840 scoped_ptr<SpdyFrame> wrapped_get1(
3841 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3842 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3843 "Content-Length: 1\r\n\r\n";
3844 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3845 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3846 scoped_ptr<SpdyFrame> wrapped_body1(
3847 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3848 scoped_ptr<SpdyFrame> window_update(
3849 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3851 // CONNECT to mail.example.org:443 via SPDY.
3852 SpdyHeaderBlock connect2_block;
3853 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3854 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
3855 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
3856 spdy_util_.MaybeAddVersionHeader(&connect2_block);
3857 scoped_ptr<SpdyFrame> connect2(
3858 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3860 scoped_ptr<SpdyFrame> conn_resp2(
3861 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3863 // Fetch https://mail.example.org/ via HTTP.
3864 const char get2[] =
3865 "GET / HTTP/1.1\r\n"
3866 "Host: mail.example.org\r\n"
3867 "Connection: keep-alive\r\n\r\n";
3868 scoped_ptr<SpdyFrame> wrapped_get2(
3869 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3870 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3871 "Content-Length: 2\r\n\r\n";
3872 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3873 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3874 scoped_ptr<SpdyFrame> wrapped_body2(
3875 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3877 MockWrite spdy_writes[] = {
3878 CreateMockWrite(*connect1, 0),
3879 CreateMockWrite(*wrapped_get1, 2),
3880 CreateMockWrite(*connect2, 5),
3881 CreateMockWrite(*wrapped_get2, 7),
3884 MockRead spdy_reads[] = {
3885 CreateMockRead(*conn_resp1, 1, ASYNC),
3886 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3887 CreateMockRead(*wrapped_body1, 4, ASYNC),
3888 CreateMockRead(*conn_resp2, 6, ASYNC),
3889 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3890 CreateMockRead(*wrapped_body2, 9, ASYNC),
3891 MockRead(ASYNC, 0, 10),
3894 DeterministicSocketData spdy_data(
3895 spdy_reads, arraysize(spdy_reads),
3896 spdy_writes, arraysize(spdy_writes));
3897 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3899 SSLSocketDataProvider ssl(ASYNC, OK);
3900 ssl.SetNextProto(GetParam());
3901 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3902 SSLSocketDataProvider ssl2(ASYNC, OK);
3903 ssl2.was_npn_negotiated = false;
3904 ssl2.protocol_negotiated = kProtoUnknown;
3905 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3906 SSLSocketDataProvider ssl3(ASYNC, OK);
3907 ssl3.was_npn_negotiated = false;
3908 ssl3.protocol_negotiated = kProtoUnknown;
3909 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3911 TestCompletionCallback callback;
3913 scoped_ptr<HttpTransaction> trans(
3914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3915 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3916 EXPECT_EQ(ERR_IO_PENDING, rv);
3917 // The first connect and request, each of their responses, and the body.
3918 spdy_data.RunFor(5);
3920 rv = callback.WaitForResult();
3921 EXPECT_EQ(OK, rv);
3923 LoadTimingInfo load_timing_info;
3924 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3925 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3927 const HttpResponseInfo* response = trans->GetResponseInfo();
3928 ASSERT_TRUE(response != NULL);
3929 ASSERT_TRUE(response->headers.get() != NULL);
3930 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3932 std::string response_data;
3933 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
3934 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3936 scoped_ptr<HttpTransaction> trans2(
3937 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3938 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3939 EXPECT_EQ(ERR_IO_PENDING, rv);
3941 // The second connect and request, each of their responses, and the body.
3942 spdy_data.RunFor(5);
3943 rv = callback.WaitForResult();
3944 EXPECT_EQ(OK, rv);
3946 LoadTimingInfo load_timing_info2;
3947 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3948 // Even though the SPDY connection is reused, a new tunnelled connection has
3949 // to be created, so the socket's load timing looks like a fresh connection.
3950 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3952 // The requests should have different IDs, since they each are using their own
3953 // separate stream.
3954 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3956 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3959 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3960 // HTTPS Proxy to the same server.
3961 TEST_P(HttpNetworkTransactionTest,
3962 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3963 // Configure against https proxy server "proxy:70".
3964 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3965 "https://proxy:70"));
3966 BoundTestNetLog log;
3967 session_deps_.net_log = log.bound().net_log();
3968 scoped_refptr<HttpNetworkSession> session(
3969 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3971 HttpRequestInfo request1;
3972 request1.method = "GET";
3973 request1.url = GURL("https://www.example.org/");
3974 request1.load_flags = 0;
3976 HttpRequestInfo request2;
3977 request2.method = "GET";
3978 request2.url = GURL("https://www.example.org/2");
3979 request2.load_flags = 0;
3981 // CONNECT to www.example.org:443 via SPDY.
3982 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
3983 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
3984 scoped_ptr<SpdyFrame> conn_resp1(
3985 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3987 // Fetch https://www.example.org/ via HTTP.
3988 const char get1[] =
3989 "GET / HTTP/1.1\r\n"
3990 "Host: www.example.org\r\n"
3991 "Connection: keep-alive\r\n\r\n";
3992 scoped_ptr<SpdyFrame> wrapped_get1(
3993 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3994 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3995 "Content-Length: 1\r\n\r\n";
3996 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3997 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3998 scoped_ptr<SpdyFrame> wrapped_body1(
3999 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
4000 scoped_ptr<SpdyFrame> window_update(
4001 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
4003 // Fetch https://www.example.org/2 via HTTP.
4004 const char get2[] =
4005 "GET /2 HTTP/1.1\r\n"
4006 "Host: www.example.org\r\n"
4007 "Connection: keep-alive\r\n\r\n";
4008 scoped_ptr<SpdyFrame> wrapped_get2(
4009 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
4010 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4011 "Content-Length: 2\r\n\r\n";
4012 scoped_ptr<SpdyFrame> wrapped_get_resp2(
4013 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
4014 scoped_ptr<SpdyFrame> wrapped_body2(
4015 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
4017 MockWrite spdy_writes[] = {
4018 CreateMockWrite(*connect1, 0),
4019 CreateMockWrite(*wrapped_get1, 2),
4020 CreateMockWrite(*wrapped_get2, 5),
4023 MockRead spdy_reads[] = {
4024 CreateMockRead(*conn_resp1, 1, ASYNC),
4025 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4026 CreateMockRead(*wrapped_body1, 4, ASYNC),
4027 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4028 CreateMockRead(*wrapped_body2, 7, ASYNC),
4029 MockRead(ASYNC, 0, 8),
4032 DeterministicSocketData spdy_data(
4033 spdy_reads, arraysize(spdy_reads),
4034 spdy_writes, arraysize(spdy_writes));
4035 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
4037 SSLSocketDataProvider ssl(ASYNC, OK);
4038 ssl.SetNextProto(GetParam());
4039 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
4040 SSLSocketDataProvider ssl2(ASYNC, OK);
4041 ssl2.was_npn_negotiated = false;
4042 ssl2.protocol_negotiated = kProtoUnknown;
4043 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
4045 TestCompletionCallback callback;
4047 scoped_ptr<HttpTransaction> trans(
4048 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4049 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4050 EXPECT_EQ(ERR_IO_PENDING, rv);
4051 // The first connect and request, each of their responses, and the body.
4052 spdy_data.RunFor(5);
4054 rv = callback.WaitForResult();
4055 EXPECT_EQ(OK, rv);
4057 LoadTimingInfo load_timing_info;
4058 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4059 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4061 const HttpResponseInfo* response = trans->GetResponseInfo();
4062 ASSERT_TRUE(response != NULL);
4063 ASSERT_TRUE(response->headers.get() != NULL);
4064 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4066 std::string response_data;
4067 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4068 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
4069 trans.reset();
4071 scoped_ptr<HttpTransaction> trans2(
4072 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4073 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4074 EXPECT_EQ(ERR_IO_PENDING, rv);
4076 // The second request, response, and body. There should not be a second
4077 // connect.
4078 spdy_data.RunFor(3);
4079 rv = callback.WaitForResult();
4080 EXPECT_EQ(OK, rv);
4082 LoadTimingInfo load_timing_info2;
4083 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4084 TestLoadTimingReused(load_timing_info2);
4086 // The requests should have the same ID.
4087 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4089 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
4092 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4093 // Proxy to different servers.
4094 TEST_P(HttpNetworkTransactionTest,
4095 HttpsProxySpdyLoadTimingTwoHttpRequests) {
4096 // Configure against https proxy server "proxy:70".
4097 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
4098 "https://proxy:70"));
4099 BoundTestNetLog log;
4100 session_deps_.net_log = log.bound().net_log();
4101 scoped_refptr<HttpNetworkSession> session(
4102 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
4104 HttpRequestInfo request1;
4105 request1.method = "GET";
4106 request1.url = GURL("http://www.example.org/");
4107 request1.load_flags = 0;
4109 HttpRequestInfo request2;
4110 request2.method = "GET";
4111 request2.url = GURL("http://mail.example.org/");
4112 request2.load_flags = 0;
4114 // http://www.example.org/
4115 scoped_ptr<SpdyHeaderBlock> headers(
4116 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4117 scoped_ptr<SpdyFrame> get1(
4118 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4119 scoped_ptr<SpdyFrame> get_resp1(
4120 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4121 scoped_ptr<SpdyFrame> body1(
4122 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
4124 // http://mail.example.org/
4125 scoped_ptr<SpdyHeaderBlock> headers2(
4126 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4127 scoped_ptr<SpdyFrame> get2(
4128 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
4129 scoped_ptr<SpdyFrame> get_resp2(
4130 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4131 scoped_ptr<SpdyFrame> body2(
4132 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
4134 MockWrite spdy_writes[] = {
4135 CreateMockWrite(*get1, 0),
4136 CreateMockWrite(*get2, 3),
4139 MockRead spdy_reads[] = {
4140 CreateMockRead(*get_resp1, 1, ASYNC),
4141 CreateMockRead(*body1, 2, ASYNC),
4142 CreateMockRead(*get_resp2, 4, ASYNC),
4143 CreateMockRead(*body2, 5, ASYNC),
4144 MockRead(ASYNC, 0, 6),
4147 DeterministicSocketData spdy_data(
4148 spdy_reads, arraysize(spdy_reads),
4149 spdy_writes, arraysize(spdy_writes));
4150 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
4152 SSLSocketDataProvider ssl(ASYNC, OK);
4153 ssl.SetNextProto(GetParam());
4154 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
4156 TestCompletionCallback callback;
4158 scoped_ptr<HttpTransaction> trans(
4159 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4160 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4161 EXPECT_EQ(ERR_IO_PENDING, rv);
4162 spdy_data.RunFor(2);
4164 rv = callback.WaitForResult();
4165 EXPECT_EQ(OK, rv);
4167 LoadTimingInfo load_timing_info;
4168 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4169 TestLoadTimingNotReused(load_timing_info,
4170 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4172 const HttpResponseInfo* response = trans->GetResponseInfo();
4173 ASSERT_TRUE(response != NULL);
4174 ASSERT_TRUE(response->headers.get() != NULL);
4175 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4177 std::string response_data;
4178 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
4179 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
4180 spdy_data.RunFor(1);
4181 EXPECT_EQ(1, callback.WaitForResult());
4182 // Delete the first request, so the second one can reuse the socket.
4183 trans.reset();
4185 scoped_ptr<HttpTransaction> trans2(
4186 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4187 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4188 EXPECT_EQ(ERR_IO_PENDING, rv);
4190 spdy_data.RunFor(2);
4191 rv = callback.WaitForResult();
4192 EXPECT_EQ(OK, rv);
4194 LoadTimingInfo load_timing_info2;
4195 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4196 TestLoadTimingReused(load_timing_info2);
4198 // The requests should have the same ID.
4199 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4201 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
4202 spdy_data.RunFor(1);
4203 EXPECT_EQ(2, callback.WaitForResult());
4206 // Test the challenge-response-retry sequence through an HTTPS Proxy
4207 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
4208 HttpRequestInfo request;
4209 request.method = "GET";
4210 request.url = GURL("http://www.example.org/");
4211 // when the no authentication data flag is set.
4212 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
4214 // Configure against https proxy server "myproxy:70".
4215 session_deps_.proxy_service.reset(
4216 ProxyService::CreateFixed("https://myproxy:70"));
4217 BoundTestNetLog log;
4218 session_deps_.net_log = log.bound().net_log();
4219 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4221 // Since we have proxy, should use full url
4222 MockWrite data_writes1[] = {
4223 MockWrite(
4224 "GET http://www.example.org/ HTTP/1.1\r\n"
4225 "Host: www.example.org\r\n"
4226 "Proxy-Connection: keep-alive\r\n\r\n"),
4228 // After calling trans->RestartWithAuth(), this is the request we should
4229 // be issuing -- the final header line contains the credentials.
4230 MockWrite(
4231 "GET http://www.example.org/ HTTP/1.1\r\n"
4232 "Host: www.example.org\r\n"
4233 "Proxy-Connection: keep-alive\r\n"
4234 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4237 // The proxy responds to the GET with a 407, using a persistent
4238 // connection.
4239 MockRead data_reads1[] = {
4240 // No credentials.
4241 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4242 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4243 MockRead("Proxy-Connection: keep-alive\r\n"),
4244 MockRead("Content-Length: 0\r\n\r\n"),
4246 MockRead("HTTP/1.1 200 OK\r\n"),
4247 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4248 MockRead("Content-Length: 100\r\n\r\n"),
4249 MockRead(SYNCHRONOUS, OK),
4252 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4253 data_writes1, arraysize(data_writes1));
4254 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4255 SSLSocketDataProvider ssl(ASYNC, OK);
4256 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4258 TestCompletionCallback callback1;
4260 scoped_ptr<HttpTransaction> trans(
4261 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4263 int rv = trans->Start(&request, callback1.callback(), log.bound());
4264 EXPECT_EQ(ERR_IO_PENDING, rv);
4266 rv = callback1.WaitForResult();
4267 EXPECT_EQ(OK, rv);
4269 LoadTimingInfo load_timing_info;
4270 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4271 TestLoadTimingNotReused(load_timing_info,
4272 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4274 const HttpResponseInfo* response = trans->GetResponseInfo();
4275 ASSERT_TRUE(response != NULL);
4276 ASSERT_FALSE(response->headers.get() == NULL);
4277 EXPECT_EQ(407, response->headers->response_code());
4278 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4279 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4281 TestCompletionCallback callback2;
4283 rv = trans->RestartWithAuth(
4284 AuthCredentials(kFoo, kBar), callback2.callback());
4285 EXPECT_EQ(ERR_IO_PENDING, rv);
4287 rv = callback2.WaitForResult();
4288 EXPECT_EQ(OK, rv);
4290 load_timing_info = LoadTimingInfo();
4291 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4292 // Retrying with HTTP AUTH is considered to be reusing a socket.
4293 TestLoadTimingReused(load_timing_info);
4295 response = trans->GetResponseInfo();
4296 ASSERT_TRUE(response != NULL);
4298 EXPECT_TRUE(response->headers->IsKeepAlive());
4299 EXPECT_EQ(200, response->headers->response_code());
4300 EXPECT_EQ(100, response->headers->GetContentLength());
4301 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4303 // The password prompt info should not be set.
4304 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4307 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4308 const MockRead& status, int expected_status) {
4309 HttpRequestInfo request;
4310 request.method = "GET";
4311 request.url = GURL("https://www.example.org/");
4312 request.load_flags = 0;
4314 // Configure against proxy server "myproxy:70".
4315 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4316 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4318 // Since we have proxy, should try to establish tunnel.
4319 MockWrite data_writes[] = {
4320 MockWrite(
4321 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4322 "Host: www.example.org\r\n"
4323 "Proxy-Connection: keep-alive\r\n\r\n"),
4326 MockRead data_reads[] = {
4327 status,
4328 MockRead("Content-Length: 10\r\n\r\n"),
4329 // No response body because the test stops reading here.
4330 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4333 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4334 data_writes, arraysize(data_writes));
4335 session_deps_.socket_factory->AddSocketDataProvider(&data);
4337 TestCompletionCallback callback;
4339 scoped_ptr<HttpTransaction> trans(
4340 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4342 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4343 EXPECT_EQ(ERR_IO_PENDING, rv);
4345 rv = callback.WaitForResult();
4346 EXPECT_EQ(expected_status, rv);
4349 void HttpNetworkTransactionTest::ConnectStatusHelper(
4350 const MockRead& status) {
4351 ConnectStatusHelperWithExpectedStatus(
4352 status, ERR_TUNNEL_CONNECTION_FAILED);
4355 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4356 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4359 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4360 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4363 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4364 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4367 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4368 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4371 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4372 ConnectStatusHelper(
4373 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4376 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4377 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4380 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4381 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4384 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4385 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4388 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4389 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4392 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4393 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4396 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4397 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4400 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4401 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4404 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4405 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4408 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4409 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4412 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4413 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4416 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4417 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4420 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4421 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4424 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4425 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4428 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4429 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4432 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4433 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4436 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4437 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4440 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4441 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4444 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4445 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4448 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4449 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4452 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4453 ConnectStatusHelperWithExpectedStatus(
4454 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4455 ERR_PROXY_AUTH_UNSUPPORTED);
4458 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4459 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4462 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4463 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4466 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4467 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4470 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4471 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4474 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4475 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4478 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4479 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4482 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4483 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4486 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4487 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4490 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4491 ConnectStatusHelper(
4492 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4495 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4496 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4499 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4500 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4503 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4504 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4507 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4508 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4511 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4512 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4515 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4516 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4519 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4520 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4523 // Test the flow when both the proxy server AND origin server require
4524 // authentication. Again, this uses basic auth for both since that is
4525 // the simplest to mock.
4526 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4527 HttpRequestInfo request;
4528 request.method = "GET";
4529 request.url = GURL("http://www.example.org/");
4530 request.load_flags = 0;
4532 // Configure against proxy server "myproxy:70".
4533 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4534 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4536 scoped_ptr<HttpTransaction> trans(
4537 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4539 MockWrite data_writes1[] = {
4540 MockWrite(
4541 "GET http://www.example.org/ HTTP/1.1\r\n"
4542 "Host: www.example.org\r\n"
4543 "Proxy-Connection: keep-alive\r\n\r\n"),
4546 MockRead data_reads1[] = {
4547 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4548 // Give a couple authenticate options (only the middle one is actually
4549 // supported).
4550 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4551 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4552 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4553 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4554 // Large content-length -- won't matter, as connection will be reset.
4555 MockRead("Content-Length: 10000\r\n\r\n"),
4556 MockRead(SYNCHRONOUS, ERR_FAILED),
4559 // After calling trans->RestartWithAuth() the first time, this is the
4560 // request we should be issuing -- the final header line contains the
4561 // proxy's credentials.
4562 MockWrite data_writes2[] = {
4563 MockWrite(
4564 "GET http://www.example.org/ HTTP/1.1\r\n"
4565 "Host: www.example.org\r\n"
4566 "Proxy-Connection: keep-alive\r\n"
4567 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4570 // Now the proxy server lets the request pass through to origin server.
4571 // The origin server responds with a 401.
4572 MockRead data_reads2[] = {
4573 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4574 // Note: We are using the same realm-name as the proxy server. This is
4575 // completely valid, as realms are unique across hosts.
4576 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4577 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4578 MockRead("Content-Length: 2000\r\n\r\n"),
4579 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4582 // After calling trans->RestartWithAuth() the second time, we should send
4583 // the credentials for both the proxy and origin server.
4584 MockWrite data_writes3[] = {
4585 MockWrite(
4586 "GET http://www.example.org/ HTTP/1.1\r\n"
4587 "Host: www.example.org\r\n"
4588 "Proxy-Connection: keep-alive\r\n"
4589 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4590 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4593 // Lastly we get the desired content.
4594 MockRead data_reads3[] = {
4595 MockRead("HTTP/1.0 200 OK\r\n"),
4596 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4597 MockRead("Content-Length: 100\r\n\r\n"),
4598 MockRead(SYNCHRONOUS, OK),
4601 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4602 data_writes1, arraysize(data_writes1));
4603 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4604 data_writes2, arraysize(data_writes2));
4605 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4606 data_writes3, arraysize(data_writes3));
4607 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4608 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4609 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4611 TestCompletionCallback callback1;
4613 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4614 EXPECT_EQ(ERR_IO_PENDING, rv);
4616 rv = callback1.WaitForResult();
4617 EXPECT_EQ(OK, rv);
4619 const HttpResponseInfo* response = trans->GetResponseInfo();
4620 ASSERT_TRUE(response != NULL);
4621 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4623 TestCompletionCallback callback2;
4625 rv = trans->RestartWithAuth(
4626 AuthCredentials(kFoo, kBar), callback2.callback());
4627 EXPECT_EQ(ERR_IO_PENDING, rv);
4629 rv = callback2.WaitForResult();
4630 EXPECT_EQ(OK, rv);
4632 response = trans->GetResponseInfo();
4633 ASSERT_TRUE(response != NULL);
4634 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4636 TestCompletionCallback callback3;
4638 rv = trans->RestartWithAuth(
4639 AuthCredentials(kFoo2, kBar2), callback3.callback());
4640 EXPECT_EQ(ERR_IO_PENDING, rv);
4642 rv = callback3.WaitForResult();
4643 EXPECT_EQ(OK, rv);
4645 response = trans->GetResponseInfo();
4646 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4647 EXPECT_EQ(100, response->headers->GetContentLength());
4650 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4651 // can't hook into its internals to cause it to generate predictable NTLM
4652 // authorization headers.
4653 #if defined(NTLM_PORTABLE)
4654 // The NTLM authentication unit tests were generated by capturing the HTTP
4655 // requests and responses using Fiddler 2 and inspecting the generated random
4656 // bytes in the debugger.
4658 // Enter the correct password and authenticate successfully.
4659 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4660 HttpRequestInfo request;
4661 request.method = "GET";
4662 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4664 // Ensure load is not disrupted by flags which suppress behaviour specific
4665 // to other auth schemes.
4666 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4668 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4669 MockGetHostName);
4670 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4672 MockWrite data_writes1[] = {
4673 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4674 "Host: 172.22.68.17\r\n"
4675 "Connection: keep-alive\r\n\r\n"),
4678 MockRead data_reads1[] = {
4679 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4680 // Negotiate and NTLM are often requested together. However, we only want
4681 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4682 // the header that requests Negotiate for this test.
4683 MockRead("WWW-Authenticate: NTLM\r\n"),
4684 MockRead("Connection: close\r\n"),
4685 MockRead("Content-Length: 42\r\n"),
4686 MockRead("Content-Type: text/html\r\n\r\n"),
4687 // Missing content -- won't matter, as connection will be reset.
4688 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4691 MockWrite data_writes2[] = {
4692 // After restarting with a null identity, this is the
4693 // request we should be issuing -- the final header line contains a Type
4694 // 1 message.
4695 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4696 "Host: 172.22.68.17\r\n"
4697 "Connection: keep-alive\r\n"
4698 "Authorization: NTLM "
4699 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4701 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4702 // (the credentials for the origin server). The second request continues
4703 // on the same connection.
4704 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4705 "Host: 172.22.68.17\r\n"
4706 "Connection: keep-alive\r\n"
4707 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4708 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4709 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4710 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4711 "ahlhx5I=\r\n\r\n"),
4714 MockRead data_reads2[] = {
4715 // The origin server responds with a Type 2 message.
4716 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4717 MockRead("WWW-Authenticate: NTLM "
4718 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4719 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4720 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4721 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4722 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4723 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4724 "BtAAAAAAA=\r\n"),
4725 MockRead("Content-Length: 42\r\n"),
4726 MockRead("Content-Type: text/html\r\n\r\n"),
4727 MockRead("You are not authorized to view this page\r\n"),
4729 // Lastly we get the desired content.
4730 MockRead("HTTP/1.1 200 OK\r\n"),
4731 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4732 MockRead("Content-Length: 13\r\n\r\n"),
4733 MockRead("Please Login\r\n"),
4734 MockRead(SYNCHRONOUS, OK),
4737 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4738 data_writes1, arraysize(data_writes1));
4739 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4740 data_writes2, arraysize(data_writes2));
4741 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4742 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4744 TestCompletionCallback callback1;
4746 scoped_ptr<HttpTransaction> trans(
4747 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4749 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4750 EXPECT_EQ(ERR_IO_PENDING, rv);
4752 rv = callback1.WaitForResult();
4753 EXPECT_EQ(OK, rv);
4755 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4757 const HttpResponseInfo* response = trans->GetResponseInfo();
4758 ASSERT_FALSE(response == NULL);
4759 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4761 TestCompletionCallback callback2;
4763 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4764 callback2.callback());
4765 EXPECT_EQ(ERR_IO_PENDING, rv);
4767 rv = callback2.WaitForResult();
4768 EXPECT_EQ(OK, rv);
4770 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4772 response = trans->GetResponseInfo();
4773 ASSERT_TRUE(response != NULL);
4774 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4776 TestCompletionCallback callback3;
4778 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4779 EXPECT_EQ(ERR_IO_PENDING, rv);
4781 rv = callback3.WaitForResult();
4782 EXPECT_EQ(OK, rv);
4784 response = trans->GetResponseInfo();
4785 ASSERT_TRUE(response != NULL);
4786 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4787 EXPECT_EQ(13, response->headers->GetContentLength());
4790 // Enter a wrong password, and then the correct one.
4791 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4792 HttpRequestInfo request;
4793 request.method = "GET";
4794 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4795 request.load_flags = 0;
4797 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4798 MockGetHostName);
4799 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4801 MockWrite data_writes1[] = {
4802 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4803 "Host: 172.22.68.17\r\n"
4804 "Connection: keep-alive\r\n\r\n"),
4807 MockRead data_reads1[] = {
4808 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4809 // Negotiate and NTLM are often requested together. However, we only want
4810 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4811 // the header that requests Negotiate for this test.
4812 MockRead("WWW-Authenticate: NTLM\r\n"),
4813 MockRead("Connection: close\r\n"),
4814 MockRead("Content-Length: 42\r\n"),
4815 MockRead("Content-Type: text/html\r\n\r\n"),
4816 // Missing content -- won't matter, as connection will be reset.
4817 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4820 MockWrite data_writes2[] = {
4821 // After restarting with a null identity, this is the
4822 // request we should be issuing -- the final header line contains a Type
4823 // 1 message.
4824 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4825 "Host: 172.22.68.17\r\n"
4826 "Connection: keep-alive\r\n"
4827 "Authorization: NTLM "
4828 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4830 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4831 // (the credentials for the origin server). The second request continues
4832 // on the same connection.
4833 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4834 "Host: 172.22.68.17\r\n"
4835 "Connection: keep-alive\r\n"
4836 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4837 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4838 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4839 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4840 "4Ww7b7E=\r\n\r\n"),
4843 MockRead data_reads2[] = {
4844 // The origin server responds with a Type 2 message.
4845 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4846 MockRead("WWW-Authenticate: NTLM "
4847 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4848 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4849 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4850 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4851 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4852 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4853 "BtAAAAAAA=\r\n"),
4854 MockRead("Content-Length: 42\r\n"),
4855 MockRead("Content-Type: text/html\r\n\r\n"),
4856 MockRead("You are not authorized to view this page\r\n"),
4858 // Wrong password.
4859 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4860 MockRead("WWW-Authenticate: NTLM\r\n"),
4861 MockRead("Connection: close\r\n"),
4862 MockRead("Content-Length: 42\r\n"),
4863 MockRead("Content-Type: text/html\r\n\r\n"),
4864 // Missing content -- won't matter, as connection will be reset.
4865 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4868 MockWrite data_writes3[] = {
4869 // After restarting with a null identity, this is the
4870 // request we should be issuing -- the final header line contains a Type
4871 // 1 message.
4872 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4873 "Host: 172.22.68.17\r\n"
4874 "Connection: keep-alive\r\n"
4875 "Authorization: NTLM "
4876 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4878 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4879 // (the credentials for the origin server). The second request continues
4880 // on the same connection.
4881 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4882 "Host: 172.22.68.17\r\n"
4883 "Connection: keep-alive\r\n"
4884 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4885 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4886 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4887 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4888 "+4MUm7c=\r\n\r\n"),
4891 MockRead data_reads3[] = {
4892 // The origin server responds with a Type 2 message.
4893 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4894 MockRead("WWW-Authenticate: NTLM "
4895 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4896 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4897 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4898 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4899 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4900 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4901 "BtAAAAAAA=\r\n"),
4902 MockRead("Content-Length: 42\r\n"),
4903 MockRead("Content-Type: text/html\r\n\r\n"),
4904 MockRead("You are not authorized to view this page\r\n"),
4906 // Lastly we get the desired content.
4907 MockRead("HTTP/1.1 200 OK\r\n"),
4908 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4909 MockRead("Content-Length: 13\r\n\r\n"),
4910 MockRead("Please Login\r\n"),
4911 MockRead(SYNCHRONOUS, OK),
4914 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4915 data_writes1, arraysize(data_writes1));
4916 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4917 data_writes2, arraysize(data_writes2));
4918 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4919 data_writes3, arraysize(data_writes3));
4920 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4921 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4922 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4924 TestCompletionCallback callback1;
4926 scoped_ptr<HttpTransaction> trans(
4927 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4929 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4930 EXPECT_EQ(ERR_IO_PENDING, rv);
4932 rv = callback1.WaitForResult();
4933 EXPECT_EQ(OK, rv);
4935 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4937 const HttpResponseInfo* response = trans->GetResponseInfo();
4938 ASSERT_TRUE(response != NULL);
4939 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4941 TestCompletionCallback callback2;
4943 // Enter the wrong password.
4944 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4945 callback2.callback());
4946 EXPECT_EQ(ERR_IO_PENDING, rv);
4948 rv = callback2.WaitForResult();
4949 EXPECT_EQ(OK, rv);
4951 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4952 TestCompletionCallback callback3;
4953 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4954 EXPECT_EQ(ERR_IO_PENDING, rv);
4955 rv = callback3.WaitForResult();
4956 EXPECT_EQ(OK, rv);
4957 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4959 response = trans->GetResponseInfo();
4960 ASSERT_FALSE(response == NULL);
4961 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4963 TestCompletionCallback callback4;
4965 // Now enter the right password.
4966 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4967 callback4.callback());
4968 EXPECT_EQ(ERR_IO_PENDING, rv);
4970 rv = callback4.WaitForResult();
4971 EXPECT_EQ(OK, rv);
4973 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4975 TestCompletionCallback callback5;
4977 // One more roundtrip
4978 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4979 EXPECT_EQ(ERR_IO_PENDING, rv);
4981 rv = callback5.WaitForResult();
4982 EXPECT_EQ(OK, rv);
4984 response = trans->GetResponseInfo();
4985 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4986 EXPECT_EQ(13, response->headers->GetContentLength());
4988 #endif // NTLM_PORTABLE
4990 // Test reading a server response which has only headers, and no body.
4991 // After some maximum number of bytes is consumed, the transaction should
4992 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4993 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4994 HttpRequestInfo request;
4995 request.method = "GET";
4996 request.url = GURL("http://www.example.org/");
4997 request.load_flags = 0;
4999 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5000 scoped_ptr<HttpTransaction> trans(
5001 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5003 // Respond with 300 kb of headers (we should fail after 256 kb).
5004 std::string large_headers_string;
5005 FillLargeHeadersString(&large_headers_string, 300 * 1024);
5007 MockRead data_reads[] = {
5008 MockRead("HTTP/1.0 200 OK\r\n"),
5009 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
5010 MockRead("\r\nBODY"),
5011 MockRead(SYNCHRONOUS, OK),
5013 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5014 session_deps_.socket_factory->AddSocketDataProvider(&data);
5016 TestCompletionCallback callback;
5018 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5019 EXPECT_EQ(ERR_IO_PENDING, rv);
5021 rv = callback.WaitForResult();
5022 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
5024 const HttpResponseInfo* response = trans->GetResponseInfo();
5025 EXPECT_TRUE(response == NULL);
5028 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5029 // establish tunnel.
5030 // http://code.google.com/p/chromium/issues/detail?id=3772
5031 TEST_P(HttpNetworkTransactionTest,
5032 DontRecycleTransportSocketForSSLTunnel) {
5033 HttpRequestInfo request;
5034 request.method = "GET";
5035 request.url = GURL("https://www.example.org/");
5036 request.load_flags = 0;
5038 // Configure against proxy server "myproxy:70".
5039 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5041 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5043 scoped_ptr<HttpTransaction> trans(
5044 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5046 // Since we have proxy, should try to establish tunnel.
5047 MockWrite data_writes1[] = {
5048 MockWrite(
5049 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5050 "Host: www.example.org\r\n"
5051 "Proxy-Connection: keep-alive\r\n\r\n"),
5054 // The proxy responds to the connect with a 404, using a persistent
5055 // connection. Usually a proxy would return 501 (not implemented),
5056 // or 200 (tunnel established).
5057 MockRead data_reads1[] = {
5058 MockRead("HTTP/1.1 404 Not Found\r\n"),
5059 MockRead("Content-Length: 10\r\n\r\n"),
5060 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
5063 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5064 data_writes1, arraysize(data_writes1));
5065 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5067 TestCompletionCallback callback1;
5069 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5070 EXPECT_EQ(ERR_IO_PENDING, rv);
5072 rv = callback1.WaitForResult();
5073 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5075 const HttpResponseInfo* response = trans->GetResponseInfo();
5076 EXPECT_TRUE(response == NULL);
5078 // Empty the current queue. This is necessary because idle sockets are
5079 // added to the connection pool asynchronously with a PostTask.
5080 base::MessageLoop::current()->RunUntilIdle();
5082 // We now check to make sure the TCPClientSocket was not added back to
5083 // the pool.
5084 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5085 trans.reset();
5086 base::MessageLoop::current()->RunUntilIdle();
5087 // Make sure that the socket didn't get recycled after calling the destructor.
5088 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5091 // Make sure that we recycle a socket after reading all of the response body.
5092 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
5093 HttpRequestInfo request;
5094 request.method = "GET";
5095 request.url = GURL("http://www.example.org/");
5096 request.load_flags = 0;
5098 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5100 scoped_ptr<HttpTransaction> trans(
5101 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5103 MockRead data_reads[] = {
5104 // A part of the response body is received with the response headers.
5105 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5106 // The rest of the response body is received in two parts.
5107 MockRead("lo"),
5108 MockRead(" world"),
5109 MockRead("junk"), // Should not be read!!
5110 MockRead(SYNCHRONOUS, OK),
5113 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5114 session_deps_.socket_factory->AddSocketDataProvider(&data);
5116 TestCompletionCallback callback;
5118 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5119 EXPECT_EQ(ERR_IO_PENDING, rv);
5121 rv = callback.WaitForResult();
5122 EXPECT_EQ(OK, rv);
5124 const HttpResponseInfo* response = trans->GetResponseInfo();
5125 ASSERT_TRUE(response != NULL);
5127 EXPECT_TRUE(response->headers.get() != NULL);
5128 std::string status_line = response->headers->GetStatusLine();
5129 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5131 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5133 std::string response_data;
5134 rv = ReadTransaction(trans.get(), &response_data);
5135 EXPECT_EQ(OK, rv);
5136 EXPECT_EQ("hello world", response_data);
5138 // Empty the current queue. This is necessary because idle sockets are
5139 // added to the connection pool asynchronously with a PostTask.
5140 base::MessageLoop::current()->RunUntilIdle();
5142 // We now check to make sure the socket was added back to the pool.
5143 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5146 // Make sure that we recycle a SSL socket after reading all of the response
5147 // body.
5148 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
5149 HttpRequestInfo request;
5150 request.method = "GET";
5151 request.url = GURL("https://www.example.org/");
5152 request.load_flags = 0;
5154 MockWrite data_writes[] = {
5155 MockWrite(
5156 "GET / HTTP/1.1\r\n"
5157 "Host: www.example.org\r\n"
5158 "Connection: keep-alive\r\n\r\n"),
5161 MockRead data_reads[] = {
5162 MockRead("HTTP/1.1 200 OK\r\n"),
5163 MockRead("Content-Length: 11\r\n\r\n"),
5164 MockRead("hello world"),
5165 MockRead(SYNCHRONOUS, OK),
5168 SSLSocketDataProvider ssl(ASYNC, OK);
5169 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5171 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5172 data_writes, arraysize(data_writes));
5173 session_deps_.socket_factory->AddSocketDataProvider(&data);
5175 TestCompletionCallback callback;
5177 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5178 scoped_ptr<HttpTransaction> trans(
5179 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5181 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5183 EXPECT_EQ(ERR_IO_PENDING, rv);
5184 EXPECT_EQ(OK, callback.WaitForResult());
5186 const HttpResponseInfo* response = trans->GetResponseInfo();
5187 ASSERT_TRUE(response != NULL);
5188 ASSERT_TRUE(response->headers.get() != NULL);
5189 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5191 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5193 std::string response_data;
5194 rv = ReadTransaction(trans.get(), &response_data);
5195 EXPECT_EQ(OK, rv);
5196 EXPECT_EQ("hello world", response_data);
5198 // Empty the current queue. This is necessary because idle sockets are
5199 // added to the connection pool asynchronously with a PostTask.
5200 base::MessageLoop::current()->RunUntilIdle();
5202 // We now check to make sure the socket was added back to the pool.
5203 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5206 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5207 // from the pool and make sure that we recover okay.
5208 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
5209 HttpRequestInfo request;
5210 request.method = "GET";
5211 request.url = GURL("https://www.example.org/");
5212 request.load_flags = 0;
5214 MockWrite data_writes[] = {
5215 MockWrite(
5216 "GET / HTTP/1.1\r\n"
5217 "Host: www.example.org\r\n"
5218 "Connection: keep-alive\r\n\r\n"),
5219 MockWrite(
5220 "GET / HTTP/1.1\r\n"
5221 "Host: www.example.org\r\n"
5222 "Connection: keep-alive\r\n\r\n"),
5225 MockRead data_reads[] = {
5226 MockRead("HTTP/1.1 200 OK\r\n"),
5227 MockRead("Content-Length: 11\r\n\r\n"),
5228 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
5229 MockRead("hello world"),
5230 MockRead(ASYNC, 0, 0) // EOF
5233 SSLSocketDataProvider ssl(ASYNC, OK);
5234 SSLSocketDataProvider ssl2(ASYNC, OK);
5235 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5236 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5238 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5239 data_writes, arraysize(data_writes));
5240 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5241 data_writes, arraysize(data_writes));
5242 session_deps_.socket_factory->AddSocketDataProvider(&data);
5243 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5245 TestCompletionCallback callback;
5247 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5248 scoped_ptr<HttpTransaction> trans(
5249 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5251 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5253 EXPECT_EQ(ERR_IO_PENDING, rv);
5254 EXPECT_EQ(OK, callback.WaitForResult());
5256 const HttpResponseInfo* response = trans->GetResponseInfo();
5257 ASSERT_TRUE(response != NULL);
5258 ASSERT_TRUE(response->headers.get() != NULL);
5259 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5261 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5263 std::string response_data;
5264 rv = ReadTransaction(trans.get(), &response_data);
5265 EXPECT_EQ(OK, rv);
5266 EXPECT_EQ("hello world", response_data);
5268 // Empty the current queue. This is necessary because idle sockets are
5269 // added to the connection pool asynchronously with a PostTask.
5270 base::MessageLoop::current()->RunUntilIdle();
5272 // We now check to make sure the socket was added back to the pool.
5273 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5275 // Now start the second transaction, which should reuse the previous socket.
5277 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5279 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5281 EXPECT_EQ(ERR_IO_PENDING, rv);
5282 EXPECT_EQ(OK, callback.WaitForResult());
5284 response = trans->GetResponseInfo();
5285 ASSERT_TRUE(response != NULL);
5286 ASSERT_TRUE(response->headers.get() != NULL);
5287 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5289 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5291 rv = ReadTransaction(trans.get(), &response_data);
5292 EXPECT_EQ(OK, rv);
5293 EXPECT_EQ("hello world", response_data);
5295 // Empty the current queue. This is necessary because idle sockets are
5296 // added to the connection pool asynchronously with a PostTask.
5297 base::MessageLoop::current()->RunUntilIdle();
5299 // We now check to make sure the socket was added back to the pool.
5300 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
5303 // Make sure that we recycle a socket after a zero-length response.
5304 // http://crbug.com/9880
5305 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
5306 HttpRequestInfo request;
5307 request.method = "GET";
5308 request.url = GURL(
5309 "http://www.example.org/csi?v=3&s=web&action=&"
5310 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5311 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5312 "rt=prt.2642,ol.2649,xjs.2951");
5313 request.load_flags = 0;
5315 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5317 scoped_ptr<HttpTransaction> trans(
5318 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5320 MockRead data_reads[] = {
5321 MockRead("HTTP/1.1 204 No Content\r\n"
5322 "Content-Length: 0\r\n"
5323 "Content-Type: text/html\r\n\r\n"),
5324 MockRead("junk"), // Should not be read!!
5325 MockRead(SYNCHRONOUS, OK),
5328 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5329 session_deps_.socket_factory->AddSocketDataProvider(&data);
5331 TestCompletionCallback callback;
5333 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5334 EXPECT_EQ(ERR_IO_PENDING, rv);
5336 rv = callback.WaitForResult();
5337 EXPECT_EQ(OK, rv);
5339 const HttpResponseInfo* response = trans->GetResponseInfo();
5340 ASSERT_TRUE(response != NULL);
5342 EXPECT_TRUE(response->headers.get() != NULL);
5343 std::string status_line = response->headers->GetStatusLine();
5344 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5346 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
5348 std::string response_data;
5349 rv = ReadTransaction(trans.get(), &response_data);
5350 EXPECT_EQ(OK, rv);
5351 EXPECT_EQ("", response_data);
5353 // Empty the current queue. This is necessary because idle sockets are
5354 // added to the connection pool asynchronously with a PostTask.
5355 base::MessageLoop::current()->RunUntilIdle();
5357 // We now check to make sure the socket was added back to the pool.
5358 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
5361 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
5362 ScopedVector<UploadElementReader> element_readers;
5363 element_readers.push_back(new UploadBytesElementReader("foo", 3));
5364 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
5366 HttpRequestInfo request[2];
5367 // Transaction 1: a GET request that succeeds. The socket is recycled
5368 // after use.
5369 request[0].method = "GET";
5370 request[0].url = GURL("http://www.google.com/");
5371 request[0].load_flags = 0;
5372 // Transaction 2: a POST request. Reuses the socket kept alive from
5373 // transaction 1. The first attempts fails when writing the POST data.
5374 // This causes the transaction to retry with a new socket. The second
5375 // attempt succeeds.
5376 request[1].method = "POST";
5377 request[1].url = GURL("http://www.google.com/login.cgi");
5378 request[1].upload_data_stream = &upload_data_stream;
5379 request[1].load_flags = 0;
5381 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5383 // The first socket is used for transaction 1 and the first attempt of
5384 // transaction 2.
5386 // The response of transaction 1.
5387 MockRead data_reads1[] = {
5388 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5389 MockRead("hello world"),
5390 MockRead(SYNCHRONOUS, OK),
5392 // The mock write results of transaction 1 and the first attempt of
5393 // transaction 2.
5394 MockWrite data_writes1[] = {
5395 MockWrite(SYNCHRONOUS, 64), // GET
5396 MockWrite(SYNCHRONOUS, 93), // POST
5397 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5399 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5400 data_writes1, arraysize(data_writes1));
5402 // The second socket is used for the second attempt of transaction 2.
5404 // The response of transaction 2.
5405 MockRead data_reads2[] = {
5406 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5407 MockRead("welcome"),
5408 MockRead(SYNCHRONOUS, OK),
5410 // The mock write results of the second attempt of transaction 2.
5411 MockWrite data_writes2[] = {
5412 MockWrite(SYNCHRONOUS, 93), // POST
5413 MockWrite(SYNCHRONOUS, 3), // POST data
5415 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5416 data_writes2, arraysize(data_writes2));
5418 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5419 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5421 const char* const kExpectedResponseData[] = {
5422 "hello world", "welcome"
5425 for (int i = 0; i < 2; ++i) {
5426 scoped_ptr<HttpTransaction> trans(
5427 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5429 TestCompletionCallback callback;
5431 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5432 EXPECT_EQ(ERR_IO_PENDING, rv);
5434 rv = callback.WaitForResult();
5435 EXPECT_EQ(OK, rv);
5437 const HttpResponseInfo* response = trans->GetResponseInfo();
5438 ASSERT_TRUE(response != NULL);
5440 EXPECT_TRUE(response->headers.get() != NULL);
5441 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5443 std::string response_data;
5444 rv = ReadTransaction(trans.get(), &response_data);
5445 EXPECT_EQ(OK, rv);
5446 EXPECT_EQ(kExpectedResponseData[i], response_data);
5450 // Test the request-challenge-retry sequence for basic auth when there is
5451 // an identity in the URL. The request should be sent as normal, but when
5452 // it fails the identity from the URL is used to answer the challenge.
5453 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5454 HttpRequestInfo request;
5455 request.method = "GET";
5456 request.url = GURL("http://foo:b@r@www.example.org/");
5457 request.load_flags = LOAD_NORMAL;
5459 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5460 scoped_ptr<HttpTransaction> trans(
5461 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5463 // The password contains an escaped character -- for this test to pass it
5464 // will need to be unescaped by HttpNetworkTransaction.
5465 EXPECT_EQ("b%40r", request.url.password());
5467 MockWrite data_writes1[] = {
5468 MockWrite(
5469 "GET / HTTP/1.1\r\n"
5470 "Host: www.example.org\r\n"
5471 "Connection: keep-alive\r\n\r\n"),
5474 MockRead data_reads1[] = {
5475 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5476 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5477 MockRead("Content-Length: 10\r\n\r\n"),
5478 MockRead(SYNCHRONOUS, ERR_FAILED),
5481 // After the challenge above, the transaction will be restarted using the
5482 // identity from the url (foo, b@r) to answer the challenge.
5483 MockWrite data_writes2[] = {
5484 MockWrite(
5485 "GET / HTTP/1.1\r\n"
5486 "Host: www.example.org\r\n"
5487 "Connection: keep-alive\r\n"
5488 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5491 MockRead data_reads2[] = {
5492 MockRead("HTTP/1.0 200 OK\r\n"),
5493 MockRead("Content-Length: 100\r\n\r\n"),
5494 MockRead(SYNCHRONOUS, OK),
5497 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5498 data_writes1, arraysize(data_writes1));
5499 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5500 data_writes2, arraysize(data_writes2));
5501 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5502 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5504 TestCompletionCallback callback1;
5505 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5506 EXPECT_EQ(ERR_IO_PENDING, rv);
5507 rv = callback1.WaitForResult();
5508 EXPECT_EQ(OK, rv);
5509 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5511 TestCompletionCallback callback2;
5512 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5513 EXPECT_EQ(ERR_IO_PENDING, rv);
5514 rv = callback2.WaitForResult();
5515 EXPECT_EQ(OK, rv);
5516 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5518 const HttpResponseInfo* response = trans->GetResponseInfo();
5519 ASSERT_TRUE(response != NULL);
5521 // There is no challenge info, since the identity in URL worked.
5522 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5524 EXPECT_EQ(100, response->headers->GetContentLength());
5526 // Empty the current queue.
5527 base::MessageLoop::current()->RunUntilIdle();
5530 // Test the request-challenge-retry sequence for basic auth when there is an
5531 // incorrect identity in the URL. The identity from the URL should be used only
5532 // once.
5533 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5534 HttpRequestInfo request;
5535 request.method = "GET";
5536 // Note: the URL has a username:password in it. The password "baz" is
5537 // wrong (should be "bar").
5538 request.url = GURL("http://foo:baz@www.example.org/");
5540 request.load_flags = LOAD_NORMAL;
5542 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5543 scoped_ptr<HttpTransaction> trans(
5544 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5546 MockWrite data_writes1[] = {
5547 MockWrite(
5548 "GET / HTTP/1.1\r\n"
5549 "Host: www.example.org\r\n"
5550 "Connection: keep-alive\r\n\r\n"),
5553 MockRead data_reads1[] = {
5554 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5555 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5556 MockRead("Content-Length: 10\r\n\r\n"),
5557 MockRead(SYNCHRONOUS, ERR_FAILED),
5560 // After the challenge above, the transaction will be restarted using the
5561 // identity from the url (foo, baz) to answer the challenge.
5562 MockWrite data_writes2[] = {
5563 MockWrite(
5564 "GET / HTTP/1.1\r\n"
5565 "Host: www.example.org\r\n"
5566 "Connection: keep-alive\r\n"
5567 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5570 MockRead data_reads2[] = {
5571 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5572 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5573 MockRead("Content-Length: 10\r\n\r\n"),
5574 MockRead(SYNCHRONOUS, ERR_FAILED),
5577 // After the challenge above, the transaction will be restarted using the
5578 // identity supplied by the user (foo, bar) to answer the challenge.
5579 MockWrite data_writes3[] = {
5580 MockWrite(
5581 "GET / HTTP/1.1\r\n"
5582 "Host: www.example.org\r\n"
5583 "Connection: keep-alive\r\n"
5584 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5587 MockRead data_reads3[] = {
5588 MockRead("HTTP/1.0 200 OK\r\n"),
5589 MockRead("Content-Length: 100\r\n\r\n"),
5590 MockRead(SYNCHRONOUS, OK),
5593 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5594 data_writes1, arraysize(data_writes1));
5595 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5596 data_writes2, arraysize(data_writes2));
5597 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5598 data_writes3, arraysize(data_writes3));
5599 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5600 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5601 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5603 TestCompletionCallback callback1;
5605 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5606 EXPECT_EQ(ERR_IO_PENDING, rv);
5608 rv = callback1.WaitForResult();
5609 EXPECT_EQ(OK, rv);
5611 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5612 TestCompletionCallback callback2;
5613 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5614 EXPECT_EQ(ERR_IO_PENDING, rv);
5615 rv = callback2.WaitForResult();
5616 EXPECT_EQ(OK, rv);
5617 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5619 const HttpResponseInfo* response = trans->GetResponseInfo();
5620 ASSERT_TRUE(response != NULL);
5621 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5623 TestCompletionCallback callback3;
5624 rv = trans->RestartWithAuth(
5625 AuthCredentials(kFoo, kBar), callback3.callback());
5626 EXPECT_EQ(ERR_IO_PENDING, rv);
5627 rv = callback3.WaitForResult();
5628 EXPECT_EQ(OK, rv);
5629 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5631 response = trans->GetResponseInfo();
5632 ASSERT_TRUE(response != NULL);
5634 // There is no challenge info, since the identity worked.
5635 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5637 EXPECT_EQ(100, response->headers->GetContentLength());
5639 // Empty the current queue.
5640 base::MessageLoop::current()->RunUntilIdle();
5644 // Test the request-challenge-retry sequence for basic auth when there is a
5645 // correct identity in the URL, but its use is being suppressed. The identity
5646 // from the URL should never be used.
5647 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5648 HttpRequestInfo request;
5649 request.method = "GET";
5650 request.url = GURL("http://foo:bar@www.example.org/");
5651 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5653 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5654 scoped_ptr<HttpTransaction> trans(
5655 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5657 MockWrite data_writes1[] = {
5658 MockWrite(
5659 "GET / HTTP/1.1\r\n"
5660 "Host: www.example.org\r\n"
5661 "Connection: keep-alive\r\n\r\n"),
5664 MockRead data_reads1[] = {
5665 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5666 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5667 MockRead("Content-Length: 10\r\n\r\n"),
5668 MockRead(SYNCHRONOUS, ERR_FAILED),
5671 // After the challenge above, the transaction will be restarted using the
5672 // identity supplied by the user, not the one in the URL, to answer the
5673 // challenge.
5674 MockWrite data_writes3[] = {
5675 MockWrite(
5676 "GET / HTTP/1.1\r\n"
5677 "Host: www.example.org\r\n"
5678 "Connection: keep-alive\r\n"
5679 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5682 MockRead data_reads3[] = {
5683 MockRead("HTTP/1.0 200 OK\r\n"),
5684 MockRead("Content-Length: 100\r\n\r\n"),
5685 MockRead(SYNCHRONOUS, OK),
5688 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5689 data_writes1, arraysize(data_writes1));
5690 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5691 data_writes3, arraysize(data_writes3));
5692 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5693 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5695 TestCompletionCallback callback1;
5696 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5697 EXPECT_EQ(ERR_IO_PENDING, rv);
5698 rv = callback1.WaitForResult();
5699 EXPECT_EQ(OK, rv);
5700 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5702 const HttpResponseInfo* response = trans->GetResponseInfo();
5703 ASSERT_TRUE(response != NULL);
5704 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5706 TestCompletionCallback callback3;
5707 rv = trans->RestartWithAuth(
5708 AuthCredentials(kFoo, kBar), callback3.callback());
5709 EXPECT_EQ(ERR_IO_PENDING, rv);
5710 rv = callback3.WaitForResult();
5711 EXPECT_EQ(OK, rv);
5712 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5714 response = trans->GetResponseInfo();
5715 ASSERT_TRUE(response != NULL);
5717 // There is no challenge info, since the identity worked.
5718 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5719 EXPECT_EQ(100, response->headers->GetContentLength());
5721 // Empty the current queue.
5722 base::MessageLoop::current()->RunUntilIdle();
5725 // Test that previously tried username/passwords for a realm get re-used.
5726 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5727 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5729 // Transaction 1: authenticate (foo, bar) on MyRealm1
5731 HttpRequestInfo request;
5732 request.method = "GET";
5733 request.url = GURL("http://www.example.org/x/y/z");
5734 request.load_flags = 0;
5736 scoped_ptr<HttpTransaction> trans(
5737 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5739 MockWrite data_writes1[] = {
5740 MockWrite(
5741 "GET /x/y/z HTTP/1.1\r\n"
5742 "Host: www.example.org\r\n"
5743 "Connection: keep-alive\r\n\r\n"),
5746 MockRead data_reads1[] = {
5747 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5748 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5749 MockRead("Content-Length: 10000\r\n\r\n"),
5750 MockRead(SYNCHRONOUS, ERR_FAILED),
5753 // Resend with authorization (username=foo, password=bar)
5754 MockWrite data_writes2[] = {
5755 MockWrite(
5756 "GET /x/y/z HTTP/1.1\r\n"
5757 "Host: www.example.org\r\n"
5758 "Connection: keep-alive\r\n"
5759 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5762 // Sever accepts the authorization.
5763 MockRead data_reads2[] = {
5764 MockRead("HTTP/1.0 200 OK\r\n"),
5765 MockRead("Content-Length: 100\r\n\r\n"),
5766 MockRead(SYNCHRONOUS, OK),
5769 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5770 data_writes1, arraysize(data_writes1));
5771 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5772 data_writes2, arraysize(data_writes2));
5773 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5774 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5776 TestCompletionCallback callback1;
5778 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5779 EXPECT_EQ(ERR_IO_PENDING, rv);
5781 rv = callback1.WaitForResult();
5782 EXPECT_EQ(OK, rv);
5784 const HttpResponseInfo* response = trans->GetResponseInfo();
5785 ASSERT_TRUE(response != NULL);
5786 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5788 TestCompletionCallback callback2;
5790 rv = trans->RestartWithAuth(
5791 AuthCredentials(kFoo, kBar), callback2.callback());
5792 EXPECT_EQ(ERR_IO_PENDING, rv);
5794 rv = callback2.WaitForResult();
5795 EXPECT_EQ(OK, rv);
5797 response = trans->GetResponseInfo();
5798 ASSERT_TRUE(response != NULL);
5799 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5800 EXPECT_EQ(100, response->headers->GetContentLength());
5803 // ------------------------------------------------------------------------
5805 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5807 HttpRequestInfo request;
5808 request.method = "GET";
5809 // Note that Transaction 1 was at /x/y/z, so this is in the same
5810 // protection space as MyRealm1.
5811 request.url = GURL("http://www.example.org/x/y/a/b");
5812 request.load_flags = 0;
5814 scoped_ptr<HttpTransaction> trans(
5815 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5817 MockWrite data_writes1[] = {
5818 MockWrite(
5819 "GET /x/y/a/b HTTP/1.1\r\n"
5820 "Host: www.example.org\r\n"
5821 "Connection: keep-alive\r\n"
5822 // Send preemptive authorization for MyRealm1
5823 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5826 // The server didn't like the preemptive authorization, and
5827 // challenges us for a different realm (MyRealm2).
5828 MockRead data_reads1[] = {
5829 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5830 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5831 MockRead("Content-Length: 10000\r\n\r\n"),
5832 MockRead(SYNCHRONOUS, ERR_FAILED),
5835 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5836 MockWrite data_writes2[] = {
5837 MockWrite(
5838 "GET /x/y/a/b HTTP/1.1\r\n"
5839 "Host: www.example.org\r\n"
5840 "Connection: keep-alive\r\n"
5841 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5844 // Sever accepts the authorization.
5845 MockRead data_reads2[] = {
5846 MockRead("HTTP/1.0 200 OK\r\n"),
5847 MockRead("Content-Length: 100\r\n\r\n"),
5848 MockRead(SYNCHRONOUS, OK),
5851 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5852 data_writes1, arraysize(data_writes1));
5853 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5854 data_writes2, arraysize(data_writes2));
5855 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5856 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5858 TestCompletionCallback callback1;
5860 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5861 EXPECT_EQ(ERR_IO_PENDING, rv);
5863 rv = callback1.WaitForResult();
5864 EXPECT_EQ(OK, rv);
5866 const HttpResponseInfo* response = trans->GetResponseInfo();
5867 ASSERT_TRUE(response != NULL);
5868 ASSERT_TRUE(response->auth_challenge.get());
5869 EXPECT_FALSE(response->auth_challenge->is_proxy);
5870 EXPECT_EQ("www.example.org:80",
5871 response->auth_challenge->challenger.ToString());
5872 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5873 EXPECT_EQ("basic", response->auth_challenge->scheme);
5875 TestCompletionCallback callback2;
5877 rv = trans->RestartWithAuth(
5878 AuthCredentials(kFoo2, kBar2), callback2.callback());
5879 EXPECT_EQ(ERR_IO_PENDING, rv);
5881 rv = callback2.WaitForResult();
5882 EXPECT_EQ(OK, rv);
5884 response = trans->GetResponseInfo();
5885 ASSERT_TRUE(response != NULL);
5886 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5887 EXPECT_EQ(100, response->headers->GetContentLength());
5890 // ------------------------------------------------------------------------
5892 // Transaction 3: Resend a request in MyRealm's protection space --
5893 // succeed with preemptive authorization.
5895 HttpRequestInfo request;
5896 request.method = "GET";
5897 request.url = GURL("http://www.example.org/x/y/z2");
5898 request.load_flags = 0;
5900 scoped_ptr<HttpTransaction> trans(
5901 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5903 MockWrite data_writes1[] = {
5904 MockWrite(
5905 "GET /x/y/z2 HTTP/1.1\r\n"
5906 "Host: www.example.org\r\n"
5907 "Connection: keep-alive\r\n"
5908 // The authorization for MyRealm1 gets sent preemptively
5909 // (since the url is in the same protection space)
5910 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5913 // Sever accepts the preemptive authorization
5914 MockRead data_reads1[] = {
5915 MockRead("HTTP/1.0 200 OK\r\n"),
5916 MockRead("Content-Length: 100\r\n\r\n"),
5917 MockRead(SYNCHRONOUS, OK),
5920 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5921 data_writes1, arraysize(data_writes1));
5922 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5924 TestCompletionCallback callback1;
5926 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5927 EXPECT_EQ(ERR_IO_PENDING, rv);
5929 rv = callback1.WaitForResult();
5930 EXPECT_EQ(OK, rv);
5932 const HttpResponseInfo* response = trans->GetResponseInfo();
5933 ASSERT_TRUE(response != NULL);
5935 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5936 EXPECT_EQ(100, response->headers->GetContentLength());
5939 // ------------------------------------------------------------------------
5941 // Transaction 4: request another URL in MyRealm (however the
5942 // url is not known to belong to the protection space, so no pre-auth).
5944 HttpRequestInfo request;
5945 request.method = "GET";
5946 request.url = GURL("http://www.example.org/x/1");
5947 request.load_flags = 0;
5949 scoped_ptr<HttpTransaction> trans(
5950 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5952 MockWrite data_writes1[] = {
5953 MockWrite(
5954 "GET /x/1 HTTP/1.1\r\n"
5955 "Host: www.example.org\r\n"
5956 "Connection: keep-alive\r\n\r\n"),
5959 MockRead data_reads1[] = {
5960 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5961 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5962 MockRead("Content-Length: 10000\r\n\r\n"),
5963 MockRead(SYNCHRONOUS, ERR_FAILED),
5966 // Resend with authorization from MyRealm's cache.
5967 MockWrite data_writes2[] = {
5968 MockWrite(
5969 "GET /x/1 HTTP/1.1\r\n"
5970 "Host: www.example.org\r\n"
5971 "Connection: keep-alive\r\n"
5972 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5975 // Sever accepts the authorization.
5976 MockRead data_reads2[] = {
5977 MockRead("HTTP/1.0 200 OK\r\n"),
5978 MockRead("Content-Length: 100\r\n\r\n"),
5979 MockRead(SYNCHRONOUS, OK),
5982 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5983 data_writes1, arraysize(data_writes1));
5984 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5985 data_writes2, arraysize(data_writes2));
5986 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5987 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5989 TestCompletionCallback callback1;
5991 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5992 EXPECT_EQ(ERR_IO_PENDING, rv);
5994 rv = callback1.WaitForResult();
5995 EXPECT_EQ(OK, rv);
5997 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5998 TestCompletionCallback callback2;
5999 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6000 EXPECT_EQ(ERR_IO_PENDING, rv);
6001 rv = callback2.WaitForResult();
6002 EXPECT_EQ(OK, rv);
6003 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6005 const HttpResponseInfo* response = trans->GetResponseInfo();
6006 ASSERT_TRUE(response != NULL);
6007 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6008 EXPECT_EQ(100, response->headers->GetContentLength());
6011 // ------------------------------------------------------------------------
6013 // Transaction 5: request a URL in MyRealm, but the server rejects the
6014 // cached identity. Should invalidate and re-prompt.
6016 HttpRequestInfo request;
6017 request.method = "GET";
6018 request.url = GURL("http://www.example.org/p/q/t");
6019 request.load_flags = 0;
6021 scoped_ptr<HttpTransaction> trans(
6022 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6024 MockWrite data_writes1[] = {
6025 MockWrite(
6026 "GET /p/q/t HTTP/1.1\r\n"
6027 "Host: www.example.org\r\n"
6028 "Connection: keep-alive\r\n\r\n"),
6031 MockRead data_reads1[] = {
6032 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6033 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6034 MockRead("Content-Length: 10000\r\n\r\n"),
6035 MockRead(SYNCHRONOUS, ERR_FAILED),
6038 // Resend with authorization from cache for MyRealm.
6039 MockWrite data_writes2[] = {
6040 MockWrite(
6041 "GET /p/q/t HTTP/1.1\r\n"
6042 "Host: www.example.org\r\n"
6043 "Connection: keep-alive\r\n"
6044 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6047 // Sever rejects the authorization.
6048 MockRead data_reads2[] = {
6049 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6050 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6051 MockRead("Content-Length: 10000\r\n\r\n"),
6052 MockRead(SYNCHRONOUS, ERR_FAILED),
6055 // At this point we should prompt for new credentials for MyRealm.
6056 // Restart with username=foo3, password=foo4.
6057 MockWrite data_writes3[] = {
6058 MockWrite(
6059 "GET /p/q/t HTTP/1.1\r\n"
6060 "Host: www.example.org\r\n"
6061 "Connection: keep-alive\r\n"
6062 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6065 // Sever accepts the authorization.
6066 MockRead data_reads3[] = {
6067 MockRead("HTTP/1.0 200 OK\r\n"),
6068 MockRead("Content-Length: 100\r\n\r\n"),
6069 MockRead(SYNCHRONOUS, OK),
6072 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6073 data_writes1, arraysize(data_writes1));
6074 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6075 data_writes2, arraysize(data_writes2));
6076 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6077 data_writes3, arraysize(data_writes3));
6078 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6079 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6080 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6082 TestCompletionCallback callback1;
6084 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6085 EXPECT_EQ(ERR_IO_PENDING, rv);
6087 rv = callback1.WaitForResult();
6088 EXPECT_EQ(OK, rv);
6090 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6091 TestCompletionCallback callback2;
6092 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6093 EXPECT_EQ(ERR_IO_PENDING, rv);
6094 rv = callback2.WaitForResult();
6095 EXPECT_EQ(OK, rv);
6096 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6098 const HttpResponseInfo* response = trans->GetResponseInfo();
6099 ASSERT_TRUE(response != NULL);
6100 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6102 TestCompletionCallback callback3;
6104 rv = trans->RestartWithAuth(
6105 AuthCredentials(kFoo3, kBar3), callback3.callback());
6106 EXPECT_EQ(ERR_IO_PENDING, rv);
6108 rv = callback3.WaitForResult();
6109 EXPECT_EQ(OK, rv);
6111 response = trans->GetResponseInfo();
6112 ASSERT_TRUE(response != NULL);
6113 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6114 EXPECT_EQ(100, response->headers->GetContentLength());
6118 // Tests that nonce count increments when multiple auth attempts
6119 // are started with the same nonce.
6120 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
6121 HttpAuthHandlerDigest::Factory* digest_factory =
6122 new HttpAuthHandlerDigest::Factory();
6123 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6124 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6125 digest_factory->set_nonce_generator(nonce_generator);
6126 session_deps_.http_auth_handler_factory.reset(digest_factory);
6127 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6129 // Transaction 1: authenticate (foo, bar) on MyRealm1
6131 HttpRequestInfo request;
6132 request.method = "GET";
6133 request.url = GURL("http://www.example.org/x/y/z");
6134 request.load_flags = 0;
6136 scoped_ptr<HttpTransaction> trans(
6137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6139 MockWrite data_writes1[] = {
6140 MockWrite(
6141 "GET /x/y/z HTTP/1.1\r\n"
6142 "Host: www.example.org\r\n"
6143 "Connection: keep-alive\r\n\r\n"),
6146 MockRead data_reads1[] = {
6147 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6148 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6149 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6150 MockRead(SYNCHRONOUS, OK),
6153 // Resend with authorization (username=foo, password=bar)
6154 MockWrite data_writes2[] = {
6155 MockWrite(
6156 "GET /x/y/z HTTP/1.1\r\n"
6157 "Host: www.example.org\r\n"
6158 "Connection: keep-alive\r\n"
6159 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6160 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6161 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6162 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6165 // Sever accepts the authorization.
6166 MockRead data_reads2[] = {
6167 MockRead("HTTP/1.0 200 OK\r\n"),
6168 MockRead(SYNCHRONOUS, OK),
6171 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6172 data_writes1, arraysize(data_writes1));
6173 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6174 data_writes2, arraysize(data_writes2));
6175 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6176 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6178 TestCompletionCallback callback1;
6180 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6181 EXPECT_EQ(ERR_IO_PENDING, rv);
6183 rv = callback1.WaitForResult();
6184 EXPECT_EQ(OK, rv);
6186 const HttpResponseInfo* response = trans->GetResponseInfo();
6187 ASSERT_TRUE(response != NULL);
6188 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
6190 TestCompletionCallback callback2;
6192 rv = trans->RestartWithAuth(
6193 AuthCredentials(kFoo, kBar), callback2.callback());
6194 EXPECT_EQ(ERR_IO_PENDING, rv);
6196 rv = callback2.WaitForResult();
6197 EXPECT_EQ(OK, rv);
6199 response = trans->GetResponseInfo();
6200 ASSERT_TRUE(response != NULL);
6201 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6204 // ------------------------------------------------------------------------
6206 // Transaction 2: Request another resource in digestive's protection space.
6207 // This will preemptively add an Authorization header which should have an
6208 // "nc" value of 2 (as compared to 1 in the first use.
6210 HttpRequestInfo request;
6211 request.method = "GET";
6212 // Note that Transaction 1 was at /x/y/z, so this is in the same
6213 // protection space as digest.
6214 request.url = GURL("http://www.example.org/x/y/a/b");
6215 request.load_flags = 0;
6217 scoped_ptr<HttpTransaction> trans(
6218 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6220 MockWrite data_writes1[] = {
6221 MockWrite(
6222 "GET /x/y/a/b HTTP/1.1\r\n"
6223 "Host: www.example.org\r\n"
6224 "Connection: keep-alive\r\n"
6225 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6226 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6227 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6228 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6231 // Sever accepts the authorization.
6232 MockRead data_reads1[] = {
6233 MockRead("HTTP/1.0 200 OK\r\n"),
6234 MockRead("Content-Length: 100\r\n\r\n"),
6235 MockRead(SYNCHRONOUS, OK),
6238 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6239 data_writes1, arraysize(data_writes1));
6240 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6242 TestCompletionCallback callback1;
6244 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6245 EXPECT_EQ(ERR_IO_PENDING, rv);
6247 rv = callback1.WaitForResult();
6248 EXPECT_EQ(OK, rv);
6250 const HttpResponseInfo* response = trans->GetResponseInfo();
6251 ASSERT_TRUE(response != NULL);
6252 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6256 // Test the ResetStateForRestart() private method.
6257 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
6258 // Create a transaction (the dependencies aren't important).
6259 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6260 scoped_ptr<HttpNetworkTransaction> trans(
6261 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6263 // Setup some state (which we expect ResetStateForRestart() will clear).
6264 trans->read_buf_ = new IOBuffer(15);
6265 trans->read_buf_len_ = 15;
6266 trans->request_headers_.SetHeader("Authorization", "NTLM");
6268 // Setup state in response_
6269 HttpResponseInfo* response = &trans->response_;
6270 response->auth_challenge = new AuthChallengeInfo();
6271 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
6272 response->response_time = base::Time::Now();
6273 response->was_cached = true; // (Wouldn't ever actually be true...)
6275 { // Setup state for response_.vary_data
6276 HttpRequestInfo request;
6277 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6278 std::replace(temp.begin(), temp.end(), '\n', '\0');
6279 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
6280 request.extra_headers.SetHeader("Foo", "1");
6281 request.extra_headers.SetHeader("bar", "23");
6282 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
6285 // Cause the above state to be reset.
6286 trans->ResetStateForRestart();
6288 // Verify that the state that needed to be reset, has been reset.
6289 EXPECT_TRUE(trans->read_buf_.get() == NULL);
6290 EXPECT_EQ(0, trans->read_buf_len_);
6291 EXPECT_TRUE(trans->request_headers_.IsEmpty());
6292 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6293 EXPECT_TRUE(response->headers.get() == NULL);
6294 EXPECT_FALSE(response->was_cached);
6295 EXPECT_EQ(0U, response->ssl_info.cert_status);
6296 EXPECT_FALSE(response->vary_data.is_valid());
6299 // Test HTTPS connections to a site with a bad certificate
6300 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
6301 HttpRequestInfo request;
6302 request.method = "GET";
6303 request.url = GURL("https://www.example.org/");
6304 request.load_flags = 0;
6306 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6307 scoped_ptr<HttpTransaction> trans(
6308 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6310 MockWrite data_writes[] = {
6311 MockWrite(
6312 "GET / HTTP/1.1\r\n"
6313 "Host: www.example.org\r\n"
6314 "Connection: keep-alive\r\n\r\n"),
6317 MockRead data_reads[] = {
6318 MockRead("HTTP/1.0 200 OK\r\n"),
6319 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6320 MockRead("Content-Length: 100\r\n\r\n"),
6321 MockRead(SYNCHRONOUS, OK),
6324 StaticSocketDataProvider ssl_bad_certificate;
6325 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6326 data_writes, arraysize(data_writes));
6327 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6328 SSLSocketDataProvider ssl(ASYNC, OK);
6330 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6331 session_deps_.socket_factory->AddSocketDataProvider(&data);
6332 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6335 TestCompletionCallback callback;
6337 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6338 EXPECT_EQ(ERR_IO_PENDING, rv);
6340 rv = callback.WaitForResult();
6341 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6343 rv = trans->RestartIgnoringLastError(callback.callback());
6344 EXPECT_EQ(ERR_IO_PENDING, rv);
6346 rv = callback.WaitForResult();
6347 EXPECT_EQ(OK, rv);
6349 const HttpResponseInfo* response = trans->GetResponseInfo();
6351 ASSERT_TRUE(response != NULL);
6352 EXPECT_EQ(100, response->headers->GetContentLength());
6355 // Test HTTPS connections to a site with a bad certificate, going through a
6356 // proxy
6357 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
6358 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6360 HttpRequestInfo request;
6361 request.method = "GET";
6362 request.url = GURL("https://www.example.org/");
6363 request.load_flags = 0;
6365 MockWrite proxy_writes[] = {
6366 MockWrite(
6367 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6368 "Host: www.example.org\r\n"
6369 "Proxy-Connection: keep-alive\r\n\r\n"),
6372 MockRead proxy_reads[] = {
6373 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6374 MockRead(SYNCHRONOUS, OK)
6377 MockWrite data_writes[] = {
6378 MockWrite(
6379 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6380 "Host: www.example.org\r\n"
6381 "Proxy-Connection: keep-alive\r\n\r\n"),
6382 MockWrite(
6383 "GET / HTTP/1.1\r\n"
6384 "Host: www.example.org\r\n"
6385 "Connection: keep-alive\r\n\r\n"),
6388 MockRead data_reads[] = {
6389 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6390 MockRead("HTTP/1.0 200 OK\r\n"),
6391 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6392 MockRead("Content-Length: 100\r\n\r\n"),
6393 MockRead(SYNCHRONOUS, OK),
6396 StaticSocketDataProvider ssl_bad_certificate(
6397 proxy_reads, arraysize(proxy_reads),
6398 proxy_writes, arraysize(proxy_writes));
6399 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6400 data_writes, arraysize(data_writes));
6401 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6402 SSLSocketDataProvider ssl(ASYNC, OK);
6404 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6405 session_deps_.socket_factory->AddSocketDataProvider(&data);
6406 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6407 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6409 TestCompletionCallback callback;
6411 for (int i = 0; i < 2; i++) {
6412 session_deps_.socket_factory->ResetNextMockIndexes();
6414 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6415 scoped_ptr<HttpTransaction> trans(
6416 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6418 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6419 EXPECT_EQ(ERR_IO_PENDING, rv);
6421 rv = callback.WaitForResult();
6422 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6424 rv = trans->RestartIgnoringLastError(callback.callback());
6425 EXPECT_EQ(ERR_IO_PENDING, rv);
6427 rv = callback.WaitForResult();
6428 EXPECT_EQ(OK, rv);
6430 const HttpResponseInfo* response = trans->GetResponseInfo();
6432 ASSERT_TRUE(response != NULL);
6433 EXPECT_EQ(100, response->headers->GetContentLength());
6438 // Test HTTPS connections to a site, going through an HTTPS proxy
6439 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6440 session_deps_.proxy_service.reset(
6441 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6442 TestNetLog net_log;
6443 session_deps_.net_log = &net_log;
6445 HttpRequestInfo request;
6446 request.method = "GET";
6447 request.url = GURL("https://www.example.org/");
6448 request.load_flags = 0;
6450 MockWrite data_writes[] = {
6451 MockWrite(
6452 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6453 "Host: www.example.org\r\n"
6454 "Proxy-Connection: keep-alive\r\n\r\n"),
6455 MockWrite(
6456 "GET / HTTP/1.1\r\n"
6457 "Host: www.example.org\r\n"
6458 "Connection: keep-alive\r\n\r\n"),
6461 MockRead data_reads[] = {
6462 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6463 MockRead("HTTP/1.1 200 OK\r\n"),
6464 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6465 MockRead("Content-Length: 100\r\n\r\n"),
6466 MockRead(SYNCHRONOUS, OK),
6469 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6470 data_writes, arraysize(data_writes));
6471 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6472 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6474 session_deps_.socket_factory->AddSocketDataProvider(&data);
6475 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6476 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6478 TestCompletionCallback callback;
6480 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6481 scoped_ptr<HttpTransaction> trans(
6482 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6484 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6485 EXPECT_EQ(ERR_IO_PENDING, rv);
6487 rv = callback.WaitForResult();
6488 EXPECT_EQ(OK, rv);
6489 const HttpResponseInfo* response = trans->GetResponseInfo();
6491 ASSERT_TRUE(response != NULL);
6493 EXPECT_TRUE(response->headers->IsKeepAlive());
6494 EXPECT_EQ(200, response->headers->response_code());
6495 EXPECT_EQ(100, response->headers->GetContentLength());
6496 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6498 LoadTimingInfo load_timing_info;
6499 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6500 TestLoadTimingNotReusedWithPac(load_timing_info,
6501 CONNECT_TIMING_HAS_SSL_TIMES);
6504 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6505 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6506 session_deps_.proxy_service.reset(
6507 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6508 TestNetLog net_log;
6509 session_deps_.net_log = &net_log;
6511 HttpRequestInfo request;
6512 request.method = "GET";
6513 request.url = GURL("https://www.example.org/");
6514 request.load_flags = 0;
6516 MockWrite data_writes[] = {
6517 MockWrite(
6518 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6519 "Host: www.example.org\r\n"
6520 "Proxy-Connection: keep-alive\r\n\r\n"),
6523 MockRead data_reads[] = {
6524 MockRead("HTTP/1.1 302 Redirect\r\n"),
6525 MockRead("Location: http://login.example.com/\r\n"),
6526 MockRead("Content-Length: 0\r\n\r\n"),
6527 MockRead(SYNCHRONOUS, OK),
6530 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6531 data_writes, arraysize(data_writes));
6532 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6534 session_deps_.socket_factory->AddSocketDataProvider(&data);
6535 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6537 TestCompletionCallback callback;
6539 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6540 scoped_ptr<HttpTransaction> trans(
6541 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6543 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6544 EXPECT_EQ(ERR_IO_PENDING, rv);
6546 rv = callback.WaitForResult();
6547 EXPECT_EQ(OK, rv);
6548 const HttpResponseInfo* response = trans->GetResponseInfo();
6550 ASSERT_TRUE(response != NULL);
6552 EXPECT_EQ(302, response->headers->response_code());
6553 std::string url;
6554 EXPECT_TRUE(response->headers->IsRedirect(&url));
6555 EXPECT_EQ("http://login.example.com/", url);
6557 // In the case of redirects from proxies, HttpNetworkTransaction returns
6558 // timing for the proxy connection instead of the connection to the host,
6559 // and no send / receive times.
6560 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6561 LoadTimingInfo load_timing_info;
6562 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6564 EXPECT_FALSE(load_timing_info.socket_reused);
6565 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6567 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6568 EXPECT_LE(load_timing_info.proxy_resolve_start,
6569 load_timing_info.proxy_resolve_end);
6570 EXPECT_LE(load_timing_info.proxy_resolve_end,
6571 load_timing_info.connect_timing.connect_start);
6572 ExpectConnectTimingHasTimes(
6573 load_timing_info.connect_timing,
6574 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6576 EXPECT_TRUE(load_timing_info.send_start.is_null());
6577 EXPECT_TRUE(load_timing_info.send_end.is_null());
6578 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6581 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6582 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6583 session_deps_.proxy_service.reset(
6584 ProxyService::CreateFixed("https://proxy:70"));
6586 HttpRequestInfo request;
6587 request.method = "GET";
6588 request.url = GURL("https://www.example.org/");
6589 request.load_flags = 0;
6591 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6592 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6593 scoped_ptr<SpdyFrame> goaway(
6594 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6595 MockWrite data_writes[] = {
6596 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6597 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
6600 static const char* const kExtraHeaders[] = {
6601 "location",
6602 "http://login.example.com/",
6604 scoped_ptr<SpdyFrame> resp(
6605 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6606 arraysize(kExtraHeaders)/2, 1));
6607 MockRead data_reads[] = {
6608 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6609 MockRead(ASYNC, 0, 2), // EOF
6612 DelayedSocketData data(
6613 1, // wait for one write to finish before reading.
6614 data_reads, arraysize(data_reads),
6615 data_writes, arraysize(data_writes));
6616 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6617 proxy_ssl.SetNextProto(GetParam());
6619 session_deps_.socket_factory->AddSocketDataProvider(&data);
6620 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6622 TestCompletionCallback callback;
6624 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6625 scoped_ptr<HttpTransaction> trans(
6626 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6628 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6629 EXPECT_EQ(ERR_IO_PENDING, rv);
6631 rv = callback.WaitForResult();
6632 EXPECT_EQ(OK, rv);
6633 const HttpResponseInfo* response = trans->GetResponseInfo();
6635 ASSERT_TRUE(response != NULL);
6637 EXPECT_EQ(302, response->headers->response_code());
6638 std::string url;
6639 EXPECT_TRUE(response->headers->IsRedirect(&url));
6640 EXPECT_EQ("http://login.example.com/", url);
6643 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6644 TEST_P(HttpNetworkTransactionTest,
6645 ErrorResponseToHttpsConnectViaHttpsProxy) {
6646 session_deps_.proxy_service.reset(
6647 ProxyService::CreateFixed("https://proxy:70"));
6649 HttpRequestInfo request;
6650 request.method = "GET";
6651 request.url = GURL("https://www.example.org/");
6652 request.load_flags = 0;
6654 MockWrite data_writes[] = {
6655 MockWrite(
6656 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6657 "Host: www.example.org\r\n"
6658 "Proxy-Connection: keep-alive\r\n\r\n"),
6661 MockRead data_reads[] = {
6662 MockRead("HTTP/1.1 404 Not Found\r\n"),
6663 MockRead("Content-Length: 23\r\n\r\n"),
6664 MockRead("The host does not exist"),
6665 MockRead(SYNCHRONOUS, OK),
6668 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6669 data_writes, arraysize(data_writes));
6670 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6672 session_deps_.socket_factory->AddSocketDataProvider(&data);
6673 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6675 TestCompletionCallback callback;
6677 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6678 scoped_ptr<HttpTransaction> trans(
6679 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6681 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6682 EXPECT_EQ(ERR_IO_PENDING, rv);
6684 rv = callback.WaitForResult();
6685 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6687 // TODO(ttuttle): Anything else to check here?
6690 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6691 TEST_P(HttpNetworkTransactionTest,
6692 ErrorResponseToHttpsConnectViaSpdyProxy) {
6693 session_deps_.proxy_service.reset(
6694 ProxyService::CreateFixed("https://proxy:70"));
6696 HttpRequestInfo request;
6697 request.method = "GET";
6698 request.url = GURL("https://www.example.org/");
6699 request.load_flags = 0;
6701 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
6702 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6703 scoped_ptr<SpdyFrame> rst(
6704 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6705 MockWrite data_writes[] = {
6706 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6707 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6710 static const char* const kExtraHeaders[] = {
6711 "location",
6712 "http://login.example.com/",
6714 scoped_ptr<SpdyFrame> resp(
6715 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6716 arraysize(kExtraHeaders)/2, 1));
6717 scoped_ptr<SpdyFrame> body(
6718 spdy_util_.ConstructSpdyBodyFrame(
6719 1, "The host does not exist", 23, true));
6720 MockRead data_reads[] = {
6721 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6722 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6723 MockRead(ASYNC, 0, 4), // EOF
6726 DelayedSocketData data(
6727 1, // wait for one write to finish before reading.
6728 data_reads, arraysize(data_reads),
6729 data_writes, arraysize(data_writes));
6730 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6731 proxy_ssl.SetNextProto(GetParam());
6733 session_deps_.socket_factory->AddSocketDataProvider(&data);
6734 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6736 TestCompletionCallback callback;
6738 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6739 scoped_ptr<HttpTransaction> trans(
6740 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6742 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6743 EXPECT_EQ(ERR_IO_PENDING, rv);
6745 rv = callback.WaitForResult();
6746 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6748 // TODO(ttuttle): Anything else to check here?
6751 // Test the request-challenge-retry sequence for basic auth, through
6752 // a SPDY proxy over a single SPDY session.
6753 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6754 HttpRequestInfo request;
6755 request.method = "GET";
6756 request.url = GURL("https://www.example.org/");
6757 // when the no authentication data flag is set.
6758 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
6760 // Configure against https proxy server "myproxy:70".
6761 session_deps_.proxy_service.reset(
6762 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6763 BoundTestNetLog log;
6764 session_deps_.net_log = log.bound().net_log();
6765 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6767 // Since we have proxy, should try to establish tunnel.
6768 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
6769 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
6770 scoped_ptr<SpdyFrame> rst(
6771 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6773 // After calling trans->RestartWithAuth(), this is the request we should
6774 // be issuing -- the final header line contains the credentials.
6775 const char* const kAuthCredentials[] = {
6776 "proxy-authorization", "Basic Zm9vOmJhcg==",
6778 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6779 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
6780 HostPortPair("www.example.org", 443)));
6781 // fetch https://www.example.org/ via HTTP
6782 const char get[] =
6783 "GET / HTTP/1.1\r\n"
6784 "Host: www.example.org\r\n"
6785 "Connection: keep-alive\r\n\r\n";
6786 scoped_ptr<SpdyFrame> wrapped_get(
6787 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6789 MockWrite spdy_writes[] = {
6790 CreateMockWrite(*req, 1, ASYNC),
6791 CreateMockWrite(*rst, 4, ASYNC),
6792 CreateMockWrite(*connect2, 5),
6793 CreateMockWrite(*wrapped_get, 8),
6796 // The proxy responds to the connect with a 407, using a persistent
6797 // connection.
6798 const char kAuthStatus[] = "407";
6799 const char* const kAuthChallenge[] = {
6800 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6802 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
6803 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
6805 scoped_ptr<SpdyFrame> conn_resp(
6806 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6807 const char resp[] = "HTTP/1.1 200 OK\r\n"
6808 "Content-Length: 5\r\n\r\n";
6810 scoped_ptr<SpdyFrame> wrapped_get_resp(
6811 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6812 scoped_ptr<SpdyFrame> wrapped_body(
6813 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6814 MockRead spdy_reads[] = {
6815 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6816 CreateMockRead(*conn_resp, 6, ASYNC),
6817 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6818 CreateMockRead(*wrapped_body, 10, ASYNC),
6819 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6822 OrderedSocketData spdy_data(
6823 spdy_reads, arraysize(spdy_reads),
6824 spdy_writes, arraysize(spdy_writes));
6825 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6826 // Negotiate SPDY to the proxy
6827 SSLSocketDataProvider proxy(ASYNC, OK);
6828 proxy.SetNextProto(GetParam());
6829 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6830 // Vanilla SSL to the server
6831 SSLSocketDataProvider server(ASYNC, OK);
6832 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6834 TestCompletionCallback callback1;
6836 scoped_ptr<HttpTransaction> trans(
6837 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6839 int rv = trans->Start(&request, callback1.callback(), log.bound());
6840 EXPECT_EQ(ERR_IO_PENDING, rv);
6842 rv = callback1.WaitForResult();
6843 EXPECT_EQ(OK, rv);
6844 TestNetLog::CapturedEntryList entries;
6845 log.GetEntries(&entries);
6846 size_t pos = ExpectLogContainsSomewhere(
6847 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6848 NetLog::PHASE_NONE);
6849 ExpectLogContainsSomewhere(
6850 entries, pos,
6851 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6852 NetLog::PHASE_NONE);
6854 const HttpResponseInfo* response = trans->GetResponseInfo();
6855 ASSERT_TRUE(response != NULL);
6856 ASSERT_FALSE(response->headers.get() == NULL);
6857 EXPECT_EQ(407, response->headers->response_code());
6858 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6859 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6860 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6862 TestCompletionCallback callback2;
6864 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6865 callback2.callback());
6866 EXPECT_EQ(ERR_IO_PENDING, rv);
6868 rv = callback2.WaitForResult();
6869 EXPECT_EQ(OK, rv);
6871 response = trans->GetResponseInfo();
6872 ASSERT_TRUE(response != NULL);
6874 EXPECT_TRUE(response->headers->IsKeepAlive());
6875 EXPECT_EQ(200, response->headers->response_code());
6876 EXPECT_EQ(5, response->headers->GetContentLength());
6877 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6879 // The password prompt info should not be set.
6880 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6882 LoadTimingInfo load_timing_info;
6883 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6884 TestLoadTimingNotReusedWithPac(load_timing_info,
6885 CONNECT_TIMING_HAS_SSL_TIMES);
6887 trans.reset();
6888 session->CloseAllConnections();
6891 // Test that an explicitly trusted SPDY proxy can push a resource from an
6892 // origin that is different from that of its associated resource.
6893 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6894 HttpRequestInfo request;
6895 HttpRequestInfo push_request;
6897 request.method = "GET";
6898 request.url = GURL("http://www.example.org/");
6899 push_request.method = "GET";
6900 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6902 // Configure against https proxy server "myproxy:70".
6903 session_deps_.proxy_service.reset(
6904 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6905 BoundTestNetLog log;
6906 session_deps_.net_log = log.bound().net_log();
6908 // Enable cross-origin push.
6909 session_deps_.trusted_spdy_proxy = "myproxy:70";
6911 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6913 scoped_ptr<SpdyFrame> stream1_syn(
6914 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6916 MockWrite spdy_writes[] = {
6917 CreateMockWrite(*stream1_syn, 1, ASYNC),
6920 scoped_ptr<SpdyFrame>
6921 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6923 scoped_ptr<SpdyFrame>
6924 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6926 scoped_ptr<SpdyFrame>
6927 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6931 "http://www.another-origin.com/foo.dat"));
6932 const char kPushedData[] = "pushed";
6933 scoped_ptr<SpdyFrame> stream2_body(
6934 spdy_util_.ConstructSpdyBodyFrame(
6935 2, kPushedData, strlen(kPushedData), true));
6937 MockRead spdy_reads[] = {
6938 CreateMockRead(*stream1_reply, 2, ASYNC),
6939 CreateMockRead(*stream2_syn, 3, ASYNC),
6940 CreateMockRead(*stream1_body, 4, ASYNC),
6941 CreateMockRead(*stream2_body, 5, ASYNC),
6942 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6945 OrderedSocketData spdy_data(
6946 spdy_reads, arraysize(spdy_reads),
6947 spdy_writes, arraysize(spdy_writes));
6948 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6949 // Negotiate SPDY to the proxy
6950 SSLSocketDataProvider proxy(ASYNC, OK);
6951 proxy.SetNextProto(GetParam());
6952 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6954 scoped_ptr<HttpTransaction> trans(
6955 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6956 TestCompletionCallback callback;
6957 int rv = trans->Start(&request, callback.callback(), log.bound());
6958 EXPECT_EQ(ERR_IO_PENDING, rv);
6960 rv = callback.WaitForResult();
6961 EXPECT_EQ(OK, rv);
6962 const HttpResponseInfo* response = trans->GetResponseInfo();
6964 scoped_ptr<HttpTransaction> push_trans(
6965 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6966 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6967 EXPECT_EQ(ERR_IO_PENDING, rv);
6969 rv = callback.WaitForResult();
6970 EXPECT_EQ(OK, rv);
6971 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6973 ASSERT_TRUE(response != NULL);
6974 EXPECT_TRUE(response->headers->IsKeepAlive());
6976 EXPECT_EQ(200, response->headers->response_code());
6977 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6979 std::string response_data;
6980 rv = ReadTransaction(trans.get(), &response_data);
6981 EXPECT_EQ(OK, rv);
6982 EXPECT_EQ("hello!", response_data);
6984 LoadTimingInfo load_timing_info;
6985 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6986 TestLoadTimingNotReusedWithPac(load_timing_info,
6987 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6989 // Verify the pushed stream.
6990 EXPECT_TRUE(push_response->headers.get() != NULL);
6991 EXPECT_EQ(200, push_response->headers->response_code());
6993 rv = ReadTransaction(push_trans.get(), &response_data);
6994 EXPECT_EQ(OK, rv);
6995 EXPECT_EQ("pushed", response_data);
6997 LoadTimingInfo push_load_timing_info;
6998 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6999 TestLoadTimingReusedWithPac(push_load_timing_info);
7000 // The transactions should share a socket ID, despite being for different
7001 // origins.
7002 EXPECT_EQ(load_timing_info.socket_log_id,
7003 push_load_timing_info.socket_log_id);
7005 trans.reset();
7006 push_trans.reset();
7007 session->CloseAllConnections();
7010 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
7011 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
7012 HttpRequestInfo request;
7014 request.method = "GET";
7015 request.url = GURL("http://www.example.org/");
7017 // Configure against https proxy server "myproxy:70".
7018 session_deps_.proxy_service.reset(
7019 ProxyService::CreateFixed("https://myproxy:70"));
7020 BoundTestNetLog log;
7021 session_deps_.net_log = log.bound().net_log();
7023 // Enable cross-origin push.
7024 session_deps_.trusted_spdy_proxy = "myproxy:70";
7026 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7028 scoped_ptr<SpdyFrame> stream1_syn(
7029 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
7031 scoped_ptr<SpdyFrame> push_rst(
7032 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
7034 MockWrite spdy_writes[] = {
7035 CreateMockWrite(*stream1_syn, 1, ASYNC),
7036 CreateMockWrite(*push_rst, 4),
7039 scoped_ptr<SpdyFrame>
7040 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
7042 scoped_ptr<SpdyFrame>
7043 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
7045 scoped_ptr<SpdyFrame>
7046 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
7050 "https://www.another-origin.com/foo.dat"));
7052 MockRead spdy_reads[] = {
7053 CreateMockRead(*stream1_reply, 2, ASYNC),
7054 CreateMockRead(*stream2_syn, 3, ASYNC),
7055 CreateMockRead(*stream1_body, 5, ASYNC),
7056 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
7059 OrderedSocketData spdy_data(
7060 spdy_reads, arraysize(spdy_reads),
7061 spdy_writes, arraysize(spdy_writes));
7062 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7063 // Negotiate SPDY to the proxy
7064 SSLSocketDataProvider proxy(ASYNC, OK);
7065 proxy.SetNextProto(GetParam());
7066 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7068 scoped_ptr<HttpTransaction> trans(
7069 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7070 TestCompletionCallback callback;
7071 int rv = trans->Start(&request, callback.callback(), log.bound());
7072 EXPECT_EQ(ERR_IO_PENDING, rv);
7074 rv = callback.WaitForResult();
7075 EXPECT_EQ(OK, rv);
7076 const HttpResponseInfo* response = trans->GetResponseInfo();
7078 ASSERT_TRUE(response != NULL);
7079 EXPECT_TRUE(response->headers->IsKeepAlive());
7081 EXPECT_EQ(200, response->headers->response_code());
7082 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7084 std::string response_data;
7085 rv = ReadTransaction(trans.get(), &response_data);
7086 EXPECT_EQ(OK, rv);
7087 EXPECT_EQ("hello!", response_data);
7089 trans.reset();
7090 session->CloseAllConnections();
7093 // Test HTTPS connections to a site with a bad certificate, going through an
7094 // HTTPS proxy
7095 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
7096 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
7097 "https://proxy:70"));
7099 HttpRequestInfo request;
7100 request.method = "GET";
7101 request.url = GURL("https://www.example.org/");
7102 request.load_flags = 0;
7104 // Attempt to fetch the URL from a server with a bad cert
7105 MockWrite bad_cert_writes[] = {
7106 MockWrite(
7107 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7108 "Host: www.example.org\r\n"
7109 "Proxy-Connection: keep-alive\r\n\r\n"),
7112 MockRead bad_cert_reads[] = {
7113 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7114 MockRead(SYNCHRONOUS, OK)
7117 // Attempt to fetch the URL with a good cert
7118 MockWrite good_data_writes[] = {
7119 MockWrite(
7120 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7121 "Host: www.example.org\r\n"
7122 "Proxy-Connection: keep-alive\r\n\r\n"),
7123 MockWrite(
7124 "GET / HTTP/1.1\r\n"
7125 "Host: www.example.org\r\n"
7126 "Connection: keep-alive\r\n\r\n"),
7129 MockRead good_cert_reads[] = {
7130 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7131 MockRead("HTTP/1.0 200 OK\r\n"),
7132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7133 MockRead("Content-Length: 100\r\n\r\n"),
7134 MockRead(SYNCHRONOUS, OK),
7137 StaticSocketDataProvider ssl_bad_certificate(
7138 bad_cert_reads, arraysize(bad_cert_reads),
7139 bad_cert_writes, arraysize(bad_cert_writes));
7140 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7141 good_data_writes, arraysize(good_data_writes));
7142 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7143 SSLSocketDataProvider ssl(ASYNC, OK);
7145 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7146 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7147 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7148 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7150 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7151 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7152 session_deps_.socket_factory->AddSocketDataProvider(&data);
7153 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7155 TestCompletionCallback callback;
7157 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7158 scoped_ptr<HttpTransaction> trans(
7159 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7161 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7162 EXPECT_EQ(ERR_IO_PENDING, rv);
7164 rv = callback.WaitForResult();
7165 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7167 rv = trans->RestartIgnoringLastError(callback.callback());
7168 EXPECT_EQ(ERR_IO_PENDING, rv);
7170 rv = callback.WaitForResult();
7171 EXPECT_EQ(OK, rv);
7173 const HttpResponseInfo* response = trans->GetResponseInfo();
7175 ASSERT_TRUE(response != NULL);
7176 EXPECT_EQ(100, response->headers->GetContentLength());
7179 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
7180 HttpRequestInfo request;
7181 request.method = "GET";
7182 request.url = GURL("http://www.example.org/");
7183 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7184 "Chromium Ultra Awesome X Edition");
7186 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7187 scoped_ptr<HttpTransaction> trans(
7188 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7190 MockWrite data_writes[] = {
7191 MockWrite(
7192 "GET / HTTP/1.1\r\n"
7193 "Host: www.example.org\r\n"
7194 "Connection: keep-alive\r\n"
7195 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7198 // Lastly, the server responds with the actual content.
7199 MockRead data_reads[] = {
7200 MockRead("HTTP/1.0 200 OK\r\n"),
7201 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7202 MockRead("Content-Length: 100\r\n\r\n"),
7203 MockRead(SYNCHRONOUS, OK),
7206 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7207 data_writes, arraysize(data_writes));
7208 session_deps_.socket_factory->AddSocketDataProvider(&data);
7210 TestCompletionCallback callback;
7212 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7213 EXPECT_EQ(ERR_IO_PENDING, rv);
7215 rv = callback.WaitForResult();
7216 EXPECT_EQ(OK, rv);
7219 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
7220 HttpRequestInfo request;
7221 request.method = "GET";
7222 request.url = GURL("https://www.example.org/");
7223 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7224 "Chromium Ultra Awesome X Edition");
7226 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7227 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7228 scoped_ptr<HttpTransaction> trans(
7229 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7231 MockWrite data_writes[] = {
7232 MockWrite(
7233 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7234 "Host: www.example.org\r\n"
7235 "Proxy-Connection: keep-alive\r\n"
7236 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7238 MockRead data_reads[] = {
7239 // Return an error, so the transaction stops here (this test isn't
7240 // interested in the rest).
7241 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7242 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7243 MockRead("Proxy-Connection: close\r\n\r\n"),
7246 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7247 data_writes, arraysize(data_writes));
7248 session_deps_.socket_factory->AddSocketDataProvider(&data);
7250 TestCompletionCallback callback;
7252 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7253 EXPECT_EQ(ERR_IO_PENDING, rv);
7255 rv = callback.WaitForResult();
7256 EXPECT_EQ(OK, rv);
7259 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
7260 HttpRequestInfo request;
7261 request.method = "GET";
7262 request.url = GURL("http://www.example.org/");
7263 request.load_flags = 0;
7264 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7265 "http://the.previous.site.com/");
7267 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7268 scoped_ptr<HttpTransaction> trans(
7269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7271 MockWrite data_writes[] = {
7272 MockWrite(
7273 "GET / HTTP/1.1\r\n"
7274 "Host: www.example.org\r\n"
7275 "Connection: keep-alive\r\n"
7276 "Referer: http://the.previous.site.com/\r\n\r\n"),
7279 // Lastly, the server responds with the actual content.
7280 MockRead data_reads[] = {
7281 MockRead("HTTP/1.0 200 OK\r\n"),
7282 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7283 MockRead("Content-Length: 100\r\n\r\n"),
7284 MockRead(SYNCHRONOUS, OK),
7287 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7288 data_writes, arraysize(data_writes));
7289 session_deps_.socket_factory->AddSocketDataProvider(&data);
7291 TestCompletionCallback callback;
7293 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7294 EXPECT_EQ(ERR_IO_PENDING, rv);
7296 rv = callback.WaitForResult();
7297 EXPECT_EQ(OK, rv);
7300 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
7301 HttpRequestInfo request;
7302 request.method = "POST";
7303 request.url = GURL("http://www.example.org/");
7305 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7306 scoped_ptr<HttpTransaction> trans(
7307 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7309 MockWrite data_writes[] = {
7310 MockWrite(
7311 "POST / HTTP/1.1\r\n"
7312 "Host: www.example.org\r\n"
7313 "Connection: keep-alive\r\n"
7314 "Content-Length: 0\r\n\r\n"),
7317 // Lastly, the server responds with the actual content.
7318 MockRead data_reads[] = {
7319 MockRead("HTTP/1.0 200 OK\r\n"),
7320 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7321 MockRead("Content-Length: 100\r\n\r\n"),
7322 MockRead(SYNCHRONOUS, OK),
7325 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7326 data_writes, arraysize(data_writes));
7327 session_deps_.socket_factory->AddSocketDataProvider(&data);
7329 TestCompletionCallback callback;
7331 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7332 EXPECT_EQ(ERR_IO_PENDING, rv);
7334 rv = callback.WaitForResult();
7335 EXPECT_EQ(OK, rv);
7338 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
7339 HttpRequestInfo request;
7340 request.method = "PUT";
7341 request.url = GURL("http://www.example.org/");
7343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7344 scoped_ptr<HttpTransaction> trans(
7345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7347 MockWrite data_writes[] = {
7348 MockWrite(
7349 "PUT / HTTP/1.1\r\n"
7350 "Host: www.example.org\r\n"
7351 "Connection: keep-alive\r\n"
7352 "Content-Length: 0\r\n\r\n"),
7355 // Lastly, the server responds with the actual content.
7356 MockRead data_reads[] = {
7357 MockRead("HTTP/1.0 200 OK\r\n"),
7358 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7359 MockRead("Content-Length: 100\r\n\r\n"),
7360 MockRead(SYNCHRONOUS, OK),
7363 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7364 data_writes, arraysize(data_writes));
7365 session_deps_.socket_factory->AddSocketDataProvider(&data);
7367 TestCompletionCallback callback;
7369 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7370 EXPECT_EQ(ERR_IO_PENDING, rv);
7372 rv = callback.WaitForResult();
7373 EXPECT_EQ(OK, rv);
7376 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
7377 HttpRequestInfo request;
7378 request.method = "HEAD";
7379 request.url = GURL("http://www.example.org/");
7381 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7382 scoped_ptr<HttpTransaction> trans(
7383 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7385 MockWrite data_writes[] = {
7386 MockWrite(
7387 "HEAD / HTTP/1.1\r\n"
7388 "Host: www.example.org\r\n"
7389 "Connection: keep-alive\r\n"
7390 "Content-Length: 0\r\n\r\n"),
7393 // Lastly, the server responds with the actual content.
7394 MockRead data_reads[] = {
7395 MockRead("HTTP/1.0 200 OK\r\n"),
7396 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7397 MockRead("Content-Length: 100\r\n\r\n"),
7398 MockRead(SYNCHRONOUS, OK),
7401 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7402 data_writes, arraysize(data_writes));
7403 session_deps_.socket_factory->AddSocketDataProvider(&data);
7405 TestCompletionCallback callback;
7407 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7408 EXPECT_EQ(ERR_IO_PENDING, rv);
7410 rv = callback.WaitForResult();
7411 EXPECT_EQ(OK, rv);
7414 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7415 HttpRequestInfo request;
7416 request.method = "GET";
7417 request.url = GURL("http://www.example.org/");
7418 request.load_flags = LOAD_BYPASS_CACHE;
7420 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7421 scoped_ptr<HttpTransaction> trans(
7422 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7424 MockWrite data_writes[] = {
7425 MockWrite(
7426 "GET / HTTP/1.1\r\n"
7427 "Host: www.example.org\r\n"
7428 "Connection: keep-alive\r\n"
7429 "Pragma: no-cache\r\n"
7430 "Cache-Control: no-cache\r\n\r\n"),
7433 // Lastly, the server responds with the actual content.
7434 MockRead data_reads[] = {
7435 MockRead("HTTP/1.0 200 OK\r\n"),
7436 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7437 MockRead("Content-Length: 100\r\n\r\n"),
7438 MockRead(SYNCHRONOUS, OK),
7441 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7442 data_writes, arraysize(data_writes));
7443 session_deps_.socket_factory->AddSocketDataProvider(&data);
7445 TestCompletionCallback callback;
7447 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7448 EXPECT_EQ(ERR_IO_PENDING, rv);
7450 rv = callback.WaitForResult();
7451 EXPECT_EQ(OK, rv);
7454 TEST_P(HttpNetworkTransactionTest,
7455 BuildRequest_CacheControlValidateCache) {
7456 HttpRequestInfo request;
7457 request.method = "GET";
7458 request.url = GURL("http://www.example.org/");
7459 request.load_flags = LOAD_VALIDATE_CACHE;
7461 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7462 scoped_ptr<HttpTransaction> trans(
7463 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7465 MockWrite data_writes[] = {
7466 MockWrite(
7467 "GET / HTTP/1.1\r\n"
7468 "Host: www.example.org\r\n"
7469 "Connection: keep-alive\r\n"
7470 "Cache-Control: max-age=0\r\n\r\n"),
7473 // Lastly, the server responds with the actual content.
7474 MockRead data_reads[] = {
7475 MockRead("HTTP/1.0 200 OK\r\n"),
7476 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7477 MockRead("Content-Length: 100\r\n\r\n"),
7478 MockRead(SYNCHRONOUS, OK),
7481 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7482 data_writes, arraysize(data_writes));
7483 session_deps_.socket_factory->AddSocketDataProvider(&data);
7485 TestCompletionCallback callback;
7487 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7488 EXPECT_EQ(ERR_IO_PENDING, rv);
7490 rv = callback.WaitForResult();
7491 EXPECT_EQ(OK, rv);
7494 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7495 HttpRequestInfo request;
7496 request.method = "GET";
7497 request.url = GURL("http://www.example.org/");
7498 request.extra_headers.SetHeader("FooHeader", "Bar");
7500 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7501 scoped_ptr<HttpTransaction> trans(
7502 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7504 MockWrite data_writes[] = {
7505 MockWrite(
7506 "GET / HTTP/1.1\r\n"
7507 "Host: www.example.org\r\n"
7508 "Connection: keep-alive\r\n"
7509 "FooHeader: Bar\r\n\r\n"),
7512 // Lastly, the server responds with the actual content.
7513 MockRead data_reads[] = {
7514 MockRead("HTTP/1.0 200 OK\r\n"),
7515 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7516 MockRead("Content-Length: 100\r\n\r\n"),
7517 MockRead(SYNCHRONOUS, OK),
7520 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7521 data_writes, arraysize(data_writes));
7522 session_deps_.socket_factory->AddSocketDataProvider(&data);
7524 TestCompletionCallback callback;
7526 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7527 EXPECT_EQ(ERR_IO_PENDING, rv);
7529 rv = callback.WaitForResult();
7530 EXPECT_EQ(OK, rv);
7533 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7534 HttpRequestInfo request;
7535 request.method = "GET";
7536 request.url = GURL("http://www.example.org/");
7537 request.extra_headers.SetHeader("referer", "www.foo.com");
7538 request.extra_headers.SetHeader("hEllo", "Kitty");
7539 request.extra_headers.SetHeader("FoO", "bar");
7541 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7542 scoped_ptr<HttpTransaction> trans(
7543 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7545 MockWrite data_writes[] = {
7546 MockWrite(
7547 "GET / HTTP/1.1\r\n"
7548 "Host: www.example.org\r\n"
7549 "Connection: keep-alive\r\n"
7550 "referer: www.foo.com\r\n"
7551 "hEllo: Kitty\r\n"
7552 "FoO: bar\r\n\r\n"),
7555 // Lastly, the server responds with the actual content.
7556 MockRead data_reads[] = {
7557 MockRead("HTTP/1.0 200 OK\r\n"),
7558 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7559 MockRead("Content-Length: 100\r\n\r\n"),
7560 MockRead(SYNCHRONOUS, OK),
7563 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7564 data_writes, arraysize(data_writes));
7565 session_deps_.socket_factory->AddSocketDataProvider(&data);
7567 TestCompletionCallback callback;
7569 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7570 EXPECT_EQ(ERR_IO_PENDING, rv);
7572 rv = callback.WaitForResult();
7573 EXPECT_EQ(OK, rv);
7576 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7577 HttpRequestInfo request;
7578 request.method = "GET";
7579 request.url = GURL("http://www.example.org/");
7580 request.load_flags = 0;
7582 session_deps_.proxy_service.reset(
7583 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7584 TestNetLog net_log;
7585 session_deps_.net_log = &net_log;
7587 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7588 scoped_ptr<HttpTransaction> trans(
7589 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7591 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7592 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7594 MockWrite data_writes[] = {
7595 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7596 MockWrite(
7597 "GET / HTTP/1.1\r\n"
7598 "Host: www.example.org\r\n"
7599 "Connection: keep-alive\r\n\r\n")};
7601 MockRead data_reads[] = {
7602 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7603 MockRead("HTTP/1.0 200 OK\r\n"),
7604 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7605 MockRead("Payload"),
7606 MockRead(SYNCHRONOUS, OK)
7609 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7610 data_writes, arraysize(data_writes));
7611 session_deps_.socket_factory->AddSocketDataProvider(&data);
7613 TestCompletionCallback callback;
7615 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7616 EXPECT_EQ(ERR_IO_PENDING, rv);
7618 rv = callback.WaitForResult();
7619 EXPECT_EQ(OK, rv);
7621 const HttpResponseInfo* response = trans->GetResponseInfo();
7622 ASSERT_TRUE(response != NULL);
7624 LoadTimingInfo load_timing_info;
7625 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7626 TestLoadTimingNotReusedWithPac(load_timing_info,
7627 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7629 std::string response_text;
7630 rv = ReadTransaction(trans.get(), &response_text);
7631 EXPECT_EQ(OK, rv);
7632 EXPECT_EQ("Payload", response_text);
7635 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7636 HttpRequestInfo request;
7637 request.method = "GET";
7638 request.url = GURL("https://www.example.org/");
7639 request.load_flags = 0;
7641 session_deps_.proxy_service.reset(
7642 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7643 TestNetLog net_log;
7644 session_deps_.net_log = &net_log;
7646 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7647 scoped_ptr<HttpTransaction> trans(
7648 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7650 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7651 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7653 MockWrite data_writes[] = {
7654 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7655 arraysize(write_buffer)),
7656 MockWrite(
7657 "GET / HTTP/1.1\r\n"
7658 "Host: www.example.org\r\n"
7659 "Connection: keep-alive\r\n\r\n")};
7661 MockRead data_reads[] = {
7662 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7663 arraysize(read_buffer)),
7664 MockRead("HTTP/1.0 200 OK\r\n"),
7665 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7666 MockRead("Payload"),
7667 MockRead(SYNCHRONOUS, OK)
7670 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7671 data_writes, arraysize(data_writes));
7672 session_deps_.socket_factory->AddSocketDataProvider(&data);
7674 SSLSocketDataProvider ssl(ASYNC, OK);
7675 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7677 TestCompletionCallback callback;
7679 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7680 EXPECT_EQ(ERR_IO_PENDING, rv);
7682 rv = callback.WaitForResult();
7683 EXPECT_EQ(OK, rv);
7685 LoadTimingInfo load_timing_info;
7686 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7687 TestLoadTimingNotReusedWithPac(load_timing_info,
7688 CONNECT_TIMING_HAS_SSL_TIMES);
7690 const HttpResponseInfo* response = trans->GetResponseInfo();
7691 ASSERT_TRUE(response != NULL);
7693 std::string response_text;
7694 rv = ReadTransaction(trans.get(), &response_text);
7695 EXPECT_EQ(OK, rv);
7696 EXPECT_EQ("Payload", response_text);
7699 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7700 HttpRequestInfo request;
7701 request.method = "GET";
7702 request.url = GURL("http://www.example.org/");
7703 request.load_flags = 0;
7705 session_deps_.proxy_service.reset(
7706 ProxyService::CreateFixed("socks4://myproxy:1080"));
7707 TestNetLog net_log;
7708 session_deps_.net_log = &net_log;
7710 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7711 scoped_ptr<HttpTransaction> trans(
7712 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7714 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7715 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7717 MockWrite data_writes[] = {
7718 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7719 MockWrite(
7720 "GET / HTTP/1.1\r\n"
7721 "Host: www.example.org\r\n"
7722 "Connection: keep-alive\r\n\r\n")};
7724 MockRead data_reads[] = {
7725 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7726 MockRead("HTTP/1.0 200 OK\r\n"),
7727 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7728 MockRead("Payload"),
7729 MockRead(SYNCHRONOUS, OK)
7732 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7733 data_writes, arraysize(data_writes));
7734 session_deps_.socket_factory->AddSocketDataProvider(&data);
7736 TestCompletionCallback callback;
7738 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7739 EXPECT_EQ(ERR_IO_PENDING, rv);
7741 rv = callback.WaitForResult();
7742 EXPECT_EQ(OK, rv);
7744 const HttpResponseInfo* response = trans->GetResponseInfo();
7745 ASSERT_TRUE(response != NULL);
7747 LoadTimingInfo load_timing_info;
7748 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7749 TestLoadTimingNotReused(load_timing_info,
7750 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7752 std::string response_text;
7753 rv = ReadTransaction(trans.get(), &response_text);
7754 EXPECT_EQ(OK, rv);
7755 EXPECT_EQ("Payload", response_text);
7758 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7759 HttpRequestInfo request;
7760 request.method = "GET";
7761 request.url = GURL("http://www.example.org/");
7762 request.load_flags = 0;
7764 session_deps_.proxy_service.reset(
7765 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7766 TestNetLog net_log;
7767 session_deps_.net_log = &net_log;
7769 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7770 scoped_ptr<HttpTransaction> trans(
7771 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7773 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7774 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7775 const char kSOCKS5OkRequest[] = {
7776 0x05, // Version
7777 0x01, // Command (CONNECT)
7778 0x00, // Reserved.
7779 0x03, // Address type (DOMAINNAME).
7780 0x0F, // Length of domain (15)
7781 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7782 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7784 const char kSOCKS5OkResponse[] =
7785 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7787 MockWrite data_writes[] = {
7788 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7789 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7790 MockWrite(
7791 "GET / HTTP/1.1\r\n"
7792 "Host: www.example.org\r\n"
7793 "Connection: keep-alive\r\n\r\n")};
7795 MockRead data_reads[] = {
7796 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7797 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7798 MockRead("HTTP/1.0 200 OK\r\n"),
7799 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7800 MockRead("Payload"),
7801 MockRead(SYNCHRONOUS, OK)
7804 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7805 data_writes, arraysize(data_writes));
7806 session_deps_.socket_factory->AddSocketDataProvider(&data);
7808 TestCompletionCallback callback;
7810 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7811 EXPECT_EQ(ERR_IO_PENDING, rv);
7813 rv = callback.WaitForResult();
7814 EXPECT_EQ(OK, rv);
7816 const HttpResponseInfo* response = trans->GetResponseInfo();
7817 ASSERT_TRUE(response != NULL);
7819 LoadTimingInfo load_timing_info;
7820 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7821 TestLoadTimingNotReusedWithPac(load_timing_info,
7822 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7824 std::string response_text;
7825 rv = ReadTransaction(trans.get(), &response_text);
7826 EXPECT_EQ(OK, rv);
7827 EXPECT_EQ("Payload", response_text);
7830 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7831 HttpRequestInfo request;
7832 request.method = "GET";
7833 request.url = GURL("https://www.example.org/");
7834 request.load_flags = 0;
7836 session_deps_.proxy_service.reset(
7837 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7838 TestNetLog net_log;
7839 session_deps_.net_log = &net_log;
7841 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7842 scoped_ptr<HttpTransaction> trans(
7843 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7845 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7846 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7847 const unsigned char kSOCKS5OkRequest[] = {
7848 0x05, // Version
7849 0x01, // Command (CONNECT)
7850 0x00, // Reserved.
7851 0x03, // Address type (DOMAINNAME).
7852 0x0F, // Length of domain (15)
7853 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7854 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7857 const char kSOCKS5OkResponse[] =
7858 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7860 MockWrite data_writes[] = {
7861 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7862 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7863 arraysize(kSOCKS5OkRequest)),
7864 MockWrite(
7865 "GET / HTTP/1.1\r\n"
7866 "Host: www.example.org\r\n"
7867 "Connection: keep-alive\r\n\r\n")};
7869 MockRead data_reads[] = {
7870 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7871 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7872 MockRead("HTTP/1.0 200 OK\r\n"),
7873 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7874 MockRead("Payload"),
7875 MockRead(SYNCHRONOUS, OK)
7878 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7879 data_writes, arraysize(data_writes));
7880 session_deps_.socket_factory->AddSocketDataProvider(&data);
7882 SSLSocketDataProvider ssl(ASYNC, OK);
7883 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7885 TestCompletionCallback callback;
7887 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7888 EXPECT_EQ(ERR_IO_PENDING, rv);
7890 rv = callback.WaitForResult();
7891 EXPECT_EQ(OK, rv);
7893 const HttpResponseInfo* response = trans->GetResponseInfo();
7894 ASSERT_TRUE(response != NULL);
7896 LoadTimingInfo load_timing_info;
7897 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7898 TestLoadTimingNotReusedWithPac(load_timing_info,
7899 CONNECT_TIMING_HAS_SSL_TIMES);
7901 std::string response_text;
7902 rv = ReadTransaction(trans.get(), &response_text);
7903 EXPECT_EQ(OK, rv);
7904 EXPECT_EQ("Payload", response_text);
7907 namespace {
7909 // Tests that for connection endpoints the group names are correctly set.
7911 struct GroupNameTest {
7912 std::string proxy_server;
7913 std::string url;
7914 std::string expected_group_name;
7915 bool ssl;
7918 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7919 NextProto next_proto,
7920 SpdySessionDependencies* session_deps_) {
7921 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7923 base::WeakPtr<HttpServerProperties> http_server_properties =
7924 session->http_server_properties();
7925 AlternativeService alternative_service(
7926 AlternateProtocolFromNextProto(next_proto), "", 443);
7927 http_server_properties->SetAlternativeService(
7928 HostPortPair("host.with.alternate", 80), alternative_service, 1.0);
7930 return session;
7933 int GroupNameTransactionHelper(
7934 const std::string& url,
7935 const scoped_refptr<HttpNetworkSession>& session) {
7936 HttpRequestInfo request;
7937 request.method = "GET";
7938 request.url = GURL(url);
7939 request.load_flags = 0;
7941 scoped_ptr<HttpTransaction> trans(
7942 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7944 TestCompletionCallback callback;
7946 // We do not complete this request, the dtor will clean the transaction up.
7947 return trans->Start(&request, callback.callback(), BoundNetLog());
7950 } // namespace
7952 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7953 const GroupNameTest tests[] = {
7955 "", // unused
7956 "http://www.example.org/direct",
7957 "www.example.org:80",
7958 false,
7961 "", // unused
7962 "http://[2001:1418:13:1::25]/direct",
7963 "[2001:1418:13:1::25]:80",
7964 false,
7967 // SSL Tests
7969 "", // unused
7970 "https://www.example.org/direct_ssl",
7971 "ssl/www.example.org:443",
7972 true,
7975 "", // unused
7976 "https://[2001:1418:13:1::25]/direct",
7977 "ssl/[2001:1418:13:1::25]:443",
7978 true,
7981 "", // unused
7982 "http://host.with.alternate/direct",
7983 "ssl/host.with.alternate:443",
7984 true,
7988 session_deps_.use_alternate_protocols = true;
7990 for (size_t i = 0; i < arraysize(tests); ++i) {
7991 session_deps_.proxy_service.reset(
7992 ProxyService::CreateFixed(tests[i].proxy_server));
7993 scoped_refptr<HttpNetworkSession> session(
7994 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7996 HttpNetworkSessionPeer peer(session);
7997 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7998 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7999 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8000 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8001 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8002 new MockClientSocketPoolManager);
8003 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8004 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
8005 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8007 EXPECT_EQ(ERR_IO_PENDING,
8008 GroupNameTransactionHelper(tests[i].url, session));
8009 if (tests[i].ssl)
8010 EXPECT_EQ(tests[i].expected_group_name,
8011 ssl_conn_pool->last_group_name_received());
8012 else
8013 EXPECT_EQ(tests[i].expected_group_name,
8014 transport_conn_pool->last_group_name_received());
8019 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
8020 const GroupNameTest tests[] = {
8022 "http_proxy",
8023 "http://www.example.org/http_proxy_normal",
8024 "www.example.org:80",
8025 false,
8028 // SSL Tests
8030 "http_proxy",
8031 "https://www.example.org/http_connect_ssl",
8032 "ssl/www.example.org:443",
8033 true,
8037 "http_proxy",
8038 "http://host.with.alternate/direct",
8039 "ssl/host.with.alternate:443",
8040 true,
8044 "http_proxy",
8045 "ftp://ftp.google.com/http_proxy_normal",
8046 "ftp/ftp.google.com:21",
8047 false,
8051 session_deps_.use_alternate_protocols = true;
8053 for (size_t i = 0; i < arraysize(tests); ++i) {
8054 session_deps_.proxy_service.reset(
8055 ProxyService::CreateFixed(tests[i].proxy_server));
8056 scoped_refptr<HttpNetworkSession> session(
8057 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8059 HttpNetworkSessionPeer peer(session);
8061 HostPortPair proxy_host("http_proxy", 80);
8062 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
8063 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
8064 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8065 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8067 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8068 new MockClientSocketPoolManager);
8069 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8070 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8071 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8073 EXPECT_EQ(ERR_IO_PENDING,
8074 GroupNameTransactionHelper(tests[i].url, session));
8075 if (tests[i].ssl)
8076 EXPECT_EQ(tests[i].expected_group_name,
8077 ssl_conn_pool->last_group_name_received());
8078 else
8079 EXPECT_EQ(tests[i].expected_group_name,
8080 http_proxy_pool->last_group_name_received());
8084 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
8085 const GroupNameTest tests[] = {
8087 "socks4://socks_proxy:1080",
8088 "http://www.example.org/socks4_direct",
8089 "socks4/www.example.org:80",
8090 false,
8093 "socks5://socks_proxy:1080",
8094 "http://www.example.org/socks5_direct",
8095 "socks5/www.example.org:80",
8096 false,
8099 // SSL Tests
8101 "socks4://socks_proxy:1080",
8102 "https://www.example.org/socks4_ssl",
8103 "socks4/ssl/www.example.org:443",
8104 true,
8107 "socks5://socks_proxy:1080",
8108 "https://www.example.org/socks5_ssl",
8109 "socks5/ssl/www.example.org:443",
8110 true,
8114 "socks4://socks_proxy:1080",
8115 "http://host.with.alternate/direct",
8116 "socks4/ssl/host.with.alternate:443",
8117 true,
8121 session_deps_.use_alternate_protocols = true;
8123 for (size_t i = 0; i < arraysize(tests); ++i) {
8124 session_deps_.proxy_service.reset(
8125 ProxyService::CreateFixed(tests[i].proxy_server));
8126 scoped_refptr<HttpNetworkSession> session(
8127 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
8129 HttpNetworkSessionPeer peer(session);
8131 HostPortPair proxy_host("socks_proxy", 1080);
8132 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
8133 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
8134 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
8135 new CaptureGroupNameSSLSocketPool(NULL, NULL);
8137 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8138 new MockClientSocketPoolManager);
8139 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8140 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
8141 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
8143 scoped_ptr<HttpTransaction> trans(
8144 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8146 EXPECT_EQ(ERR_IO_PENDING,
8147 GroupNameTransactionHelper(tests[i].url, session));
8148 if (tests[i].ssl)
8149 EXPECT_EQ(tests[i].expected_group_name,
8150 ssl_conn_pool->last_group_name_received());
8151 else
8152 EXPECT_EQ(tests[i].expected_group_name,
8153 socks_conn_pool->last_group_name_received());
8157 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
8158 HttpRequestInfo request;
8159 request.method = "GET";
8160 request.url = GURL("http://www.example.org/");
8162 session_deps_.proxy_service.reset(
8163 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8165 // This simulates failure resolving all hostnames; that means we will fail
8166 // connecting to both proxies (myproxy:70 and foobar:80).
8167 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
8169 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8170 scoped_ptr<HttpTransaction> trans(
8171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8173 TestCompletionCallback callback;
8175 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8176 EXPECT_EQ(ERR_IO_PENDING, rv);
8178 rv = callback.WaitForResult();
8179 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
8182 // Base test to make sure that when the load flags for a request specify to
8183 // bypass the cache, the DNS cache is not used.
8184 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8185 int load_flags) {
8186 // Issue a request, asking to bypass the cache(s).
8187 HttpRequestInfo request;
8188 request.method = "GET";
8189 request.load_flags = load_flags;
8190 request.url = GURL("http://www.example.org/");
8192 // Select a host resolver that does caching.
8193 session_deps_.host_resolver.reset(new MockCachingHostResolver);
8195 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8196 scoped_ptr<HttpTransaction> trans(
8197 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8199 // Warm up the host cache so it has an entry for "www.example.org".
8200 AddressList addrlist;
8201 TestCompletionCallback callback;
8202 int rv = session_deps_.host_resolver->Resolve(
8203 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8204 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8205 EXPECT_EQ(ERR_IO_PENDING, rv);
8206 rv = callback.WaitForResult();
8207 EXPECT_EQ(OK, rv);
8209 // Verify that it was added to host cache, by doing a subsequent async lookup
8210 // and confirming it completes synchronously.
8211 rv = session_deps_.host_resolver->Resolve(
8212 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8213 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
8214 ASSERT_EQ(OK, rv);
8216 // Inject a failure the next time that "www.example.org" is resolved. This way
8217 // we can tell if the next lookup hit the cache, or the "network".
8218 // (cache --> success, "network" --> failure).
8219 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
8221 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8222 // first read -- this won't be reached as the host resolution will fail first.
8223 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
8224 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8225 session_deps_.socket_factory->AddSocketDataProvider(&data);
8227 // Run the request.
8228 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8229 ASSERT_EQ(ERR_IO_PENDING, rv);
8230 rv = callback.WaitForResult();
8232 // If we bypassed the cache, we would have gotten a failure while resolving
8233 // "www.example.org".
8234 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8237 // There are multiple load flags that should trigger the host cache bypass.
8238 // Test each in isolation:
8239 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
8240 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8243 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
8244 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8247 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
8248 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8251 // Make sure we can handle an error when writing the request.
8252 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
8253 HttpRequestInfo request;
8254 request.method = "GET";
8255 request.url = GURL("http://www.foo.com/");
8256 request.load_flags = 0;
8258 MockWrite write_failure[] = {
8259 MockWrite(ASYNC, ERR_CONNECTION_RESET),
8261 StaticSocketDataProvider data(NULL, 0,
8262 write_failure, arraysize(write_failure));
8263 session_deps_.socket_factory->AddSocketDataProvider(&data);
8264 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8266 TestCompletionCallback callback;
8268 scoped_ptr<HttpTransaction> trans(
8269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8271 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8272 EXPECT_EQ(ERR_IO_PENDING, rv);
8274 rv = callback.WaitForResult();
8275 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
8278 // Check that a connection closed after the start of the headers finishes ok.
8279 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
8280 HttpRequestInfo request;
8281 request.method = "GET";
8282 request.url = GURL("http://www.foo.com/");
8283 request.load_flags = 0;
8285 MockRead data_reads[] = {
8286 MockRead("HTTP/1."),
8287 MockRead(SYNCHRONOUS, OK),
8290 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8291 session_deps_.socket_factory->AddSocketDataProvider(&data);
8292 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8294 TestCompletionCallback callback;
8296 scoped_ptr<HttpTransaction> trans(
8297 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8299 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8300 EXPECT_EQ(ERR_IO_PENDING, rv);
8302 rv = callback.WaitForResult();
8303 EXPECT_EQ(OK, rv);
8305 const HttpResponseInfo* response = trans->GetResponseInfo();
8306 ASSERT_TRUE(response != NULL);
8308 EXPECT_TRUE(response->headers.get() != NULL);
8309 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8311 std::string response_data;
8312 rv = ReadTransaction(trans.get(), &response_data);
8313 EXPECT_EQ(OK, rv);
8314 EXPECT_EQ("", response_data);
8317 // Make sure that a dropped connection while draining the body for auth
8318 // restart does the right thing.
8319 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
8320 HttpRequestInfo request;
8321 request.method = "GET";
8322 request.url = GURL("http://www.example.org/");
8323 request.load_flags = 0;
8325 MockWrite data_writes1[] = {
8326 MockWrite(
8327 "GET / HTTP/1.1\r\n"
8328 "Host: www.example.org\r\n"
8329 "Connection: keep-alive\r\n\r\n"),
8332 MockRead data_reads1[] = {
8333 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8334 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8335 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8336 MockRead("Content-Length: 14\r\n\r\n"),
8337 MockRead("Unauth"),
8338 MockRead(ASYNC, ERR_CONNECTION_RESET),
8341 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8342 data_writes1, arraysize(data_writes1));
8343 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8345 // After calling trans->RestartWithAuth(), this is the request we should
8346 // be issuing -- the final header line contains the credentials.
8347 MockWrite data_writes2[] = {
8348 MockWrite(
8349 "GET / HTTP/1.1\r\n"
8350 "Host: www.example.org\r\n"
8351 "Connection: keep-alive\r\n"
8352 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8355 // Lastly, the server responds with the actual content.
8356 MockRead data_reads2[] = {
8357 MockRead("HTTP/1.1 200 OK\r\n"),
8358 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8359 MockRead("Content-Length: 100\r\n\r\n"),
8360 MockRead(SYNCHRONOUS, OK),
8363 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8364 data_writes2, arraysize(data_writes2));
8365 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8366 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8368 TestCompletionCallback callback1;
8370 scoped_ptr<HttpTransaction> trans(
8371 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8373 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8374 EXPECT_EQ(ERR_IO_PENDING, rv);
8376 rv = callback1.WaitForResult();
8377 EXPECT_EQ(OK, rv);
8379 const HttpResponseInfo* response = trans->GetResponseInfo();
8380 ASSERT_TRUE(response != NULL);
8381 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
8383 TestCompletionCallback callback2;
8385 rv = trans->RestartWithAuth(
8386 AuthCredentials(kFoo, kBar), callback2.callback());
8387 EXPECT_EQ(ERR_IO_PENDING, rv);
8389 rv = callback2.WaitForResult();
8390 EXPECT_EQ(OK, rv);
8392 response = trans->GetResponseInfo();
8393 ASSERT_TRUE(response != NULL);
8394 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8395 EXPECT_EQ(100, response->headers->GetContentLength());
8398 // Test HTTPS connections going through a proxy that sends extra data.
8399 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8400 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8402 HttpRequestInfo request;
8403 request.method = "GET";
8404 request.url = GURL("https://www.example.org/");
8405 request.load_flags = 0;
8407 MockRead proxy_reads[] = {
8408 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8409 MockRead(SYNCHRONOUS, OK)
8412 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8413 SSLSocketDataProvider ssl(ASYNC, OK);
8415 session_deps_.socket_factory->AddSocketDataProvider(&data);
8416 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8418 TestCompletionCallback callback;
8420 session_deps_.socket_factory->ResetNextMockIndexes();
8422 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8423 scoped_ptr<HttpTransaction> trans(
8424 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8426 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8427 EXPECT_EQ(ERR_IO_PENDING, rv);
8429 rv = callback.WaitForResult();
8430 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8433 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8434 HttpRequestInfo request;
8435 request.method = "GET";
8436 request.url = GURL("http://www.example.org/");
8437 request.load_flags = 0;
8439 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8440 scoped_ptr<HttpTransaction> trans(
8441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8443 MockRead data_reads[] = {
8444 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8445 MockRead(SYNCHRONOUS, OK),
8448 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8449 session_deps_.socket_factory->AddSocketDataProvider(&data);
8451 TestCompletionCallback callback;
8453 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8454 EXPECT_EQ(ERR_IO_PENDING, rv);
8456 EXPECT_EQ(OK, callback.WaitForResult());
8458 const HttpResponseInfo* response = trans->GetResponseInfo();
8459 ASSERT_TRUE(response != NULL);
8461 EXPECT_TRUE(response->headers.get() != NULL);
8462 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8464 std::string response_data;
8465 rv = ReadTransaction(trans.get(), &response_data);
8466 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8469 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8470 base::FilePath temp_file_path;
8471 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8472 const uint64 kFakeSize = 100000; // file is actually blank
8473 UploadFileElementReader::ScopedOverridingContentLengthForTests
8474 overriding_content_length(kFakeSize);
8476 ScopedVector<UploadElementReader> element_readers;
8477 element_readers.push_back(
8478 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8479 temp_file_path,
8481 kuint64max,
8482 base::Time()));
8483 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8485 HttpRequestInfo request;
8486 request.method = "POST";
8487 request.url = GURL("http://www.example.org/upload");
8488 request.upload_data_stream = &upload_data_stream;
8489 request.load_flags = 0;
8491 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8492 scoped_ptr<HttpTransaction> trans(
8493 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8495 MockRead data_reads[] = {
8496 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8497 MockRead("hello world"),
8498 MockRead(SYNCHRONOUS, OK),
8500 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8501 session_deps_.socket_factory->AddSocketDataProvider(&data);
8503 TestCompletionCallback callback;
8505 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8506 EXPECT_EQ(ERR_IO_PENDING, rv);
8508 rv = callback.WaitForResult();
8509 EXPECT_EQ(OK, rv);
8511 const HttpResponseInfo* response = trans->GetResponseInfo();
8512 ASSERT_TRUE(response != NULL);
8514 EXPECT_TRUE(response->headers.get() != NULL);
8515 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8517 std::string response_data;
8518 rv = ReadTransaction(trans.get(), &response_data);
8519 EXPECT_EQ(OK, rv);
8520 EXPECT_EQ("hello world", response_data);
8522 base::DeleteFile(temp_file_path, false);
8525 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8526 base::FilePath temp_file;
8527 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8528 std::string temp_file_content("Unreadable file.");
8529 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8530 temp_file_content.length()));
8531 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
8533 ScopedVector<UploadElementReader> element_readers;
8534 element_readers.push_back(
8535 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8536 temp_file,
8538 kuint64max,
8539 base::Time()));
8540 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8542 HttpRequestInfo request;
8543 request.method = "POST";
8544 request.url = GURL("http://www.example.org/upload");
8545 request.upload_data_stream = &upload_data_stream;
8546 request.load_flags = 0;
8548 // If we try to upload an unreadable file, the transaction should fail.
8549 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8550 scoped_ptr<HttpTransaction> trans(
8551 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8553 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8554 session_deps_.socket_factory->AddSocketDataProvider(&data);
8556 TestCompletionCallback callback;
8558 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8559 EXPECT_EQ(ERR_IO_PENDING, rv);
8561 rv = callback.WaitForResult();
8562 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8564 const HttpResponseInfo* response = trans->GetResponseInfo();
8565 EXPECT_FALSE(response);
8567 base::DeleteFile(temp_file, false);
8570 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8571 class FakeUploadElementReader : public UploadElementReader {
8572 public:
8573 FakeUploadElementReader() {}
8574 ~FakeUploadElementReader() override {}
8576 const CompletionCallback& callback() const { return callback_; }
8578 // UploadElementReader overrides:
8579 int Init(const CompletionCallback& callback) override {
8580 callback_ = callback;
8581 return ERR_IO_PENDING;
8583 uint64 GetContentLength() const override { return 0; }
8584 uint64 BytesRemaining() const override { return 0; }
8585 int Read(IOBuffer* buf,
8586 int buf_length,
8587 const CompletionCallback& callback) override {
8588 return ERR_FAILED;
8591 private:
8592 CompletionCallback callback_;
8595 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8596 ScopedVector<UploadElementReader> element_readers;
8597 element_readers.push_back(fake_reader);
8598 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
8600 HttpRequestInfo request;
8601 request.method = "POST";
8602 request.url = GURL("http://www.example.org/upload");
8603 request.upload_data_stream = &upload_data_stream;
8604 request.load_flags = 0;
8606 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8607 scoped_ptr<HttpTransaction> trans(
8608 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8610 StaticSocketDataProvider data;
8611 session_deps_.socket_factory->AddSocketDataProvider(&data);
8613 TestCompletionCallback callback;
8614 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8615 EXPECT_EQ(ERR_IO_PENDING, rv);
8616 base::MessageLoop::current()->RunUntilIdle();
8618 // Transaction is pending on request body initialization.
8619 ASSERT_FALSE(fake_reader->callback().is_null());
8621 // Return Init()'s result after the transaction gets destroyed.
8622 trans.reset();
8623 fake_reader->callback().Run(OK); // Should not crash.
8626 // Tests that changes to Auth realms are treated like auth rejections.
8627 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8629 HttpRequestInfo request;
8630 request.method = "GET";
8631 request.url = GURL("http://www.example.org/");
8632 request.load_flags = 0;
8634 // First transaction will request a resource and receive a Basic challenge
8635 // with realm="first_realm".
8636 MockWrite data_writes1[] = {
8637 MockWrite(
8638 "GET / HTTP/1.1\r\n"
8639 "Host: www.example.org\r\n"
8640 "Connection: keep-alive\r\n"
8641 "\r\n"),
8643 MockRead data_reads1[] = {
8644 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8645 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8646 "\r\n"),
8649 // After calling trans->RestartWithAuth(), provide an Authentication header
8650 // for first_realm. The server will reject and provide a challenge with
8651 // second_realm.
8652 MockWrite data_writes2[] = {
8653 MockWrite(
8654 "GET / HTTP/1.1\r\n"
8655 "Host: www.example.org\r\n"
8656 "Connection: keep-alive\r\n"
8657 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8658 "\r\n"),
8660 MockRead data_reads2[] = {
8661 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8662 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8663 "\r\n"),
8666 // This again fails, and goes back to first_realm. Make sure that the
8667 // entry is removed from cache.
8668 MockWrite data_writes3[] = {
8669 MockWrite(
8670 "GET / HTTP/1.1\r\n"
8671 "Host: www.example.org\r\n"
8672 "Connection: keep-alive\r\n"
8673 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8674 "\r\n"),
8676 MockRead data_reads3[] = {
8677 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8678 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8679 "\r\n"),
8682 // Try one last time (with the correct password) and get the resource.
8683 MockWrite data_writes4[] = {
8684 MockWrite(
8685 "GET / HTTP/1.1\r\n"
8686 "Host: www.example.org\r\n"
8687 "Connection: keep-alive\r\n"
8688 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8689 "\r\n"),
8691 MockRead data_reads4[] = {
8692 MockRead("HTTP/1.1 200 OK\r\n"
8693 "Content-Type: text/html; charset=iso-8859-1\r\n"
8694 "Content-Length: 5\r\n"
8695 "\r\n"
8696 "hello"),
8699 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8700 data_writes1, arraysize(data_writes1));
8701 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8702 data_writes2, arraysize(data_writes2));
8703 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8704 data_writes3, arraysize(data_writes3));
8705 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8706 data_writes4, arraysize(data_writes4));
8707 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8708 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8709 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8710 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8712 TestCompletionCallback callback1;
8714 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8715 scoped_ptr<HttpTransaction> trans(
8716 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8718 // Issue the first request with Authorize headers. There should be a
8719 // password prompt for first_realm waiting to be filled in after the
8720 // transaction completes.
8721 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8722 EXPECT_EQ(ERR_IO_PENDING, rv);
8723 rv = callback1.WaitForResult();
8724 EXPECT_EQ(OK, rv);
8725 const HttpResponseInfo* response = trans->GetResponseInfo();
8726 ASSERT_TRUE(response != NULL);
8727 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8728 ASSERT_FALSE(challenge == NULL);
8729 EXPECT_FALSE(challenge->is_proxy);
8730 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8731 EXPECT_EQ("first_realm", challenge->realm);
8732 EXPECT_EQ("basic", challenge->scheme);
8734 // Issue the second request with an incorrect password. There should be a
8735 // password prompt for second_realm waiting to be filled in after the
8736 // transaction completes.
8737 TestCompletionCallback callback2;
8738 rv = trans->RestartWithAuth(
8739 AuthCredentials(kFirst, kBaz), callback2.callback());
8740 EXPECT_EQ(ERR_IO_PENDING, rv);
8741 rv = callback2.WaitForResult();
8742 EXPECT_EQ(OK, rv);
8743 response = trans->GetResponseInfo();
8744 ASSERT_TRUE(response != NULL);
8745 challenge = response->auth_challenge.get();
8746 ASSERT_FALSE(challenge == NULL);
8747 EXPECT_FALSE(challenge->is_proxy);
8748 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8749 EXPECT_EQ("second_realm", challenge->realm);
8750 EXPECT_EQ("basic", challenge->scheme);
8752 // Issue the third request with another incorrect password. There should be
8753 // a password prompt for first_realm waiting to be filled in. If the password
8754 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8755 // first_realm was not correctly removed.
8756 TestCompletionCallback callback3;
8757 rv = trans->RestartWithAuth(
8758 AuthCredentials(kSecond, kFou), callback3.callback());
8759 EXPECT_EQ(ERR_IO_PENDING, rv);
8760 rv = callback3.WaitForResult();
8761 EXPECT_EQ(OK, rv);
8762 response = trans->GetResponseInfo();
8763 ASSERT_TRUE(response != NULL);
8764 challenge = response->auth_challenge.get();
8765 ASSERT_FALSE(challenge == NULL);
8766 EXPECT_FALSE(challenge->is_proxy);
8767 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
8768 EXPECT_EQ("first_realm", challenge->realm);
8769 EXPECT_EQ("basic", challenge->scheme);
8771 // Issue the fourth request with the correct password and username.
8772 TestCompletionCallback callback4;
8773 rv = trans->RestartWithAuth(
8774 AuthCredentials(kFirst, kBar), callback4.callback());
8775 EXPECT_EQ(ERR_IO_PENDING, rv);
8776 rv = callback4.WaitForResult();
8777 EXPECT_EQ(OK, rv);
8778 response = trans->GetResponseInfo();
8779 ASSERT_TRUE(response != NULL);
8780 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8783 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8784 session_deps_.next_protos = SpdyNextProtos();
8785 session_deps_.use_alternate_protocols = true;
8787 std::string alternate_protocol_http_header =
8788 GetAlternateProtocolHttpHeader();
8790 MockRead data_reads[] = {
8791 MockRead("HTTP/1.1 200 OK\r\n"),
8792 MockRead(alternate_protocol_http_header.c_str()),
8793 MockRead("hello world"),
8794 MockRead(SYNCHRONOUS, OK),
8797 HttpRequestInfo request;
8798 request.method = "GET";
8799 request.url = GURL("http://www.example.org/");
8800 request.load_flags = 0;
8802 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8804 session_deps_.socket_factory->AddSocketDataProvider(&data);
8806 TestCompletionCallback callback;
8808 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8809 scoped_ptr<HttpTransaction> trans(
8810 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8812 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8813 EXPECT_EQ(ERR_IO_PENDING, rv);
8815 HostPortPair http_host_port_pair("www.example.org", 80);
8816 HttpServerProperties& http_server_properties =
8817 *session->http_server_properties();
8818 AlternativeService alternative_service =
8819 http_server_properties.GetAlternativeService(http_host_port_pair);
8820 EXPECT_EQ(alternative_service.protocol, UNINITIALIZED_ALTERNATE_PROTOCOL);
8822 EXPECT_EQ(OK, callback.WaitForResult());
8824 const HttpResponseInfo* response = trans->GetResponseInfo();
8825 ASSERT_TRUE(response != NULL);
8826 ASSERT_TRUE(response->headers.get() != NULL);
8827 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8828 EXPECT_FALSE(response->was_fetched_via_spdy);
8829 EXPECT_FALSE(response->was_npn_negotiated);
8831 std::string response_data;
8832 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8833 EXPECT_EQ("hello world", response_data);
8835 alternative_service =
8836 http_server_properties.GetAlternativeService(http_host_port_pair);
8837 EXPECT_EQ(443, alternative_service.port);
8838 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8839 alternative_service.protocol);
8842 TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
8843 session_deps_.next_protos = SpdyNextProtos();
8844 session_deps_.use_alternate_protocols = true;
8846 MockRead data_reads[] = {
8847 MockRead("HTTP/1.1 200 OK\r\n"),
8848 MockRead("Alternate-Protocol: \r\n\r\n"),
8849 MockRead("hello world"),
8850 MockRead(SYNCHRONOUS, OK),
8853 HttpRequestInfo request;
8854 request.method = "GET";
8855 request.url = GURL("http://www.example.org/");
8856 request.load_flags = 0;
8858 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8860 session_deps_.socket_factory->AddSocketDataProvider(&data);
8862 TestCompletionCallback callback;
8864 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8866 HostPortPair http_host_port_pair("www.example.org", 80);
8867 HttpServerProperties& http_server_properties =
8868 *session->http_server_properties();
8869 AlternativeService alternative_service(QUIC, "", 80);
8870 http_server_properties.SetAlternativeService(http_host_port_pair,
8871 alternative_service, 1.0);
8873 alternative_service =
8874 http_server_properties.GetAlternativeService(http_host_port_pair);
8875 EXPECT_EQ(alternative_service.protocol, QUIC);
8877 scoped_ptr<HttpTransaction> trans(
8878 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8880 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8881 EXPECT_EQ(ERR_IO_PENDING, rv);
8883 EXPECT_EQ(OK, callback.WaitForResult());
8885 const HttpResponseInfo* response = trans->GetResponseInfo();
8886 ASSERT_TRUE(response != NULL);
8887 ASSERT_TRUE(response->headers.get() != NULL);
8888 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8889 EXPECT_FALSE(response->was_fetched_via_spdy);
8890 EXPECT_FALSE(response->was_npn_negotiated);
8892 std::string response_data;
8893 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8894 EXPECT_EQ("hello world", response_data);
8896 alternative_service =
8897 http_server_properties.GetAlternativeService(http_host_port_pair);
8898 EXPECT_EQ(alternative_service.protocol, UNINITIALIZED_ALTERNATE_PROTOCOL);
8901 TEST_P(HttpNetworkTransactionTest,
8902 MarkBrokenAlternateProtocolAndFallback) {
8903 session_deps_.use_alternate_protocols = true;
8905 HttpRequestInfo request;
8906 request.method = "GET";
8907 request.url = GURL("http://www.example.org/");
8908 request.load_flags = 0;
8910 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8911 StaticSocketDataProvider first_data;
8912 first_data.set_connect_data(mock_connect);
8913 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8915 MockRead data_reads[] = {
8916 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8917 MockRead("hello world"),
8918 MockRead(ASYNC, OK),
8920 StaticSocketDataProvider second_data(
8921 data_reads, arraysize(data_reads), NULL, 0);
8922 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8924 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8926 base::WeakPtr<HttpServerProperties> http_server_properties =
8927 session->http_server_properties();
8928 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
8929 // Port must be < 1024, or the header will be ignored (since initial port was
8930 // port 80 (another restricted port).
8931 AlternativeService alternative_service(
8932 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8933 666); /* port is ignored by MockConnect anyway */
8934 http_server_properties->SetAlternativeService(host_port_pair,
8935 alternative_service, 1.0);
8937 scoped_ptr<HttpTransaction> trans(
8938 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8939 TestCompletionCallback callback;
8941 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8942 EXPECT_EQ(ERR_IO_PENDING, rv);
8943 EXPECT_EQ(OK, callback.WaitForResult());
8945 const HttpResponseInfo* response = trans->GetResponseInfo();
8946 ASSERT_TRUE(response != NULL);
8947 ASSERT_TRUE(response->headers.get() != NULL);
8948 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8950 std::string response_data;
8951 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8952 EXPECT_EQ("hello world", response_data);
8954 alternative_service =
8955 http_server_properties->GetAlternativeService(host_port_pair);
8956 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL, alternative_service.protocol);
8957 EXPECT_TRUE(
8958 http_server_properties->IsAlternativeServiceBroken(alternative_service));
8961 TEST_P(HttpNetworkTransactionTest,
8962 AlternateProtocolPortRestrictedBlocked) {
8963 // Ensure that we're not allowed to redirect traffic via an alternate
8964 // protocol to an unrestricted (port >= 1024) when the original traffic was
8965 // on a restricted port (port < 1024). Ensure that we can redirect in all
8966 // other cases.
8967 session_deps_.use_alternate_protocols = true;
8969 HttpRequestInfo restricted_port_request;
8970 restricted_port_request.method = "GET";
8971 restricted_port_request.url = GURL("http://www.example.org:1023/");
8972 restricted_port_request.load_flags = 0;
8974 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8975 StaticSocketDataProvider first_data;
8976 first_data.set_connect_data(mock_connect);
8977 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8979 MockRead data_reads[] = {
8980 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8981 MockRead("hello world"),
8982 MockRead(ASYNC, OK),
8984 StaticSocketDataProvider second_data(
8985 data_reads, arraysize(data_reads), NULL, 0);
8986 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8988 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8990 base::WeakPtr<HttpServerProperties> http_server_properties =
8991 session->http_server_properties();
8992 const int kUnrestrictedAlternatePort = 1024;
8993 AlternativeService alternative_service(
8994 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8995 kUnrestrictedAlternatePort);
8996 http_server_properties->SetAlternativeService(
8997 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
8998 1.0);
9000 scoped_ptr<HttpTransaction> trans(
9001 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9002 TestCompletionCallback callback;
9004 int rv = trans->Start(
9005 &restricted_port_request,
9006 callback.callback(), BoundNetLog());
9007 EXPECT_EQ(ERR_IO_PENDING, rv);
9008 // Invalid change to unrestricted port should fail.
9009 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
9012 TEST_P(HttpNetworkTransactionTest,
9013 AlternateProtocolPortRestrictedPermitted) {
9014 // Ensure that we're allowed to redirect traffic via an alternate
9015 // protocol to an unrestricted (port >= 1024) when the original traffic was
9016 // on a restricted port (port < 1024) if we set
9017 // enable_user_alternate_protocol_ports.
9019 session_deps_.use_alternate_protocols = true;
9020 session_deps_.enable_user_alternate_protocol_ports = true;
9022 HttpRequestInfo restricted_port_request;
9023 restricted_port_request.method = "GET";
9024 restricted_port_request.url = GURL("http://www.example.org:1023/");
9025 restricted_port_request.load_flags = 0;
9027 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9028 StaticSocketDataProvider first_data;
9029 first_data.set_connect_data(mock_connect);
9030 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9032 MockRead data_reads[] = {
9033 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9034 MockRead("hello world"),
9035 MockRead(ASYNC, OK),
9037 StaticSocketDataProvider second_data(
9038 data_reads, arraysize(data_reads), NULL, 0);
9039 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9041 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9043 base::WeakPtr<HttpServerProperties> http_server_properties =
9044 session->http_server_properties();
9045 const int kUnrestrictedAlternatePort = 1024;
9046 AlternativeService alternative_service(
9047 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9048 kUnrestrictedAlternatePort);
9049 http_server_properties->SetAlternativeService(
9050 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9051 1.0);
9053 scoped_ptr<HttpTransaction> trans(
9054 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9055 TestCompletionCallback callback;
9057 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
9058 &restricted_port_request,
9059 callback.callback(), BoundNetLog()));
9060 // Change to unrestricted port should succeed.
9061 EXPECT_EQ(OK, callback.WaitForResult());
9064 TEST_P(HttpNetworkTransactionTest,
9065 AlternateProtocolPortRestrictedAllowed) {
9066 // Ensure that we're not allowed to redirect traffic via an alternate
9067 // protocol to an unrestricted (port >= 1024) when the original traffic was
9068 // on a restricted port (port < 1024). Ensure that we can redirect in all
9069 // other cases.
9070 session_deps_.use_alternate_protocols = true;
9072 HttpRequestInfo restricted_port_request;
9073 restricted_port_request.method = "GET";
9074 restricted_port_request.url = GURL("http://www.example.org:1023/");
9075 restricted_port_request.load_flags = 0;
9077 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9078 StaticSocketDataProvider first_data;
9079 first_data.set_connect_data(mock_connect);
9080 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9082 MockRead data_reads[] = {
9083 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9084 MockRead("hello world"),
9085 MockRead(ASYNC, OK),
9087 StaticSocketDataProvider second_data(
9088 data_reads, arraysize(data_reads), NULL, 0);
9089 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9091 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9093 base::WeakPtr<HttpServerProperties> http_server_properties =
9094 session->http_server_properties();
9095 const int kRestrictedAlternatePort = 80;
9096 AlternativeService alternative_service(
9097 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9098 kRestrictedAlternatePort);
9099 http_server_properties->SetAlternativeService(
9100 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
9101 1.0);
9103 scoped_ptr<HttpTransaction> trans(
9104 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9105 TestCompletionCallback callback;
9107 int rv = trans->Start(
9108 &restricted_port_request,
9109 callback.callback(), BoundNetLog());
9110 EXPECT_EQ(ERR_IO_PENDING, rv);
9111 // Valid change to restricted port should pass.
9112 EXPECT_EQ(OK, callback.WaitForResult());
9115 TEST_P(HttpNetworkTransactionTest,
9116 AlternateProtocolPortUnrestrictedAllowed1) {
9117 // Ensure that we're not allowed to redirect traffic via an alternate
9118 // protocol to an unrestricted (port >= 1024) when the original traffic was
9119 // on a restricted port (port < 1024). Ensure that we can redirect in all
9120 // other cases.
9121 session_deps_.use_alternate_protocols = true;
9123 HttpRequestInfo unrestricted_port_request;
9124 unrestricted_port_request.method = "GET";
9125 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9126 unrestricted_port_request.load_flags = 0;
9128 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9129 StaticSocketDataProvider first_data;
9130 first_data.set_connect_data(mock_connect);
9131 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9133 MockRead data_reads[] = {
9134 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9135 MockRead("hello world"),
9136 MockRead(ASYNC, OK),
9138 StaticSocketDataProvider second_data(
9139 data_reads, arraysize(data_reads), NULL, 0);
9140 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9142 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9144 base::WeakPtr<HttpServerProperties> http_server_properties =
9145 session->http_server_properties();
9146 const int kRestrictedAlternatePort = 80;
9147 AlternativeService alternative_service(
9148 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9149 kRestrictedAlternatePort);
9150 http_server_properties->SetAlternativeService(
9151 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9152 1.0);
9154 scoped_ptr<HttpTransaction> trans(
9155 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9156 TestCompletionCallback callback;
9158 int rv = trans->Start(
9159 &unrestricted_port_request, callback.callback(), BoundNetLog());
9160 EXPECT_EQ(ERR_IO_PENDING, rv);
9161 // Valid change to restricted port should pass.
9162 EXPECT_EQ(OK, callback.WaitForResult());
9165 TEST_P(HttpNetworkTransactionTest,
9166 AlternateProtocolPortUnrestrictedAllowed2) {
9167 // Ensure that we're not allowed to redirect traffic via an alternate
9168 // protocol to an unrestricted (port >= 1024) when the original traffic was
9169 // on a restricted port (port < 1024). Ensure that we can redirect in all
9170 // other cases.
9171 session_deps_.use_alternate_protocols = true;
9173 HttpRequestInfo unrestricted_port_request;
9174 unrestricted_port_request.method = "GET";
9175 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
9176 unrestricted_port_request.load_flags = 0;
9178 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9179 StaticSocketDataProvider first_data;
9180 first_data.set_connect_data(mock_connect);
9181 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9183 MockRead data_reads[] = {
9184 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9185 MockRead("hello world"),
9186 MockRead(ASYNC, OK),
9188 StaticSocketDataProvider second_data(
9189 data_reads, arraysize(data_reads), NULL, 0);
9190 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9192 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9194 base::WeakPtr<HttpServerProperties> http_server_properties =
9195 session->http_server_properties();
9196 const int kUnrestrictedAlternatePort = 1024;
9197 AlternativeService alternative_service(
9198 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9199 kUnrestrictedAlternatePort);
9200 http_server_properties->SetAlternativeService(
9201 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
9202 1.0);
9204 scoped_ptr<HttpTransaction> trans(
9205 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9206 TestCompletionCallback callback;
9208 int rv = trans->Start(
9209 &unrestricted_port_request, callback.callback(), BoundNetLog());
9210 EXPECT_EQ(ERR_IO_PENDING, rv);
9211 // Valid change to an unrestricted port should pass.
9212 EXPECT_EQ(OK, callback.WaitForResult());
9215 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
9216 // Ensure that we're not allowed to redirect traffic via an alternate
9217 // protocol to an unsafe port, and that we resume the second
9218 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9219 session_deps_.use_alternate_protocols = true;
9221 HttpRequestInfo request;
9222 request.method = "GET";
9223 request.url = GURL("http://www.example.org/");
9224 request.load_flags = 0;
9226 // The alternate protocol request will error out before we attempt to connect,
9227 // so only the standard HTTP request will try to connect.
9228 MockRead data_reads[] = {
9229 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9230 MockRead("hello world"),
9231 MockRead(ASYNC, OK),
9233 StaticSocketDataProvider data(
9234 data_reads, arraysize(data_reads), NULL, 0);
9235 session_deps_.socket_factory->AddSocketDataProvider(&data);
9237 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9239 base::WeakPtr<HttpServerProperties> http_server_properties =
9240 session->http_server_properties();
9241 const int kUnsafePort = 7;
9242 AlternativeService alternative_service(
9243 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9244 kUnsafePort);
9245 http_server_properties->SetAlternativeService(
9246 HostPortPair::FromURL(request.url), alternative_service, 1.0);
9248 scoped_ptr<HttpTransaction> trans(
9249 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9250 TestCompletionCallback callback;
9252 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9253 EXPECT_EQ(ERR_IO_PENDING, rv);
9254 // The HTTP request should succeed.
9255 EXPECT_EQ(OK, callback.WaitForResult());
9257 // Disable alternate protocol before the asserts.
9258 // HttpStreamFactory::set_use_alternate_protocols(false);
9260 const HttpResponseInfo* response = trans->GetResponseInfo();
9261 ASSERT_TRUE(response != NULL);
9262 ASSERT_TRUE(response->headers.get() != NULL);
9263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9265 std::string response_data;
9266 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9267 EXPECT_EQ("hello world", response_data);
9270 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
9271 session_deps_.use_alternate_protocols = true;
9272 session_deps_.next_protos = SpdyNextProtos();
9274 HttpRequestInfo request;
9275 request.method = "GET";
9276 request.url = GURL("http://www.example.org/");
9277 request.load_flags = 0;
9279 std::string alternate_protocol_http_header =
9280 GetAlternateProtocolHttpHeader();
9282 MockRead data_reads[] = {
9283 MockRead("HTTP/1.1 200 OK\r\n"),
9284 MockRead(alternate_protocol_http_header.c_str()),
9285 MockRead("hello world"),
9286 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9287 MockRead(ASYNC, OK)
9290 StaticSocketDataProvider first_transaction(
9291 data_reads, arraysize(data_reads), NULL, 0);
9292 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9294 SSLSocketDataProvider ssl(ASYNC, OK);
9295 ssl.SetNextProto(GetParam());
9296 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9297 ASSERT_TRUE(ssl.cert.get());
9298 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9300 scoped_ptr<SpdyFrame> req(
9301 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9302 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9304 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9305 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9306 MockRead spdy_reads[] = {
9307 CreateMockRead(*resp),
9308 CreateMockRead(*data),
9309 MockRead(ASYNC, 0, 0),
9312 DelayedSocketData spdy_data(
9313 1, // wait for one write to finish before reading.
9314 spdy_reads, arraysize(spdy_reads),
9315 spdy_writes, arraysize(spdy_writes));
9316 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9318 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9319 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9320 NULL, 0, NULL, 0);
9321 hanging_non_alternate_protocol_socket.set_connect_data(
9322 never_finishing_connect);
9323 session_deps_.socket_factory->AddSocketDataProvider(
9324 &hanging_non_alternate_protocol_socket);
9326 TestCompletionCallback callback;
9328 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9329 scoped_ptr<HttpTransaction> trans(
9330 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9332 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9333 EXPECT_EQ(ERR_IO_PENDING, rv);
9334 EXPECT_EQ(OK, callback.WaitForResult());
9336 const HttpResponseInfo* response = trans->GetResponseInfo();
9337 ASSERT_TRUE(response != NULL);
9338 ASSERT_TRUE(response->headers.get() != NULL);
9339 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9341 std::string response_data;
9342 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9343 EXPECT_EQ("hello world", response_data);
9345 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9347 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9348 EXPECT_EQ(ERR_IO_PENDING, rv);
9349 EXPECT_EQ(OK, callback.WaitForResult());
9351 response = trans->GetResponseInfo();
9352 ASSERT_TRUE(response != NULL);
9353 ASSERT_TRUE(response->headers.get() != NULL);
9354 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9355 EXPECT_TRUE(response->was_fetched_via_spdy);
9356 EXPECT_TRUE(response->was_npn_negotiated);
9358 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9359 EXPECT_EQ("hello!", response_data);
9362 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
9363 session_deps_.use_alternate_protocols = true;
9364 session_deps_.next_protos = SpdyNextProtos();
9366 HttpRequestInfo request;
9367 request.method = "GET";
9368 request.url = GURL("http://www.example.org/");
9369 request.load_flags = 0;
9371 std::string alternate_protocol_http_header =
9372 GetAlternateProtocolHttpHeader();
9374 MockRead data_reads[] = {
9375 MockRead("HTTP/1.1 200 OK\r\n"),
9376 MockRead(alternate_protocol_http_header.c_str()),
9377 MockRead("hello world"),
9378 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9379 MockRead(ASYNC, OK),
9382 StaticSocketDataProvider first_transaction(
9383 data_reads, arraysize(data_reads), NULL, 0);
9384 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9385 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9387 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9388 StaticSocketDataProvider hanging_socket(
9389 NULL, 0, NULL, 0);
9390 hanging_socket.set_connect_data(never_finishing_connect);
9391 // Socket 2 and 3 are the hanging Alternate-Protocol and
9392 // non-Alternate-Protocol jobs from the 2nd transaction.
9393 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9394 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9396 SSLSocketDataProvider ssl(ASYNC, OK);
9397 ssl.SetNextProto(GetParam());
9398 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9399 ASSERT_TRUE(ssl.cert.get());
9400 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9402 scoped_ptr<SpdyFrame> req1(
9403 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9404 scoped_ptr<SpdyFrame> req2(
9405 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9406 MockWrite spdy_writes[] = {
9407 CreateMockWrite(*req1),
9408 CreateMockWrite(*req2),
9410 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9411 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
9412 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9413 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9414 MockRead spdy_reads[] = {
9415 CreateMockRead(*resp1),
9416 CreateMockRead(*data1),
9417 CreateMockRead(*resp2),
9418 CreateMockRead(*data2),
9419 MockRead(ASYNC, 0, 0),
9422 DelayedSocketData spdy_data(
9423 2, // wait for writes to finish before reading.
9424 spdy_reads, arraysize(spdy_reads),
9425 spdy_writes, arraysize(spdy_writes));
9426 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9427 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9429 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9430 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
9432 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9433 TestCompletionCallback callback1;
9434 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9436 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
9437 EXPECT_EQ(ERR_IO_PENDING, rv);
9438 EXPECT_EQ(OK, callback1.WaitForResult());
9440 const HttpResponseInfo* response = trans1.GetResponseInfo();
9441 ASSERT_TRUE(response != NULL);
9442 ASSERT_TRUE(response->headers.get() != NULL);
9443 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9445 std::string response_data;
9446 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9447 EXPECT_EQ("hello world", response_data);
9449 TestCompletionCallback callback2;
9450 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9451 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
9452 EXPECT_EQ(ERR_IO_PENDING, rv);
9454 TestCompletionCallback callback3;
9455 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
9456 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
9457 EXPECT_EQ(ERR_IO_PENDING, rv);
9459 EXPECT_EQ(OK, callback2.WaitForResult());
9460 EXPECT_EQ(OK, callback3.WaitForResult());
9462 response = trans2.GetResponseInfo();
9463 ASSERT_TRUE(response != NULL);
9464 ASSERT_TRUE(response->headers.get() != NULL);
9465 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9466 EXPECT_TRUE(response->was_fetched_via_spdy);
9467 EXPECT_TRUE(response->was_npn_negotiated);
9468 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9469 EXPECT_EQ("hello!", response_data);
9471 response = trans3.GetResponseInfo();
9472 ASSERT_TRUE(response != NULL);
9473 ASSERT_TRUE(response->headers.get() != NULL);
9474 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9475 EXPECT_TRUE(response->was_fetched_via_spdy);
9476 EXPECT_TRUE(response->was_npn_negotiated);
9477 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9478 EXPECT_EQ("hello!", response_data);
9481 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9482 session_deps_.use_alternate_protocols = true;
9483 session_deps_.next_protos = SpdyNextProtos();
9485 HttpRequestInfo request;
9486 request.method = "GET";
9487 request.url = GURL("http://www.example.org/");
9488 request.load_flags = 0;
9490 std::string alternate_protocol_http_header =
9491 GetAlternateProtocolHttpHeader();
9493 MockRead data_reads[] = {
9494 MockRead("HTTP/1.1 200 OK\r\n"),
9495 MockRead(alternate_protocol_http_header.c_str()),
9496 MockRead("hello world"),
9497 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9498 MockRead(ASYNC, OK),
9501 StaticSocketDataProvider first_transaction(
9502 data_reads, arraysize(data_reads), NULL, 0);
9503 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9505 SSLSocketDataProvider ssl(ASYNC, OK);
9506 ssl.SetNextProto(GetParam());
9507 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9509 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9510 StaticSocketDataProvider hanging_alternate_protocol_socket(
9511 NULL, 0, NULL, 0);
9512 hanging_alternate_protocol_socket.set_connect_data(
9513 never_finishing_connect);
9514 session_deps_.socket_factory->AddSocketDataProvider(
9515 &hanging_alternate_protocol_socket);
9517 // 2nd request is just a copy of the first one, over HTTP again.
9518 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9520 TestCompletionCallback callback;
9522 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9523 scoped_ptr<HttpTransaction> trans(
9524 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9526 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9527 EXPECT_EQ(ERR_IO_PENDING, rv);
9528 EXPECT_EQ(OK, callback.WaitForResult());
9530 const HttpResponseInfo* response = trans->GetResponseInfo();
9531 ASSERT_TRUE(response != NULL);
9532 ASSERT_TRUE(response->headers.get() != NULL);
9533 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9535 std::string response_data;
9536 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9537 EXPECT_EQ("hello world", response_data);
9539 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9541 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9542 EXPECT_EQ(ERR_IO_PENDING, rv);
9543 EXPECT_EQ(OK, callback.WaitForResult());
9545 response = trans->GetResponseInfo();
9546 ASSERT_TRUE(response != NULL);
9547 ASSERT_TRUE(response->headers.get() != NULL);
9548 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9549 EXPECT_FALSE(response->was_fetched_via_spdy);
9550 EXPECT_FALSE(response->was_npn_negotiated);
9552 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9553 EXPECT_EQ("hello world", response_data);
9556 class CapturingProxyResolver : public ProxyResolver {
9557 public:
9558 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9559 ~CapturingProxyResolver() override {}
9561 int GetProxyForURL(const GURL& url,
9562 ProxyInfo* results,
9563 const CompletionCallback& callback,
9564 RequestHandle* request,
9565 const BoundNetLog& net_log) override {
9566 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9567 HostPortPair("myproxy", 80));
9568 results->UseProxyServer(proxy_server);
9569 resolved_.push_back(url);
9570 return OK;
9573 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
9575 LoadState GetLoadState(RequestHandle request) const override {
9576 NOTREACHED();
9577 return LOAD_STATE_IDLE;
9580 void CancelSetPacScript() override { NOTREACHED(); }
9582 int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9583 const CompletionCallback& /*callback*/) override {
9584 return OK;
9587 const std::vector<GURL>& resolved() const { return resolved_; }
9589 private:
9590 std::vector<GURL> resolved_;
9592 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9595 TEST_P(HttpNetworkTransactionTest,
9596 UseAlternateProtocolForTunneledNpnSpdy) {
9597 session_deps_.use_alternate_protocols = true;
9598 session_deps_.next_protos = SpdyNextProtos();
9600 ProxyConfig proxy_config;
9601 proxy_config.set_auto_detect(true);
9602 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9604 CapturingProxyResolver capturing_proxy_resolver;
9605 session_deps_.proxy_service.reset(new ProxyService(
9606 new ProxyConfigServiceFixed(proxy_config),
9607 make_scoped_ptr(
9608 new ForwardingProxyResolverFactory(&capturing_proxy_resolver)),
9609 NULL));
9610 TestNetLog net_log;
9611 session_deps_.net_log = &net_log;
9613 HttpRequestInfo request;
9614 request.method = "GET";
9615 request.url = GURL("http://www.example.org/");
9616 request.load_flags = 0;
9618 std::string alternate_protocol_http_header =
9619 GetAlternateProtocolHttpHeader();
9621 MockRead data_reads[] = {
9622 MockRead("HTTP/1.1 200 OK\r\n"),
9623 MockRead(alternate_protocol_http_header.c_str()),
9624 MockRead("hello world"),
9625 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9626 MockRead(ASYNC, OK),
9629 StaticSocketDataProvider first_transaction(
9630 data_reads, arraysize(data_reads), NULL, 0);
9631 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9633 SSLSocketDataProvider ssl(ASYNC, OK);
9634 ssl.SetNextProto(GetParam());
9635 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9636 ASSERT_TRUE(ssl.cert.get());
9637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9639 scoped_ptr<SpdyFrame> req(
9640 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9641 MockWrite spdy_writes[] = {
9642 MockWrite(
9643 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9644 "Host: www.example.org\r\n"
9645 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9646 CreateMockWrite(*req), // 3
9649 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9651 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9652 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9653 MockRead spdy_reads[] = {
9654 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
9655 CreateMockRead(*resp.get(), 4), // 2, 4
9656 CreateMockRead(*data.get(), 4), // 5
9657 MockRead(ASYNC, 0, 0, 4), // 6
9660 OrderedSocketData spdy_data(
9661 spdy_reads, arraysize(spdy_reads),
9662 spdy_writes, arraysize(spdy_writes));
9663 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9665 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9666 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9667 NULL, 0, NULL, 0);
9668 hanging_non_alternate_protocol_socket.set_connect_data(
9669 never_finishing_connect);
9670 session_deps_.socket_factory->AddSocketDataProvider(
9671 &hanging_non_alternate_protocol_socket);
9673 TestCompletionCallback callback;
9675 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9676 scoped_ptr<HttpTransaction> trans(
9677 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9679 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9680 EXPECT_EQ(ERR_IO_PENDING, rv);
9681 EXPECT_EQ(OK, callback.WaitForResult());
9683 const HttpResponseInfo* response = trans->GetResponseInfo();
9684 ASSERT_TRUE(response != NULL);
9685 ASSERT_TRUE(response->headers.get() != NULL);
9686 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9687 EXPECT_FALSE(response->was_fetched_via_spdy);
9688 EXPECT_FALSE(response->was_npn_negotiated);
9690 std::string response_data;
9691 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9692 EXPECT_EQ("hello world", response_data);
9694 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9696 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9697 EXPECT_EQ(ERR_IO_PENDING, rv);
9698 EXPECT_EQ(OK, callback.WaitForResult());
9700 response = trans->GetResponseInfo();
9701 ASSERT_TRUE(response != NULL);
9702 ASSERT_TRUE(response->headers.get() != NULL);
9703 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9704 EXPECT_TRUE(response->was_fetched_via_spdy);
9705 EXPECT_TRUE(response->was_npn_negotiated);
9707 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9708 EXPECT_EQ("hello!", response_data);
9709 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
9710 EXPECT_EQ("http://www.example.org/",
9711 capturing_proxy_resolver.resolved()[0].spec());
9712 EXPECT_EQ("https://www.example.org/",
9713 capturing_proxy_resolver.resolved()[1].spec());
9715 LoadTimingInfo load_timing_info;
9716 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9717 TestLoadTimingNotReusedWithPac(load_timing_info,
9718 CONNECT_TIMING_HAS_SSL_TIMES);
9721 TEST_P(HttpNetworkTransactionTest,
9722 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9723 session_deps_.use_alternate_protocols = true;
9724 session_deps_.next_protos = SpdyNextProtos();
9726 HttpRequestInfo request;
9727 request.method = "GET";
9728 request.url = GURL("http://www.example.org/");
9729 request.load_flags = 0;
9731 std::string alternate_protocol_http_header =
9732 GetAlternateProtocolHttpHeader();
9734 MockRead data_reads[] = {
9735 MockRead("HTTP/1.1 200 OK\r\n"),
9736 MockRead(alternate_protocol_http_header.c_str()),
9737 MockRead("hello world"),
9738 MockRead(ASYNC, OK),
9741 StaticSocketDataProvider first_transaction(
9742 data_reads, arraysize(data_reads), NULL, 0);
9743 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9745 SSLSocketDataProvider ssl(ASYNC, OK);
9746 ssl.SetNextProto(GetParam());
9747 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9748 ASSERT_TRUE(ssl.cert.get());
9749 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9751 scoped_ptr<SpdyFrame> req(
9752 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9753 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9755 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9756 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9757 MockRead spdy_reads[] = {
9758 CreateMockRead(*resp),
9759 CreateMockRead(*data),
9760 MockRead(ASYNC, 0, 0),
9763 DelayedSocketData spdy_data(
9764 1, // wait for one write to finish before reading.
9765 spdy_reads, arraysize(spdy_reads),
9766 spdy_writes, arraysize(spdy_writes));
9767 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9769 TestCompletionCallback callback;
9771 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9773 scoped_ptr<HttpTransaction> trans(
9774 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9776 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9777 EXPECT_EQ(ERR_IO_PENDING, rv);
9778 EXPECT_EQ(OK, callback.WaitForResult());
9780 const HttpResponseInfo* response = trans->GetResponseInfo();
9781 ASSERT_TRUE(response != NULL);
9782 ASSERT_TRUE(response->headers.get() != NULL);
9783 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9785 std::string response_data;
9786 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9787 EXPECT_EQ("hello world", response_data);
9789 // Set up an initial SpdySession in the pool to reuse.
9790 HostPortPair host_port_pair("www.example.org", 443);
9791 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9792 PRIVACY_MODE_DISABLED);
9793 base::WeakPtr<SpdySession> spdy_session =
9794 CreateSecureSpdySession(session, key, BoundNetLog());
9796 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9798 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9799 EXPECT_EQ(ERR_IO_PENDING, rv);
9800 EXPECT_EQ(OK, callback.WaitForResult());
9802 response = trans->GetResponseInfo();
9803 ASSERT_TRUE(response != NULL);
9804 ASSERT_TRUE(response->headers.get() != NULL);
9805 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9806 EXPECT_TRUE(response->was_fetched_via_spdy);
9807 EXPECT_TRUE(response->was_npn_negotiated);
9809 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9810 EXPECT_EQ("hello!", response_data);
9813 // GenerateAuthToken is a mighty big test.
9814 // It tests all permutation of GenerateAuthToken behavior:
9815 // - Synchronous and Asynchronous completion.
9816 // - OK or error on completion.
9817 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9818 // - HTTP or HTTPS backend (to include proxy tunneling).
9819 // - Non-authenticating and authenticating backend.
9821 // In all, there are 44 reasonable permuations (for example, if there are
9822 // problems generating an auth token for an authenticating proxy, we don't
9823 // need to test all permutations of the backend server).
9825 // The test proceeds by going over each of the configuration cases, and
9826 // potentially running up to three rounds in each of the tests. The TestConfig
9827 // specifies both the configuration for the test as well as the expectations
9828 // for the results.
9829 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9830 static const char kServer[] = "http://www.example.com";
9831 static const char kSecureServer[] = "https://www.example.com";
9832 static const char kProxy[] = "myproxy:70";
9833 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9835 enum AuthTiming {
9836 AUTH_NONE,
9837 AUTH_SYNC,
9838 AUTH_ASYNC,
9841 const MockWrite kGet(
9842 "GET / HTTP/1.1\r\n"
9843 "Host: www.example.com\r\n"
9844 "Connection: keep-alive\r\n\r\n");
9845 const MockWrite kGetProxy(
9846 "GET http://www.example.com/ HTTP/1.1\r\n"
9847 "Host: www.example.com\r\n"
9848 "Proxy-Connection: keep-alive\r\n\r\n");
9849 const MockWrite kGetAuth(
9850 "GET / HTTP/1.1\r\n"
9851 "Host: www.example.com\r\n"
9852 "Connection: keep-alive\r\n"
9853 "Authorization: auth_token\r\n\r\n");
9854 const MockWrite kGetProxyAuth(
9855 "GET http://www.example.com/ HTTP/1.1\r\n"
9856 "Host: www.example.com\r\n"
9857 "Proxy-Connection: keep-alive\r\n"
9858 "Proxy-Authorization: auth_token\r\n\r\n");
9859 const MockWrite kGetAuthThroughProxy(
9860 "GET http://www.example.com/ HTTP/1.1\r\n"
9861 "Host: www.example.com\r\n"
9862 "Proxy-Connection: keep-alive\r\n"
9863 "Authorization: auth_token\r\n\r\n");
9864 const MockWrite kGetAuthWithProxyAuth(
9865 "GET http://www.example.com/ HTTP/1.1\r\n"
9866 "Host: www.example.com\r\n"
9867 "Proxy-Connection: keep-alive\r\n"
9868 "Proxy-Authorization: auth_token\r\n"
9869 "Authorization: auth_token\r\n\r\n");
9870 const MockWrite kConnect(
9871 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9872 "Host: www.example.com\r\n"
9873 "Proxy-Connection: keep-alive\r\n\r\n");
9874 const MockWrite kConnectProxyAuth(
9875 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9876 "Host: www.example.com\r\n"
9877 "Proxy-Connection: keep-alive\r\n"
9878 "Proxy-Authorization: auth_token\r\n\r\n");
9880 const MockRead kSuccess(
9881 "HTTP/1.1 200 OK\r\n"
9882 "Content-Type: text/html; charset=iso-8859-1\r\n"
9883 "Content-Length: 3\r\n\r\n"
9884 "Yes");
9885 const MockRead kFailure(
9886 "Should not be called.");
9887 const MockRead kServerChallenge(
9888 "HTTP/1.1 401 Unauthorized\r\n"
9889 "WWW-Authenticate: Mock realm=server\r\n"
9890 "Content-Type: text/html; charset=iso-8859-1\r\n"
9891 "Content-Length: 14\r\n\r\n"
9892 "Unauthorized\r\n");
9893 const MockRead kProxyChallenge(
9894 "HTTP/1.1 407 Unauthorized\r\n"
9895 "Proxy-Authenticate: Mock realm=proxy\r\n"
9896 "Proxy-Connection: close\r\n"
9897 "Content-Type: text/html; charset=iso-8859-1\r\n"
9898 "Content-Length: 14\r\n\r\n"
9899 "Unauthorized\r\n");
9900 const MockRead kProxyConnected(
9901 "HTTP/1.1 200 Connection Established\r\n\r\n");
9903 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9904 // no constructors, but the C++ compiler on Windows warns about
9905 // unspecified data in compound literals. So, moved to using constructors,
9906 // and TestRound's created with the default constructor should not be used.
9907 struct TestRound {
9908 TestRound()
9909 : expected_rv(ERR_UNEXPECTED),
9910 extra_write(NULL),
9911 extra_read(NULL) {
9913 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9914 int expected_rv_arg)
9915 : write(write_arg),
9916 read(read_arg),
9917 expected_rv(expected_rv_arg),
9918 extra_write(NULL),
9919 extra_read(NULL) {
9921 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9922 int expected_rv_arg, const MockWrite* extra_write_arg,
9923 const MockRead* extra_read_arg)
9924 : write(write_arg),
9925 read(read_arg),
9926 expected_rv(expected_rv_arg),
9927 extra_write(extra_write_arg),
9928 extra_read(extra_read_arg) {
9930 MockWrite write;
9931 MockRead read;
9932 int expected_rv;
9933 const MockWrite* extra_write;
9934 const MockRead* extra_read;
9937 static const int kNoSSL = 500;
9939 struct TestConfig {
9940 const char* const proxy_url;
9941 AuthTiming proxy_auth_timing;
9942 int proxy_auth_rv;
9943 const char* const server_url;
9944 AuthTiming server_auth_timing;
9945 int server_auth_rv;
9946 int num_auth_rounds;
9947 int first_ssl_round;
9948 TestRound rounds[3];
9949 } test_configs[] = {
9950 // Non-authenticating HTTP server with a direct connection.
9951 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9952 { TestRound(kGet, kSuccess, OK)}},
9953 // Authenticating HTTP server with a direct connection.
9954 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9955 { TestRound(kGet, kServerChallenge, OK),
9956 TestRound(kGetAuth, kSuccess, OK)}},
9957 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9958 { TestRound(kGet, kServerChallenge, OK),
9959 TestRound(kGetAuth, kFailure, kAuthErr)}},
9960 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9961 { TestRound(kGet, kServerChallenge, OK),
9962 TestRound(kGetAuth, kSuccess, OK)}},
9963 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9964 { TestRound(kGet, kServerChallenge, OK),
9965 TestRound(kGetAuth, kFailure, kAuthErr)}},
9966 // Non-authenticating HTTP server through a non-authenticating proxy.
9967 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9968 { TestRound(kGetProxy, kSuccess, OK)}},
9969 // Authenticating HTTP server through a non-authenticating proxy.
9970 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9971 { TestRound(kGetProxy, kServerChallenge, OK),
9972 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9973 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9974 { TestRound(kGetProxy, kServerChallenge, OK),
9975 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9976 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9977 { TestRound(kGetProxy, kServerChallenge, OK),
9978 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9979 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9980 { TestRound(kGetProxy, kServerChallenge, OK),
9981 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9982 // Non-authenticating HTTP server through an authenticating proxy.
9983 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9984 { TestRound(kGetProxy, kProxyChallenge, OK),
9985 TestRound(kGetProxyAuth, kSuccess, OK)}},
9986 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9987 { TestRound(kGetProxy, kProxyChallenge, OK),
9988 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9989 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9990 { TestRound(kGetProxy, kProxyChallenge, OK),
9991 TestRound(kGetProxyAuth, kSuccess, OK)}},
9992 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9993 { TestRound(kGetProxy, kProxyChallenge, OK),
9994 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9995 // Authenticating HTTP server through an authenticating proxy.
9996 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9997 { TestRound(kGetProxy, kProxyChallenge, OK),
9998 TestRound(kGetProxyAuth, kServerChallenge, OK),
9999 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10000 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10001 { TestRound(kGetProxy, kProxyChallenge, OK),
10002 TestRound(kGetProxyAuth, kServerChallenge, OK),
10003 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10004 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10005 { TestRound(kGetProxy, kProxyChallenge, OK),
10006 TestRound(kGetProxyAuth, kServerChallenge, OK),
10007 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10008 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10009 { TestRound(kGetProxy, kProxyChallenge, OK),
10010 TestRound(kGetProxyAuth, kServerChallenge, OK),
10011 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10012 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10013 { TestRound(kGetProxy, kProxyChallenge, OK),
10014 TestRound(kGetProxyAuth, kServerChallenge, OK),
10015 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10016 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10017 { TestRound(kGetProxy, kProxyChallenge, OK),
10018 TestRound(kGetProxyAuth, kServerChallenge, OK),
10019 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10020 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10021 { TestRound(kGetProxy, kProxyChallenge, OK),
10022 TestRound(kGetProxyAuth, kServerChallenge, OK),
10023 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10024 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10025 { TestRound(kGetProxy, kProxyChallenge, OK),
10026 TestRound(kGetProxyAuth, kServerChallenge, OK),
10027 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10028 // Non-authenticating HTTPS server with a direct connection.
10029 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10030 { TestRound(kGet, kSuccess, OK)}},
10031 // Authenticating HTTPS server with a direct connection.
10032 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10033 { TestRound(kGet, kServerChallenge, OK),
10034 TestRound(kGetAuth, kSuccess, OK)}},
10035 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10036 { TestRound(kGet, kServerChallenge, OK),
10037 TestRound(kGetAuth, kFailure, kAuthErr)}},
10038 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10039 { TestRound(kGet, kServerChallenge, OK),
10040 TestRound(kGetAuth, kSuccess, OK)}},
10041 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10042 { TestRound(kGet, kServerChallenge, OK),
10043 TestRound(kGetAuth, kFailure, kAuthErr)}},
10044 // Non-authenticating HTTPS server with a non-authenticating proxy.
10045 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10046 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
10047 // Authenticating HTTPS server through a non-authenticating proxy.
10048 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10049 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10050 TestRound(kGetAuth, kSuccess, OK)}},
10051 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10052 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10053 TestRound(kGetAuth, kFailure, kAuthErr)}},
10054 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10055 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10056 TestRound(kGetAuth, kSuccess, OK)}},
10057 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10058 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10059 TestRound(kGetAuth, kFailure, kAuthErr)}},
10060 // Non-Authenticating HTTPS server through an authenticating proxy.
10061 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10062 { TestRound(kConnect, kProxyChallenge, OK),
10063 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10064 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10065 { TestRound(kConnect, kProxyChallenge, OK),
10066 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10067 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10068 { TestRound(kConnect, kProxyChallenge, OK),
10069 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10070 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10071 { TestRound(kConnect, kProxyChallenge, OK),
10072 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10073 // Authenticating HTTPS server through an authenticating proxy.
10074 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10075 { TestRound(kConnect, kProxyChallenge, OK),
10076 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10077 &kGet, &kServerChallenge),
10078 TestRound(kGetAuth, kSuccess, OK)}},
10079 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10080 { TestRound(kConnect, kProxyChallenge, OK),
10081 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10082 &kGet, &kServerChallenge),
10083 TestRound(kGetAuth, kFailure, kAuthErr)}},
10084 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
10085 { TestRound(kConnect, kProxyChallenge, OK),
10086 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10087 &kGet, &kServerChallenge),
10088 TestRound(kGetAuth, kSuccess, OK)}},
10089 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
10090 { TestRound(kConnect, kProxyChallenge, OK),
10091 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10092 &kGet, &kServerChallenge),
10093 TestRound(kGetAuth, kFailure, kAuthErr)}},
10094 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10095 { TestRound(kConnect, kProxyChallenge, OK),
10096 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10097 &kGet, &kServerChallenge),
10098 TestRound(kGetAuth, kSuccess, OK)}},
10099 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10100 { TestRound(kConnect, kProxyChallenge, OK),
10101 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10102 &kGet, &kServerChallenge),
10103 TestRound(kGetAuth, kFailure, kAuthErr)}},
10104 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
10105 { TestRound(kConnect, kProxyChallenge, OK),
10106 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10107 &kGet, &kServerChallenge),
10108 TestRound(kGetAuth, kSuccess, OK)}},
10109 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
10110 { TestRound(kConnect, kProxyChallenge, OK),
10111 TestRound(kConnectProxyAuth, kProxyConnected, OK,
10112 &kGet, &kServerChallenge),
10113 TestRound(kGetAuth, kFailure, kAuthErr)}},
10116 for (size_t i = 0; i < arraysize(test_configs); ++i) {
10117 HttpAuthHandlerMock::Factory* auth_factory(
10118 new HttpAuthHandlerMock::Factory());
10119 session_deps_.http_auth_handler_factory.reset(auth_factory);
10120 const TestConfig& test_config = test_configs[i];
10122 // Set up authentication handlers as necessary.
10123 if (test_config.proxy_auth_timing != AUTH_NONE) {
10124 for (int n = 0; n < 2; n++) {
10125 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10126 std::string auth_challenge = "Mock realm=proxy";
10127 GURL origin(test_config.proxy_url);
10128 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10129 auth_challenge.end());
10130 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
10131 origin, BoundNetLog());
10132 auth_handler->SetGenerateExpectation(
10133 test_config.proxy_auth_timing == AUTH_ASYNC,
10134 test_config.proxy_auth_rv);
10135 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10138 if (test_config.server_auth_timing != AUTH_NONE) {
10139 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10140 std::string auth_challenge = "Mock realm=server";
10141 GURL origin(test_config.server_url);
10142 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10143 auth_challenge.end());
10144 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10145 origin, BoundNetLog());
10146 auth_handler->SetGenerateExpectation(
10147 test_config.server_auth_timing == AUTH_ASYNC,
10148 test_config.server_auth_rv);
10149 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10151 if (test_config.proxy_url) {
10152 session_deps_.proxy_service.reset(
10153 ProxyService::CreateFixed(test_config.proxy_url));
10154 } else {
10155 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10158 HttpRequestInfo request;
10159 request.method = "GET";
10160 request.url = GURL(test_config.server_url);
10161 request.load_flags = 0;
10163 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10164 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10166 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
10167 const TestRound& read_write_round = test_config.rounds[round];
10169 // Set up expected reads and writes.
10170 MockRead reads[2];
10171 reads[0] = read_write_round.read;
10172 size_t length_reads = 1;
10173 if (read_write_round.extra_read) {
10174 reads[1] = *read_write_round.extra_read;
10175 length_reads = 2;
10178 MockWrite writes[2];
10179 writes[0] = read_write_round.write;
10180 size_t length_writes = 1;
10181 if (read_write_round.extra_write) {
10182 writes[1] = *read_write_round.extra_write;
10183 length_writes = 2;
10185 StaticSocketDataProvider data_provider(
10186 reads, length_reads, writes, length_writes);
10187 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10189 // Add an SSL sequence if necessary.
10190 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
10191 if (round >= test_config.first_ssl_round)
10192 session_deps_.socket_factory->AddSSLSocketDataProvider(
10193 &ssl_socket_data_provider);
10195 // Start or restart the transaction.
10196 TestCompletionCallback callback;
10197 int rv;
10198 if (round == 0) {
10199 rv = trans.Start(&request, callback.callback(), BoundNetLog());
10200 } else {
10201 rv = trans.RestartWithAuth(
10202 AuthCredentials(kFoo, kBar), callback.callback());
10204 if (rv == ERR_IO_PENDING)
10205 rv = callback.WaitForResult();
10207 // Compare results with expected data.
10208 EXPECT_EQ(read_write_round.expected_rv, rv);
10209 const HttpResponseInfo* response = trans.GetResponseInfo();
10210 if (read_write_round.expected_rv == OK) {
10211 ASSERT_TRUE(response != NULL);
10212 } else {
10213 EXPECT_TRUE(response == NULL);
10214 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
10215 continue;
10217 if (round + 1 < test_config.num_auth_rounds) {
10218 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10219 } else {
10220 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10226 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
10227 // Do multi-round authentication and make sure it works correctly.
10228 HttpAuthHandlerMock::Factory* auth_factory(
10229 new HttpAuthHandlerMock::Factory());
10230 session_deps_.http_auth_handler_factory.reset(auth_factory);
10231 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
10232 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
10233 session_deps_.host_resolver->set_synchronous_mode(true);
10235 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
10236 auth_handler->set_connection_based(true);
10237 std::string auth_challenge = "Mock realm=server";
10238 GURL origin("http://www.example.com");
10239 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
10240 auth_challenge.end());
10241 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
10242 origin, BoundNetLog());
10243 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
10245 int rv = OK;
10246 const HttpResponseInfo* response = NULL;
10247 HttpRequestInfo request;
10248 request.method = "GET";
10249 request.url = origin;
10250 request.load_flags = 0;
10252 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10254 // Use a TCP Socket Pool with only one connection per group. This is used
10255 // to validate that the TCP socket is not released to the pool between
10256 // each round of multi-round authentication.
10257 HttpNetworkSessionPeer session_peer(session);
10258 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
10259 50, // Max sockets for pool
10260 1, // Max sockets per group
10261 session_deps_.host_resolver.get(),
10262 session_deps_.socket_factory.get(),
10263 session_deps_.net_log);
10264 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
10265 new MockClientSocketPoolManager);
10266 mock_pool_manager->SetTransportSocketPool(transport_pool);
10267 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
10269 scoped_ptr<HttpTransaction> trans(
10270 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10271 TestCompletionCallback callback;
10273 const MockWrite kGet(
10274 "GET / HTTP/1.1\r\n"
10275 "Host: www.example.com\r\n"
10276 "Connection: keep-alive\r\n\r\n");
10277 const MockWrite kGetAuth(
10278 "GET / HTTP/1.1\r\n"
10279 "Host: www.example.com\r\n"
10280 "Connection: keep-alive\r\n"
10281 "Authorization: auth_token\r\n\r\n");
10283 const MockRead kServerChallenge(
10284 "HTTP/1.1 401 Unauthorized\r\n"
10285 "WWW-Authenticate: Mock realm=server\r\n"
10286 "Content-Type: text/html; charset=iso-8859-1\r\n"
10287 "Content-Length: 14\r\n\r\n"
10288 "Unauthorized\r\n");
10289 const MockRead kSuccess(
10290 "HTTP/1.1 200 OK\r\n"
10291 "Content-Type: text/html; charset=iso-8859-1\r\n"
10292 "Content-Length: 3\r\n\r\n"
10293 "Yes");
10295 MockWrite writes[] = {
10296 // First round
10297 kGet,
10298 // Second round
10299 kGetAuth,
10300 // Third round
10301 kGetAuth,
10302 // Fourth round
10303 kGetAuth,
10304 // Competing request
10305 kGet,
10307 MockRead reads[] = {
10308 // First round
10309 kServerChallenge,
10310 // Second round
10311 kServerChallenge,
10312 // Third round
10313 kServerChallenge,
10314 // Fourth round
10315 kSuccess,
10316 // Competing response
10317 kSuccess,
10319 StaticSocketDataProvider data_provider(reads, arraysize(reads),
10320 writes, arraysize(writes));
10321 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
10323 const char kSocketGroup[] = "www.example.com:80";
10325 // First round of authentication.
10326 auth_handler->SetGenerateExpectation(false, OK);
10327 rv = trans->Start(&request, callback.callback(), BoundNetLog());
10328 if (rv == ERR_IO_PENDING)
10329 rv = callback.WaitForResult();
10330 EXPECT_EQ(OK, rv);
10331 response = trans->GetResponseInfo();
10332 ASSERT_TRUE(response != NULL);
10333 EXPECT_FALSE(response->auth_challenge.get() == NULL);
10334 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10336 // In between rounds, another request comes in for the same domain.
10337 // It should not be able to grab the TCP socket that trans has already
10338 // claimed.
10339 scoped_ptr<HttpTransaction> trans_compete(
10340 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10341 TestCompletionCallback callback_compete;
10342 rv = trans_compete->Start(
10343 &request, callback_compete.callback(), BoundNetLog());
10344 EXPECT_EQ(ERR_IO_PENDING, rv);
10345 // callback_compete.WaitForResult at this point would stall forever,
10346 // since the HttpNetworkTransaction does not release the request back to
10347 // the pool until after authentication completes.
10349 // Second round of authentication.
10350 auth_handler->SetGenerateExpectation(false, OK);
10351 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
10352 if (rv == ERR_IO_PENDING)
10353 rv = callback.WaitForResult();
10354 EXPECT_EQ(OK, rv);
10355 response = trans->GetResponseInfo();
10356 ASSERT_TRUE(response != NULL);
10357 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10358 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10360 // Third round of authentication.
10361 auth_handler->SetGenerateExpectation(false, OK);
10362 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10363 if (rv == ERR_IO_PENDING)
10364 rv = callback.WaitForResult();
10365 EXPECT_EQ(OK, rv);
10366 response = trans->GetResponseInfo();
10367 ASSERT_TRUE(response != NULL);
10368 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10369 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10371 // Fourth round of authentication, which completes successfully.
10372 auth_handler->SetGenerateExpectation(false, OK);
10373 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
10374 if (rv == ERR_IO_PENDING)
10375 rv = callback.WaitForResult();
10376 EXPECT_EQ(OK, rv);
10377 response = trans->GetResponseInfo();
10378 ASSERT_TRUE(response != NULL);
10379 EXPECT_TRUE(response->auth_challenge.get() == NULL);
10380 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10382 // Read the body since the fourth round was successful. This will also
10383 // release the socket back to the pool.
10384 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
10385 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10386 if (rv == ERR_IO_PENDING)
10387 rv = callback.WaitForResult();
10388 EXPECT_EQ(3, rv);
10389 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
10390 EXPECT_EQ(0, rv);
10391 // There are still 0 idle sockets, since the trans_compete transaction
10392 // will be handed it immediately after trans releases it to the group.
10393 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10395 // The competing request can now finish. Wait for the headers and then
10396 // read the body.
10397 rv = callback_compete.WaitForResult();
10398 EXPECT_EQ(OK, rv);
10399 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10400 if (rv == ERR_IO_PENDING)
10401 rv = callback.WaitForResult();
10402 EXPECT_EQ(3, rv);
10403 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
10404 EXPECT_EQ(0, rv);
10406 // Finally, the socket is released to the group.
10407 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
10410 // This tests the case that a request is issued via http instead of spdy after
10411 // npn is negotiated.
10412 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
10413 session_deps_.use_alternate_protocols = true;
10414 NextProtoVector next_protos;
10415 next_protos.push_back(kProtoHTTP11);
10416 session_deps_.next_protos = next_protos;
10418 HttpRequestInfo request;
10419 request.method = "GET";
10420 request.url = GURL("https://www.example.org/");
10421 request.load_flags = 0;
10423 MockWrite data_writes[] = {
10424 MockWrite(
10425 "GET / HTTP/1.1\r\n"
10426 "Host: www.example.org\r\n"
10427 "Connection: keep-alive\r\n\r\n"),
10430 std::string alternate_protocol_http_header =
10431 GetAlternateProtocolHttpHeader();
10433 MockRead data_reads[] = {
10434 MockRead("HTTP/1.1 200 OK\r\n"),
10435 MockRead(alternate_protocol_http_header.c_str()),
10436 MockRead("hello world"),
10437 MockRead(SYNCHRONOUS, OK),
10440 SSLSocketDataProvider ssl(ASYNC, OK);
10441 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
10442 ssl.next_proto = "http/1.1";
10443 ssl.protocol_negotiated = kProtoHTTP11;
10445 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10447 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
10448 data_writes, arraysize(data_writes));
10449 session_deps_.socket_factory->AddSocketDataProvider(&data);
10451 TestCompletionCallback callback;
10453 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10454 scoped_ptr<HttpTransaction> trans(
10455 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10457 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10459 EXPECT_EQ(ERR_IO_PENDING, rv);
10460 EXPECT_EQ(OK, callback.WaitForResult());
10462 const HttpResponseInfo* response = trans->GetResponseInfo();
10463 ASSERT_TRUE(response != NULL);
10464 ASSERT_TRUE(response->headers.get() != NULL);
10465 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10467 std::string response_data;
10468 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10469 EXPECT_EQ("hello world", response_data);
10471 EXPECT_FALSE(response->was_fetched_via_spdy);
10472 EXPECT_TRUE(response->was_npn_negotiated);
10475 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
10476 // Simulate the SSL handshake completing with an NPN negotiation
10477 // followed by an immediate server closing of the socket.
10478 // Fix crash: http://crbug.com/46369
10479 session_deps_.use_alternate_protocols = true;
10480 session_deps_.next_protos = SpdyNextProtos();
10482 HttpRequestInfo request;
10483 request.method = "GET";
10484 request.url = GURL("https://www.example.org/");
10485 request.load_flags = 0;
10487 SSLSocketDataProvider ssl(ASYNC, OK);
10488 ssl.SetNextProto(GetParam());
10489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10491 scoped_ptr<SpdyFrame> req(
10492 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10493 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10495 MockRead spdy_reads[] = {
10496 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10499 DelayedSocketData spdy_data(
10500 0, // don't wait in this case, immediate hangup.
10501 spdy_reads, arraysize(spdy_reads),
10502 spdy_writes, arraysize(spdy_writes));
10503 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10505 TestCompletionCallback callback;
10507 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10508 scoped_ptr<HttpTransaction> trans(
10509 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10511 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10512 EXPECT_EQ(ERR_IO_PENDING, rv);
10513 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10516 // A subclass of HttpAuthHandlerMock that records the request URL when
10517 // it gets it. This is needed since the auth handler may get destroyed
10518 // before we get a chance to query it.
10519 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10520 public:
10521 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10523 ~UrlRecordingHttpAuthHandlerMock() override {}
10525 protected:
10526 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10527 const HttpRequestInfo* request,
10528 const CompletionCallback& callback,
10529 std::string* auth_token) override {
10530 *url_ = request->url;
10531 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10532 credentials, request, callback, auth_token);
10535 private:
10536 GURL* url_;
10539 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10540 // This test ensures that the URL passed into the proxy is upgraded
10541 // to https when doing an Alternate Protocol upgrade.
10542 session_deps_.use_alternate_protocols = true;
10543 session_deps_.next_protos = SpdyNextProtos();
10545 session_deps_.proxy_service.reset(
10546 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10547 TestNetLog net_log;
10548 session_deps_.net_log = &net_log;
10549 GURL request_url;
10551 HttpAuthHandlerMock::Factory* auth_factory =
10552 new HttpAuthHandlerMock::Factory();
10553 UrlRecordingHttpAuthHandlerMock* auth_handler =
10554 new UrlRecordingHttpAuthHandlerMock(&request_url);
10555 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10556 auth_factory->set_do_init_from_challenge(true);
10557 session_deps_.http_auth_handler_factory.reset(auth_factory);
10560 HttpRequestInfo request;
10561 request.method = "GET";
10562 request.url = GURL("http://www.example.org");
10563 request.load_flags = 0;
10565 // First round goes unauthenticated through the proxy.
10566 MockWrite data_writes_1[] = {
10567 MockWrite(
10568 "GET http://www.example.org/ HTTP/1.1\r\n"
10569 "Host: www.example.org\r\n"
10570 "Proxy-Connection: keep-alive\r\n"
10571 "\r\n"),
10573 MockRead data_reads_1[] = {
10574 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10575 MockRead("HTTP/1.1 200 OK\r\n"),
10576 MockRead("Alternate-Protocol: 443:"),
10577 MockRead(GetAlternateProtocolFromParam()),
10578 MockRead("\r\n"),
10579 MockRead("Proxy-Connection: close\r\n"),
10580 MockRead("\r\n"),
10582 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10583 data_writes_1, arraysize(data_writes_1));
10585 // Second round tries to tunnel to www.example.org due to the
10586 // Alternate-Protocol announcement in the first round. It fails due
10587 // to a proxy authentication challenge.
10588 // After the failure, a tunnel is established to www.example.org using
10589 // Proxy-Authorization headers. There is then a SPDY request round.
10591 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10592 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10593 // does a Disconnect and Connect on the same socket, rather than trying
10594 // to obtain a new one.
10596 // NOTE: Originally, the proxy response to the second CONNECT request
10597 // simply returned another 407 so the unit test could skip the SSL connection
10598 // establishment and SPDY framing issues. Alas, the
10599 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10600 // complicated to set up expectations for than the SPDY session.
10602 scoped_ptr<SpdyFrame> req(
10603 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10604 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10605 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10607 MockWrite data_writes_2[] = {
10608 // First connection attempt without Proxy-Authorization.
10609 MockWrite(
10610 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10611 "Host: www.example.org\r\n"
10612 "Proxy-Connection: keep-alive\r\n"
10613 "\r\n"),
10615 // Second connection attempt with Proxy-Authorization.
10616 MockWrite(
10617 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10618 "Host: www.example.org\r\n"
10619 "Proxy-Connection: keep-alive\r\n"
10620 "Proxy-Authorization: auth_token\r\n"
10621 "\r\n"),
10623 // SPDY request
10624 CreateMockWrite(*req),
10626 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10627 "Proxy-Authenticate: Mock\r\n"
10628 "Proxy-Connection: close\r\n"
10629 "\r\n");
10630 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10631 MockRead data_reads_2[] = {
10632 // First connection attempt fails
10633 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
10634 MockRead(ASYNC, kRejectConnectResponse,
10635 arraysize(kRejectConnectResponse) - 1, 1),
10637 // Second connection attempt passes
10638 MockRead(ASYNC, kAcceptConnectResponse,
10639 arraysize(kAcceptConnectResponse) -1, 4),
10641 // SPDY response
10642 CreateMockRead(*resp.get(), 6),
10643 CreateMockRead(*data.get(), 6),
10644 MockRead(ASYNC, 0, 0, 6),
10646 OrderedSocketData data_2(
10647 data_reads_2, arraysize(data_reads_2),
10648 data_writes_2, arraysize(data_writes_2));
10650 SSLSocketDataProvider ssl(ASYNC, OK);
10651 ssl.SetNextProto(GetParam());
10652 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10653 ASSERT_TRUE(ssl.cert.get());
10655 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10656 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10657 NULL, 0, NULL, 0);
10658 hanging_non_alternate_protocol_socket.set_connect_data(
10659 never_finishing_connect);
10661 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10662 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10663 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10664 session_deps_.socket_factory->AddSocketDataProvider(
10665 &hanging_non_alternate_protocol_socket);
10666 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10668 // First round should work and provide the Alternate-Protocol state.
10669 TestCompletionCallback callback_1;
10670 scoped_ptr<HttpTransaction> trans_1(
10671 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10672 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10673 EXPECT_EQ(ERR_IO_PENDING, rv);
10674 EXPECT_EQ(OK, callback_1.WaitForResult());
10676 // Second round should attempt a tunnel connect and get an auth challenge.
10677 TestCompletionCallback callback_2;
10678 scoped_ptr<HttpTransaction> trans_2(
10679 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10680 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10681 EXPECT_EQ(ERR_IO_PENDING, rv);
10682 EXPECT_EQ(OK, callback_2.WaitForResult());
10683 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10684 ASSERT_TRUE(response != NULL);
10685 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10687 // Restart with auth. Tunnel should work and response received.
10688 TestCompletionCallback callback_3;
10689 rv = trans_2->RestartWithAuth(
10690 AuthCredentials(kFoo, kBar), callback_3.callback());
10691 EXPECT_EQ(ERR_IO_PENDING, rv);
10692 EXPECT_EQ(OK, callback_3.WaitForResult());
10694 // After all that work, these two lines (or actually, just the scheme) are
10695 // what this test is all about. Make sure it happens correctly.
10696 EXPECT_EQ("https", request_url.scheme());
10697 EXPECT_EQ("www.example.org", request_url.host());
10699 LoadTimingInfo load_timing_info;
10700 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10701 TestLoadTimingNotReusedWithPac(load_timing_info,
10702 CONNECT_TIMING_HAS_SSL_TIMES);
10705 // Test that if we cancel the transaction as the connection is completing, that
10706 // everything tears down correctly.
10707 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10708 // Setup everything about the connection to complete synchronously, so that
10709 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10710 // for is the callback from the HttpStreamRequest.
10711 // Then cancel the transaction.
10712 // Verify that we don't crash.
10713 MockConnect mock_connect(SYNCHRONOUS, OK);
10714 MockRead data_reads[] = {
10715 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10716 MockRead(SYNCHRONOUS, "hello world"),
10717 MockRead(SYNCHRONOUS, OK),
10720 HttpRequestInfo request;
10721 request.method = "GET";
10722 request.url = GURL("http://www.example.org/");
10723 request.load_flags = 0;
10725 session_deps_.host_resolver->set_synchronous_mode(true);
10726 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10727 scoped_ptr<HttpTransaction> trans(
10728 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10730 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10731 data.set_connect_data(mock_connect);
10732 session_deps_.socket_factory->AddSocketDataProvider(&data);
10734 TestCompletionCallback callback;
10736 BoundTestNetLog log;
10737 int rv = trans->Start(&request, callback.callback(), log.bound());
10738 EXPECT_EQ(ERR_IO_PENDING, rv);
10739 trans.reset(); // Cancel the transaction here.
10741 base::MessageLoop::current()->RunUntilIdle();
10744 // Test that if a transaction is cancelled after receiving the headers, the
10745 // stream is drained properly and added back to the socket pool. The main
10746 // purpose of this test is to make sure that an HttpStreamParser can be read
10747 // from after the HttpNetworkTransaction and the objects it owns have been
10748 // deleted.
10749 // See http://crbug.com/368418
10750 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10751 MockRead data_reads[] = {
10752 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10753 MockRead(ASYNC, "Content-Length: 2\r\n"),
10754 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10755 MockRead(ASYNC, "1"),
10756 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10757 // HttpNetworkTransaction has been deleted.
10758 MockRead(ASYNC, "2"),
10759 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10761 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10762 session_deps_.socket_factory->AddSocketDataProvider(&data);
10764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10767 HttpRequestInfo request;
10768 request.method = "GET";
10769 request.url = GURL("http://www.example.org/");
10770 request.load_flags = 0;
10772 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10773 TestCompletionCallback callback;
10775 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10776 EXPECT_EQ(ERR_IO_PENDING, rv);
10777 callback.WaitForResult();
10779 const HttpResponseInfo* response = trans.GetResponseInfo();
10780 ASSERT_TRUE(response != NULL);
10781 EXPECT_TRUE(response->headers.get() != NULL);
10782 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10784 // The transaction and HttpRequestInfo are deleted.
10787 // Let the HttpResponseBodyDrainer drain the socket.
10788 base::MessageLoop::current()->RunUntilIdle();
10790 // Socket should now be idle, waiting to be reused.
10791 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
10794 // Test a basic GET request through a proxy.
10795 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10796 session_deps_.proxy_service.reset(
10797 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10798 BoundTestNetLog log;
10799 session_deps_.net_log = log.bound().net_log();
10800 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10802 HttpRequestInfo request;
10803 request.method = "GET";
10804 request.url = GURL("http://www.example.org/");
10806 MockWrite data_writes1[] = {
10807 MockWrite(
10808 "GET http://www.example.org/ HTTP/1.1\r\n"
10809 "Host: www.example.org\r\n"
10810 "Proxy-Connection: keep-alive\r\n\r\n"),
10813 MockRead data_reads1[] = {
10814 MockRead("HTTP/1.1 200 OK\r\n"),
10815 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10816 MockRead("Content-Length: 100\r\n\r\n"),
10817 MockRead(SYNCHRONOUS, OK),
10820 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10821 data_writes1, arraysize(data_writes1));
10822 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10824 TestCompletionCallback callback1;
10826 scoped_ptr<HttpTransaction> trans(
10827 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10828 BeforeProxyHeadersSentHandler proxy_headers_handler;
10829 trans->SetBeforeProxyHeadersSentCallback(
10830 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
10831 base::Unretained(&proxy_headers_handler)));
10833 int rv = trans->Start(&request, callback1.callback(), log.bound());
10834 EXPECT_EQ(ERR_IO_PENDING, rv);
10836 rv = callback1.WaitForResult();
10837 EXPECT_EQ(OK, rv);
10839 const HttpResponseInfo* response = trans->GetResponseInfo();
10840 ASSERT_TRUE(response != NULL);
10842 EXPECT_TRUE(response->headers->IsKeepAlive());
10843 EXPECT_EQ(200, response->headers->response_code());
10844 EXPECT_EQ(100, response->headers->GetContentLength());
10845 EXPECT_TRUE(response->was_fetched_via_proxy);
10846 EXPECT_TRUE(
10847 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10848 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
10849 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
10850 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10852 LoadTimingInfo load_timing_info;
10853 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10854 TestLoadTimingNotReusedWithPac(load_timing_info,
10855 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10858 // Test a basic HTTPS GET request through a proxy.
10859 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10860 session_deps_.proxy_service.reset(
10861 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10862 BoundTestNetLog log;
10863 session_deps_.net_log = log.bound().net_log();
10864 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10866 HttpRequestInfo request;
10867 request.method = "GET";
10868 request.url = GURL("https://www.example.org/");
10870 // Since we have proxy, should try to establish tunnel.
10871 MockWrite data_writes1[] = {
10872 MockWrite(
10873 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10874 "Host: www.example.org\r\n"
10875 "Proxy-Connection: keep-alive\r\n\r\n"),
10877 MockWrite(
10878 "GET / HTTP/1.1\r\n"
10879 "Host: www.example.org\r\n"
10880 "Connection: keep-alive\r\n\r\n"),
10883 MockRead data_reads1[] = {
10884 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10886 MockRead("HTTP/1.1 200 OK\r\n"),
10887 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10888 MockRead("Content-Length: 100\r\n\r\n"),
10889 MockRead(SYNCHRONOUS, OK),
10892 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10893 data_writes1, arraysize(data_writes1));
10894 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10895 SSLSocketDataProvider ssl(ASYNC, OK);
10896 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10898 TestCompletionCallback callback1;
10900 scoped_ptr<HttpTransaction> trans(
10901 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10903 int rv = trans->Start(&request, callback1.callback(), log.bound());
10904 EXPECT_EQ(ERR_IO_PENDING, rv);
10906 rv = callback1.WaitForResult();
10907 EXPECT_EQ(OK, rv);
10908 TestNetLog::CapturedEntryList entries;
10909 log.GetEntries(&entries);
10910 size_t pos = ExpectLogContainsSomewhere(
10911 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10912 NetLog::PHASE_NONE);
10913 ExpectLogContainsSomewhere(
10914 entries, pos,
10915 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10916 NetLog::PHASE_NONE);
10918 const HttpResponseInfo* response = trans->GetResponseInfo();
10919 ASSERT_TRUE(response != NULL);
10921 EXPECT_TRUE(response->headers->IsKeepAlive());
10922 EXPECT_EQ(200, response->headers->response_code());
10923 EXPECT_EQ(100, response->headers->GetContentLength());
10924 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10925 EXPECT_TRUE(response->was_fetched_via_proxy);
10926 EXPECT_TRUE(
10927 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10929 LoadTimingInfo load_timing_info;
10930 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10931 TestLoadTimingNotReusedWithPac(load_timing_info,
10932 CONNECT_TIMING_HAS_SSL_TIMES);
10935 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10936 // while establishing the tunnel.
10937 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10938 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10939 BoundTestNetLog log;
10940 session_deps_.net_log = log.bound().net_log();
10941 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10943 HttpRequestInfo request;
10944 request.method = "GET";
10945 request.url = GURL("https://www.example.org/");
10947 // Since we have proxy, should try to establish tunnel.
10948 MockWrite data_writes1[] = {
10949 MockWrite(
10950 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10951 "Host: www.example.org\r\n"
10952 "Proxy-Connection: keep-alive\r\n\r\n"),
10954 MockWrite(
10955 "GET / HTTP/1.1\r\n"
10956 "Host: www.example.org\r\n"
10957 "Connection: keep-alive\r\n\r\n"),
10960 MockRead data_reads1[] = {
10961 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10962 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10963 MockRead(ASYNC, 0, 0), // EOF
10966 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10967 data_writes1, arraysize(data_writes1));
10968 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10969 SSLSocketDataProvider ssl(ASYNC, OK);
10970 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10972 TestCompletionCallback callback1;
10974 scoped_ptr<HttpTransaction> trans(
10975 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10977 int rv = trans->Start(&request, callback1.callback(), log.bound());
10978 EXPECT_EQ(ERR_IO_PENDING, rv);
10980 rv = callback1.WaitForResult();
10981 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10982 TestNetLog::CapturedEntryList entries;
10983 log.GetEntries(&entries);
10984 size_t pos = ExpectLogContainsSomewhere(
10985 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10986 NetLog::PHASE_NONE);
10987 ExpectLogContainsSomewhere(
10988 entries, pos,
10989 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10990 NetLog::PHASE_NONE);
10993 // Test for crbug.com/55424.
10994 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10995 scoped_ptr<SpdyFrame> req(
10996 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
10997 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10999 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11000 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
11001 MockRead spdy_reads[] = {
11002 CreateMockRead(*resp),
11003 CreateMockRead(*data),
11004 MockRead(ASYNC, 0, 0),
11007 DelayedSocketData spdy_data(
11008 1, // wait for one write to finish before reading.
11009 spdy_reads, arraysize(spdy_reads),
11010 spdy_writes, arraysize(spdy_writes));
11011 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11013 SSLSocketDataProvider ssl(ASYNC, OK);
11014 ssl.SetNextProto(GetParam());
11015 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11017 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11019 // Set up an initial SpdySession in the pool to reuse.
11020 HostPortPair host_port_pair("www.example.org", 443);
11021 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
11022 PRIVACY_MODE_DISABLED);
11023 base::WeakPtr<SpdySession> spdy_session =
11024 CreateInsecureSpdySession(session, key, BoundNetLog());
11026 HttpRequestInfo request;
11027 request.method = "GET";
11028 request.url = GURL("https://www.example.org/");
11029 request.load_flags = 0;
11031 // This is the important line that marks this as a preconnect.
11032 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
11034 scoped_ptr<HttpTransaction> trans(
11035 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11037 TestCompletionCallback callback;
11038 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11039 EXPECT_EQ(ERR_IO_PENDING, rv);
11040 EXPECT_EQ(OK, callback.WaitForResult());
11043 // Given a net error, cause that error to be returned from the first Write()
11044 // call and verify that the HttpTransaction fails with that error.
11045 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11046 int error, IoMode mode) {
11047 HttpRequestInfo request_info;
11048 request_info.url = GURL("https://www.example.com/");
11049 request_info.method = "GET";
11050 request_info.load_flags = LOAD_NORMAL;
11052 SSLSocketDataProvider ssl_data(mode, OK);
11053 MockWrite data_writes[] = {
11054 MockWrite(mode, error),
11056 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
11057 session_deps_.socket_factory->AddSocketDataProvider(&data);
11058 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
11060 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11061 scoped_ptr<HttpTransaction> trans(
11062 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11064 TestCompletionCallback callback;
11065 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11066 if (rv == ERR_IO_PENDING)
11067 rv = callback.WaitForResult();
11068 ASSERT_EQ(error, rv);
11071 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
11072 // Just check a grab bag of cert errors.
11073 static const int kErrors[] = {
11074 ERR_CERT_COMMON_NAME_INVALID,
11075 ERR_CERT_AUTHORITY_INVALID,
11076 ERR_CERT_DATE_INVALID,
11078 for (size_t i = 0; i < arraysize(kErrors); i++) {
11079 CheckErrorIsPassedBack(kErrors[i], ASYNC);
11080 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
11084 // Ensure that a client certificate is removed from the SSL client auth
11085 // cache when:
11086 // 1) No proxy is involved.
11087 // 2) TLS False Start is disabled.
11088 // 3) The initial TLS handshake requests a client certificate.
11089 // 4) The client supplies an invalid/unacceptable certificate.
11090 TEST_P(HttpNetworkTransactionTest,
11091 ClientAuthCertCache_Direct_NoFalseStart) {
11092 HttpRequestInfo request_info;
11093 request_info.url = GURL("https://www.example.com/");
11094 request_info.method = "GET";
11095 request_info.load_flags = LOAD_NORMAL;
11097 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11098 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11100 // [ssl_]data1 contains the data for the first SSL handshake. When a
11101 // CertificateRequest is received for the first time, the handshake will
11102 // be aborted to allow the caller to provide a certificate.
11103 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11104 ssl_data1.cert_request_info = cert_request.get();
11105 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11106 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11107 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11109 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11110 // False Start is not being used, the result of the SSL handshake will be
11111 // returned as part of the SSLClientSocket::Connect() call. This test
11112 // matches the result of a server sending a handshake_failure alert,
11113 // rather than a Finished message, because it requires a client
11114 // certificate and none was supplied.
11115 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11116 ssl_data2.cert_request_info = cert_request.get();
11117 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11118 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11119 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11121 // [ssl_]data3 contains the data for the third SSL handshake. When a
11122 // connection to a server fails during an SSL handshake,
11123 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11124 // connection was attempted with TLSv1.1. This is transparent to the caller
11125 // of the HttpNetworkTransaction. Because this test failure is due to
11126 // requiring a client certificate, this fallback handshake should also
11127 // fail.
11128 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11129 ssl_data3.cert_request_info = cert_request.get();
11130 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11131 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11132 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11134 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11135 // connection to a server fails during an SSL handshake,
11136 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
11137 // connection was attempted with TLSv1. This is transparent to the caller
11138 // of the HttpNetworkTransaction. Because this test failure is due to
11139 // requiring a client certificate, this fallback handshake should also
11140 // fail.
11141 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11142 ssl_data4.cert_request_info = cert_request.get();
11143 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11144 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
11145 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11147 // Need one more if TLSv1.2 is enabled.
11148 SSLSocketDataProvider ssl_data5(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11149 ssl_data5.cert_request_info = cert_request.get();
11150 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11151 StaticSocketDataProvider data5(NULL, 0, NULL, 0);
11152 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11154 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11155 scoped_ptr<HttpTransaction> trans(
11156 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11158 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11159 TestCompletionCallback callback;
11160 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11161 ASSERT_EQ(ERR_IO_PENDING, rv);
11163 // Complete the SSL handshake, which should abort due to requiring a
11164 // client certificate.
11165 rv = callback.WaitForResult();
11166 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11168 // Indicate that no certificate should be supplied. From the perspective
11169 // of SSLClientCertCache, NULL is just as meaningful as a real
11170 // certificate, so this is the same as supply a
11171 // legitimate-but-unacceptable certificate.
11172 rv = trans->RestartWithCertificate(NULL, callback.callback());
11173 ASSERT_EQ(ERR_IO_PENDING, rv);
11175 // Ensure the certificate was added to the client auth cache before
11176 // allowing the connection to continue restarting.
11177 scoped_refptr<X509Certificate> client_cert;
11178 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11179 HostPortPair("www.example.com", 443), &client_cert));
11180 ASSERT_EQ(NULL, client_cert.get());
11182 // Restart the handshake. This will consume ssl_data2, which fails, and
11183 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11184 // The result code is checked against what ssl_data4 should return.
11185 rv = callback.WaitForResult();
11186 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11188 // Ensure that the client certificate is removed from the cache on a
11189 // handshake failure.
11190 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11191 HostPortPair("www.example.com", 443), &client_cert));
11194 // Ensure that a client certificate is removed from the SSL client auth
11195 // cache when:
11196 // 1) No proxy is involved.
11197 // 2) TLS False Start is enabled.
11198 // 3) The initial TLS handshake requests a client certificate.
11199 // 4) The client supplies an invalid/unacceptable certificate.
11200 TEST_P(HttpNetworkTransactionTest,
11201 ClientAuthCertCache_Direct_FalseStart) {
11202 HttpRequestInfo request_info;
11203 request_info.url = GURL("https://www.example.com/");
11204 request_info.method = "GET";
11205 request_info.load_flags = LOAD_NORMAL;
11207 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11208 cert_request->host_and_port = HostPortPair("www.example.com", 443);
11210 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11211 // return successfully after reading up to the peer's Certificate message.
11212 // This is to allow the caller to call SSLClientSocket::Write(), which can
11213 // enqueue application data to be sent in the same packet as the
11214 // ChangeCipherSpec and Finished messages.
11215 // The actual handshake will be finished when SSLClientSocket::Read() is
11216 // called, which expects to process the peer's ChangeCipherSpec and
11217 // Finished messages. If there was an error negotiating with the peer,
11218 // such as due to the peer requiring a client certificate when none was
11219 // supplied, the alert sent by the peer won't be processed until Read() is
11220 // called.
11222 // Like the non-False Start case, when a client certificate is requested by
11223 // the peer, the handshake is aborted during the Connect() call.
11224 // [ssl_]data1 represents the initial SSL handshake with the peer.
11225 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11226 ssl_data1.cert_request_info = cert_request.get();
11227 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11228 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11229 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11231 // When a client certificate is supplied, Connect() will not be aborted
11232 // when the peer requests the certificate. Instead, the handshake will
11233 // artificially succeed, allowing the caller to write the HTTP request to
11234 // the socket. The handshake messages are not processed until Read() is
11235 // called, which then detects that the handshake was aborted, due to the
11236 // peer sending a handshake_failure because it requires a client
11237 // certificate.
11238 SSLSocketDataProvider ssl_data2(ASYNC, OK);
11239 ssl_data2.cert_request_info = cert_request.get();
11240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11241 MockRead data2_reads[] = {
11242 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
11244 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
11245 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11247 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11248 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11249 // TLSv1. It has the same behaviour as [ssl_]data2.
11250 SSLSocketDataProvider ssl_data3(ASYNC, OK);
11251 ssl_data3.cert_request_info = cert_request.get();
11252 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11253 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
11254 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11256 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11257 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11258 SSLSocketDataProvider ssl_data4(ASYNC, OK);
11259 ssl_data4.cert_request_info = cert_request.get();
11260 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
11261 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
11262 session_deps_.socket_factory->AddSocketDataProvider(&data4);
11264 // Need one more if TLSv1.2 is enabled.
11265 SSLSocketDataProvider ssl_data5(ASYNC, OK);
11266 ssl_data5.cert_request_info = cert_request.get();
11267 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
11268 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
11269 session_deps_.socket_factory->AddSocketDataProvider(&data5);
11271 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11272 scoped_ptr<HttpTransaction> trans(
11273 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11275 // Begin the initial SSL handshake.
11276 TestCompletionCallback callback;
11277 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11278 ASSERT_EQ(ERR_IO_PENDING, rv);
11280 // Complete the SSL handshake, which should abort due to requiring a
11281 // client certificate.
11282 rv = callback.WaitForResult();
11283 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11285 // Indicate that no certificate should be supplied. From the perspective
11286 // of SSLClientCertCache, NULL is just as meaningful as a real
11287 // certificate, so this is the same as supply a
11288 // legitimate-but-unacceptable certificate.
11289 rv = trans->RestartWithCertificate(NULL, callback.callback());
11290 ASSERT_EQ(ERR_IO_PENDING, rv);
11292 // Ensure the certificate was added to the client auth cache before
11293 // allowing the connection to continue restarting.
11294 scoped_refptr<X509Certificate> client_cert;
11295 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11296 HostPortPair("www.example.com", 443), &client_cert));
11297 ASSERT_EQ(NULL, client_cert.get());
11299 // Restart the handshake. This will consume ssl_data2, which fails, and
11300 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11301 // The result code is checked against what ssl_data4 should return.
11302 rv = callback.WaitForResult();
11303 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
11305 // Ensure that the client certificate is removed from the cache on a
11306 // handshake failure.
11307 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11308 HostPortPair("www.example.com", 443), &client_cert));
11311 // Ensure that a client certificate is removed from the SSL client auth
11312 // cache when:
11313 // 1) An HTTPS proxy is involved.
11314 // 3) The HTTPS proxy requests a client certificate.
11315 // 4) The client supplies an invalid/unacceptable certificate for the
11316 // proxy.
11317 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11318 // then for connecting to an HTTP endpoint.
11319 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
11320 session_deps_.proxy_service.reset(
11321 ProxyService::CreateFixed("https://proxy:70"));
11322 BoundTestNetLog log;
11323 session_deps_.net_log = log.bound().net_log();
11325 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
11326 cert_request->host_and_port = HostPortPair("proxy", 70);
11328 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11329 // [ssl_]data[1-3]. Rather than represending the endpoint
11330 // (www.example.com:443), they represent failures with the HTTPS proxy
11331 // (proxy:70).
11332 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
11333 ssl_data1.cert_request_info = cert_request.get();
11334 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
11335 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
11336 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11338 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11339 ssl_data2.cert_request_info = cert_request.get();
11340 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
11341 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
11342 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11344 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11345 #if 0
11346 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
11347 ssl_data3.cert_request_info = cert_request.get();
11348 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
11349 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
11350 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11351 #endif
11353 HttpRequestInfo requests[2];
11354 requests[0].url = GURL("https://www.example.com/");
11355 requests[0].method = "GET";
11356 requests[0].load_flags = LOAD_NORMAL;
11358 requests[1].url = GURL("http://www.example.com/");
11359 requests[1].method = "GET";
11360 requests[1].load_flags = LOAD_NORMAL;
11362 for (size_t i = 0; i < arraysize(requests); ++i) {
11363 session_deps_.socket_factory->ResetNextMockIndexes();
11364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11365 scoped_ptr<HttpNetworkTransaction> trans(
11366 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11368 // Begin the SSL handshake with the proxy.
11369 TestCompletionCallback callback;
11370 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
11371 ASSERT_EQ(ERR_IO_PENDING, rv);
11373 // Complete the SSL handshake, which should abort due to requiring a
11374 // client certificate.
11375 rv = callback.WaitForResult();
11376 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
11378 // Indicate that no certificate should be supplied. From the perspective
11379 // of SSLClientCertCache, NULL is just as meaningful as a real
11380 // certificate, so this is the same as supply a
11381 // legitimate-but-unacceptable certificate.
11382 rv = trans->RestartWithCertificate(NULL, callback.callback());
11383 ASSERT_EQ(ERR_IO_PENDING, rv);
11385 // Ensure the certificate was added to the client auth cache before
11386 // allowing the connection to continue restarting.
11387 scoped_refptr<X509Certificate> client_cert;
11388 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
11389 HostPortPair("proxy", 70), &client_cert));
11390 ASSERT_EQ(NULL, client_cert.get());
11391 // Ensure the certificate was NOT cached for the endpoint. This only
11392 // applies to HTTPS requests, but is fine to check for HTTP requests.
11393 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11394 HostPortPair("www.example.com", 443), &client_cert));
11396 // Restart the handshake. This will consume ssl_data2, which fails, and
11397 // then consume ssl_data3, which should also fail. The result code is
11398 // checked against what ssl_data3 should return.
11399 rv = callback.WaitForResult();
11400 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
11402 // Now that the new handshake has failed, ensure that the client
11403 // certificate was removed from the client auth cache.
11404 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11405 HostPortPair("proxy", 70), &client_cert));
11406 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
11407 HostPortPair("www.example.com", 443), &client_cert));
11411 // Unlike TEST/TEST_F, which are macros that expand to further macros,
11412 // TEST_P is a macro that expands directly to code that stringizes the
11413 // arguments. As a result, macros passed as parameters (such as prefix
11414 // or test_case_name) will not be expanded by the preprocessor. To
11415 // work around this, indirect the macro for TEST_P, so that the
11416 // pre-processor will expand macros such as MAYBE_test_name before
11417 // instantiating the test.
11418 #define WRAPPED_TEST_P(test_case_name, test_name) \
11419 TEST_P(test_case_name, test_name)
11421 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11422 #if defined(OS_WIN)
11423 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
11424 #else
11425 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
11426 #endif
11427 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
11428 session_deps_.use_alternate_protocols = true;
11429 session_deps_.next_protos = SpdyNextProtos();
11431 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11432 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11433 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11434 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11435 pool_peer.DisableDomainAuthenticationVerification();
11437 SSLSocketDataProvider ssl(ASYNC, OK);
11438 ssl.SetNextProto(GetParam());
11439 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11441 scoped_ptr<SpdyFrame> host1_req(
11442 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11443 scoped_ptr<SpdyFrame> host2_req(
11444 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11445 MockWrite spdy_writes[] = {
11446 CreateMockWrite(*host1_req, 1),
11447 CreateMockWrite(*host2_req, 4),
11449 scoped_ptr<SpdyFrame> host1_resp(
11450 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11451 scoped_ptr<SpdyFrame> host1_resp_body(
11452 spdy_util_.ConstructSpdyBodyFrame(1, true));
11453 scoped_ptr<SpdyFrame> host2_resp(
11454 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11455 scoped_ptr<SpdyFrame> host2_resp_body(
11456 spdy_util_.ConstructSpdyBodyFrame(3, true));
11457 MockRead spdy_reads[] = {
11458 CreateMockRead(*host1_resp, 2),
11459 CreateMockRead(*host1_resp_body, 3),
11460 CreateMockRead(*host2_resp, 5),
11461 CreateMockRead(*host2_resp_body, 6),
11462 MockRead(ASYNC, 0, 7),
11465 IPAddressNumber ip;
11466 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11467 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11468 MockConnect connect(ASYNC, OK, peer_addr);
11469 OrderedSocketData spdy_data(
11470 connect,
11471 spdy_reads, arraysize(spdy_reads),
11472 spdy_writes, arraysize(spdy_writes));
11473 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11475 TestCompletionCallback callback;
11476 HttpRequestInfo request1;
11477 request1.method = "GET";
11478 request1.url = GURL("https://www.example.org/");
11479 request1.load_flags = 0;
11480 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11482 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11483 EXPECT_EQ(ERR_IO_PENDING, rv);
11484 EXPECT_EQ(OK, callback.WaitForResult());
11486 const HttpResponseInfo* response = trans1.GetResponseInfo();
11487 ASSERT_TRUE(response != NULL);
11488 ASSERT_TRUE(response->headers.get() != NULL);
11489 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11491 std::string response_data;
11492 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11493 EXPECT_EQ("hello!", response_data);
11495 // Preload www.gmail.com into HostCache.
11496 HostPortPair host_port("www.gmail.com", 443);
11497 HostResolver::RequestInfo resolve_info(host_port);
11498 AddressList ignored;
11499 rv = session_deps_.host_resolver->Resolve(resolve_info,
11500 DEFAULT_PRIORITY,
11501 &ignored,
11502 callback.callback(),
11503 NULL,
11504 BoundNetLog());
11505 EXPECT_EQ(ERR_IO_PENDING, rv);
11506 rv = callback.WaitForResult();
11507 EXPECT_EQ(OK, rv);
11509 HttpRequestInfo request2;
11510 request2.method = "GET";
11511 request2.url = GURL("https://www.gmail.com/");
11512 request2.load_flags = 0;
11513 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11515 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11516 EXPECT_EQ(ERR_IO_PENDING, rv);
11517 EXPECT_EQ(OK, callback.WaitForResult());
11519 response = trans2.GetResponseInfo();
11520 ASSERT_TRUE(response != NULL);
11521 ASSERT_TRUE(response->headers.get() != NULL);
11522 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11523 EXPECT_TRUE(response->was_fetched_via_spdy);
11524 EXPECT_TRUE(response->was_npn_negotiated);
11525 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11526 EXPECT_EQ("hello!", response_data);
11528 #undef MAYBE_UseIPConnectionPooling
11530 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11531 session_deps_.use_alternate_protocols = true;
11532 session_deps_.next_protos = SpdyNextProtos();
11534 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11535 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11536 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11537 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11538 pool_peer.DisableDomainAuthenticationVerification();
11540 SSLSocketDataProvider ssl(ASYNC, OK);
11541 ssl.SetNextProto(GetParam());
11542 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11544 scoped_ptr<SpdyFrame> host1_req(
11545 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11546 scoped_ptr<SpdyFrame> host2_req(
11547 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11548 MockWrite spdy_writes[] = {
11549 CreateMockWrite(*host1_req, 1),
11550 CreateMockWrite(*host2_req, 4),
11552 scoped_ptr<SpdyFrame> host1_resp(
11553 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11554 scoped_ptr<SpdyFrame> host1_resp_body(
11555 spdy_util_.ConstructSpdyBodyFrame(1, true));
11556 scoped_ptr<SpdyFrame> host2_resp(
11557 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11558 scoped_ptr<SpdyFrame> host2_resp_body(
11559 spdy_util_.ConstructSpdyBodyFrame(3, true));
11560 MockRead spdy_reads[] = {
11561 CreateMockRead(*host1_resp, 2),
11562 CreateMockRead(*host1_resp_body, 3),
11563 CreateMockRead(*host2_resp, 5),
11564 CreateMockRead(*host2_resp_body, 6),
11565 MockRead(ASYNC, 0, 7),
11568 IPAddressNumber ip;
11569 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11570 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11571 MockConnect connect(ASYNC, OK, peer_addr);
11572 OrderedSocketData spdy_data(
11573 connect,
11574 spdy_reads, arraysize(spdy_reads),
11575 spdy_writes, arraysize(spdy_writes));
11576 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11578 TestCompletionCallback callback;
11579 HttpRequestInfo request1;
11580 request1.method = "GET";
11581 request1.url = GURL("https://www.example.org/");
11582 request1.load_flags = 0;
11583 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11585 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11586 EXPECT_EQ(ERR_IO_PENDING, rv);
11587 EXPECT_EQ(OK, callback.WaitForResult());
11589 const HttpResponseInfo* response = trans1.GetResponseInfo();
11590 ASSERT_TRUE(response != NULL);
11591 ASSERT_TRUE(response->headers.get() != NULL);
11592 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11594 std::string response_data;
11595 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11596 EXPECT_EQ("hello!", response_data);
11598 HttpRequestInfo request2;
11599 request2.method = "GET";
11600 request2.url = GURL("https://www.gmail.com/");
11601 request2.load_flags = 0;
11602 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11604 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11605 EXPECT_EQ(ERR_IO_PENDING, rv);
11606 EXPECT_EQ(OK, callback.WaitForResult());
11608 response = trans2.GetResponseInfo();
11609 ASSERT_TRUE(response != NULL);
11610 ASSERT_TRUE(response->headers.get() != NULL);
11611 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11612 EXPECT_TRUE(response->was_fetched_via_spdy);
11613 EXPECT_TRUE(response->was_npn_negotiated);
11614 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11615 EXPECT_EQ("hello!", response_data);
11618 class OneTimeCachingHostResolver : public HostResolver {
11619 public:
11620 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11621 : host_port_(host_port) {}
11622 ~OneTimeCachingHostResolver() override {}
11624 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11626 // HostResolver methods:
11627 int Resolve(const RequestInfo& info,
11628 RequestPriority priority,
11629 AddressList* addresses,
11630 const CompletionCallback& callback,
11631 RequestHandle* out_req,
11632 const BoundNetLog& net_log) override {
11633 return host_resolver_.Resolve(
11634 info, priority, addresses, callback, out_req, net_log);
11637 int ResolveFromCache(const RequestInfo& info,
11638 AddressList* addresses,
11639 const BoundNetLog& net_log) override {
11640 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11641 if (rv == OK && info.host_port_pair().Equals(host_port_))
11642 host_resolver_.GetHostCache()->clear();
11643 return rv;
11646 void CancelRequest(RequestHandle req) override {
11647 host_resolver_.CancelRequest(req);
11650 MockCachingHostResolver* GetMockHostResolver() {
11651 return &host_resolver_;
11654 private:
11655 MockCachingHostResolver host_resolver_;
11656 const HostPortPair host_port_;
11659 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11660 #if defined(OS_WIN)
11661 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11662 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11663 #else
11664 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11665 UseIPConnectionPoolingWithHostCacheExpiration
11666 #endif
11667 WRAPPED_TEST_P(HttpNetworkTransactionTest,
11668 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
11669 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11670 // prefix doesn't work with parametrized tests).
11671 #if defined(OS_WIN)
11672 return;
11673 #else
11674 session_deps_.use_alternate_protocols = true;
11675 session_deps_.next_protos = SpdyNextProtos();
11677 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11678 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11679 HttpNetworkSession::Params params =
11680 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11681 params.host_resolver = &host_resolver;
11682 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11683 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11684 pool_peer.DisableDomainAuthenticationVerification();
11686 SSLSocketDataProvider ssl(ASYNC, OK);
11687 ssl.SetNextProto(GetParam());
11688 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11690 scoped_ptr<SpdyFrame> host1_req(
11691 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
11692 scoped_ptr<SpdyFrame> host2_req(
11693 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11694 MockWrite spdy_writes[] = {
11695 CreateMockWrite(*host1_req, 1),
11696 CreateMockWrite(*host2_req, 4),
11698 scoped_ptr<SpdyFrame> host1_resp(
11699 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11700 scoped_ptr<SpdyFrame> host1_resp_body(
11701 spdy_util_.ConstructSpdyBodyFrame(1, true));
11702 scoped_ptr<SpdyFrame> host2_resp(
11703 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11704 scoped_ptr<SpdyFrame> host2_resp_body(
11705 spdy_util_.ConstructSpdyBodyFrame(3, true));
11706 MockRead spdy_reads[] = {
11707 CreateMockRead(*host1_resp, 2),
11708 CreateMockRead(*host1_resp_body, 3),
11709 CreateMockRead(*host2_resp, 5),
11710 CreateMockRead(*host2_resp_body, 6),
11711 MockRead(ASYNC, 0, 7),
11714 IPAddressNumber ip;
11715 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11716 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11717 MockConnect connect(ASYNC, OK, peer_addr);
11718 OrderedSocketData spdy_data(
11719 connect,
11720 spdy_reads, arraysize(spdy_reads),
11721 spdy_writes, arraysize(spdy_writes));
11722 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11724 TestCompletionCallback callback;
11725 HttpRequestInfo request1;
11726 request1.method = "GET";
11727 request1.url = GURL("https://www.example.org/");
11728 request1.load_flags = 0;
11729 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11731 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11732 EXPECT_EQ(ERR_IO_PENDING, rv);
11733 EXPECT_EQ(OK, callback.WaitForResult());
11735 const HttpResponseInfo* response = trans1.GetResponseInfo();
11736 ASSERT_TRUE(response != NULL);
11737 ASSERT_TRUE(response->headers.get() != NULL);
11738 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11740 std::string response_data;
11741 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11742 EXPECT_EQ("hello!", response_data);
11744 // Preload cache entries into HostCache.
11745 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11746 AddressList ignored;
11747 rv = host_resolver.Resolve(resolve_info,
11748 DEFAULT_PRIORITY,
11749 &ignored,
11750 callback.callback(),
11751 NULL,
11752 BoundNetLog());
11753 EXPECT_EQ(ERR_IO_PENDING, rv);
11754 rv = callback.WaitForResult();
11755 EXPECT_EQ(OK, rv);
11757 HttpRequestInfo request2;
11758 request2.method = "GET";
11759 request2.url = GURL("https://www.gmail.com/");
11760 request2.load_flags = 0;
11761 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11763 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11764 EXPECT_EQ(ERR_IO_PENDING, rv);
11765 EXPECT_EQ(OK, callback.WaitForResult());
11767 response = trans2.GetResponseInfo();
11768 ASSERT_TRUE(response != NULL);
11769 ASSERT_TRUE(response->headers.get() != NULL);
11770 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11771 EXPECT_TRUE(response->was_fetched_via_spdy);
11772 EXPECT_TRUE(response->was_npn_negotiated);
11773 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11774 EXPECT_EQ("hello!", response_data);
11775 #endif
11777 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11779 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11780 const std::string https_url = "https://www.example.org:8080/";
11781 const std::string http_url = "http://www.example.org:8080/";
11783 // SPDY GET for HTTPS URL
11784 scoped_ptr<SpdyFrame> req1(
11785 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11787 MockWrite writes1[] = {
11788 CreateMockWrite(*req1, 0),
11791 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11792 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11793 MockRead reads1[] = {
11794 CreateMockRead(*resp1, 1),
11795 CreateMockRead(*body1, 2),
11796 MockRead(ASYNC, ERR_IO_PENDING, 3)
11799 DelayedSocketData data1(
11800 1, reads1, arraysize(reads1),
11801 writes1, arraysize(writes1));
11802 MockConnect connect_data1(ASYNC, OK);
11803 data1.set_connect_data(connect_data1);
11805 // HTTP GET for the HTTP URL
11806 MockWrite writes2[] = {
11807 MockWrite(ASYNC, 4,
11808 "GET / HTTP/1.1\r\n"
11809 "Host: www.example.org:8080\r\n"
11810 "Connection: keep-alive\r\n\r\n"),
11813 MockRead reads2[] = {
11814 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11815 MockRead(ASYNC, 6, "hello"),
11816 MockRead(ASYNC, 7, OK),
11819 DelayedSocketData data2(
11820 1, reads2, arraysize(reads2),
11821 writes2, arraysize(writes2));
11823 SSLSocketDataProvider ssl(ASYNC, OK);
11824 ssl.SetNextProto(GetParam());
11825 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11826 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11827 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11829 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11831 // Start the first transaction to set up the SpdySession
11832 HttpRequestInfo request1;
11833 request1.method = "GET";
11834 request1.url = GURL(https_url);
11835 request1.load_flags = 0;
11836 HttpNetworkTransaction trans1(LOWEST, session.get());
11837 TestCompletionCallback callback1;
11838 EXPECT_EQ(ERR_IO_PENDING,
11839 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11840 base::MessageLoop::current()->RunUntilIdle();
11842 EXPECT_EQ(OK, callback1.WaitForResult());
11843 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11845 // Now, start the HTTP request
11846 HttpRequestInfo request2;
11847 request2.method = "GET";
11848 request2.url = GURL(http_url);
11849 request2.load_flags = 0;
11850 HttpNetworkTransaction trans2(MEDIUM, session.get());
11851 TestCompletionCallback callback2;
11852 EXPECT_EQ(ERR_IO_PENDING,
11853 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11854 base::MessageLoop::current()->RunUntilIdle();
11856 EXPECT_EQ(OK, callback2.WaitForResult());
11857 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11860 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
11861 const std::string https_url = "https://www.example.org:8080/";
11862 const std::string http_url = "http://www.example.org:8080/";
11864 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11865 const HostPortPair host_port_pair("www.example.org", 8080);
11866 scoped_ptr<SpdyFrame> connect(
11867 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
11868 scoped_ptr<SpdyFrame> req1(
11869 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11870 scoped_ptr<SpdyFrame> wrapped_req1(
11871 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
11873 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11874 SpdyHeaderBlock req2_block;
11875 req2_block[spdy_util_.GetMethodKey()] = "GET";
11876 req2_block[spdy_util_.GetPathKey()] = "/";
11877 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
11878 req2_block[spdy_util_.GetSchemeKey()] = "http";
11879 spdy_util_.MaybeAddVersionHeader(&req2_block);
11880 scoped_ptr<SpdyFrame> req2(
11881 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
11883 MockWrite writes1[] = {
11884 CreateMockWrite(*connect, 0),
11885 CreateMockWrite(*wrapped_req1, 2),
11886 CreateMockWrite(*req2, 5),
11889 scoped_ptr<SpdyFrame> conn_resp(
11890 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11891 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11892 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11893 scoped_ptr<SpdyFrame> wrapped_resp1(
11894 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
11895 scoped_ptr<SpdyFrame> wrapped_body1(
11896 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
11897 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11898 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11899 MockRead reads1[] = {
11900 CreateMockRead(*conn_resp, 1),
11901 CreateMockRead(*wrapped_resp1, 3),
11902 CreateMockRead(*wrapped_body1, 4),
11903 CreateMockRead(*resp2, 6),
11904 CreateMockRead(*body2, 7),
11905 MockRead(ASYNC, ERR_IO_PENDING, 8)
11908 DeterministicSocketData data1(reads1, arraysize(reads1),
11909 writes1, arraysize(writes1));
11910 MockConnect connect_data1(ASYNC, OK);
11911 data1.set_connect_data(connect_data1);
11913 session_deps_.proxy_service.reset(
11914 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11915 TestNetLog log;
11916 session_deps_.net_log = &log;
11917 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11918 ssl1.SetNextProto(GetParam());
11919 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11920 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11921 ssl2.SetNextProto(GetParam());
11922 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11923 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
11925 scoped_refptr<HttpNetworkSession> session(
11926 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11928 // Start the first transaction to set up the SpdySession
11929 HttpRequestInfo request1;
11930 request1.method = "GET";
11931 request1.url = GURL(https_url);
11932 request1.load_flags = 0;
11933 HttpNetworkTransaction trans1(LOWEST, session.get());
11934 TestCompletionCallback callback1;
11935 EXPECT_EQ(ERR_IO_PENDING,
11936 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11937 base::MessageLoop::current()->RunUntilIdle();
11938 data1.RunFor(4);
11940 EXPECT_EQ(OK, callback1.WaitForResult());
11941 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11943 LoadTimingInfo load_timing_info1;
11944 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
11945 TestLoadTimingNotReusedWithPac(load_timing_info1,
11946 CONNECT_TIMING_HAS_SSL_TIMES);
11948 // Now, start the HTTP request
11949 HttpRequestInfo request2;
11950 request2.method = "GET";
11951 request2.url = GURL(http_url);
11952 request2.load_flags = 0;
11953 HttpNetworkTransaction trans2(MEDIUM, session.get());
11954 TestCompletionCallback callback2;
11955 EXPECT_EQ(ERR_IO_PENDING,
11956 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11957 base::MessageLoop::current()->RunUntilIdle();
11958 data1.RunFor(3);
11960 EXPECT_EQ(OK, callback2.WaitForResult());
11961 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11963 LoadTimingInfo load_timing_info2;
11964 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
11965 // The established SPDY sessions is considered reused by the HTTP request.
11966 TestLoadTimingReusedWithPac(load_timing_info2);
11967 // HTTP requests over a SPDY session should have a different connection
11968 // socket_log_id than requests over a tunnel.
11969 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
11972 // Test that in the case where we have a SPDY session to a SPDY proxy
11973 // that we do not pool other origins that resolve to the same IP when
11974 // the certificate does not match the new origin.
11975 // http://crbug.com/134690
11976 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11977 const std::string url1 = "http://www.example.org/";
11978 const std::string url2 = "https://news.example.org/";
11979 const std::string ip_addr = "1.2.3.4";
11981 // SPDY GET for HTTP URL (through SPDY proxy)
11982 scoped_ptr<SpdyHeaderBlock> headers(
11983 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
11984 scoped_ptr<SpdyFrame> req1(
11985 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
11987 MockWrite writes1[] = {
11988 CreateMockWrite(*req1, 0),
11991 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11992 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11993 MockRead reads1[] = {
11994 CreateMockRead(*resp1, 1),
11995 CreateMockRead(*body1, 2),
11996 MockRead(ASYNC, OK, 3) // EOF
11999 scoped_ptr<DeterministicSocketData> data1(
12000 new DeterministicSocketData(reads1, arraysize(reads1),
12001 writes1, arraysize(writes1)));
12002 IPAddressNumber ip;
12003 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
12004 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12005 MockConnect connect_data1(ASYNC, OK, peer_addr);
12006 data1->set_connect_data(connect_data1);
12008 // SPDY GET for HTTPS URL (direct)
12009 scoped_ptr<SpdyFrame> req2(
12010 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
12012 MockWrite writes2[] = {
12013 CreateMockWrite(*req2, 0),
12016 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12017 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12018 MockRead reads2[] = {
12019 CreateMockRead(*resp2, 1),
12020 CreateMockRead(*body2, 2),
12021 MockRead(ASYNC, OK, 3) // EOF
12024 scoped_ptr<DeterministicSocketData> data2(
12025 new DeterministicSocketData(reads2, arraysize(reads2),
12026 writes2, arraysize(writes2)));
12027 MockConnect connect_data2(ASYNC, OK);
12028 data2->set_connect_data(connect_data2);
12030 // Set up a proxy config that sends HTTP requests to a proxy, and
12031 // all others direct.
12032 ProxyConfig proxy_config;
12033 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
12034 session_deps_.proxy_service.reset(new ProxyService(
12035 new ProxyConfigServiceFixed(proxy_config), nullptr, NULL));
12037 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
12038 ssl1.SetNextProto(GetParam());
12039 // Load a valid cert. Note, that this does not need to
12040 // be valid for proxy because the MockSSLClientSocket does
12041 // not actually verify it. But SpdySession will use this
12042 // to see if it is valid for the new origin
12043 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12044 ASSERT_TRUE(ssl1.cert.get());
12045 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12046 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12047 data1.get());
12049 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
12050 ssl2.SetNextProto(GetParam());
12051 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12052 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12053 data2.get());
12055 session_deps_.host_resolver.reset(new MockCachingHostResolver());
12056 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
12057 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
12059 scoped_refptr<HttpNetworkSession> session(
12060 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12062 // Start the first transaction to set up the SpdySession
12063 HttpRequestInfo request1;
12064 request1.method = "GET";
12065 request1.url = GURL(url1);
12066 request1.load_flags = 0;
12067 HttpNetworkTransaction trans1(LOWEST, session.get());
12068 TestCompletionCallback callback1;
12069 ASSERT_EQ(ERR_IO_PENDING,
12070 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12071 data1->RunFor(3);
12073 ASSERT_TRUE(callback1.have_result());
12074 EXPECT_EQ(OK, callback1.WaitForResult());
12075 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12077 // Now, start the HTTP request
12078 HttpRequestInfo request2;
12079 request2.method = "GET";
12080 request2.url = GURL(url2);
12081 request2.load_flags = 0;
12082 HttpNetworkTransaction trans2(MEDIUM, session.get());
12083 TestCompletionCallback callback2;
12084 EXPECT_EQ(ERR_IO_PENDING,
12085 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12086 base::MessageLoop::current()->RunUntilIdle();
12087 data2->RunFor(3);
12089 ASSERT_TRUE(callback2.have_result());
12090 EXPECT_EQ(OK, callback2.WaitForResult());
12091 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12094 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12095 // error) in SPDY session, removes the socket from pool and closes the SPDY
12096 // session. Verify that new url's from the same HttpNetworkSession (and a new
12097 // SpdySession) do work. http://crbug.com/224701
12098 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
12099 const std::string https_url = "https://www.example.org/";
12101 MockRead reads1[] = {
12102 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
12105 scoped_ptr<DeterministicSocketData> data1(
12106 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
12107 data1->SetStop(1);
12109 scoped_ptr<SpdyFrame> req2(
12110 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
12111 MockWrite writes2[] = {
12112 CreateMockWrite(*req2, 0),
12115 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12116 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
12117 MockRead reads2[] = {
12118 CreateMockRead(*resp2, 1),
12119 CreateMockRead(*body2, 2),
12120 MockRead(ASYNC, OK, 3) // EOF
12123 scoped_ptr<DeterministicSocketData> data2(
12124 new DeterministicSocketData(reads2, arraysize(reads2),
12125 writes2, arraysize(writes2)));
12127 SSLSocketDataProvider ssl1(ASYNC, OK);
12128 ssl1.SetNextProto(GetParam());
12129 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
12130 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12131 data1.get());
12133 SSLSocketDataProvider ssl2(ASYNC, OK);
12134 ssl2.SetNextProto(GetParam());
12135 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
12136 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
12137 data2.get());
12139 scoped_refptr<HttpNetworkSession> session(
12140 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
12142 // Start the first transaction to set up the SpdySession and verify that
12143 // connection was closed.
12144 HttpRequestInfo request1;
12145 request1.method = "GET";
12146 request1.url = GURL(https_url);
12147 request1.load_flags = 0;
12148 HttpNetworkTransaction trans1(MEDIUM, session.get());
12149 TestCompletionCallback callback1;
12150 EXPECT_EQ(ERR_IO_PENDING,
12151 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
12152 base::MessageLoop::current()->RunUntilIdle();
12153 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
12155 // Now, start the second request and make sure it succeeds.
12156 HttpRequestInfo request2;
12157 request2.method = "GET";
12158 request2.url = GURL(https_url);
12159 request2.load_flags = 0;
12160 HttpNetworkTransaction trans2(MEDIUM, session.get());
12161 TestCompletionCallback callback2;
12162 EXPECT_EQ(ERR_IO_PENDING,
12163 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
12164 base::MessageLoop::current()->RunUntilIdle();
12165 data2->RunFor(3);
12167 ASSERT_TRUE(callback2.have_result());
12168 EXPECT_EQ(OK, callback2.WaitForResult());
12169 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12172 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
12173 session_deps_.next_protos = SpdyNextProtos();
12174 ClientSocketPoolManager::set_max_sockets_per_group(
12175 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12176 ClientSocketPoolManager::set_max_sockets_per_pool(
12177 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12179 // Use two different hosts with different IPs so they don't get pooled.
12180 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
12181 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
12182 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12184 SSLSocketDataProvider ssl1(ASYNC, OK);
12185 ssl1.SetNextProto(GetParam());
12186 SSLSocketDataProvider ssl2(ASYNC, OK);
12187 ssl2.SetNextProto(GetParam());
12188 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12189 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12191 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
12192 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
12193 MockWrite spdy1_writes[] = {
12194 CreateMockWrite(*host1_req, 1),
12196 scoped_ptr<SpdyFrame> host1_resp(
12197 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12198 scoped_ptr<SpdyFrame> host1_resp_body(
12199 spdy_util_.ConstructSpdyBodyFrame(1, true));
12200 MockRead spdy1_reads[] = {
12201 CreateMockRead(*host1_resp, 2),
12202 CreateMockRead(*host1_resp_body, 3),
12203 MockRead(ASYNC, ERR_IO_PENDING, 4),
12206 scoped_ptr<OrderedSocketData> spdy1_data(
12207 new OrderedSocketData(
12208 spdy1_reads, arraysize(spdy1_reads),
12209 spdy1_writes, arraysize(spdy1_writes)));
12210 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
12212 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
12213 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
12214 MockWrite spdy2_writes[] = {
12215 CreateMockWrite(*host2_req, 1),
12217 scoped_ptr<SpdyFrame> host2_resp(
12218 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12219 scoped_ptr<SpdyFrame> host2_resp_body(
12220 spdy_util_.ConstructSpdyBodyFrame(1, true));
12221 MockRead spdy2_reads[] = {
12222 CreateMockRead(*host2_resp, 2),
12223 CreateMockRead(*host2_resp_body, 3),
12224 MockRead(ASYNC, ERR_IO_PENDING, 4),
12227 scoped_ptr<OrderedSocketData> spdy2_data(
12228 new OrderedSocketData(
12229 spdy2_reads, arraysize(spdy2_reads),
12230 spdy2_writes, arraysize(spdy2_writes)));
12231 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
12233 MockWrite http_write[] = {
12234 MockWrite("GET / HTTP/1.1\r\n"
12235 "Host: www.a.com\r\n"
12236 "Connection: keep-alive\r\n\r\n"),
12239 MockRead http_read[] = {
12240 MockRead("HTTP/1.1 200 OK\r\n"),
12241 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12242 MockRead("Content-Length: 6\r\n\r\n"),
12243 MockRead("hello!"),
12245 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
12246 http_write, arraysize(http_write));
12247 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12249 HostPortPair host_port_pair_a("www.a.com", 443);
12250 SpdySessionKey spdy_session_key_a(
12251 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12252 EXPECT_FALSE(
12253 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12255 TestCompletionCallback callback;
12256 HttpRequestInfo request1;
12257 request1.method = "GET";
12258 request1.url = GURL("https://www.a.com/");
12259 request1.load_flags = 0;
12260 scoped_ptr<HttpNetworkTransaction> trans(
12261 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12263 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
12264 EXPECT_EQ(ERR_IO_PENDING, rv);
12265 EXPECT_EQ(OK, callback.WaitForResult());
12267 const HttpResponseInfo* response = trans->GetResponseInfo();
12268 ASSERT_TRUE(response != NULL);
12269 ASSERT_TRUE(response->headers.get() != NULL);
12270 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12271 EXPECT_TRUE(response->was_fetched_via_spdy);
12272 EXPECT_TRUE(response->was_npn_negotiated);
12274 std::string response_data;
12275 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12276 EXPECT_EQ("hello!", response_data);
12277 trans.reset();
12278 EXPECT_TRUE(
12279 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12281 HostPortPair host_port_pair_b("www.b.com", 443);
12282 SpdySessionKey spdy_session_key_b(
12283 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12284 EXPECT_FALSE(
12285 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12286 HttpRequestInfo request2;
12287 request2.method = "GET";
12288 request2.url = GURL("https://www.b.com/");
12289 request2.load_flags = 0;
12290 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12292 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
12293 EXPECT_EQ(ERR_IO_PENDING, rv);
12294 EXPECT_EQ(OK, callback.WaitForResult());
12296 response = trans->GetResponseInfo();
12297 ASSERT_TRUE(response != NULL);
12298 ASSERT_TRUE(response->headers.get() != NULL);
12299 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12300 EXPECT_TRUE(response->was_fetched_via_spdy);
12301 EXPECT_TRUE(response->was_npn_negotiated);
12302 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12303 EXPECT_EQ("hello!", response_data);
12304 EXPECT_FALSE(
12305 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12306 EXPECT_TRUE(
12307 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12309 HostPortPair host_port_pair_a1("www.a.com", 80);
12310 SpdySessionKey spdy_session_key_a1(
12311 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
12312 EXPECT_FALSE(
12313 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
12314 HttpRequestInfo request3;
12315 request3.method = "GET";
12316 request3.url = GURL("http://www.a.com/");
12317 request3.load_flags = 0;
12318 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12320 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
12321 EXPECT_EQ(ERR_IO_PENDING, rv);
12322 EXPECT_EQ(OK, callback.WaitForResult());
12324 response = trans->GetResponseInfo();
12325 ASSERT_TRUE(response != NULL);
12326 ASSERT_TRUE(response->headers.get() != NULL);
12327 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12328 EXPECT_FALSE(response->was_fetched_via_spdy);
12329 EXPECT_FALSE(response->was_npn_negotiated);
12330 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
12331 EXPECT_EQ("hello!", response_data);
12332 EXPECT_FALSE(
12333 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
12334 EXPECT_FALSE(
12335 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
12338 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
12339 HttpRequestInfo request;
12340 request.method = "GET";
12341 request.url = GURL("http://www.example.org/");
12342 request.load_flags = 0;
12344 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12345 scoped_ptr<HttpTransaction> trans(
12346 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12348 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
12349 StaticSocketDataProvider data;
12350 data.set_connect_data(mock_connect);
12351 session_deps_.socket_factory->AddSocketDataProvider(&data);
12353 TestCompletionCallback callback;
12355 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12356 EXPECT_EQ(ERR_IO_PENDING, rv);
12358 rv = callback.WaitForResult();
12359 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12361 EXPECT_EQ(NULL, trans->GetResponseInfo());
12363 // We don't care whether this succeeds or fails, but it shouldn't crash.
12364 HttpRequestHeaders request_headers;
12365 trans->GetFullRequestHeaders(&request_headers);
12368 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
12369 HttpRequestInfo request;
12370 request.method = "GET";
12371 request.url = GURL("http://www.example.org/");
12372 request.load_flags = 0;
12374 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12375 scoped_ptr<HttpTransaction> trans(
12376 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12378 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12379 StaticSocketDataProvider data;
12380 data.set_connect_data(mock_connect);
12381 session_deps_.socket_factory->AddSocketDataProvider(&data);
12383 TestCompletionCallback callback;
12385 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12386 EXPECT_EQ(ERR_IO_PENDING, rv);
12388 rv = callback.WaitForResult();
12389 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12391 EXPECT_EQ(NULL, trans->GetResponseInfo());
12393 // We don't care whether this succeeds or fails, but it shouldn't crash.
12394 HttpRequestHeaders request_headers;
12395 trans->GetFullRequestHeaders(&request_headers);
12398 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
12399 HttpRequestInfo request;
12400 request.method = "GET";
12401 request.url = GURL("http://www.example.org/");
12402 request.load_flags = 0;
12404 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12405 scoped_ptr<HttpTransaction> trans(
12406 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12408 MockWrite data_writes[] = {
12409 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12411 MockRead data_reads[] = {
12412 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12415 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12416 data_writes, arraysize(data_writes));
12417 session_deps_.socket_factory->AddSocketDataProvider(&data);
12419 TestCompletionCallback callback;
12421 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12422 EXPECT_EQ(ERR_IO_PENDING, rv);
12424 rv = callback.WaitForResult();
12425 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12427 EXPECT_EQ(NULL, trans->GetResponseInfo());
12429 HttpRequestHeaders request_headers;
12430 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12431 EXPECT_TRUE(request_headers.HasHeader("Host"));
12434 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
12435 HttpRequestInfo request;
12436 request.method = "GET";
12437 request.url = GURL("http://www.example.org/");
12438 request.load_flags = 0;
12440 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12441 scoped_ptr<HttpTransaction> trans(
12442 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12444 MockWrite data_writes[] = {
12445 MockWrite(ASYNC, ERR_CONNECTION_RESET),
12447 MockRead data_reads[] = {
12448 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12451 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12452 data_writes, arraysize(data_writes));
12453 session_deps_.socket_factory->AddSocketDataProvider(&data);
12455 TestCompletionCallback callback;
12457 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12458 EXPECT_EQ(ERR_IO_PENDING, rv);
12460 rv = callback.WaitForResult();
12461 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12463 EXPECT_EQ(NULL, trans->GetResponseInfo());
12465 HttpRequestHeaders request_headers;
12466 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12467 EXPECT_TRUE(request_headers.HasHeader("Host"));
12470 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
12471 HttpRequestInfo request;
12472 request.method = "GET";
12473 request.url = GURL("http://www.example.org/");
12474 request.load_flags = 0;
12476 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12477 scoped_ptr<HttpTransaction> trans(
12478 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12480 MockWrite data_writes[] = {
12481 MockWrite(
12482 "GET / HTTP/1.1\r\n"
12483 "Host: www.example.org\r\n"
12484 "Connection: keep-alive\r\n\r\n"),
12486 MockRead data_reads[] = {
12487 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
12490 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12491 data_writes, arraysize(data_writes));
12492 session_deps_.socket_factory->AddSocketDataProvider(&data);
12494 TestCompletionCallback callback;
12496 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12497 EXPECT_EQ(ERR_IO_PENDING, rv);
12499 rv = callback.WaitForResult();
12500 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12502 EXPECT_EQ(NULL, trans->GetResponseInfo());
12504 HttpRequestHeaders request_headers;
12505 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12506 EXPECT_TRUE(request_headers.HasHeader("Host"));
12509 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
12510 HttpRequestInfo request;
12511 request.method = "GET";
12512 request.url = GURL("http://www.example.org/");
12513 request.load_flags = 0;
12515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12516 scoped_ptr<HttpTransaction> trans(
12517 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12519 MockWrite data_writes[] = {
12520 MockWrite(
12521 "GET / HTTP/1.1\r\n"
12522 "Host: www.example.org\r\n"
12523 "Connection: keep-alive\r\n\r\n"),
12525 MockRead data_reads[] = {
12526 MockRead(ASYNC, ERR_CONNECTION_RESET),
12529 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12530 data_writes, arraysize(data_writes));
12531 session_deps_.socket_factory->AddSocketDataProvider(&data);
12533 TestCompletionCallback callback;
12535 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12536 EXPECT_EQ(ERR_IO_PENDING, rv);
12538 rv = callback.WaitForResult();
12539 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12541 EXPECT_EQ(NULL, trans->GetResponseInfo());
12543 HttpRequestHeaders request_headers;
12544 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12545 EXPECT_TRUE(request_headers.HasHeader("Host"));
12548 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12549 HttpRequestInfo request;
12550 request.method = "GET";
12551 request.url = GURL("http://www.example.org/");
12552 request.load_flags = 0;
12553 request.extra_headers.SetHeader("X-Foo", "bar");
12555 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12556 scoped_ptr<HttpTransaction> trans(
12557 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12559 MockWrite data_writes[] = {
12560 MockWrite(
12561 "GET / HTTP/1.1\r\n"
12562 "Host: www.example.org\r\n"
12563 "Connection: keep-alive\r\n"
12564 "X-Foo: bar\r\n\r\n"),
12566 MockRead data_reads[] = {
12567 MockRead("HTTP/1.1 200 OK\r\n"
12568 "Content-Length: 5\r\n\r\n"
12569 "hello"),
12570 MockRead(ASYNC, ERR_UNEXPECTED),
12573 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12574 data_writes, arraysize(data_writes));
12575 session_deps_.socket_factory->AddSocketDataProvider(&data);
12577 TestCompletionCallback callback;
12579 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12580 EXPECT_EQ(ERR_IO_PENDING, rv);
12582 rv = callback.WaitForResult();
12583 EXPECT_EQ(OK, rv);
12585 HttpRequestHeaders request_headers;
12586 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12587 std::string foo;
12588 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12589 EXPECT_EQ("bar", foo);
12592 namespace {
12594 // Fake HttpStream that simply records calls to SetPriority().
12595 class FakeStream : public HttpStream,
12596 public base::SupportsWeakPtr<FakeStream> {
12597 public:
12598 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12599 ~FakeStream() override {}
12601 RequestPriority priority() const { return priority_; }
12603 int InitializeStream(const HttpRequestInfo* request_info,
12604 RequestPriority priority,
12605 const BoundNetLog& net_log,
12606 const CompletionCallback& callback) override {
12607 return ERR_IO_PENDING;
12610 int SendRequest(const HttpRequestHeaders& request_headers,
12611 HttpResponseInfo* response,
12612 const CompletionCallback& callback) override {
12613 ADD_FAILURE();
12614 return ERR_UNEXPECTED;
12617 int ReadResponseHeaders(const CompletionCallback& callback) override {
12618 ADD_FAILURE();
12619 return ERR_UNEXPECTED;
12622 int ReadResponseBody(IOBuffer* buf,
12623 int buf_len,
12624 const CompletionCallback& callback) override {
12625 ADD_FAILURE();
12626 return ERR_UNEXPECTED;
12629 void Close(bool not_reusable) override {}
12631 bool IsResponseBodyComplete() const override {
12632 ADD_FAILURE();
12633 return false;
12636 bool CanFindEndOfResponse() const override { return false; }
12638 bool IsConnectionReused() const override {
12639 ADD_FAILURE();
12640 return false;
12643 void SetConnectionReused() override { ADD_FAILURE(); }
12645 bool IsConnectionReusable() const override {
12646 ADD_FAILURE();
12647 return false;
12650 int64 GetTotalReceivedBytes() const override {
12651 ADD_FAILURE();
12652 return 0;
12655 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
12656 ADD_FAILURE();
12657 return false;
12660 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
12662 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
12663 ADD_FAILURE();
12666 bool IsSpdyHttpStream() const override {
12667 ADD_FAILURE();
12668 return false;
12671 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
12673 void SetPriority(RequestPriority priority) override { priority_ = priority; }
12675 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
12677 HttpStream* RenewStreamForAuth() override { return NULL; }
12679 private:
12680 RequestPriority priority_;
12682 DISALLOW_COPY_AND_ASSIGN(FakeStream);
12685 // Fake HttpStreamRequest that simply records calls to SetPriority()
12686 // and vends FakeStreams with its current priority.
12687 class FakeStreamRequest : public HttpStreamRequest,
12688 public base::SupportsWeakPtr<FakeStreamRequest> {
12689 public:
12690 FakeStreamRequest(RequestPriority priority,
12691 HttpStreamRequest::Delegate* delegate)
12692 : priority_(priority),
12693 delegate_(delegate),
12694 websocket_stream_create_helper_(NULL) {}
12696 FakeStreamRequest(RequestPriority priority,
12697 HttpStreamRequest::Delegate* delegate,
12698 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
12699 : priority_(priority),
12700 delegate_(delegate),
12701 websocket_stream_create_helper_(create_helper) {}
12703 ~FakeStreamRequest() override {}
12705 RequestPriority priority() const { return priority_; }
12707 const WebSocketHandshakeStreamBase::CreateHelper*
12708 websocket_stream_create_helper() const {
12709 return websocket_stream_create_helper_;
12712 // Create a new FakeStream and pass it to the request's
12713 // delegate. Returns a weak pointer to the FakeStream.
12714 base::WeakPtr<FakeStream> FinishStreamRequest() {
12715 FakeStream* fake_stream = new FakeStream(priority_);
12716 // Do this before calling OnStreamReady() as OnStreamReady() may
12717 // immediately delete |fake_stream|.
12718 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
12719 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
12720 return weak_stream;
12723 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
12724 ADD_FAILURE();
12725 return ERR_UNEXPECTED;
12728 LoadState GetLoadState() const override {
12729 ADD_FAILURE();
12730 return LoadState();
12733 void SetPriority(RequestPriority priority) override { priority_ = priority; }
12735 bool was_npn_negotiated() const override { return false; }
12737 NextProto protocol_negotiated() const override { return kProtoUnknown; }
12739 bool using_spdy() const override { return false; }
12741 private:
12742 RequestPriority priority_;
12743 HttpStreamRequest::Delegate* const delegate_;
12744 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
12746 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12749 // Fake HttpStreamFactory that vends FakeStreamRequests.
12750 class FakeStreamFactory : public HttpStreamFactory {
12751 public:
12752 FakeStreamFactory() {}
12753 ~FakeStreamFactory() override {}
12755 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12756 // RequestStream() (which may be NULL if it was destroyed already).
12757 base::WeakPtr<FakeStreamRequest> last_stream_request() {
12758 return last_stream_request_;
12761 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
12762 RequestPriority priority,
12763 const SSLConfig& server_ssl_config,
12764 const SSLConfig& proxy_ssl_config,
12765 HttpStreamRequest::Delegate* delegate,
12766 const BoundNetLog& net_log) override {
12767 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12768 last_stream_request_ = fake_request->AsWeakPtr();
12769 return fake_request;
12772 HttpStreamRequest* RequestWebSocketHandshakeStream(
12773 const HttpRequestInfo& info,
12774 RequestPriority priority,
12775 const SSLConfig& server_ssl_config,
12776 const SSLConfig& proxy_ssl_config,
12777 HttpStreamRequest::Delegate* delegate,
12778 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
12779 const BoundNetLog& net_log) override {
12780 FakeStreamRequest* fake_request =
12781 new FakeStreamRequest(priority, delegate, create_helper);
12782 last_stream_request_ = fake_request->AsWeakPtr();
12783 return fake_request;
12786 void PreconnectStreams(int num_streams,
12787 const HttpRequestInfo& info,
12788 RequestPriority priority,
12789 const SSLConfig& server_ssl_config,
12790 const SSLConfig& proxy_ssl_config) override {
12791 ADD_FAILURE();
12794 const HostMappingRules* GetHostMappingRules() const override {
12795 ADD_FAILURE();
12796 return NULL;
12799 private:
12800 base::WeakPtr<FakeStreamRequest> last_stream_request_;
12802 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12805 // TODO(ricea): Maybe unify this with the one in
12806 // url_request_http_job_unittest.cc ?
12807 class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
12808 public:
12809 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
12810 bool using_proxy)
12811 : state_(connection.release(), using_proxy) {}
12813 // Fake implementation of HttpStreamBase methods.
12814 // This ends up being quite "real" because this object has to really send data
12815 // on the mock socket. It might be easier to use the real implementation, but
12816 // the fact that the WebSocket code is not compiled on iOS makes that
12817 // difficult.
12818 int InitializeStream(const HttpRequestInfo* request_info,
12819 RequestPriority priority,
12820 const BoundNetLog& net_log,
12821 const CompletionCallback& callback) override {
12822 state_.Initialize(request_info, priority, net_log, callback);
12823 return OK;
12826 int SendRequest(const HttpRequestHeaders& request_headers,
12827 HttpResponseInfo* response,
12828 const CompletionCallback& callback) override {
12829 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
12830 response, callback);
12833 int ReadResponseHeaders(const CompletionCallback& callback) override {
12834 return parser()->ReadResponseHeaders(callback);
12837 int ReadResponseBody(IOBuffer* buf,
12838 int buf_len,
12839 const CompletionCallback& callback) override {
12840 NOTREACHED();
12841 return ERR_IO_PENDING;
12844 void Close(bool not_reusable) override {
12845 if (parser())
12846 parser()->Close(true);
12849 bool IsResponseBodyComplete() const override {
12850 NOTREACHED();
12851 return false;
12854 bool CanFindEndOfResponse() const override {
12855 return parser()->CanFindEndOfResponse();
12858 bool IsConnectionReused() const override {
12859 NOTREACHED();
12860 return false;
12862 void SetConnectionReused() override { NOTREACHED(); }
12864 bool IsConnectionReusable() const override {
12865 NOTREACHED();
12866 return false;
12869 int64 GetTotalReceivedBytes() const override {
12870 NOTREACHED();
12871 return 0;
12874 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
12875 NOTREACHED();
12876 return false;
12879 void GetSSLInfo(SSLInfo* ssl_info) override {}
12881 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
12882 NOTREACHED();
12885 bool IsSpdyHttpStream() const override {
12886 NOTREACHED();
12887 return false;
12890 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
12892 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
12894 UploadProgress GetUploadProgress() const override {
12895 NOTREACHED();
12896 return UploadProgress();
12899 HttpStream* RenewStreamForAuth() override {
12900 NOTREACHED();
12901 return nullptr;
12904 // Fake implementation of WebSocketHandshakeStreamBase method(s)
12905 scoped_ptr<WebSocketStream> Upgrade() override {
12906 NOTREACHED();
12907 return scoped_ptr<WebSocketStream>();
12910 private:
12911 HttpStreamParser* parser() const { return state_.parser(); }
12912 HttpBasicState state_;
12914 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
12917 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12918 // worth doing.
12919 class FakeWebSocketStreamCreateHelper :
12920 public WebSocketHandshakeStreamBase::CreateHelper {
12921 public:
12922 WebSocketHandshakeStreamBase* CreateBasicStream(
12923 scoped_ptr<ClientSocketHandle> connection,
12924 bool using_proxy) override {
12925 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
12926 using_proxy);
12929 WebSocketHandshakeStreamBase* CreateSpdyStream(
12930 const base::WeakPtr<SpdySession>& session,
12931 bool use_relative_url) override {
12932 NOTREACHED();
12933 return NULL;
12936 ~FakeWebSocketStreamCreateHelper() override {}
12938 virtual scoped_ptr<WebSocketStream> Upgrade() {
12939 NOTREACHED();
12940 return scoped_ptr<WebSocketStream>();
12944 } // namespace
12946 // Make sure that HttpNetworkTransaction passes on its priority to its
12947 // stream request on start.
12948 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
12949 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12950 HttpNetworkSessionPeer peer(session);
12951 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12952 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12954 HttpNetworkTransaction trans(LOW, session.get());
12956 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
12958 HttpRequestInfo request;
12959 TestCompletionCallback callback;
12960 EXPECT_EQ(ERR_IO_PENDING,
12961 trans.Start(&request, callback.callback(), BoundNetLog()));
12963 base::WeakPtr<FakeStreamRequest> fake_request =
12964 fake_factory->last_stream_request();
12965 ASSERT_TRUE(fake_request != NULL);
12966 EXPECT_EQ(LOW, fake_request->priority());
12969 // Make sure that HttpNetworkTransaction passes on its priority
12970 // updates to its stream request.
12971 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
12972 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12973 HttpNetworkSessionPeer peer(session);
12974 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12975 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12977 HttpNetworkTransaction trans(LOW, session.get());
12979 HttpRequestInfo request;
12980 TestCompletionCallback callback;
12981 EXPECT_EQ(ERR_IO_PENDING,
12982 trans.Start(&request, callback.callback(), BoundNetLog()));
12984 base::WeakPtr<FakeStreamRequest> fake_request =
12985 fake_factory->last_stream_request();
12986 ASSERT_TRUE(fake_request != NULL);
12987 EXPECT_EQ(LOW, fake_request->priority());
12989 trans.SetPriority(LOWEST);
12990 ASSERT_TRUE(fake_request != NULL);
12991 EXPECT_EQ(LOWEST, fake_request->priority());
12994 // Make sure that HttpNetworkTransaction passes on its priority
12995 // updates to its stream.
12996 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
12997 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12998 HttpNetworkSessionPeer peer(session);
12999 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13000 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
13002 HttpNetworkTransaction trans(LOW, session.get());
13004 HttpRequestInfo request;
13005 TestCompletionCallback callback;
13006 EXPECT_EQ(ERR_IO_PENDING,
13007 trans.Start(&request, callback.callback(), BoundNetLog()));
13009 base::WeakPtr<FakeStreamRequest> fake_request =
13010 fake_factory->last_stream_request();
13011 ASSERT_TRUE(fake_request != NULL);
13012 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
13013 ASSERT_TRUE(fake_stream != NULL);
13014 EXPECT_EQ(LOW, fake_stream->priority());
13016 trans.SetPriority(LOWEST);
13017 EXPECT_EQ(LOWEST, fake_stream->priority());
13020 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
13021 // The same logic needs to be tested for both ws: and wss: schemes, but this
13022 // test is already parameterised on NextProto, so it uses a loop to verify
13023 // that the different schemes work.
13024 std::string test_cases[] = {"ws://www.example.org/",
13025 "wss://www.example.org/"};
13026 for (size_t i = 0; i < arraysize(test_cases); ++i) {
13027 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13028 HttpNetworkSessionPeer peer(session);
13029 FakeStreamFactory* fake_factory = new FakeStreamFactory();
13030 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13031 peer.SetHttpStreamFactoryForWebSocket(
13032 scoped_ptr<HttpStreamFactory>(fake_factory));
13034 HttpNetworkTransaction trans(LOW, session.get());
13035 trans.SetWebSocketHandshakeStreamCreateHelper(
13036 &websocket_stream_create_helper);
13038 HttpRequestInfo request;
13039 TestCompletionCallback callback;
13040 request.method = "GET";
13041 request.url = GURL(test_cases[i]);
13043 EXPECT_EQ(ERR_IO_PENDING,
13044 trans.Start(&request, callback.callback(), BoundNetLog()));
13046 base::WeakPtr<FakeStreamRequest> fake_request =
13047 fake_factory->last_stream_request();
13048 ASSERT_TRUE(fake_request != NULL);
13049 EXPECT_EQ(&websocket_stream_create_helper,
13050 fake_request->websocket_stream_create_helper());
13054 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13055 // if the transport socket pool is stalled on the global socket limit.
13056 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
13057 ClientSocketPoolManager::set_max_sockets_per_group(
13058 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13059 ClientSocketPoolManager::set_max_sockets_per_pool(
13060 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13062 // Set up SSL request.
13064 HttpRequestInfo ssl_request;
13065 ssl_request.method = "GET";
13066 ssl_request.url = GURL("https://www.example.org/");
13068 MockWrite ssl_writes[] = {
13069 MockWrite(
13070 "GET / HTTP/1.1\r\n"
13071 "Host: www.example.org\r\n"
13072 "Connection: keep-alive\r\n\r\n"),
13074 MockRead ssl_reads[] = {
13075 MockRead("HTTP/1.1 200 OK\r\n"),
13076 MockRead("Content-Length: 11\r\n\r\n"),
13077 MockRead("hello world"),
13078 MockRead(SYNCHRONOUS, OK),
13080 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
13081 ssl_writes, arraysize(ssl_writes));
13082 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13084 SSLSocketDataProvider ssl(ASYNC, OK);
13085 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13087 // Set up HTTP request.
13089 HttpRequestInfo http_request;
13090 http_request.method = "GET";
13091 http_request.url = GURL("http://www.example.org/");
13093 MockWrite http_writes[] = {
13094 MockWrite(
13095 "GET / HTTP/1.1\r\n"
13096 "Host: www.example.org\r\n"
13097 "Connection: keep-alive\r\n\r\n"),
13099 MockRead http_reads[] = {
13100 MockRead("HTTP/1.1 200 OK\r\n"),
13101 MockRead("Content-Length: 7\r\n\r\n"),
13102 MockRead("falafel"),
13103 MockRead(SYNCHRONOUS, OK),
13105 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13106 http_writes, arraysize(http_writes));
13107 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13111 // Start the SSL request.
13112 TestCompletionCallback ssl_callback;
13113 scoped_ptr<HttpTransaction> ssl_trans(
13114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13115 ASSERT_EQ(ERR_IO_PENDING,
13116 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
13117 BoundNetLog()));
13119 // Start the HTTP request. Pool should stall.
13120 TestCompletionCallback http_callback;
13121 scoped_ptr<HttpTransaction> http_trans(
13122 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13123 ASSERT_EQ(ERR_IO_PENDING,
13124 http_trans->Start(&http_request, http_callback.callback(),
13125 BoundNetLog()));
13126 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13128 // Wait for response from SSL request.
13129 ASSERT_EQ(OK, ssl_callback.WaitForResult());
13130 std::string response_data;
13131 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
13132 EXPECT_EQ("hello world", response_data);
13134 // The SSL socket should automatically be closed, so the HTTP request can
13135 // start.
13136 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13137 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
13139 // The HTTP request can now complete.
13140 ASSERT_EQ(OK, http_callback.WaitForResult());
13141 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13142 EXPECT_EQ("falafel", response_data);
13144 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13147 // Tests that when a SSL connection is established but there's no corresponding
13148 // request that needs it, the new socket is closed if the transport socket pool
13149 // is stalled on the global socket limit.
13150 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
13151 ClientSocketPoolManager::set_max_sockets_per_group(
13152 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13153 ClientSocketPoolManager::set_max_sockets_per_pool(
13154 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13156 // Set up an ssl request.
13158 HttpRequestInfo ssl_request;
13159 ssl_request.method = "GET";
13160 ssl_request.url = GURL("https://www.foopy.com/");
13162 // No data will be sent on the SSL socket.
13163 StaticSocketDataProvider ssl_data;
13164 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
13166 SSLSocketDataProvider ssl(ASYNC, OK);
13167 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13169 // Set up HTTP request.
13171 HttpRequestInfo http_request;
13172 http_request.method = "GET";
13173 http_request.url = GURL("http://www.example.org/");
13175 MockWrite http_writes[] = {
13176 MockWrite(
13177 "GET / HTTP/1.1\r\n"
13178 "Host: www.example.org\r\n"
13179 "Connection: keep-alive\r\n\r\n"),
13181 MockRead http_reads[] = {
13182 MockRead("HTTP/1.1 200 OK\r\n"),
13183 MockRead("Content-Length: 7\r\n\r\n"),
13184 MockRead("falafel"),
13185 MockRead(SYNCHRONOUS, OK),
13187 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13188 http_writes, arraysize(http_writes));
13189 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13191 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13193 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13194 // cancelled when a normal transaction is cancelled.
13195 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
13196 SSLConfig ssl_config;
13197 session->ssl_config_service()->GetSSLConfig(&ssl_config);
13198 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
13199 ssl_config, ssl_config);
13200 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
13202 // Start the HTTP request. Pool should stall.
13203 TestCompletionCallback http_callback;
13204 scoped_ptr<HttpTransaction> http_trans(
13205 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13206 ASSERT_EQ(ERR_IO_PENDING,
13207 http_trans->Start(&http_request, http_callback.callback(),
13208 BoundNetLog()));
13209 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
13211 // The SSL connection will automatically be closed once the connection is
13212 // established, to let the HTTP request start.
13213 ASSERT_EQ(OK, http_callback.WaitForResult());
13214 std::string response_data;
13215 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
13216 EXPECT_EQ("falafel", response_data);
13218 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
13221 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
13222 ScopedVector<UploadElementReader> element_readers;
13223 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13224 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13226 HttpRequestInfo request;
13227 request.method = "POST";
13228 request.url = GURL("http://www.foo.com/");
13229 request.upload_data_stream = &upload_data_stream;
13230 request.load_flags = 0;
13232 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13233 scoped_ptr<HttpTransaction> trans(
13234 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13235 // Send headers successfully, but get an error while sending the body.
13236 MockWrite data_writes[] = {
13237 MockWrite("POST / HTTP/1.1\r\n"
13238 "Host: www.foo.com\r\n"
13239 "Connection: keep-alive\r\n"
13240 "Content-Length: 3\r\n\r\n"),
13241 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13244 MockRead data_reads[] = {
13245 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13246 MockRead("hello world"),
13247 MockRead(SYNCHRONOUS, OK),
13249 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13250 arraysize(data_writes));
13251 session_deps_.socket_factory->AddSocketDataProvider(&data);
13253 TestCompletionCallback callback;
13255 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13256 EXPECT_EQ(ERR_IO_PENDING, rv);
13258 rv = callback.WaitForResult();
13259 EXPECT_EQ(OK, rv);
13261 const HttpResponseInfo* response = trans->GetResponseInfo();
13262 ASSERT_TRUE(response != NULL);
13264 EXPECT_TRUE(response->headers.get() != NULL);
13265 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13267 std::string response_data;
13268 rv = ReadTransaction(trans.get(), &response_data);
13269 EXPECT_EQ(OK, rv);
13270 EXPECT_EQ("hello world", response_data);
13273 // This test makes sure the retry logic doesn't trigger when reading an error
13274 // response from a server that rejected a POST with a CONNECTION_RESET.
13275 TEST_P(HttpNetworkTransactionTest,
13276 PostReadsErrorResponseAfterResetOnReusedSocket) {
13277 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13278 MockWrite data_writes[] = {
13279 MockWrite("GET / HTTP/1.1\r\n"
13280 "Host: www.foo.com\r\n"
13281 "Connection: keep-alive\r\n\r\n"),
13282 MockWrite("POST / HTTP/1.1\r\n"
13283 "Host: www.foo.com\r\n"
13284 "Connection: keep-alive\r\n"
13285 "Content-Length: 3\r\n\r\n"),
13286 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13289 MockRead data_reads[] = {
13290 MockRead("HTTP/1.1 200 Peachy\r\n"
13291 "Content-Length: 14\r\n\r\n"),
13292 MockRead("first response"),
13293 MockRead("HTTP/1.1 400 Not OK\r\n"
13294 "Content-Length: 15\r\n\r\n"),
13295 MockRead("second response"),
13296 MockRead(SYNCHRONOUS, OK),
13298 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13299 arraysize(data_writes));
13300 session_deps_.socket_factory->AddSocketDataProvider(&data);
13302 TestCompletionCallback callback;
13303 HttpRequestInfo request1;
13304 request1.method = "GET";
13305 request1.url = GURL("http://www.foo.com/");
13306 request1.load_flags = 0;
13308 scoped_ptr<HttpTransaction> trans1(
13309 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13310 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
13311 EXPECT_EQ(ERR_IO_PENDING, rv);
13313 rv = callback.WaitForResult();
13314 EXPECT_EQ(OK, rv);
13316 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13317 ASSERT_TRUE(response1 != NULL);
13319 EXPECT_TRUE(response1->headers.get() != NULL);
13320 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
13322 std::string response_data1;
13323 rv = ReadTransaction(trans1.get(), &response_data1);
13324 EXPECT_EQ(OK, rv);
13325 EXPECT_EQ("first response", response_data1);
13326 // Delete the transaction to release the socket back into the socket pool.
13327 trans1.reset();
13329 ScopedVector<UploadElementReader> element_readers;
13330 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13331 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13333 HttpRequestInfo request2;
13334 request2.method = "POST";
13335 request2.url = GURL("http://www.foo.com/");
13336 request2.upload_data_stream = &upload_data_stream;
13337 request2.load_flags = 0;
13339 scoped_ptr<HttpTransaction> trans2(
13340 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13341 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
13342 EXPECT_EQ(ERR_IO_PENDING, rv);
13344 rv = callback.WaitForResult();
13345 EXPECT_EQ(OK, rv);
13347 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
13348 ASSERT_TRUE(response2 != NULL);
13350 EXPECT_TRUE(response2->headers.get() != NULL);
13351 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
13353 std::string response_data2;
13354 rv = ReadTransaction(trans2.get(), &response_data2);
13355 EXPECT_EQ(OK, rv);
13356 EXPECT_EQ("second response", response_data2);
13359 TEST_P(HttpNetworkTransactionTest,
13360 PostReadsErrorResponseAfterResetPartialBodySent) {
13361 ScopedVector<UploadElementReader> element_readers;
13362 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13363 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13365 HttpRequestInfo request;
13366 request.method = "POST";
13367 request.url = GURL("http://www.foo.com/");
13368 request.upload_data_stream = &upload_data_stream;
13369 request.load_flags = 0;
13371 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13372 scoped_ptr<HttpTransaction> trans(
13373 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13374 // Send headers successfully, but get an error while sending the body.
13375 MockWrite data_writes[] = {
13376 MockWrite("POST / HTTP/1.1\r\n"
13377 "Host: www.foo.com\r\n"
13378 "Connection: keep-alive\r\n"
13379 "Content-Length: 3\r\n\r\n"
13380 "fo"),
13381 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13384 MockRead data_reads[] = {
13385 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13386 MockRead("hello world"),
13387 MockRead(SYNCHRONOUS, OK),
13389 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13390 arraysize(data_writes));
13391 session_deps_.socket_factory->AddSocketDataProvider(&data);
13393 TestCompletionCallback callback;
13395 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13396 EXPECT_EQ(ERR_IO_PENDING, rv);
13398 rv = callback.WaitForResult();
13399 EXPECT_EQ(OK, rv);
13401 const HttpResponseInfo* response = trans->GetResponseInfo();
13402 ASSERT_TRUE(response != NULL);
13404 EXPECT_TRUE(response->headers.get() != NULL);
13405 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13407 std::string response_data;
13408 rv = ReadTransaction(trans.get(), &response_data);
13409 EXPECT_EQ(OK, rv);
13410 EXPECT_EQ("hello world", response_data);
13413 // This tests the more common case than the previous test, where headers and
13414 // body are not merged into a single request.
13415 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
13416 ScopedVector<UploadElementReader> element_readers;
13417 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13418 ChunkedUploadDataStream upload_data_stream(0);
13420 HttpRequestInfo request;
13421 request.method = "POST";
13422 request.url = GURL("http://www.foo.com/");
13423 request.upload_data_stream = &upload_data_stream;
13424 request.load_flags = 0;
13426 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13427 scoped_ptr<HttpTransaction> trans(
13428 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13429 // Send headers successfully, but get an error while sending the body.
13430 MockWrite data_writes[] = {
13431 MockWrite("POST / HTTP/1.1\r\n"
13432 "Host: www.foo.com\r\n"
13433 "Connection: keep-alive\r\n"
13434 "Transfer-Encoding: chunked\r\n\r\n"),
13435 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13438 MockRead data_reads[] = {
13439 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13440 MockRead("hello world"),
13441 MockRead(SYNCHRONOUS, OK),
13443 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13444 arraysize(data_writes));
13445 session_deps_.socket_factory->AddSocketDataProvider(&data);
13447 TestCompletionCallback callback;
13449 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13450 EXPECT_EQ(ERR_IO_PENDING, rv);
13451 // Make sure the headers are sent before adding a chunk. This ensures that
13452 // they can't be merged with the body in a single send. Not currently
13453 // necessary since a chunked body is never merged with headers, but this makes
13454 // the test more future proof.
13455 base::RunLoop().RunUntilIdle();
13457 upload_data_stream.AppendData("last chunk", 10, true);
13459 rv = callback.WaitForResult();
13460 EXPECT_EQ(OK, rv);
13462 const HttpResponseInfo* response = trans->GetResponseInfo();
13463 ASSERT_TRUE(response != NULL);
13465 EXPECT_TRUE(response->headers.get() != NULL);
13466 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13468 std::string response_data;
13469 rv = ReadTransaction(trans.get(), &response_data);
13470 EXPECT_EQ(OK, rv);
13471 EXPECT_EQ("hello world", response_data);
13474 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
13475 ScopedVector<UploadElementReader> element_readers;
13476 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13477 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13479 HttpRequestInfo request;
13480 request.method = "POST";
13481 request.url = GURL("http://www.foo.com/");
13482 request.upload_data_stream = &upload_data_stream;
13483 request.load_flags = 0;
13485 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13486 scoped_ptr<HttpTransaction> trans(
13487 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13489 MockWrite data_writes[] = {
13490 MockWrite("POST / HTTP/1.1\r\n"
13491 "Host: www.foo.com\r\n"
13492 "Connection: keep-alive\r\n"
13493 "Content-Length: 3\r\n\r\n"),
13494 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13497 MockRead data_reads[] = {
13498 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13499 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13500 MockRead("hello world"),
13501 MockRead(SYNCHRONOUS, OK),
13503 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13504 arraysize(data_writes));
13505 session_deps_.socket_factory->AddSocketDataProvider(&data);
13507 TestCompletionCallback callback;
13509 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13510 EXPECT_EQ(ERR_IO_PENDING, rv);
13512 rv = callback.WaitForResult();
13513 EXPECT_EQ(OK, rv);
13515 const HttpResponseInfo* response = trans->GetResponseInfo();
13516 ASSERT_TRUE(response != NULL);
13518 EXPECT_TRUE(response->headers.get() != NULL);
13519 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13521 std::string response_data;
13522 rv = ReadTransaction(trans.get(), &response_data);
13523 EXPECT_EQ(OK, rv);
13524 EXPECT_EQ("hello world", response_data);
13527 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
13528 ScopedVector<UploadElementReader> element_readers;
13529 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13530 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13532 HttpRequestInfo request;
13533 request.method = "POST";
13534 request.url = GURL("http://www.foo.com/");
13535 request.upload_data_stream = &upload_data_stream;
13536 request.load_flags = 0;
13538 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13539 scoped_ptr<HttpTransaction> trans(
13540 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13541 // Send headers successfully, but get an error while sending the body.
13542 MockWrite data_writes[] = {
13543 MockWrite("POST / HTTP/1.1\r\n"
13544 "Host: www.foo.com\r\n"
13545 "Connection: keep-alive\r\n"
13546 "Content-Length: 3\r\n\r\n"),
13547 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13550 MockRead data_reads[] = {
13551 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13552 MockRead("hello world"),
13553 MockRead(SYNCHRONOUS, OK),
13555 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13556 arraysize(data_writes));
13557 session_deps_.socket_factory->AddSocketDataProvider(&data);
13559 TestCompletionCallback callback;
13561 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13562 EXPECT_EQ(ERR_IO_PENDING, rv);
13564 rv = callback.WaitForResult();
13565 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13567 const HttpResponseInfo* response = trans->GetResponseInfo();
13568 EXPECT_TRUE(response == NULL);
13571 TEST_P(HttpNetworkTransactionTest,
13572 PostIgnoresNonErrorResponseAfterResetAnd100) {
13573 ScopedVector<UploadElementReader> element_readers;
13574 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13575 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13577 HttpRequestInfo request;
13578 request.method = "POST";
13579 request.url = GURL("http://www.foo.com/");
13580 request.upload_data_stream = &upload_data_stream;
13581 request.load_flags = 0;
13583 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13584 scoped_ptr<HttpTransaction> trans(
13585 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13586 // Send headers successfully, but get an error while sending the body.
13587 MockWrite data_writes[] = {
13588 MockWrite("POST / HTTP/1.1\r\n"
13589 "Host: www.foo.com\r\n"
13590 "Connection: keep-alive\r\n"
13591 "Content-Length: 3\r\n\r\n"),
13592 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13595 MockRead data_reads[] = {
13596 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13597 MockRead("HTTP/1.0 302 Redirect\r\n"),
13598 MockRead("Location: http://somewhere-else.com/\r\n"),
13599 MockRead("Content-Length: 0\r\n\r\n"),
13600 MockRead(SYNCHRONOUS, OK),
13602 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13603 arraysize(data_writes));
13604 session_deps_.socket_factory->AddSocketDataProvider(&data);
13606 TestCompletionCallback callback;
13608 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13609 EXPECT_EQ(ERR_IO_PENDING, rv);
13611 rv = callback.WaitForResult();
13612 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13614 const HttpResponseInfo* response = trans->GetResponseInfo();
13615 EXPECT_TRUE(response == NULL);
13618 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
13619 ScopedVector<UploadElementReader> element_readers;
13620 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13621 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13623 HttpRequestInfo request;
13624 request.method = "POST";
13625 request.url = GURL("http://www.foo.com/");
13626 request.upload_data_stream = &upload_data_stream;
13627 request.load_flags = 0;
13629 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13630 scoped_ptr<HttpTransaction> trans(
13631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13632 // Send headers successfully, but get an error while sending the body.
13633 MockWrite data_writes[] = {
13634 MockWrite("POST / HTTP/1.1\r\n"
13635 "Host: www.foo.com\r\n"
13636 "Connection: keep-alive\r\n"
13637 "Content-Length: 3\r\n\r\n"),
13638 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13641 MockRead data_reads[] = {
13642 MockRead("HTTP 0.9 rocks!"),
13643 MockRead(SYNCHRONOUS, OK),
13645 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13646 arraysize(data_writes));
13647 session_deps_.socket_factory->AddSocketDataProvider(&data);
13649 TestCompletionCallback callback;
13651 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13652 EXPECT_EQ(ERR_IO_PENDING, rv);
13654 rv = callback.WaitForResult();
13655 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13657 const HttpResponseInfo* response = trans->GetResponseInfo();
13658 EXPECT_TRUE(response == NULL);
13661 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
13662 ScopedVector<UploadElementReader> element_readers;
13663 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13664 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
13666 HttpRequestInfo request;
13667 request.method = "POST";
13668 request.url = GURL("http://www.foo.com/");
13669 request.upload_data_stream = &upload_data_stream;
13670 request.load_flags = 0;
13672 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13673 scoped_ptr<HttpTransaction> trans(
13674 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13675 // Send headers successfully, but get an error while sending the body.
13676 MockWrite data_writes[] = {
13677 MockWrite("POST / HTTP/1.1\r\n"
13678 "Host: www.foo.com\r\n"
13679 "Connection: keep-alive\r\n"
13680 "Content-Length: 3\r\n\r\n"),
13681 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13684 MockRead data_reads[] = {
13685 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13686 MockRead(SYNCHRONOUS, OK),
13688 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13689 arraysize(data_writes));
13690 session_deps_.socket_factory->AddSocketDataProvider(&data);
13692 TestCompletionCallback callback;
13694 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13695 EXPECT_EQ(ERR_IO_PENDING, rv);
13697 rv = callback.WaitForResult();
13698 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13700 const HttpResponseInfo* response = trans->GetResponseInfo();
13701 EXPECT_TRUE(response == NULL);
13704 // Verify that proxy headers are not sent to the destination server when
13705 // establishing a tunnel for a secure WebSocket connection.
13706 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
13707 HttpRequestInfo request;
13708 request.method = "GET";
13709 request.url = GURL("wss://www.example.org/");
13710 AddWebSocketHeaders(&request.extra_headers);
13712 // Configure against proxy server "myproxy:70".
13713 session_deps_.proxy_service.reset(
13714 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13716 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13718 // Since a proxy is configured, try to establish a tunnel.
13719 MockWrite data_writes[] = {
13720 MockWrite(
13721 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13722 "Host: www.example.org\r\n"
13723 "Proxy-Connection: keep-alive\r\n\r\n"),
13725 // After calling trans->RestartWithAuth(), this is the request we should
13726 // be issuing -- the final header line contains the credentials.
13727 MockWrite(
13728 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13729 "Host: www.example.org\r\n"
13730 "Proxy-Connection: keep-alive\r\n"
13731 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13733 MockWrite(
13734 "GET / HTTP/1.1\r\n"
13735 "Host: www.example.org\r\n"
13736 "Connection: Upgrade\r\n"
13737 "Upgrade: websocket\r\n"
13738 "Origin: http://www.example.org\r\n"
13739 "Sec-WebSocket-Version: 13\r\n"
13740 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13743 // The proxy responds to the connect with a 407, using a persistent
13744 // connection.
13745 MockRead data_reads[] = {
13746 // No credentials.
13747 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
13748 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13749 MockRead("Proxy-Connection: close\r\n\r\n"),
13751 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13753 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13754 MockRead("Upgrade: websocket\r\n"),
13755 MockRead("Connection: Upgrade\r\n"),
13756 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13759 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13760 arraysize(data_writes));
13761 session_deps_.socket_factory->AddSocketDataProvider(&data);
13762 SSLSocketDataProvider ssl(ASYNC, OK);
13763 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13765 scoped_ptr<HttpTransaction> trans(
13766 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13767 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13768 trans->SetWebSocketHandshakeStreamCreateHelper(
13769 &websocket_stream_create_helper);
13772 TestCompletionCallback callback;
13774 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13775 EXPECT_EQ(ERR_IO_PENDING, rv);
13777 rv = callback.WaitForResult();
13778 EXPECT_EQ(OK, rv);
13781 const HttpResponseInfo* response = trans->GetResponseInfo();
13782 ASSERT_TRUE(response);
13783 ASSERT_TRUE(response->headers.get());
13784 EXPECT_EQ(407, response->headers->response_code());
13787 TestCompletionCallback callback;
13789 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
13790 callback.callback());
13791 EXPECT_EQ(ERR_IO_PENDING, rv);
13793 rv = callback.WaitForResult();
13794 EXPECT_EQ(OK, rv);
13797 response = trans->GetResponseInfo();
13798 ASSERT_TRUE(response);
13799 ASSERT_TRUE(response->headers.get());
13801 EXPECT_EQ(101, response->headers->response_code());
13803 trans.reset();
13804 session->CloseAllConnections();
13807 // Verify that proxy headers are not sent to the destination server when
13808 // establishing a tunnel for an insecure WebSocket connection.
13809 // This requires the authentication info to be injected into the auth cache
13810 // due to crbug.com/395064
13811 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
13812 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
13813 HttpRequestInfo request;
13814 request.method = "GET";
13815 request.url = GURL("ws://www.example.org/");
13816 AddWebSocketHeaders(&request.extra_headers);
13818 // Configure against proxy server "myproxy:70".
13819 session_deps_.proxy_service.reset(
13820 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13822 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13824 MockWrite data_writes[] = {
13825 // Try to establish a tunnel for the WebSocket connection, with
13826 // credentials. Because WebSockets have a separate set of socket pools,
13827 // they cannot and will not use the same TCP/IP connection as the
13828 // preflight HTTP request.
13829 MockWrite(
13830 "CONNECT www.example.org:80 HTTP/1.1\r\n"
13831 "Host: www.example.org:80\r\n"
13832 "Proxy-Connection: keep-alive\r\n"
13833 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13835 MockWrite(
13836 "GET / HTTP/1.1\r\n"
13837 "Host: www.example.org\r\n"
13838 "Connection: Upgrade\r\n"
13839 "Upgrade: websocket\r\n"
13840 "Origin: http://www.example.org\r\n"
13841 "Sec-WebSocket-Version: 13\r\n"
13842 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13845 MockRead data_reads[] = {
13846 // HTTP CONNECT with credentials.
13847 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13849 // WebSocket connection established inside tunnel.
13850 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13851 MockRead("Upgrade: websocket\r\n"),
13852 MockRead("Connection: Upgrade\r\n"),
13853 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13856 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13857 arraysize(data_writes));
13858 session_deps_.socket_factory->AddSocketDataProvider(&data);
13860 session->http_auth_cache()->Add(
13861 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
13862 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
13864 scoped_ptr<HttpTransaction> trans(
13865 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13866 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
13867 trans->SetWebSocketHandshakeStreamCreateHelper(
13868 &websocket_stream_create_helper);
13870 TestCompletionCallback callback;
13872 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13873 EXPECT_EQ(ERR_IO_PENDING, rv);
13875 rv = callback.WaitForResult();
13876 EXPECT_EQ(OK, rv);
13878 const HttpResponseInfo* response = trans->GetResponseInfo();
13879 ASSERT_TRUE(response);
13880 ASSERT_TRUE(response->headers.get());
13882 EXPECT_EQ(101, response->headers->response_code());
13884 trans.reset();
13885 session->CloseAllConnections();
13888 } // namespace net